文本編輯框的右鍵菜單不可修改?

  最近寫了個小工具,用來處理特定的文字編輯任務。 編輯後的內容通過剪貼板複製到其他的程序中。

  全選 ->  複製  ->  切換到其他程序  ->  全選  -> 粘帖。
  這本是個極簡單的操作過程,不過操作的次數多了,還是覺得不勝其煩,就想把這個操作在精簡一下。於是就想了個主意:在系統的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 of our 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.


 
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章