📄 documents1.htm
字号:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<meta name="GENERATOR" content="Microsoft FrontPage 3.0">
<style><!--
body,table {font-family:"宋体"; font-size: 9pt; line-height:11pt;}
a {text-decoration:none} a:hover {color:red;text-decoration:underline}
--></style>
<title>屏蔽文本框默认的右键菜单——浅谈如何控制Windows消息</title>
</head>
<body link="#FF0000" vlink="#FF0000" alink="#FF0000" bgcolor="#FFC8C8">
<table border="0" width="100%" cellspacing="4" cellpadding="6">
<tr>
<td width="100%" bgcolor="#336699"><font color="#FFFFFF">屏蔽文本框默认的右键菜单——浅谈如何控制Windows消息</font></td>
</tr>
</table>
<p>
屏蔽文本框的右键菜单,曾经看到一个程序是这样做的:</p>
<p> <font color="#000080">Private Sub</font> Text1_MouseDown(Button <font
color="#000080">As Integer</font>, Shift <font color="#000080">As Integer</font>, X <font
color="#000080">As Single</font>, Y <font color="#000080">As Single</font>)<br>
Text1.Enabled = <font color="#000080">False</font><br>
Text1.Enabled = <font color="#000080">True</font><br>
PopupMenu yourmenu<br>
<font color="#000080">End Sub</font></p>
<p> 这当然是个简单的实现方法,但作为一个以api为主题的网站,我在此想介绍一种用api函数来实现的方法,并想谈的深入一些。<br>
首先,谈谈消息和窗口函数。在Windows里,消息有两方面的用途:首先,它们由Windows传给窗口函数,指出发生了一个特定的事件。比如用户单击了鼠标,或者按下了键盘上的某个键。消息也可由Windows用于通告发生了一个内部事件,比如输入焦点的变更。另外,可将消息作为Windows的一种命令使用。这种命令用于通知一个窗口执行特定的任务。其次,通常可将消息传给一个控件或窗口,请求它执行特定的操作。而每个窗口都有一个窗口函数,它的作用是对消息进行处理。该函数就象一个特殊的VB程序,其中包含了对事件进行处理的代码。<br>
对于右击文本框,首先是产生一条 WM_CONTEXTMENU
消息,该消息被文本框的窗口函数接收,就会弹出默认的菜单。所以,我的思路是:接收所有的文本框消息,如果消息为
WM_CONTEXTMENU
,那么弹出自定义菜单,否则,把消息传递给默认的窗口函数由它处理。<br>
如何接收消息?一个方法是,用 AddressOf
关键字,它可以把一个自定义模块的地址变为窗口函数的地址。这样,窗口函数就成了你的自定义模块了。而消息仍然传递到原先窗口函数的地址(这时,这个地址指向的窗口函数已经是你的自定义模块)</p>
<p> 现在就看看是如何实现的吧。首先建议你看看VB联机手册关于
AddressOf
的帮助。程序需要一个窗体、窗体中有一个文本框,以及一个标准模块。</p>
<p> 标准模块的代码:</p>
<p><font color="#000080"> Option Explicit</font></p>
<p> <font color="#000080">Public</font> OldWindowProc <font
color="#000080">As Long</font><br>
<font color="#008000"> ' 保存默认的窗口函数的地址<br>
</font> <font color="#000080">Public Const</font> WM_CONTEXTMENU =
&H7B<br>
<font color="#008000"> ' 当右击文本框时,产生这条消息<br>
</font><br>
<font color="#000080">Public Declare Function</font> GetWindowLong <font
color="#000080">Lib</font> "user32" <font color="#000080">Alias</font>
"GetWindowLongA" (<font color="#000080">ByVal</font> hWnd <font color="#000080">As
Long</font>, <font color="#000080">ByVal</font> nIndex <font color="#000080">As Long</font>)
<font color="#000080">As Long</font><br>
<font color="#000080">Public Declare Function</font> SetWindowLong <font
color="#000080">Lib</font> "user32" <font color="#000080">Alias</font>
"SetWindowLongA" (<font color="#000080">ByVal</font> hWnd <font color="#000080">As
Long</font>, <font color="#000080">ByVal</font> nIndex <font color="#000080">As Long</font>,
<font color="#000080">ByVal</font> dwNewLong <font color="#000080">As Long</font>) <font
color="#000080">As Long</font><br>
<font color="#000080">Private Declare Function</font> CallWindowProc <font
color="#000080">Lib</font> "user32" <font color="#000080">Alias</font>
"CallWindowProcA" (<font color="#000080">ByVal</font> lpPrevWndFunc <font
color="#000080">As Long</font>, <font color="#000080">ByVal</font> hWnd <font
color="#000080">As Long</font>, <font color="#000080">ByVal</font> Msg <font
color="#000080">As Long</font>, <font color="#000080">ByVal</font> wParam <font
color="#000080">As Long</font>, <font color="#000080">ByVal</font> lParam <font
color="#000080">As Long</font>) <font color="#000080">As Long</font><br>
<br>
<br>
<font color="#000080">Public Function</font> SubClass1_WndMessage(<font
color="#000080">ByVal</font> hWnd <font color="#000080">As</font> OLE_HANDLE, <font
color="#000080">ByVal</font> Msg <font color="#000080">As</font> OLE_HANDLE, <font
color="#000080">ByVal</font> wp <font color="#000080">As</font> OLE_HANDLE, <font
color="#000080">ByVal</font> lp <font color="#000080">As Long</font>) As <font
color="#000080">Long</font><br>
<font color="#000080">If</font> Msg <>
WM_CONTEXTMENU <font color="#000080">Then</font><br>
SubClass1_WndMessage =
CallWindowProc(OldWindowProc, hWnd, Msg, wp, lp)<br>
<font color="#008000"> '
如果消息不是WM_CONTEXTMENU,就调用默认的窗口函数处理<br>
</font><font color="#000080">
Exit Function<br>
End If<br>
</font> SubClass1_WndMessage = <font
color="#000080">True</font><br>
<font color="#000080"> End Function</font></p>
<p> 窗体的代码:</p>
<p><font color="#000080"> Option Explicit</font></p>
<p><font color="#000080"> Private Const</font> GWL_WNDPROC = (-4)</p>
<p> <font color="#000080">Private Sub</font> Text1_MouseDown(Button <font
color="#000080">As Integer</font>, Shift <font color="#000080">As Integer</font>, X <font
color="#000080">As Single</font>, Y <font color="#000080">As Single</font>)<br>
<font color="#000080">If</font> Button = 1 <font
color="#000080">Then Exit Sub</font><br>
OldWindowProc = GetWindowLong(Text1.hWnd,
GWL_WNDPROC)<br>
<font color="#008000"> '
取得窗口函数的地址<br>
</font> <font color="#000080">Call</font>
SetWindowLong(Text1.hWnd, GWL_WNDPROC, <font color="#000080">AddressOf</font>
SubClass1_WndMessage)<br>
<font color="#008000"> ' 用SubClass1_WndMessage代替窗口函数处理消息<br>
</font><font color="#000080"> End Sub<br>
</font><br>
<font color="#000080">Private Sub</font> Text1_MouseUp(Button <font
color="#000080">As Integer</font>, Shift <font color="#000080">As Integer</font>, X <font
color="#000080">As Single</font>, Y <font color="#000080">As Single</font>)<br>
<font color="#000080">If</font> Button = 1 <font
color="#000080">Then Exit Sub</font><br>
<font color="#000080">Call</font>
SetWindowLong(Text1.hWnd, GWL_WNDPROC, OldWindowProc)<br>
<font color="#008000"> '
恢复窗口的默认函数<br>
</font> PopupMenu usermenu<br>
<font color="#008000"> ' 弹出自定义菜单<br>
</font> <font color="#000080">End Sub</font></p>
<p>
运行这个程序,右键菜单已被自定义菜单取代,不会出现两个菜单的情况。关于这个程序,你可以在<a
href="sample.htm">例程</a>中下载它,实现的功能比这里的要完整。最后要说明的是,尽量不要使用
AddressOf
来改变一个窗口的默认窗口函数,它可能引起不可预料的后果。在VB的联机手册里也是这样建议的,我在编这个程序时,死过几次机,其中一次,搞的我的Windows的“开始”菜单没有反应。</p>
<p> 在Windows 98 + VB5.0下通过。本文涉及的api函数本站有介绍。</p>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -