WPF中自制窗口标题栏

在WPF程序开发中,我们常常会发现默认的窗口标题栏过于不合适,而想修改其样式。有不少办法可以达到这一目的,但往往都不那么容易。而最简单的方法就是,直接不要默认的标题栏,转而在窗体内部重新制作一个,这样就可以充分使用我们所熟知的WPF的开发方式。不过,这样一来又有一个问题,即模拟的标题栏毕竟不是真正的标题栏,按住它无法拖动窗口,也无法双击最大化。Aland Li提供了一个好办法解决这一问题。

Windows使用WM_NCHITTEST窗口消息来判断鼠标的位置的类型,比如是否是标题栏,我们可以捕获这个消息,然后检查鼠标的坐标,如果在我们所设计的标题栏内,我们就告诉系统这个位置在标题栏上(返回HTCAPTION(2))。下面是详细代码:

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(PointFromScreen(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;如此,只要点击窗口上方0-100的区域,便可以拖动窗口,也可以双击窗口进行最大化了。

而要去掉默认的标题栏,只需要将WindowStyle设为None即可。

BTW,其实并不一定要WPF才行吧,这个方法同时也适用于Winform,不过一般WPF程序更有美化标题栏的需求而已。


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/mane_yao/archive/2010/07/02/5708487.aspx

posted @ 2010-09-18 10:51  Yao,Mane  阅读(1688)  评论(0编辑  收藏  举报