就任何一个程序员来说,对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.Data; 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 code
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()); } } }
|
请发表评论