+2  A: 

The trick is to add the border your self. I did so by making the main content element a DockPanel and adding a Border. You can use the border to customize the look to match the Vista Style windows. I'm not good with colors so I can't name that particular one but used Gray as an example.

Try the following

<Window x:Class="WpfApplication10.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" 
    Height="300" 
    Width="300"
    WindowStyle="None"
    ResizeMode="NoResize">
    <DockPanel>
        <Border
            BorderBrush="Gray"
            BorderThickness="5">

            <TextBlock>Here we go</TextBlock>

        </Border>
    </DockPanel>
</Window>
JaredPar
I did consider this approach but then problem is getting the border to match the system visual style.
Jonathan
Actually you don't even need the DockPanel.
Bryan Anderson
@Bryan, I tried without the DockPanel and the Border was not filling the client area. Adding the DockPanel fixed it.
JaredPar
A: 

There is a solution in code posted here. I'm going to look into doing it in straight XAML though, there should be a way to style your window border so it looks close. You should also take a look at this for a better explanation of what the forum post is doing.

Bryan Anderson
A: 

I figured I'd post what I've come up with so far. This gets pretty close:

<Window.Style>
 <Style TargetType="{x:Type Window}">
  <Setter Property="AllowsTransparency"  Value="True"   />
  <Setter Property="Background"   Value="{x:Null}"  />
  <Setter Property="BorderBrush"   Value="{x:Null}"  />
  <Setter Property="BorderThickness"  Value="0"   />
  <Setter Property="OverridesDefaultStyle" Value="True"   />
  <Setter Property="ResizeMode"   Value="NoResize"  />
  <Setter Property="SizeToContent"  Value="WidthAndHeight"  />
  <Setter Property="WindowStyle"   Value="None"   />
  <Setter Property="Template">
   <Setter.Value>
    <ControlTemplate TargetType="{x:Type Window}">
     <Border BorderThickness="1" CornerRadius="4" Background="{x:Null}">
      <Border.BorderBrush>
       <SolidColorBrush Color="{x:Static SystemColors.WindowFrameColor}" Opacity="0.75" />
      </Border.BorderBrush>
      <Border BorderThickness="5" Background="{x:Null}">
       <Border.BorderBrush>
        <SolidColorBrush Color="{x:Static SystemColors.ActiveBorderColor}" Opacity="0.5" />
       </Border.BorderBrush>
       <Border BorderThickness="1" Background="White">
        <Border.BorderBrush>
         <SolidColorBrush Color="{x:Static SystemColors.WindowFrameColor}" Opacity="0.75" />
        </Border.BorderBrush>

        <ContentPresenter />
       </Border>
      </Border>
     </Border>
    </ControlTemplate>
   </Setter.Value>
  </Setter>
 </Style>
</Window.Style>

Clearly they are using more than just a transparency on the ActiveWindowBorderColor to draw the middle of the border. It seems that the top 1/4 has a white overlay while the bottom 3/4 has a black overlay. Also the outer border has an accent color on the right and bottom edges. If I were to do this for real I would create a UserControl that derives from Border to handle all of the little details like that (and allow me to resize if I want) and throw the Window's style into a resource dictionary.

Bryan Anderson
+1  A: 

What you need is to specify the right combination of window styles, WPF does not expose all the options available in Windows but you can set them yourself using pinvoke.

I'm not at a Vista machine right now so I can't test style combination to see what gives the correct look but the list of styles (in C#) is here http://pinvoke.net/default.aspx/user32/GetWindowLong.html

in you're Window class:

[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);

[DllImport("user32.dll")]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

private const int GWL_STYLE = -16;
private const int GWL_EXSTYLE = -20;
private const UInt32 SWP_NOSIZE = 0x0001;
private const UInt32 SWP_NOMOVE = 0x0002;
private const UInt32 SWP_NOZORDER = 0x0004;
private const UInt32 SWP_NOREDRAW = 0x0008;
private const UInt32 SWP_NOACTIVATE = 0x0010;
private const UInt32 SWP_FRAMECHANGED = 0x0020;

public override void OnSourceInitialized(EventArgs e)
{
    IntPtr hwnd = new System.Windows.Interop.WindowInteropHelper(this).Handle;

    // set styles to a combination of WS_ flags and exstyles to a combination of WS_EX_ flags

    SetWindowLong(hwnd, GWL_STYLE, styles);
    SetWindowLong(hwnd, GWL_EXSTYLE, exstyles);

    // and to activate changes:
    SetWindowPos(hwnd,IntPtr.Zero,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_FRAMECHANGED);
}
Nir
I can't get this to work. If I leave WS_CAPTION then the Aero frame stays but there is a large border at the top for the caption (which can be used to move the window.) If I omit WS_CAPTION then I lose the Aero frame and get a thin window frame instead.
Jonathan
+2  A: 

I finally figured it out: If you set WindowStyle to "None" and ResizeMode to "CanResize" then you'll get the correct thick border without a caption, the only hitch is that you can still resize the window.

Fortunately this problem is easily rectified by handling WM_NCHITTEST for your Window instance:

private IntPtr _hwnd;

protected override void OnSourceInitialized(EventArgs e) {
    _hwnd = new System.Windows.Interop.WindowInteropHelper(this).Handle;
    System.Windows.Interop.HwndSource.FromHwnd(_hwnd).AddHook(_WndProc);
    base.OnSourceInitialized(e);
}

private const int WM_NCHITTEST = 132;
private const int HTCLIENT = 1;

private IntPtr _WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) {
    // We should only receive messages for our own window handle.
    System.Diagnostics.Debug.Assert(hwnd == _hwnd);

    if (msg == WM_NCHITTEST) {
        handled = true;
        return (IntPtr)HTCLIENT;
    }
    return IntPtr.Zero;
}

By never letting Windows know that the cursor is on a border, we will never be presented with a resize cursor.

Jonathan