【问题标题】:Emulating the Vista notification icon dialog boxes with WPF使用 WPF 模拟 Vista 通知图标对话框
【发布时间】:2009-03-22 13:25:59
【问题描述】:

在 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 像素的细实线边框。)

【问题讨论】:

    标签: wpf dialog icons notifications


    【解决方案1】:

    诀窍是自己添加边框。我通过将主要内容元素设为 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>
    

    【讨论】:

    • 我确实考虑过这种方法,但问题是让边框与系统视觉风格相匹配。
    • 其实你甚至不需要 DockPanel。
    • @Bryan,我尝试不使用 DockPanel 并且边框没有填充客户区。添加 DockPanel 修复它。
    【解决方案2】:

    我终于想通了:如果您将 WindowStyle 设置为“None”并将 ResizeMode 设置为“CanResize”,那么您将获得正确的粗边框而没有标题,唯一的问题是您仍然可以调整窗口大小。

    幸运的是,通过为您的 Window 实例处理 WM_NCHITTEST 可以轻松解决此问题:

    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 知道光标在边框上,我们将永远不会看到调整大小的光标。

    【讨论】:

      【解决方案3】:

      您需要指定正确的窗口样式组合,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);
      }
      

      【讨论】:

      • 我无法让它工作。如果我离开 WS_CAPTION,则 Aero 框架会保留,但标题顶部有一个大边框(可用于移动窗口。)如果我省略 WS_CAPTION,那么我会丢失 Aero 框架并获得一个薄的窗口框架。
      【解决方案4】:

      我想我会发布到目前为止我想出的东西。这非常接近:

      <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 有一个黑色覆盖层。此外,外边框在右侧和底部边缘有强调色。如果我真的要这样做,我会创建一个派生自 Border 的 UserControl 来处理所有类似的小细节(并允许我根据需要调整大小)并将 Window 的样式放入资源字典中。

      【讨论】:

        【解决方案5】:

        here 发布的代码中有一个解决方案。我打算直接用 XAML 来做,应该有一种方法来设置你的窗口边框的样式,让它看起来很接近。您还应该查看this,以更好地了解论坛帖子的用途。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-07-27
          • 1970-01-01
          • 2017-09-07
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多