首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Winforms:在UserControl中添加关闭"x“按钮

Winforms:在UserControl中添加关闭"x“按钮
EN

Stack Overflow用户
提问于 2011-05-16 22:37:03
回答 3查看 2.8K关注 0票数 2

我需要在UserControl的左上角添加一个关闭"x“按钮。我希望该按钮有类似的风格,通常的Winforms关闭按钮(蓝色在XP的风格,等等)。

有可能做这样的事情吗?

EN

回答 3

Stack Overflow用户

发布于 2011-05-16 23:36:51

下面是一个如何制作模拟按钮的示例。它在窗体本身上执行此操作,但在自定义控件上的工作方式相同。

它还展示了如何在ControlPaint样式太“旧”的情况下使用VisualStyleRenderer获得“花哨”的按钮样式。

在六次编辑后更新了,我想我对它很满意。

代码语言:javascript
复制
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;

class Form1 : Form
{
    [STAThread]
    static void Main()
    {
        //Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }

    public Form1()
    {
        SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.Opaque | ControlStyles.AllPaintingInWmPaint, true);
    }

    Rectangle buttonRect = new Rectangle(10, 10, 50, 20);
    ButtonState buttonState = ButtonState.Normal;

    protected override void OnMouseMove(MouseEventArgs e)
    {
        if (buttonRect.Contains(e.Location))
            buttonState = Capture ? ButtonState.Pushed : ButtonState.Checked;
        else
            buttonState = ButtonState.Normal;
        Invalidate(buttonRect);

        base.OnMouseMove(e);
    }

    protected override void OnMouseDown(MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left && buttonRect.Contains(e.Location))
        {
            Capture = true;
            buttonState = ButtonState.Pushed;
            Invalidate(buttonRect);
        }

        base.OnMouseDown(e);
    }

    protected override void OnMouseUp(MouseEventArgs e)
    {
        if (Capture)
        {
            Capture = false;
            Invalidate(buttonRect);
            if (buttonRect.Contains(e.Location))
            {
                // The button was clicked

                MessageBox.Show("You clicked the button.");
            }
        }

        base.OnMouseUp(e);
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        e.Graphics.FillRectangle(SystemBrushes.Window, e.ClipRectangle);

        VisualStyleRenderer renderer = null;
        if (Application.RenderWithVisualStyles)
        {
            switch (buttonState)
            {
                case ButtonState.Checked:
                    if (VisualStyleRenderer.IsElementDefined(VisualStyleElement.Window.CloseButton.Hot))
                        renderer = new VisualStyleRenderer(VisualStyleElement.Window.CloseButton.Hot);
                    break;
                case ButtonState.Pushed:
                    if (VisualStyleRenderer.IsElementDefined(VisualStyleElement.Window.CloseButton.Pressed))
                        renderer = new VisualStyleRenderer(VisualStyleElement.Window.CloseButton.Pressed);
                    break;
                default:
                    if (VisualStyleRenderer.IsElementDefined(VisualStyleElement.Window.CloseButton.Normal))
                        renderer = new VisualStyleRenderer(VisualStyleElement.Window.CloseButton.Normal);
                    break;
            }
        }

        if (renderer != null)
            renderer.DrawBackground(e.Graphics, buttonRect);
        else
            ControlPaint.DrawCaptionButton(e.Graphics, buttonRect, CaptionButton.Close, buttonState);

        base.OnPaint(e);
    }
}

Extended Comment

扩展操作的开始是用户按下鼠标按钮,(可选)移动鼠标,然后释放该按钮。单击UI按钮始终是一个扩展操作。捕获鼠标的目的是防止它在该操作过程中与其他窗口交互。

你现在就可以看到这个演示:

首先请注意,当您将鼠标移到此页面上的元素(如注释)上时,它们如何改变背景颜色。

现在打开窗口运行对话框(Win+R)。

单击Cancel或Browse...按钮,并保持按住按钮。

将鼠标移动到浏览器窗口,您会注意到它不再记录您的鼠标移动。

这就是所有按钮的工作原理。虽然几乎没有人注意到它,因为您通常在不移动鼠标的情况下单击并释放。

将鼠标从按钮上移开并释放是提供给用户的一种机制,以允许他们改变主意,而不是“点击”按钮。这就是为什么您要在button up事件中再次测试,以确保在确定用户已执行单击之前它们仍在按钮上。

因此,捕获鼠标有三个原因:

首先,您不希望其他窗口执行高亮显示之类的操作,因为用户正忙于与您的窗口交互,让其他窗口在操作过程中进行操作会分散注意力,并且可能会造成混乱。

其次,您不希望用户释放鼠标按钮时被发送到另一个窗口,以免用户将鼠标一直移动到另一个窗口。没有附带按键的虚假鼠标释放可能会混淆编写得很差的应用程序。

第三,对于某些扩展操作,比如绘画或"wrangling",你想知道鼠标的坐标,即使它们在你的窗口边界之外。您可以通过在桌面上单击并按住并移动鼠标来查看争执的示例。请注意,即使将鼠标移到其他窗口上,矩形也会发生变化。

票数 5
EN

Stack Overflow用户

发布于 2011-05-16 22:50:56

已更新答案

我刚发现.net中的ControlPaint类,它与DrawFrameControl函数做同样的事情。用它来代替吧!

您可以使用ControlPaint类来实现一个按钮控件,该控件将自身绘制为类似于窗口的“关闭”按钮(覆盖OnPaint)。根据所需的复杂程度,您还可以实现鼠标悬停事件和鼠标按下事件,以提供当前状态的可视反馈。如果您将控件放在UserControl上,那么您应该在正确的轨道上。

原始、过时的答案

您可能需要查看windows中的DrawFrameControl API函数。

DFC_CAPTIONDFCS_CAPTIONCLOSE的组合应该可以做您想做的事情。

票数 3
EN

Stack Overflow用户

发布于 2011-05-16 22:49:49

我不确定这是不是可能的,但如果你的主控件托管这个UserContorl将有这3个按钮(最小,最大/关闭)和你的UserControl,这肯定会让用户感到困惑。这背后的理性是什么?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6018980

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档