当前位置:  开发笔记 > 编程语言 > 正文

如何使用Windows窗体在Window Titlebar中绘制自定义按钮?

如何解决《如何使用Windows窗体在WindowTitlebar中绘制自定义按钮?》经验,为你挑选了1个好方法。

如何在表单的标题栏中最小化,最大化和关闭按钮旁边绘制自定义按钮?

我知道您需要使用Win32 API调用并覆盖WndProc过程,但我无法找到一个正常的解决方案.

有谁知道如何做到这一点?更具体地说,有没有人知道在Vista中有效的方法?



1> Matthew Scha..:

以下将在XP中工作,我没有Vista机器方便测试它,但我认为你的问题源于一个不正确的hWnd.无论如何,使用评论不佳的代码.

// The state of our little button
ButtonState _buttState = ButtonState.Normal;
Rectangle _buttPosition = new Rectangle();

[DllImport("user32.dll")]
private static extern IntPtr GetWindowDC(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern int GetWindowRect(IntPtr hWnd, 
                                        ref Rectangle lpRect);
[DllImport("user32.dll")]
private static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
protected override void WndProc(ref Message m)
{
    int x, y;
    Rectangle windowRect = new Rectangle();
    GetWindowRect(m.HWnd, ref windowRect);

    switch (m.Msg)
    {
        // WM_NCPAINT
        case 0x85:
        // WM_PAINT
        case 0x0A:
            base.WndProc(ref m);

            DrawButton(m.HWnd);

            m.Result = IntPtr.Zero;

            break;

        // WM_ACTIVATE
        case 0x86:
            base.WndProc(ref m);
            DrawButton(m.HWnd);

            break;

        // WM_NCMOUSEMOVE
        case 0xA0:
            // Extract the least significant 16 bits
            x = ((int)m.LParam << 16) >> 16;
            // Extract the most significant 16 bits
            y = (int)m.LParam >> 16;

            x -= windowRect.Left;
            y -= windowRect.Top;

            base.WndProc(ref m);

            if (!_buttPosition.Contains(new Point(x, y)) && 
                _buttState == ButtonState.Pushed)
            {
                _buttState = ButtonState.Normal;
                DrawButton(m.HWnd);
            }

            break;

        // WM_NCLBUTTONDOWN
        case 0xA1:
            // Extract the least significant 16 bits
            x = ((int)m.LParam << 16) >> 16;
            // Extract the most significant 16 bits
            y = (int)m.LParam >> 16;

            x -= windowRect.Left;
            y -= windowRect.Top;

            if (_buttPosition.Contains(new Point(x, y)))
            {
                _buttState = ButtonState.Pushed;
                DrawButton(m.HWnd);
            }
            else
                base.WndProc(ref m);

            break;

        // WM_NCLBUTTONUP
        case 0xA2:
            // Extract the least significant 16 bits
            x = ((int)m.LParam << 16) >> 16;
            // Extract the most significant 16 bits
            y = (int)m.LParam >> 16;

            x -= windowRect.Left;
            y -= windowRect.Top;

            if (_buttPosition.Contains(new Point(x, y)) &&
                _buttState == ButtonState.Pushed)
            {
                _buttState = ButtonState.Normal;
                // [[TODO]]: Fire a click event for your button 
                //           however you want to do it.
                DrawButton(m.HWnd);
            }
            else
                base.WndProc(ref m);

            break;

        // WM_NCHITTEST
        case 0x84:
            // Extract the least significant 16 bits
            x = ((int)m.LParam << 16) >> 16;
            // Extract the most significant 16 bits
            y = (int)m.LParam >> 16;

            x -= windowRect.Left;
            y -= windowRect.Top;

            if (_buttPosition.Contains(new Point(x, y)))
                m.Result = (IntPtr)18; // HTBORDER
            else
                base.WndProc(ref m);

            break;

        default:
            base.WndProc(ref m);
            break;
    }
}

private void DrawButton(IntPtr hwnd)
{
    IntPtr hDC = GetWindowDC(hwnd);
    int x, y;

    using (Graphics g = Graphics.FromHdc(hDC))
    {
        // Work out size and positioning
        int CaptionHeight = Bounds.Height - ClientRectangle.Height;
        Size ButtonSize = SystemInformation.CaptionButtonSize;
        x = Bounds.Width - 4 * ButtonSize.Width;
        y = (CaptionHeight - ButtonSize.Height) / 2;
        _buttPosition.Location = new Point(x, y);

        // Work out color
        Brush color;
        if (_buttState == ButtonState.Pushed)
            color = Brushes.LightGreen;
        else
            color = Brushes.Red;

        // Draw our "button"
        g.FillRectangle(color, x, y, ButtonSize.Width, ButtonSize.Height);
    }

    ReleaseDC(hwnd, hDC);
}

private void Form1_Load(object sender, EventArgs e)
{
    _buttPosition.Size = SystemInformation.CaptionButtonSize;
}

推荐阅读
我我檬檬我我186
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有