如何在Windows窗体应用程序中设计自定义关闭,最小化和最大化按钮?

时间:2015-03-13 04:32:06

标签: c# winforms

我正在创建一个Windows窗体应用程序项目,其中我想要一个自定义边框和我自己设计的三个按钮(关闭,最小化和最大化)。我不知道该怎么做,我甚至不确定它是否可行。但如果有可能请告诉我解决方案。感谢

5 个答案:

答案 0 :(得分:22)

是的,没有额外的库就可以。

首先,隐藏窗口的原始边框。

public Form1()
{
    InitializeComponent();

    FormBorderStyle = FormBorderStyle.None;
}

接下来,使用您的三个按钮创建一个面板或任何您想要的面板(我知道它很难看,用于演示目的):

enter image description here

然后,使用WindowState

为每个人分配正确的操作
private void minimizeButton_Click(object sender, System.EventArgs e)
{
    WindowState = FormWindowState.Minimized;
}

private void maximizeButton_Click(object sender, System.EventArgs e)
{
    WindowState = FormWindowState.Maximized;
}

private void closeButton_Click(object sender, System.EventArgs e)
{
    Close();
}

最后,使用我们的面板使表单可拖动。在课程级别添加:

public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HTCAPTION = 0x2;
[DllImport("User32.dll")]
public static extern bool ReleaseCapture();
[DllImport("User32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);

并将它们插入面板的MouseDown事件中:

private void OnMouseDown(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        ReleaseCapture();
        SendMessage(Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
    }
}

现在你有一个可拖动的表格,顶部有你自己的栏。

如果您希望它可以调整大小,正如@PhilWright所提到的那样,您可以捕获来自WM_NCHITTEST的{​​{1}}消息并返回WndProc以触发调整大小:

HTBOTTOMRIGHT

正如@BenVoigt所提到的,您可以使用按钮/面板上的protected override void WndProc(ref Message m) { if (m.Msg == 0x84) { const int resizeArea = 10; Point cursorPosition = PointToClient(new Point(m.LParam.ToInt32() & 0xffff, m.LParam.ToInt32() >> 16)); if (cursorPosition.X >= ClientSize.Width - resizeArea && cursorPosition.Y >= ClientSize.Height - resizeArea ) { m.Result = (IntPtr)17; return; } } base.WndProc(ref m); } Dock属性,以便他们可以正确调整大小。如果你没有,他们将不会在调整大小时遵循表格。

答案 1 :(得分:2)

只需完成 @ Pierre-Luc 的有用解决方案。当窗口最大化时,如果我们再次单击最大化按钮,如何将其调整到正常位置。这是代码:

private static bool MAXIMIZED = false;
private void maximizeButton_Click(object sender, System.EventArgs e)
{
    if(MAXIMIZED)
    {
        WindowState = FormWindowState.Normal;
        MAXIMIZED = false;
    }
    else
    {
        WindowState = FormWindowState.Maximized;
        MAXIMIZED = true;
    }
}

编辑:正如@LarsTech在评论

中所建议的那样
private void maximizeButton_Click(object sender, System.EventArgs e)
{
    if (this.WindowState != FormWindowState.Maximized)
        this.WindowState = FormWindowState.Maximized;
    else
        this.WindowState = FormWindowState.Normal;
}

答案 2 :(得分:1)

@Pierre_Luc未涵盖的小细节。 如果您在该面板上添加任何控件,例如标题或图标,单击这些控件时将无法拖动该窗体。为此,我发现将相同的事件处理程序添加到窗体的加载事件中的所有控件(从“最小化”,“最大化”和“关闭”按钮中除外)控件很方便。

private void Form1_Load(object sender, EventArgs e)
    {
        foreach (Control Control in this.HeaderPanel.Controls)
        {
            if (!(Control is Button)) //Change here depending on the Library you use for your contols
            {
                Control.MouseDown += new System.Windows.Forms.MouseEventHandler(this.OnMouseDown);
            }
        }
    }

Morevoer,这是 WndProc 的完整版本,可在各个方向(左,右,下)调整大小。

protected override void WndProc(ref Message m)
    {
        if (m.Msg == 0x84)
        {
            const int resizeArea = 10;
            Point cursorPosition = PointToClient(new Point(m.LParam.ToInt32() & 0xffff, m.LParam.ToInt32() >> 16));
            if (cursorPosition.X >= ClientSize.Width - resizeArea && cursorPosition.Y >= ClientSize.Height - resizeArea)
            {
                m.Result = (IntPtr)17; //HTBOTTOMRIGHT
                return;
            }
            else if (cursorPosition.X <= resizeArea && cursorPosition.Y >= ClientSize.Height - resizeArea)
            {
                m.Result = (IntPtr)16; //HTBOTTOMLEFT
                return;
            }
            else if (cursorPosition.X <= resizeArea)
            {
                m.Result = (IntPtr)10; //HTLEFT
                return;
            }
            else if (cursorPosition.X >= ClientSize.Width - resizeArea)
            {
                m.Result = (IntPtr)11; //HTRIGHT
                return;
            }
            else if (cursorPosition.Y >= ClientSize.Height - resizeArea)
            {
                m.Result = (IntPtr)15; //HTBOTTOM
                return;
            }
        }

        base.WndProc(ref m);
    }

答案 3 :(得分:0)

我知道它很旧,但希望它可以帮助某人...

不要使用“最大化”,而是使用“工作区”,否则它会覆盖任务栏。

有一个全局布尔值:private static bool trip = false;

然后在您的函数中:

        if (trip == false)
        {
            Left = Top = 0;
            Width = Screen.PrimaryScreen.WorkingArea.Width;
            Height = Screen.PrimaryScreen.WorkingArea.Height;
            trip = true;
        }
        else if (trip == true)
        {
            Width = 1535; // my original form size
            Height = 937; // my original form size
            this.Left = leftPOS; // POS are filled on form load for current positions
            this.Top = topPOS;
            trip = false;
        }

没有trip bool,再次按下最大化按钮后,我无法将表单恢复到正常大小。

答案 4 :(得分:-2)

这当然是可能的,但不适合初学者。主要组件供应商,如Infragistics,DevExpress,ComponentOne,SyncFusion等,都有可以自定义表单外观的库。