问题
I wrote an attached property that I can set on a window to extend the glass frame into the client area (using the DwmExtendFrameIntoClientArea
API). It works fine in most cases. Now I want my window to be borderless, so I set the following attributes on my window :
WindowStyle="None"
ResizeMode="NoResize"
Background="Transparent"
u:WinUtil.EnableGlass="True"
ShowInTaskbar="False"
But with these attributes, the glass doesn't show up at all : my window just has a transparent background. If I set ResizeMode
to CanResize
, the glass is shown, but I don't want the window to be resizable.
I suspect it is due to the fact that the glass effect is obtained by extending the non-client frame into the client area : with WindowStyle = None
and ResizeMode = NoResize
, there is no non-client frame, so there's nothing to extend. When I enable resizing, it creates a frame around the window, so the frame can be extended.
I guess it should be possible to create a window that has a thin border, no title bar, and can't be resized, by setting the appropriate WS_* bits, but I don't know which ones exactly
So my questions are :
- Which style bits should be set or unset to have the desired appearance and behavior ?
- How can I initialize the window's style bits ? The Window class doesn't seem to have anything like Windows Forms
CreateParams
property... Is it OK to set these bits after the handle has been created ? - I found the
HwndSource
class that could be an answer to question 2, but it seems a bit complex to use if you're not a Win32 expert... Would it be a sensible solution to my problem ?
Any advice is welcome
回答1:
Have you tried using DwmEnableBlurBehindWindow? This enables you to make a specific part of a window's client area transparent.
回答2:
I had a Window that I wanted to give just a glass boarder (no title bar and non-resizable) and ran into the same problem as you. You cannot accomplish this just by setting the Window's style. My solution was to set ResizeMode="CanResize" and WindowStyle="None" then handle the WM_NCHITTEST event to convert resizable border hits to non-resizable border hits. It was also necessary to modify the Window's style to disable maximizing and minimizing (using Windows shortcuts) and the system menu:
private void Window_SourceInitialized(object sender, EventArgs e)
{
System.Windows.Interop.HwndSource source = (System.Windows.Interop.HwndSource)PresentationSource.FromVisual(this);
source.AddHook(new System.Windows.Interop.HwndSourceHook(HwndSourceHook));
IntPtr hWnd = new System.Windows.Interop.WindowInteropHelper(this).Handle;
IntPtr flags = GetWindowLongPtr(hWnd, -16 /*GWL_STYLE*/);
SetWindowLongPtr(hWnd, -16 /*GWL_STYLE*/, new IntPtr(flags.ToInt64() & ~(0x00010000L /*WS_MAXIMIZEBOX*/ | 0x00020000L /*WS_MINIMIZEBOX*/ | 0x00080000L /*WS_SYSMENU*/)));
}
private static IntPtr HwndSourceHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch (msg)
{
case 0x0084 /*WM_NCHITTEST*/:
IntPtr result = DefWindowProc(hwnd, msg, wParam, lParam);
if (result.ToInt32() >= 10 /*HTLEFT*/ && result.ToInt32() <= 17 /*HTBOTTOMRIGHT*/ )
{
handled = true;
return new IntPtr(18 /*HTBORDER*/);
}
break;
}
return IntPtr.Zero;
}
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern IntPtr DefWindowProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
[System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
[System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex);
This gives you a Window in Windows 7 suitable for notification area flyouts (e.g. the clock or volume flyouts). BTW, you can reproduce the shading at the bottom of the flyout by creating a control of height 44 and setting it's background:
<Control.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="{x:Static SystemColors.GradientActiveCaptionColor}" Offset="0"/>
<GradientStop Color="{x:Static SystemColors.InactiveBorderColor}" Offset="0.1"/>
</LinearGradientBrush>
</Control.Background>
来源:https://stackoverflow.com/questions/1324398/enable-vista-glass-effect-on-a-borderless-wpf-window