none
WPF如何改变标题栏?或者操作没有边框的窗体 RRS feed

答案

  • Glidor 提供了一个好方法。至于让标题栏区域表现的确实像标题栏(例如点击拖动窗体之类),我们可以捕获WM_NCHITTEST消息,然后检查坐标,如果坐标在标题栏范围内,则欺骗系统鼠标点在标题栏上。下面是详细代码:

    Aland Li

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
          //添加一个消息过滤器
          IntPtr hwnd = new WindowInteropHelper(this).Handle;
          HwndSource.FromHwnd(hwnd).AddHook(new HwndSourceHook(WndProc));
        }
    
        private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
          if (msg == WM_NCHITTEST)
          {
            // 获取屏幕坐标
            Point p = new Point();
            int pInt = lParam.ToInt32();
            p.X = (pInt << 16) >> 16; 
            p.Y = pInt >> 16; 
            if (IsOnTitleBar(p))
            {
              //欺骗系统鼠标点击在标题栏上
              handled = true;
              return new IntPtr(2);
            }
          }
    
          return IntPtr.Zero;
        }
    
        private bool IsOnTitleBar(Point p)
        {
          //假设标题栏在0和100之间
          if (p.Y >= 0 && p.Y < 100)
            return true;
          else
            return false;
        }
    
        private const int WM_NCHITTEST = 0x0084;

    Please mark the replies as answers if they help and unmark if they don't. This can be beneficial to other community members reading the thread.
    • 已标记为答案 Rayman Zhai 2010年6月29日 12:29
    2010年6月29日 6:18
    版主
  • 学习了!我在回答时还并不清楚具体要怎么实现,多谢指点!

    不过我测试了一下,似乎有点小问题,查阅MSDN后发现对于WM_NCHITTEST消息的参数是这样说的:

    lParam

    The low-order word specifies the x-coordinate of the cursor. The coordinate is relative to the upper-left corner of the screen.

    The high-order word specifies the y-coordinate of the cursor. The coordinate is relative to the upper-left corner of the screen.

    也就是说这里的坐标是相对于屏幕左上角的,所以是不是应该做如下修改:

    if(IsOnTitleBar(PointFromScreen(p)))
    {
        //欺骗系统鼠标在标题栏上
        handled = true;
        return new IntPtr(2);
    }

    这样在我这里运行就正常了。


    Tech Blog: http://gildor.cnblogs.com
    • 已标记为答案 Rayman Zhai 2010年6月29日 12:29
    2010年6月29日 9:29

全部回复

  • 拦截消息干什么??

    Window有个Title属性.这个就是标题栏的名称了.

    还有一个属性叫WindowStyle, 具体值可以是 WindowStyle 枚举值之一,包括 None(这个应是是你想要设置的)、ToolWindow、SingleBorderWindow(默认值)和 ThreeDBorderWindow

    2010年6月13日 8:27
  • 您好,

    您可以参考下面的文档:
    http://alandli.spaces.live.com/blog/cns!B5038E2897597982!325.entry?wa=wsignin1.0&sa=618929361

    Regards,
    Aland Li


    Please mark the replies as answers if they help and unmark if they don't. This can be beneficial to other community members reading the thread.
    2010年6月14日 8:52
    版主
  • 您好,

    那您到底想做什么呢? 是不是想hook WPF的windows啊?

    Aland Li


    Please mark the replies as answers if they help and unmark if they don't. This can be beneficial to other community members reading the thread.
    2010年6月24日 5:47
    版主
  • 您好,非常感謝您的回答,

    簡單來説我就説想重繪WPF窗體的標題欄。


    欢迎到我的博客一起讨论 http://www.raymanzhai.com
    2010年6月27日 17:20
  • 把原有的Window标题栏隐藏掉,自己重新做一个。只是要适当控制窗口移动功能。
    Tech Blog: http://gildor.cnblogs.com
    2010年6月28日 13:05
  • Glidor 提供了一个好方法。至于让标题栏区域表现的确实像标题栏(例如点击拖动窗体之类),我们可以捕获WM_NCHITTEST消息,然后检查坐标,如果坐标在标题栏范围内,则欺骗系统鼠标点在标题栏上。下面是详细代码:

    Aland Li

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
          //添加一个消息过滤器
          IntPtr hwnd = new WindowInteropHelper(this).Handle;
          HwndSource.FromHwnd(hwnd).AddHook(new HwndSourceHook(WndProc));
        }
    
        private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
          if (msg == WM_NCHITTEST)
          {
            // 获取屏幕坐标
            Point p = new Point();
            int pInt = lParam.ToInt32();
            p.X = (pInt << 16) >> 16; 
            p.Y = pInt >> 16; 
            if (IsOnTitleBar(p))
            {
              //欺骗系统鼠标点击在标题栏上
              handled = true;
              return new IntPtr(2);
            }
          }
    
          return IntPtr.Zero;
        }
    
        private bool IsOnTitleBar(Point p)
        {
          //假设标题栏在0和100之间
          if (p.Y >= 0 && p.Y < 100)
            return true;
          else
            return false;
        }
    
        private const int WM_NCHITTEST = 0x0084;

    Please mark the replies as answers if they help and unmark if they don't. This can be beneficial to other community members reading the thread.
    • 已标记为答案 Rayman Zhai 2010年6月29日 12:29
    2010年6月29日 6:18
    版主
  • 学习了!我在回答时还并不清楚具体要怎么实现,多谢指点!

    不过我测试了一下,似乎有点小问题,查阅MSDN后发现对于WM_NCHITTEST消息的参数是这样说的:

    lParam

    The low-order word specifies the x-coordinate of the cursor. The coordinate is relative to the upper-left corner of the screen.

    The high-order word specifies the y-coordinate of the cursor. The coordinate is relative to the upper-left corner of the screen.

    也就是说这里的坐标是相对于屏幕左上角的,所以是不是应该做如下修改:

    if(IsOnTitleBar(PointFromScreen(p)))
    {
        //欺骗系统鼠标在标题栏上
        handled = true;
        return new IntPtr(2);
    }

    这样在我这里运行就正常了。


    Tech Blog: http://gildor.cnblogs.com
    • 已标记为答案 Rayman Zhai 2010年6月29日 12:29
    2010年6月29日 9:29
  • 不好意思,代码我没仔细测试,只是写了个大概思路。

    Aland Li


    Please mark the replies as answers if they help and unmark if they don't. This can be beneficial to other community members reading the thread.
    2010年6月29日 12:37
    版主