Tec*_*Man 4 clipboard winapi contextmenu editcontrol
如何在本机Windows操作系统编辑控件的上下文菜单中禁用这3个标准剪切/复制/粘贴命令?
我还需要禁用等效的剪贴板相关命令,如CTRL + C/CTRL + V.
是否有一种特殊的编辑控件样式或其他任何我们可以用一个简单设置禁用所有复制/粘贴操作的东西?
通常,当控制显示一个弹出式菜单,WM_INITPOPUPMENU生成消息,该消息" 允许在显示之前,在不改变整个菜单应用程序修改菜单. "
遗憾的是,标准的Win32 Edit控件没有为其默认弹出菜单生成该消息,如2000年11月MSDN杂志上的文章所证实的(MSDN上的链接已经死了,但此链接来自Internet Archive):
问:右键单击编辑控件时为什么不生成WM_INITMENUPOPUP消息?
答:我不能告诉你为什么没有,但我可以确认它是真的......编辑控件不发送WM_INITMENUPOPUP.编辑控件必须使用空HWND句柄和/或TPM_NONOTIFY调用TrackPopupMenu,它告诉菜单不要发送通知.可能(并且我只是猜测)作者试图通过减少消息流量来提高性能......无论如何,假设您想要将自己的菜单项添加到编辑控件上下文菜单中.你怎么做呢?唉,你别无选择,只能重新发明轮子
因此,唯一可用的选项是子类化编辑控件并处理WM_CONTEXTMENU消息,根据需要创建和显示您自己的自定义弹出菜单.这意味着您必须手动复制要在自定义菜单中显示的任何标准菜单项的功能.
更新:毕竟有一种方法可以访问和修改编辑控件的标准弹出菜单(我刚测试它并且它工作正常).TecMan提供了一个VBForums讨论的链接,讨论它,但它有一些细节错误.我从PureBasic论坛讨论中得到了正确的细节.
正确的方法如下:
子类编辑控件来拦截WM_CONTEXTMENU消息.可以使用SetWindowSubClass()或者SetWindowLongPtr(GWL_WNDPROC)可以使用,但首先是首选.
在当WM_CONTENTMENU接收到消息,调用SetWindowsHookEx()安装一个线程局部钩(使用0作为hMod参数,并GetCurrentThreadId()为dwThreadId参数).可以使用a WH_CBT或WH_CALLWNDPROChook.然后WM_CONTENTMENU通过DefSubclassProc()或CallWindowProc()调用标准弹出菜单调度到默认消息处理程序.
在钩子程序内部,当收到HCBT_CREATEWND(WH_CBT钩子)或WM_CREATE(WH_CALLWNDPROC钩子)通知时,将提供的内容传递HWND给GetClassName().如果类名是#32768(菜单的标准窗口类名,如MSDN中所述),请发布(非常重要!)一个自定义窗口消息PostMessage(),指定HWND消息WPARAM或LPARAM参数中的菜单窗口,指向您控制的任何 窗口消息HWND,例如您的主窗口,甚至编辑控件本身(因为它已经是子类).您将需要HWND在下一步中使用菜单.您现在可以选择卸载挂钩,或等待DefSubclassProc()/CallWindowProc()退出(菜单被解除后将退出).您需要使用,PostMessage()因为此时菜单窗口尚未创建它HMENU. PostMessage()延迟下一步直到HMENU准备好之后.
当接收到自定义窗口消息时,发送一个MN_GETMENU通过消息SendMessage()的菜单是HWND您从钩获得.你现在有菜单HMENU,可以随心所欲.
禁用Cut,Copy和Paste菜单项,调用EnableMenuItem().他们的菜单项标识符为相同的值WM_CUT,WM_COPY和WM_PASTE消息,分别为(这不是微软的记载,但跨Windows的版本是一致的).
更新:我刚刚找到了一个更简单的解决方案(当我测试它时也有效).
WM_CONTEXTMENU如上所述,将编辑控件子类化为截距.
收到消息时,调用SetWinEventHook()安装线程本地事件挂钩(将hmodWinEventProc参数设置为0,idProcess参数设置为GetCurrentProcessId(),idThread参数设置为GetCurrentThreadId(),dwFlags参数设置为0 - 不WINEVENT_INCONTEXT!).将两者eventMin和eventMax参数都设置为,EVENT_SYSTEM_MENUPOPUPSTART这是您收到的唯一事件.然后将消息调度到默认处理程序以调用弹出菜单.
当你的事件回调被调用时,菜单已经完全初始化,所以你可以将MN_GETMENU消息发送到提供的HWND,这将是菜单的窗口(回调的idObject参数将是OBJID_CLIENT,idChild参数将是0).
HMENU根据需要操纵.
如上所述,在使用它时取消挂钩事件挂钩.
正如你在这里看到的,这确实有效.
在修改菜单之前:
禁用菜单项后:
甚至删除菜单项: