文本编辑框的右键菜单不可修改?

来源:互联网 发布:win10安装mysql未响应 编辑:程序博客网 时间:2024/05/17 22:38
  最近写了个小工具,用来处理特定的文字编辑任务。 编辑后的内容通过剪贴板复制到其他的程序中。

  全选 ->  复制  ->  切换到其他程序  ->  全选  -> 粘帖。
  这本是个极简单的操作过程,不过操作的次数多了,还是觉得不胜其烦,就想把这个操作在精简一下。于是就想了个主意:在系统的Edit control的右键菜单中追加一项菜单,直接完成进程间通讯的功能, 这样子就能向任意文本窗口发送内容了。


  想到就做,于是翻了翻资料,把一些subclassing,superclassing的东西重新捡起来看了一下,拦截了Edit的窗口过程,在菜单弹出的通知WM_INITMENUPOPUP中修改了一下菜单。跑起来一看,没反应。

 
  第一次运行嘛,这很正常,于是加了些诊断调试的语句。发现确实是成功加载了的。而且修改其他的地方都有效,比如把所有输入的文字都+1: a变成b,b变成c......。运行后新打开一个记事本,都和预期一样。就是拦截菜单消息的地方没反应。

  这就奇怪了,难道消息不对? 不应该啊,MSDN上说的清清楚楚的菜单弹出的通知消息。而且在测试程序里,在对话框上弹出个菜单是完全能收到通知的。于是就用Spy++验证一下。不验证不知道,一验证吓一跳,在记事本里弹出右键菜单,根本没有任何菜单通知消息!

  这可不妙,没有菜单通知消息,就没办法在菜单弹出前获得机会修改他了。通常窗口弹出菜单都有通知消息,难不成Edit control特殊?例外? 于是上网搜了搜,发现果真有人碰到同样的问题。

  而答案呢,普遍的说法是Edit的右键菜单是无法修改的,只能替换。而且msdn论坛上的微软专家也是这么说的。

 这种结果真是让人扫兴,而且解释的太牵强,于是就像继续找找原因,看看有没有可以变通的地方。结果有位强人提到了MN_GETHMENU消息。这个消息以前是不公开的,2000以后的msdn中才开始公开。这个消息可以获得窗口的菜单句柄,对于一些针对菜单处理的程序可能有用。对于本例是没什么帮助的,不过这位强人贴出了一份windows源码中使用MN_GETHMENU的函数。
这倒给了我一点思路,源码泄漏那阵子我也一时兴起收藏了一份,却没怎么真正看过,这回正好可以拿来看看为什么Edit不支持菜单通知消息。

 一番搜索之后,找到了Edit的右键菜单处理源码(private/ntos/w32/ntuser/client/editec.c),发现:果真他是不支持通知消息的,注释中就有Note that this is NOT subclassing friendly, like most ofour functions,for speed and convenience.

  接着往下看,就发现了为什么不支持了,他在TrackPopupMenuEx的时候加入了TPM_NONOTIFY风格,指定不发送任何通知消息,而是通过返回值的方式立即处理菜单结果。
  这种处理方式本来无可非议,也似乎符合c的风格,简单方便,有时候偷懒我也这么用来着。问题是有段说明为什么加上TPM_NONOTIFY风格的注释让我郁闷着了:

We need to use TPM_NONOTIFY because VBRUN100 and VBRUN200 GP-fault on unexpected menu messages.

  又一个古老的妥协造成的bug遗留到了今天?? 而且,居然是Windows系统级的 Edit 向 应用级的 VB 妥协???? 大家今天受的这些困惑全来自于恐龙时代的VBRUN100, VBRUN200.


 
 
原创粉丝点击