就任何一个程序员来说,对WINDOWS消息机制的认知和对消息的处理,可以说是必修的内容。我们知道,WINDOWS消息的两个参数wParam 、lParam有时是数值类型,有时则是指针类型。特别是指针类型,它指向的是一个内存地址,那么对它们的处理则因开发语言的不同而有所不同。
都说C#取消了指针(非安全模式例外),可我个人觉得,C#并没有真正取消指针,只是把她装扮得更加迷人罢了!而不需程序员通过 *p 之类去直接处理而已。
下面我就以一个例程,来看看C#中是如何处理WINDOWS消息中指针类型的参数的。这个例程是AOGO曾经用MASM汇编来实现的,这就是限制一个窗体大小的变化在一个许可的范围内。本例程只限制宽度不超过600。
这里主要涉及到两个问题:
1. 如何取得指针所指向的内存地址中的内容?
2. 如何将指针指向新的内容?(也可能是将新内容复制到指针所指向的内存地址中)
处理这两个问题的方法哦是知道了,至于它的内部实现机制哦就不明白了 ^_^ ^_^ ^_^
有了这两个方法,我们就可以对WINDOWS的任何消息进行处理了。C#的厉害由此可见!!!
好啦,哦不多说啦。看源码就啥都明白了
===================== Form1.cs =====================
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Da
using System.Runtime.InteropServices; // 注意这个命名空间
namespace WinMsgApp
{
public class Form1 : System.Windows.Forms.Form
{
// 声明Winodws消息常量
private const int WM_SIZEING = 0x0214;
// 声明RECT结构
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
// 以下是C# IDE自动生成的代码
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.TextBox textBox2;
private System.Windows.Forms.TextBox textBox3;
private System.Windows.Forms.TextBox textBox4;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label4;
private System.ComponentModel.Container components = null;
public Form1()
{
InitializeComponent();
}
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated co
private void InitializeComponent()
{
this.textBox1 = new System.Windows.Forms.TextBox();
this.textBox2 = new System.Windows.Forms.TextBox();
this.textBox3 = new System.Windows.Forms.TextBox();
this.textBox4 = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.label4 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(80, 8);
this.textBox1.Name = "textBox1";
this.textBox1.TabIndex = 0;
this.textBox1.Text = "";
//
// textBox2
//
this.textBox2.Location = new System.Drawing.Point(80, 32);
this.textBox2.Name = "textBox2";
this.textBox2.TabIndex = 1;
this.textBox2.Text = "";
//
// textBox3
//
this.textBox3.Location = new System.Drawing.Point(80, 56);
this.textBox3.Name = "textBox3";
this.textBox3.TabIndex = 2;
this.textBox3.Text = "";
//
// textBox4
//
this.textBox4.Location = new System.Drawing.Point(80, 80);
this.textBox4.Name = "textBox4";
this.textBox4.TabIndex = 3;
this.textBox4.Text = "";
//
// label1
//
this.label1.Location = new System.Drawing.Point(0, 8);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(78, 23);
this.label1.TabIndex = 4;
this.label1.Text = "Left:";
this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// label2
//
this.label2.Location = new System.Drawing.Point(0, 32);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(78, 23);
this.label2.TabIndex = 5;
this.label2.Text = "Top:";
this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// label3
//
this.label3.Location = new System.Drawing.Point(0, 56);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(78, 23);
this.label3.TabIndex = 6;
this.label3.Text = "Right:";
this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// label4
//
this.label4.Location = new System.Drawing.Point(0, 80);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(78, 23);
this.label4.TabIndex = 7;
this.label4.Text = "Bottom:";
this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
this.ClientSize = new System.Drawing.Size(296, 117);
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.label4,
this.label3,
this.label2,
this.label1,
this.textBox4,
this.textBox3,
this.textBox2,
this.textBox1});
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}
#endregion
// 自动生成的代码到此结束
// 以下是处理WINDOWS消息的主要代码
protected override void WndProc(ref System.Windows.Forms.Message m )
{
switch(m.Msg)
{
case WM_SIZEING:
// 第一种方法,简洁明了
// RECT rc = (RECT)m.GetLParam(typeof(RECT));
// 第二种方法,易懂稍繁
RECT rc = new RECT();
// 将m.LParam指针所指向的RECT结构复制到rc
rc = (RECT)m.GetLParam(rc.GetType());
// 将结构rc各字段的值显示出来
textBox1.Text = rc.left.ToString();
textBox2.Text = rc.top.ToString();
textBox3.Text = rc.right.ToString();
textBox4.Text = rc.bottom.ToString();
// 限制窗体宽度不超过600
if (rc.right - rc.left >600)
{
rc.right =rc.left +600;
}
// 将结构rc复制到m.LParam指针所指向的RECT结构
Marshal.StructureToPtr(rc,m.LParam,true);
break;
default:
base.WndProc(ref m); // 调用基类函数处理其他消息。
break;
}
}
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
}
}