使用 WPF 模拟 Vista 通知图标对话框
-
21-08-2019 - |
题
当单击 Vista 中的通知图标(例如网络或声音图标)时,您会看到一个带边框但无标题的对话框(http://i.msdn.microsoft.com/Aa511448.NotificationArea22(en-us,MSDN.10).png):
http://i.msdn.microsoft.com/Aa511448.NotificationArea22(en-us,MSDN.10).png
我如何在 WPF 中模拟这些?创建一个新窗口并将 WindowStyle 设置为“None”并将 ResizeMode 设置为“CanResize”会产生接近的结果,只是框架稍微太薄并且对话框可调整大小,这是不希望的。将 ResizeMode 设置为“NoResize”会导致窗口没有 Aero 边框(只有 2 像素的细实线边框。)
解决方案 2
我终于想通了:如果设置WindowStyle为“无”和ResizeMode为“CanResize”那么你会得到正确的厚边框不带字幕的,唯一的障碍是,你仍然可以调整窗口大小。 p>
好在这个问题通过处理WM_NCHITTEST您Window
实例容易修正:
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;
}
这是从来没有让Windows知道光标在一个边界,我们将永远不会出现一个大小调整光标。
其他提示
关键是要添加边框你的自我。我通过使主要内容元素的DockPanel中和添加边框这样做了。您可以使用边界自定义外观,以配合Vista的风格的窗户。我不擅长颜色,所以我不能名称特定的一个而使用格雷,例如,
尝试使用以下
<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>
您需要的是指定的窗口样式的正确组合,WPF不公开所有可用的选项在Windows,但你可以使用的PInvoke自行设置。
我不是在Vista的机器所以我现在不能测试相结合的风格,看看能给出正确的外观,但样式列表(在C#)是这里的 http://pinvoke.net/default.aspx/user32/GetWindowLong.html
在你的Window类:
[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);
}
我想我会后我已经想出这么远。这得到相当接近:
<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>
显然,他们是利用不仅仅是在ActiveWindowBorderColor透明度更绘制边框的正中间。看来,前1/4有一个白色的覆盖而底部3/4有一个黑色覆盖。另外,外边框对右边和底部边缘的强调色。如果我是真正的我会创建一个从边境派生来处理所有的这样的小细节的用户控件做到这一点(和允许我来调整,如果我想),并抛出窗口的风格融入了资源字典。