C# Winform 捕获窗体的最小化和最大化事件、关闭按钮事件
http://blog.csdn.net/wxm3630478/article/details/4579981
const int WM_SYSCOMMAND = 0x112;
const int SC_CLOSE = 0xF060;
const int SC_MINIMIZE = 0xF020;
const int SC_MAXIMIZE = 0xF030;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_SYSCOMMAND)
{
if (m.WParam.ToInt32() == SC_MINIMIZE) //是否点击最小化
{
//这里写操作代码
this.Visible = false; //隐藏窗体
return;
}
if (m.WParam.ToInt32() == SC_MAXIMIZE )
{
//.....................
}
if (m.WParam.ToInt32() == SC_CLOSE )
{ //.....................}
}
base.WndProc(ref m);
}
//这个功能是 捕获最小化按钮事件 ,隐藏当前窗体.
关于winForm窗体最大化的设置
转载自http://blog.sina.com.cn/s/blog_6ab738af0100jux6.html
1. 窗体最大化时 非全屏 不会遮盖任务栏
private void btnFormMax_Click(object sender, EventArgs e)
{
if (this.WindowState == FormWindowState.Maximized)
{
this.WindowState = FormWindowState.Normal;
}
else
{
this.WindowState = FormWindowState.Maximized;
}
}
此时this.FormBorderStyle. 默认为 Sizable
2. 窗体最大化时 会全屏 及遮盖任务栏
private void btnFormMax_Click(object sender, EventArgs e)
{
if (this.WindowState == FormWindowState.Maximized)
{
this.WindowState = FormWindowState.Normal;
}
else
{
this.FormBorderStyle. = FormBorderStyle.None;
this.WindowState = FormWindowState.Maximized;
}
}
此时this.FormBorderStyle. 为 None 不会显示窗体标题栏等相关
3. 窗体最大化时 非全屏 不会遮盖任务栏
private void btnFormMax_Click(object sender, EventArgs e)
{
if (this.WindowState == FormWindowState.Maximized)
{
this.WindowState = FormWindowState.Normal;
}
else
{
this.FormBorderStyle. = FormBorderStyle.None;
this.MaximumSize = new Size(Screen.PrimaryScreen.WorkingArea.Width, Screen.PrimaryScreen.WorkingArea.Height);
this.WindowState = FormWindowState.Maximized;
}
}
此时this.FormBorderStyle. 为 None 不会显示窗体标题栏等相关
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace WindowsApplication1
{
public partial class FormRegion : Form.
{
private const long WM_GETMINMAXINFO = 0x24;
public struct POINTAPI
{
public int x;
public int y;
}
public struct MINMAXINFO
{
public POINTAPI ptReserved;
public POINTAPI ptMaxSize;
public POINTAPI ptMaxPosition;
public POINTAPI ptMinTrackSize;
public POINTAPI ptMaxTrackSize;
}
public FormRegion()
{
InitializeComponent();
this.MaximumSize = new Size(Screen.PrimaryScreen.WorkingArea.Width, Screen.PrimaryScreen.WorkingArea.Height);
}
protected override void WndProc(ref System.Windows.Forms.Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_GETMINMAXINFO)
{
MINMAXINFO mmi = (MINMAXINFO)m.GetLParam(typeof(MINMAXINFO));
mmi.ptMinTrackSize.x = this.MinimumSize.Width;
mmi.ptMinTrackSize.y = this.MinimumSize.Height;
if (this.MaximumSize.Width != 0 || this.MaximumSize.Height != 0)
{
mmi.ptMaxTrackSize.x = this.MaximumSize.Width;
mmi.ptMaxTrackSize.y = this.MaximumSize.Height;
}
mmi.ptMaxPosition.x = 1;
mmi.ptMaxPosition.y = 1;
System.Runtime.InteropServices.Marshal.StructureToPtr(mmi, m.LParam, true);
}
}
}
}
MessageBox.Show("当前窗体标题栏高度"+(this.Height - this.ClientRectangle.Height).ToString());//获得当前窗体标题栏高度
ClientRectangle//获取表示控件的工作区的矩形
MessageBox.Show(SystemInformation.PrimaryMonitorSize.ToString()); //获取主显示器屏幕的尺寸(像素)
//获取主显示器当前当前视频模式的尺寸(以象素为单位)
MessageBox.Show("菜单栏高度"+SystemInformation.MenuHeight.ToString()); //获取标准菜单栏的高度
MessageBox.Show("标题栏高度"+SystemInformation.CaptionHeight.ToString()); //获取标准标题栏的高度
MenuHeight//获取一个菜单行的高度(以象素为单位)
CaptionHeight//获取窗口的标准标题栏区域的高度(以象素为单位)
转载自http://www.cnblogs.com/lanmiao/articles/2238239.html
接收拦截+发送消息
对于处理所有消息.net 提供了wndproc进行重写
WndProc(ref Message m)
protected override void WndProc(ref Message m)
{
const int WM_SYSCOMMAND = 0x0112;
const int SC_CLOSE = 0xF060;
if (m.Msg == WM_SYSCOMMAND && (int) m.WParam == SC_CLOSE)
{
// 屏蔽传入的消息事件
this.WindowState = FormWindowState.Minimized;
return;
}
base.WndProc(ref m);
}
//.net 提供了ProcessCmdKey 重新实现Form的键盘消息
protected override bool ProcessCmdKey(ref System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData)
{
int WM_KEYDOWN = 256;
int WM_SYSKEYDOWN = 260;
if (msg.Msg == WM_KEYDOWN | msg.Msg == WM_SYSKEYDOWN)
{
switch (keyData)
{
case Keys.Escape:
this.Close();//Esc退出
break;
}
}
return false;
}
C#中如何编写使用SendMessage
在.net中,程序驱动采用了事件驱动而不是原来的消息驱动,
虽然.net框架提供的事件已经十分丰富,但是在以前的系统中定义了
丰富的消息对系统的编程提供了方便的实现方法,因此在.net中使用消
息有时候可以提高编程的效率的。
1 定义消息
在c#中消息需要定义成windows系统中的原始的16进制数字,比如
const int WM_Lbutton = 0x201; //定义了鼠标的左键点击消息
public const int USER = 0x0400; // 是windows系统定义的用户消息
2 消息发送
消息发送是通过windows提供的API函数SendMessage来实现的它的原型定义为
[DllImport("User32.dll",EntryPoint="SendMessage")]
private static extern int SendMessage(
int hWnd, // handle to destination window
int Msg, // message
int wParam, // first message parameter
int lParam // second message parameter
);
3 消息的接受
在.net中,任何一个窗口都有消息的接收处理函数,就是wndproc函数
你可以在form中重写该函数来处理消息
protected override void WndProc ( ref System.WinForms.Message m )
{
switch(m.msg)
{
case WM_Lbutton :
string message = string.Format("收到消息!参数为:{0},{1}",m.wParam,m.lParam);
MessageBox.Show(message);
break;
default:
base.DefWndProc(ref m);//调用基类函数处理非自定义消息。
break;
}
}
其实,C#中的事件也是通过封装系统消息来实现的,如果你在WndProc函数中不处理该消息
那么,它会被交给系统来处理该消息,系统便会通过代理来实现鼠标单击的处理函数,因此你可以通过
WndProc函数来拦截消息,比如你想拦截某个按钮的单击消息
4 C#中其他的消息处理方法
在C#中有的时候需要对控件的消息进行预处理,比如你用owc的spreedsheet控件来处理
Excel文件,你不想让用户可以随便选中数据进行编辑,你就可以屏蔽掉鼠标事件,这个时
候就必须拦截系统预先定义好的事件(这在MFC中称为子类化),你可以通过C#提供的一个
接口
IMessageFilter来实现消息的过滤
public class Form1: System..Forms.Form,IMessageFilter
{
const int WM_MOUSEMOVE = 0x200;
public bool PreFilterMessage(ref Message m) //实现接口
{
Keys keyCode = (Keys)(int)m.WParam & Keys.KeyCode;
if( m.Msg==WM_MOUSEMOVE) //或m.Msg == WM_LBUTTONDOWN
{
MessageBox.Show("Ignoring Escape...");
return true;
}
return false;
}
}
(转)有用的WndProc(ref Message m)方法
在Windows操作中,所有的操作都是基于消息的。
我们编写的程序,也是这个道理。同样,我们也可能查看事件发生时,到底触发了什么样的消息。
在CS中,可以重写WndProc函数,来捕捉所有发生有窗口消息。这样,我们就可以"篡改"传入的消息,而人为的让窗口改变行为。
大家用MSN的时候会发现,当直接关闭窗口时,窗口不会关闭而会最小化到托盘。我估计它使用的也是这样的道理。
下面就看一下关于这种方法的使用。
{
const int WM_SYSCOMMAND = 0x0112;
const int SC_CLOSE = 0xF060;
if (m.Msg == WM_SYSCOMMAND && (int) m.WParam == SC_CLOSE)
{
// 屏蔽传入的消息事件
this.WindowState = FormWindowState.Minimized;
return;
}
base.WndProc(ref m);
}
base.WndProc(ref m)的原理和使用
WndProc 窗体主要的消息处理函数
WndProc的实现大概是这样的:
protected void WndProc(ref Message m)
{
switch(m)
{
case WM_QUIT: /*处理退出消息....;*/ break;
case WM_PAINT:/*处理paint消息...*/ break;
... ...
default:
defWndProc(ref m); //其他消息调用默认的消息处理函数
}
}
因为我已经实现了无标题栏窗体的移动,当双击窗体时,会使窗体最大化,我想禁止找个消息,怎么写呢
protected override void WndProc(ref Message m)
{
const int WM_NCHITTEST = 0x84;
const int HTCLIENT = 0x01;
const int HTCAPTION = 0x02;
const int WM_SYSCOMMAND = 0x112;
const int SC_MAXMIZE = 0xF030;
switch (m.Msg)
{
case WM_NCHITTEST://鼠标点任意位置后可以拖动窗体
this.DefWndProc(ref m);
if (m.Result.ToInt32() == HTCLIENT)
{
m.Result = new IntPtr(HTCAPTION);
return;
}
break;
case WM_SYSCOMMAND://禁止最大化
if (m.WParam.ToInt32() ==SC_MAXMIZE)
{
/./代码
return;
}
break;
default:
base.WndProc(ref m);
break;
}
}
当去掉第二个case后,可以拖动窗体,但是双击窗体会最大化;加上第二个case想禁止最大化,但是加了后什么功能也不能实现,怎么回事
protected override void WndProc(ref Message m)
{
const int WM_NCHITTEST = 0x84;
const int HTCLIENT = 0x01;
const int HTCAPTION = 0x02;
const int WM_SYSCOMMAND = 0x112;
const int SC_MAXMIZE = 0xF030;
const int WM_NCLBUTTONDBLCLK = 0xA3;
switch (m.Msg)
{
case 0x4e:
case 0xd:
case 0xe:
case 0x14:
base.WndProc(ref m);
break;
case WM_NCHITTEST://鼠标点任意位置后可以拖动窗体
this.DefWndProc(ref m);
if (m.Result.ToInt32() == HTCLIENT)
{
m.Result = new IntPtr(HTCAPTION);
return;
}
break;
case WM_NCLBUTTONDBLCLK://禁止双击最大化
Console.WriteLine(this.WindowState);
return;
break;
default:
base.WndProc(ref m);
break;
}
}
- 提问者评价
-
非常谢谢,我光想这拦截最大化了,忘了拦截双击了,太谢谢了。
我们在做winform的时候,很多时候因为需求问题,要把窗体做的好看点,所以就给窗体加上了很多图片,或者其他资源
从而导致了用户在用鼠标拖动窗体的时候,窗体很卡,CPU占用很高的问题,这些都是因为窗体在拖动的时候频繁的绘制
造成的,那么要避免这些问题,其中的一个解决方法就是减少窗体绘制,或者说只绘制一次,即在用户鼠标放开(MouseUp事件)的时候绘制,代码如下:
2 {
3 [DllImport("user32.dll")]
4 public static extern bool ReleaseCapture();
5 [DllImport("user32.dll")]
6 public static extern bool SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);
7
8 private const int WM_SYSCOMMAND = 0x0112;//点击窗口左上角那个图标时的系统信息
9 private const int WM_MOVING = 0x216;//鼠标移动消息
10 private const int SC_MOVE = 0xF010;//移动信息
11 private const int HTCAPTION = 0x0002;//表示鼠标在窗口标题栏时的系统信息
12 private const int WM_NCHITTEST = 0x84;//鼠标在窗体客户区(除了标题栏和边框以外的部分)时发送的消息
13 private const int HTCLIENT = 0x1;//表示鼠标在窗口客户区的系统消息
14 private const int SC_MAXIMIZE = 0xF030;//最大化信息
15 private const int SC_MINIMIZE = 0xF020;//最小化信息
16
17 protected override void WndProc(ref Message m)
18 {
19 switch (m.Msg)
20 {
21 case WM_MOVING: //如果鼠标移
22 base.WndProc(ref m);//调用基类的窗口过程——WndProc方法处理这个消息
23 if (m.Result == (IntPtr)HTCLIENT)//如果返回的是HTCLIENT
24 {
25 m.Result = (IntPtr)HTCAPTION;//把它改为HTCAPTION
26 return;//直接返回退出方法
27 }
28 break;
29 }
30 base.WndProc(ref m);//如果不是鼠标移动或单击消息就调用基类的窗口过程进行处理
31 }
32
33 protected override void OnMouseMove(MouseEventArgs e)
34 {
35 if (e.Button == MouseButtons.Left)
36 {
37 ReleaseCapture();
38 SendMessage(this.Handle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);
39 }
40 base.OnMouseMove(e);
41 }
42 }