最近做了一个无边框的主窗体界面,过程中遇到了很多问题,解决的过程也费了不少精力,因此做完了之后就想把过程写下来,留个纪念,也给遇到同样问题的网友一点帮助。由于没有了边框,所以最大化、最小化、关闭等按钮都没有了,也不能拖动窗体了,任务栏没有右键菜单了,不能调整大小了,设置全屏的时候填满了整个屏幕,把任务栏都给遮盖了,这些都是遇到的问题,下面对每个问题逐一解决:
1、最大化、最小化、关闭按钮,这三个按钮只要拖三个普通的按钮上去就可以了,当然,需要把背景图片设置好,以达到看上去漂亮的结果,这个没什么可说的,就很简单的三个按钮,对应的事件中分别设置窗体的windowstate为最大化,最小化,和关闭就可以了。
2、拖动窗体,这个方法很多,主要有两种,一种是使用windows api,另一种是自己添加mousemove事件,下面分别是两种方法的介绍:
第一种方法:
在窗体类中加入如下代码:
using System.Runtime.InteropServices;
[DllImport("user32.dll")]
public static extern bool ReleaseCapture();
[DllImport("user32.dll")]
public static extern bool SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);
public const int WM_SYSCOMMAND = 0x0112;
public const int SC_MOVE = 0xF010;
public const int HTCAPTION = 0x0002;
然后,在窗体的MouseDown事件中加入以下两句:
ReleaseCapture();
SendMessage(this.Handle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);
就搞定了。
第二种方法:
窗体类中添加两个变量:
Point mouseOff;
bool leftFlag;
在窗体的MouseDown、MouseUp、MouseMove 事件中分别加入如下代码:
//MouseDown
if (e.Button == MouseButtons.Left)
{
mouseOff = new Point(-e.X, -e.Y);
leftFlag = true;
}
//MouseUp
if (leftFlag)
{
leftFlag = false;
}
//MouseMove
if (leftFlag)
{
Point mouseSet = System.Windows.Forms.Control.MousePosition;
mouseSet.Offset(mouseOff.X, mouseOff.Y);
Location = mouseSet;
}
3、添加任务栏右键菜单
在窗体类中加入如下代码:
[DllImport("user32.dll", EntryPoint = "GetWindowLong", CharSet = CharSet.Auto)]
public static extern int GetWindowLong(HandleRef hWnd, int nIndex);
[DllImport("user32.dll", EntryPoint = "SetWindowLong", CharSet = CharSet.Auto)]
public static extern IntPtr SetWindowLong(HandleRef hWnd, int nIndex, int dwNewLong);
然后在构造函数或者窗体Load事件中加入下面三句代码:
int WS_SYSMENU = 0x00080000;
int windowLong = (GetWindowLong(new HandleRef(this, this.Handle), -16));
SetWindowLong(new HandleRef(this, this.Handle), -16, windowLong | WS_SYSMENU);
4、 调整窗体大小
在网上看到一种方案,是在窗体类中加入如下代码(源自:http://blog.sina.com.cn/s/blog_7010d0100100lqpu.html)
#region 控制改变窗体大小
const int WM_NCHITTEST = 0x0084;
const int HTLEFT = 10; //左边界
const int HTRIGHT = 11; //右边界
const int HTTOP = 12; //上边界
const int HTTOPLEFT = 13; //左上角
const int HTTOPRIGHT = 14; //右上角
const int HTBOTTOM = 15; //下边界
const int HTBOTTOMLEFT = 0x10; //左下角
const int HTBOTTOMRIGHT = 17; //右下角
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
switch (m.Msg)
{
case WM_NCHITTEST:
{
Point vPoint = new Point((int)m.LParam & 0xFFFF,
(int)m.LParam >> 16 & 0xFFFF);
vPoint = PointToClient(vPoint);
//判断:仅当当前窗体状态不是最大化时,相关鼠标事件生效
if (this.WindowState != FormWindowState.Maximized)
{
if (vPoint.X <= 5)
{
if (vPoint.Y <= 5)
{
m.Result = (IntPtr)HTTOPLEFT;
}
else if (vPoint.Y >= ClientSize.Height - 5)
{
m.Result = (IntPtr)HTBOTTOMLEFT;
}
else
{
m.Result = (IntPtr)HTLEFT;
}
}
else if (vPoint.X >= ClientSize.Width - 5)
{
if (vPoint.Y <= 5)
{
m.Result = (IntPtr)HTTOPRIGHT;
}
else if (vPoint.Y >= ClientSize.Height - 5)
{
m.Result = (IntPtr)HTBOTTOMRIGHT;
}
else
{
m.Result = (IntPtr)HTRIGHT;
}
}
else if (vPoint.Y <= 5)
{
m.Result = (IntPtr)HTTOP;
}
else if (vPoint.Y >= ClientSize.Height - 5)
{
m.Result = (IntPtr)HTBOTTOM;
}
}
break;
}
}
}
#endregion
经实验,在不加入SetWindowLong(new HandleRef(this, this.Handle), -16, windowLong | WS_SYSMENU);这句代码的时候是可用的,但是加上这句,上面的代码就无效了,也就说用前面的方法加上了任务栏右键菜单后使用上述代码不能够起到调整大小的作用了,于是,搜集其他解决方案,在MSDN论坛上看到一个外国网友的解决方法不错,就是拖一个panel放到窗体的右下角,让这个panel很小,设置panel的Cursor为SizeNWSE,然后在这个panel 的MouseMove事件中加入一下代码:
if (e.Button == MouseButtons.Left)
{
this.Size = new Size(this.PointToClient(MousePosition).X, this.PointToClient(MousePosition).Y);
}
这样就实现了类似的拖动效果,只不过在右下角有拖动的标志。
5、解决最大化后铺满全屏的问题
在构造函数中加入以下代码:
this.MaximizedBounds = Screen.PrimaryScreen.WorkingArea;
至此,所有的问题已经解决或者说大致解决,接下来就尽情的美化自己的窗体了