C#改写WM_GETTEXT处理例程

开发 后端
这里介绍C#改写WM_GETTEXT处理例程,包括介绍示范如何在C#程序中定制和修改MDI应用的窗口标题和MainWindow 是唯一一个存取该字符串的类。

在向大家详细介绍C#改写WM_GETTEXT处理例程之前,首先让大家了解下MDI应用,然后全面介绍C#改写WM_GETTEXT处理例程。

如果你用 MFC 编写过多文档界面(MDI)Windows 程序,那么肯定知道:如果父窗口标题为“PCaption”,子窗口标题为“CCaption”,那么每当子窗口***化并处于激活状态时,子窗口标题一般都会与父窗口标题合二为一,变成“PCaption-[CCaption]”。 这是一种 MDI 的默认行为。用 C# 编写多文档界面程序也不例外。很多用户都不喜欢这种缺省特性,往往想用定制的窗口标题取而代之。以及将示范如何在C#程序中定制和修改MDI应用的窗口标题。 

如果用MFC来编程,只要改写框架窗口类的虚函数 CFrameWnd::OnUpdateFrameTitle 即可。那么在微软的 .NET 框架中如何用C#实现相同的功能呢?首先,我们必须理解 MDI 本身是如何通过 Windows 核心 API 来实现自己的行为特性的,其实这与MFC或者.NET的公共语言运行时(CLR)没有什么关系。在创建MDI应用时,框架及其子窗口有各自专门的窗口过程,DefFrameProc 和 DefMDIChildProc,一个处理各种 WM_MDIXXX 消息以及其它类似 WM_SIZE, WM_SYSCOMMAND 的消息,另一个实现 MDI 行为。

如果用纯 C 代码编写,那么必须自己负责用 DefFrameProc 和 DefMDIChildProc 创建窗口;在 MFC 中则使用 CMDIFrameWnd/CMDIChildWnd;.NET 框架平台里则设置 Form.IsMdiContainer 和 Form.MdiParent,不管用哪种方式,其核心都是 user kernel,尤其是 DefFrameProc,当 MDI 子窗口***化时,它会联接父子窗口的标题文本来产生主窗口标题串。理解了这一点,下面我来示范如何改写MDI。这个例子的原始版本来自 MSDN 库中用C#写的 Scribble MDI(用 “scribble sample”搜索一下即可找到)。基本思路是首先在 Scribble 例子的 MainWindow 中改写 WM_GETTEXT 消息处理例程,必须添加两个数据成员:NormalText 和 MaximizedText,用它们来保存常态和***化状态的标题 :

  1. // in Scribble.cs, MainWindow class  
  2. private String NormalText = "Scribble2";  
  3. private String MaximizedText = "Window is now maximized";  
  4. //如果想让其它类存取这两个成员,那么可以通过属性机制代替数据成员  
  5. private String normaltext;  
  6. public String NormalText  
  7. {  
  8. get { return normaltext; }  
  9. set { normaltext = value; }  

因为在例子程序中 MainWindow 是唯一一个存取该字符串的类,所以没有必要使用属性机制。有了这两个新的数据成员,你要做的只是C#改写WM_GETTEXT处理例程,返回子窗口***化状态以及常态时的标题文本。那么如何C#改写WM_GETTEXT处理例程呢?

Windows.Forms 提供了一些 处理 WM_XXX 消息的虚拟函数,如 OnResize/WM_SIZE等,但是恰恰缺少与 WM_GETTEXT 相关东东(OnGetText/WM_GETTEXT)。不要担心,没有虚函数,我们总是可以改写包罗万象的 WndProc 处理例程。为此必须知道所处理的消息ID,也就是 WM_GETTEXT 的消息 ID = 0x000D,有人会问,你是怎么知道这个消息的 ID 是 0x000D 啊,很简单,一种方法是运行 SPY 获取,另一种方法是直接查找Windows SDK 中的 winuser.h 头文件。一旦你能深入到 WndProc 这一层次编写代码,那么你基本上能用 C 语言写程序了,因为 Win32 API 和其它语言之间所有东东通过 WPARAMs 和 LPARAMs 参数传递的,包括字符串在内。对于 WM_GETTEXT 来说,Message.LParam 是指向 char* 的指针,Message.WParam 是该指针长度。也就是说你必须完成将文本串拷贝到调用者的缓冲里。好在这并不是太难,下面是程序代码:

  1. public class MainWindow : System.Windows.Forms.Form  
  2. {  
  3. private String NormalText = "Scribble2";  
  4. private String MaximizedText = "Window is now maximized";   
  5. // Handle WM_GETTEXT: Return maximized or  
  6. // normal text, depending on  
  7. // state of active MDI child window.  
  8. protected override void WndProc(ref Message m)  
  9. {  
  10. const int WM_GETTEXT = 0x000D;  
  11. if (m.Msg==WM_GETTEXT) {  
  12. Form active = this.ActiveMdiChild;  
  13. String s = active!=null &&  
  14. active.WindowState==FormWindowState.Maximized ? MaximizedText :  
  15. NormalText;  
  16. char[] c = s.ToCharArray();  
  17. IntPtr buf = m.LParam;  
  18. int len = c.Length;  
  19. Marshal.Copy(c, 0, buf, Math.Min((int)m.WParam, len));  
  20. m.Result = (IntPtr)len;  
  21. return;  
  22. }  
  23. base.WndProc(ref m)  
  24. }  
  25. ...... 
  26. // rest of MainWindow unchanged from Scribble sample  

【编辑推荐】

  1. C# this关键字详解
  2. C#调用析构方法详解
  3. C#释放托管资源简单描述
  4. C#单路代理简单分析
  5. C#文法产生式概述
责任编辑:佚名 来源: CSDN
相关推荐

2009-08-14 17:38:08

C#改写方法

2009-08-12 15:20:21

C#事件处理

2009-08-12 18:28:09

C#事件处理程序

2009-08-31 17:26:32

C#异常处理

2009-08-07 17:41:40

C#预处理

2009-08-06 14:08:08

C#语言异常处理

2009-08-07 17:45:29

C#预处理

2009-08-19 15:54:33

处理C#消息

2009-08-27 18:02:22

C#事件处理

2009-08-05 18:28:05

C#异常处理

2009-09-01 10:10:51

C# StreamRe

2009-09-02 19:13:08

C#处理文本文件

2009-08-06 18:33:45

C#处理文本文件

2009-07-31 16:48:44

C#位运算

2009-08-05 18:09:17

C#异常处理机制

2009-09-02 14:00:34

C#文件处理

2009-09-17 09:20:45

C#操作XML

2009-09-07 15:21:38

Java与C#事件处理

2009-09-23 09:36:34

C#数组

2020-07-07 10:55:01

C++C语言代码
点赞
收藏

51CTO技术栈公众号