如何在Windows编辑控件上下文菜单中禁用复制/粘贴命令? [英] How to disable copy/paste commands in the Windows edit control context menu?

查看:248
本文介绍了如何在Windows编辑控件上下文菜单中禁用复制/粘贴命令?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在本机Windows OS编辑控件的上下文菜单中禁用这3个标准的剪切/复制/粘贴命令?

How can I disable those 3 standard cut/copy/paste commands in the context menu of the native Windows OS edit control?

我还需要禁用与剪贴板相关的等效命令,例如CTRL + C/CTRL + V.

I also need to disable the equivalent clipboard-related commands like CTRL+C/CTRL+V.

是否有一种特殊的编辑控件样式,或者可以通过一种简单的设置来禁用所有复制/粘贴操作的其他功能?

Is there a special edit control style or anything else we can use to disable all copy/paste operations with one easy setting?

推荐答案

通常,当控件显示弹出菜单时, WM_INITPOPUPMENU 消息,该消息"允许应用程序在显示菜单之前对其进行修改,而无需更改整个菜单."

Typically, when a control displays a popup menu, a WM_INITPOPUPMENU message is generated which "allows an application to modify the menu before it is displayed, without changing the entire menu."

不幸的是,标准的Win32 Edit控件不会为其默认弹出菜单生成该消息,正如2000年11月的《 MSDN杂志》所证实的那样(MSDN上的链接本身已失效,但是此链接来自 Internet存档):

Unfortunately, a standard Win32 Edit control does not generate that message for its default popup menu, as confirmed in a November 2000 article of MSDN Magazine (the link on MSDN itself is dead, but this link is from the Internet Archive):

MSDN杂志,2000年11月,C ++问题与解答:

问:为什么右键单击编辑控件时未生成WM_INITMENUPOPUP消息?

Q: Why isn't a WM_INITMENUPOPUP message generated when you right-click an edit control?

A:我不能告诉你为什么没有一个,但是我可以确认这是真的...编辑控件不会发送WM_INITMENUPOPUP .编辑控件必须正在使用具有空HWND句柄和/或TPM_NONOTIFY的TrackPopupMenu进行调用,这将告诉菜单不发送通知.作者有可能(也是在我的猜测中)作者试图通过减少消息流量来提高性能……无论如何,假设您想将自己的菜单项添加到编辑控件上下文菜单中.你怎么做呢? las,您别无选择,只能重新发明轮子

A: I can't tell you why there isn't one, but I can confirm it's true ... edit controls don't send WM_INITMENUPOPUP. The edit control must be calling TrackPopupMenu with a null HWND handle and/or TPM_NONOTIFY, which tells the menu not to send notifications. It's possible (and again I'm only guessing) that the authors were trying to improve performance by reducing message traffic ... In any case, suppose you want to add your own menu items to the edit control context menu. How do you do it? Alas, you have no choice but to reinvent the wheel

因此,唯一可用的选项是对编辑控件进行子类化并处理

So the only option available is to subclass the edit control and handle the WM_CONTEXTMENU message instead, creating and displaying your own custom popup menu as needed. Which means you have to manually duplicate the functionality of any standard menu items that you want to appear in your custom menu.

更新:毕竟,有一种方法可以访问和修改编辑控件的标准弹出菜单(我刚刚对其进行了测试,并且可以正常工作). TecMan提供了指向 PureBasic论坛讨论中获得了正确的详细信息.

Update: there is a way to access and modify the edit control's standard popup menu after all (I just tested it and it worked). TecMan provided a link to a VBForums discussion that talks about it, however it gets a few details wrong. I got the correct details from a PureBasic forum discussion.

正确的方法如下:

  1. 子类化编辑控件以拦截WM_CONTEXTMENU消息. SetWindowSubClass() SetWindowLongPtr(GWL_WNDPROC) //blogs.msdn.com/b/oldnewthing/archive/2003/11/11/55653.aspx"rel =" nofollow noreferrer>首选第一个.

当收到WM_CONTEXTMENU消息时,呼叫 DefSubclassProc()WM_CONTENTMENU分派到默认消息处理程序 CallWindowProc() 进行调用标准弹出菜单.

when the WM_CONTEXTMENU message is received, call SetWindowsHookEx() to install a thread-local hook (use 0 for the hMod parameter and GetCurrentThreadId() for the dwThreadId parameter). Either a WH_CBT or WH_CALLWNDPROC hook can be used. Then dispatch WM_CONTENTMENU to the default message handler via DefSubclassProc() or CallWindowProc() to invoke the standard popup menu.

,当收到HCBT_CREATEWND(WH_CBT挂钩)或WM_CREATE(WH_CALLWNDPROC挂钩)通知时,将提供的HWND传递给记录在MSDN上),发布(非常重要!),使用

inside the hook procedure, when a HCBT_CREATEWND (WH_CBT hook) or WM_CREATE (WH_CALLWNDPROC hook) notification is received, pass the provided HWND to GetClassName(). If the class name is #32768 (the standard window class name for menus, as documented on MSDN), post (very important!) a custom window message using PostMessage(), specifying the menu window's HWND in the message's WPARAM or LPARAM parameter, to any HWND that you control, such as your main window, or even the edit control itself (since it is already subclassed). You will need the menu's HWND in the next step. You can optionally now uninstall the hook at this time, or wait for DefSubclassProc()/CallWindowProc() to exit (it will exit after the menu has been dismissed). You need to use PostMessage() because the menu window has not created its HMENU yet at this time. PostMessage() delays the next step until after the HMENU is ready.

在收到自定义窗口消息时,发送一个

when the custom window message is received, send a MN_GETMENU message via SendMessage() to the menu's HWND that you obtained from the hook. You now have the menu's HMENU and can do whatever you want with it.

要禁用CutCopyPaste菜单项,请调用 EnableMenuItem() .它们的菜单项标识符分别与WM_CUTWM_COPYWM_PASTE消息具有相同的值(Microsoft并未对此进行记录,但是在Windows版本之间是一致的).

to disable the Cut, Copy, and Paste menu items, call EnableMenuItem(). Their menu item identifiers are the same values as the WM_CUT, WM_COPY and WM_PASTE messages, respectively (this is not documented by Microsoft, but is consistent across Windows versions).

更新:我刚刚找到了一个简单得多的解决方案(在我测试它时也可以使用).

Update: I just found a much simpler solution (which also worked when I tested it).

  1. 将编辑控件子类化以拦截WM_CONTEXTMENU,如上所述.

收到消息后,请致电 SetWinEventHook() 安装线程本地事件挂钩(将hmodWinEventProc参数设置为0,将idProcess参数设置为GetCurrentProcessId(),将idThread参数设置为GetCurrentThreadId(),并且将dwFlags参数设置为为0-不是WINEVENT_INCONTEXT!).将eventMineventMax参数都设置为EVENT_SYSTEM_MENUPOPUPSTART,这样它是您收到的唯一事件.然后将消息分派到默认处理程序以调用弹出菜单.

when the message is received, call SetWinEventHook() to install a thread-local event hook (set the hmodWinEventProc parameter to 0, the idProcess parameter to GetCurrentProcessId(), the idThread parameter to GetCurrentThreadId(), and the dwFlags parameter to 0 - not WINEVENT_INCONTEXT!). Set the eventMin and eventMax parameters both to EVENT_SYSTEM_MENUPOPUPSTART so that it is the only event you receive. Then dispatch the message to the default handler to invoke the popup menu.

在调用事件回调时,菜单已经完全初始化,因此您可以将MN_GETMENU消息发送到提供的HWND,这将是菜单的窗口(回调的idObject参数将为OBJID_CLIENT,而idChild参数将为0).

when your event callback is called, the menu has already been fully initialized, so you can send the MN_GETMENU message to the provided HWND, which will be the menu's window (the callback's idObject parameter will be OBJID_CLIENT and the idChild parameter will be 0).

根据需要操纵HMENU.

使用完事件钩子后,将其解钩,如上所述.

unhook the event hook when done using it, as described above.


正如您在这里看到的那样,它确实有效.


As you can see here, this does work.

在修改菜单之前:

禁用菜单项后:

甚至删除菜单项:

这篇关于如何在Windows编辑控件上下文菜单中禁用复制/粘贴命令?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆