我正在使用Windows窗体处理应用程序的UI。在咨询this question和this one之后,我制作了可调整大小的无边框格式。
我有一台多屏幕电脑。当我在主屏幕上最大化时,表单正常最大化。如果我将表单完全移动到我的第二个屏幕,然后使用最大化,表单就会消失。在调查后我发现即使第二个屏幕的属性'this.MaximizedBounds'被正确确定,即当我使用该语句时,{X = -1440,Y = 0,Width = 1440,Height = 900}
this.WindowState = FormWindowState.Maximized;
在{X = -2880,Y = 0,宽度= 1440,高度= 900}处绘制表格,好像由于某种原因绘制方向是反转的?鉴于此,我知道我可以通过编程方式确定绘制形式,但我想知道我是否缺少设置一些额外的属性以确保绘制方向是正确的?
以编程方式最大化形式的问题是表单的状态仍然是FormWindowState.Normal并且我无法将其更改为FormWindowState.Maximized而不会导致from重绘在错误的位置
使表格无边框的代码
protected override void WndProc(ref Message m)
{
const int RESIZE_HANDLE_SIZE = 10;
switch (m.Msg)
{
case 0x0084/*NCHITTEST*/ :
base.WndProc(ref m);
if ((int)m.Result == 0x01/*HTCLIENT*/)
{
Point screenPoint = new Point(m.LParam.ToInt32());
Point clientPoint = this.PointToClient(screenPoint);
if (clientPoint.Y <= RESIZE_HANDLE_SIZE)
{
if (clientPoint.X <= RESIZE_HANDLE_SIZE)
m.Result = (IntPtr)13/*HTTOPLEFT*/ ;
else if (clientPoint.X < (Size.Width - RESIZE_HANDLE_SIZE))
m.Result = (IntPtr)12/*HTTOP*/ ;
else
m.Result = (IntPtr)14/*HTTOPRIGHT*/ ;
}
else if (clientPoint.Y <= (Size.Height - RESIZE_HANDLE_SIZE))
{
if (clientPoint.X <= RESIZE_HANDLE_SIZE)
m.Result = (IntPtr)10/*HTLEFT*/ ;
else if (clientPoint.X < (Size.Width - RESIZE_HANDLE_SIZE))
m.Result = (IntPtr)2/*HTCAPTION*/ ;
else
m.Result = (IntPtr)11/*HTRIGHT*/ ;
}
else
{
if (clientPoint.X <= RESIZE_HANDLE_SIZE)
m.Result = (IntPtr)16/*HTBOTTOMLEFT*/ ;
else if (clientPoint.X < (Size.Width - RESIZE_HANDLE_SIZE))
m.Result = (IntPtr)15/*HTBOTTOM*/ ;
else
m.Result = (IntPtr)17/*HTBOTTOMRIGHT*/ ;
}
}
return;
}
base.WndProc(ref m);
}
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.Style |= 0x20000; // <--- use 0x20000
cp.ClassStyle |= 0x08;
return cp;
}
}
退出,最大化/恢复,最小化的代码
private void button1_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void button2_Click(object sender, EventArgs e)
{
if(this.WindowState==FormWindowState.Normal)
{
this.button2.Image = ((System.Drawing.Image)(Properties.Resources.Restore_Down));
this.MaximizedBounds = Screen.FromHandle(this.Handle).WorkingArea;
this.WindowState = FormWindowState.Maximized;
}
else if(this.WindowState == FormWindowState.Maximized)
{
this.WindowState = FormWindowState.Normal;
this.button2.Image = ((System.Drawing.Image)(Properties.Resources.Maximize));
}
}
private void button3_Click(object sender, EventArgs e)
{
this.WindowState = FormWindowState.Minimized;
}
答案 0 :(得分:1)
我的假设是您正在创建无边框表单,然后创建自己的工具栏。无需WndProc
即可实现最大化,最小化和恢复。所有需要的是三个按钮和它们的点击事件处理程序(它也适用于多个监视器):
private void ClickMinimizeButton(object sender, EventArgs e)
{
WindowState = FormWindowState.Minimized;
}
private void ClickRestoreButton(object sender, EventArgs e)
{
WindowState = FormWindowState.Normal;
}
private void ClickMaximizeButton(object sender, EventArgs e)
{
WindowState = FormWindowState.Maximized;
}
要移动表单,您需要使用WndProc
。具体处理WM_NCLBUTTONDOWN
窗口消息。这应该在MouseDown
事件处理程序中完成。
if (e.Button == MouseButtons.Left)
{
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
}
ReleaseCapture
和SendMessage
都是user32.dll
的一部分。
要调整大小,您将再次需要使用WndProc。但是,由于您有2台显示器,因此您需要自己获取屏幕坐标。以下 已接受的答复来自this问题。它可能会帮助您获得正确的坐标。
static class ControlExtensions
{
///<summary>
/// Returns the position of the point in screen coordinates of that control instead
/// of the main-screen coordinates
///</summary>
public static Point PointToCurrentScreen(this Control self, Point location)
{
var screenBounds = Screen.FromControl(self).Bounds;
var globalCoordinates = self.PointToScreen(location);
return new Point(globalCoordinates.X - screenBounds.X, globalCoordinates.Y - screenBounds.Y);
}
}
答案 1 :(得分:0)
为什么使用WndProc使其无边界?
Windows窗体具有属性&#34; FormBorderStyle&#34;,
this.FormBorderStyle = FormBorderStyle.None;
这应该使它无边界,也许这种更默认的方法也解决了窗口位置问题