我正在创建一个Windows窗体应用程序项目,我想要自定义边框和三个按钮(关闭,最小化和最大化),并且要使用我的设计。我不知道该如何实现这一点,甚至不确定是否可能。如果可以,请告诉我解决方案。谢谢。
是的,这是可能的,而且不需要额外的库。
首先,隐藏窗口的原始边框。
public Form1()
{
InitializeComponent();
FormBorderStyle = FormBorderStyle.None;
}
接下来,创建一个面板或者其他你想要的东西,包含三个按钮(我知道它很丑,只是为了演示):
然后,使用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所提到的,您可以从WndProc
捕获WM_NCHITTEST
消息,并返回HTBOTTOMRIGHT
以触发调整大小:
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);
}
如 @BenVoigt 所述,您可以在按钮/面板上使用 Dock
和 Anchor
属性,以便它们可以适当地调整大小。 如果您不这样做,它们将不会随着表单的调整而改变大小。
补充一下 @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;
}
if (this.WindowState == FormWindowState.Maximized)
已经可以提供这个信息了。 - LarsTechprivate 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);
}
}
}
此外,这是一个完整的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);
}
我知道这已经过时了,但希望它能帮助到某些人...
与其使用“最大化”,不如使用“工作区”,否则它会覆盖任务栏。
有一个全局布尔变量: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,我无法在再次按下最大化按钮后将表单返回到正常大小。
这是完全可能的,但对于初学者来说并不容易。主要的组件供应商,如Infragistics、DevExpress、ComponentOne、SyncFusion等都提供了可以自定义窗体外观的库。
Dock
和Anchor
属性,则不需要手动调整,这些属性是专门用于此设计的。 - Ben Voigt