2015-10-07 3 views
2

Как отключить эти 3 команды стандартного вырезания/копирования/вставки в контекстном меню собственного редактора редактирования ОС Windows?Как отключить команды копирования/вставки в контекстном меню управления редактированием Windows?

enter image description here

Также нужно отключить эквивалентные команды, связанные с буфером обмена, как CTRL + C/CTRL + V.

Есть ли специальный стиль управления редактированием или что-то еще, что мы можем использовать, чтобы отключить все операции копирования/вставки с помощью одной простой настройки?

+0

Зачем вам это нужно? –

+0

@DavidHeffernan, это требование некоторых конечных пользователей;). В общем случае нам также необходимо добавить наши пользовательские элементы в контекстное меню ОС по умолчанию. – TecMan

+0

Странные пользователи! Вероятно, проще всего заменить все меню своим. –

ответ

5

Обычно, когда элемент управления отображает всплывающее меню, WM_INITPOPUPMENU генерируется сообщение, которое «позволяет приложению модифицировать меню перед его отображением, не изменяя все меню.»

К сожалению, стандартный Win32 Edit управления не генерирует это сообщение для его всплывающего меню по умолчанию, как это было подтверждено в статье MSDN Magazine за ноябрь 2000 года (ссылка на MSDN сам умер, но эта связь с Internet Archive):

MSDN Magazine, November 2000, C++ Q&A:

В: Почему не создается сообщение WM_INITMENUPOPUP при щелчке правой кнопкой мыши на элементе управления редактированием?

A: Я не могу сказать вам, почему его нет, но я могу подтвердить, что это правда ... редактировать элементы управления не отправлять WM_INITMENUPOPUP. Элемент управления редактирования должен вызывать TrackPopupMenu с помощью дескриптора HWND и/или TPM_NONOTIFY, который сообщает меню не отправлять уведомления. Возможно (и снова я только догадываюсь), что авторы пытались повысить производительность за счет сокращения трафика сообщений ... В любом случае, предположим, вы хотите добавить свои собственные пункты меню в контекстное меню управления редактированием. Как ты делаешь это? Увы, у вас нет выбора, кроме как изобретать колесо

Так что единственный вариант доступного подкласса управления редактированием и обработки WM_CONTEXTMENU сообщения вместо создания и отображения вашего собственного меню настраиваемых всплывающего по мере необходимости. Это означает, что вам необходимо вручную дублировать функциональность любых стандартных элементов меню, которые вы хотите отобразить в своем пользовательском меню.

Обновление: есть способ доступа и изменения стандартного всплывающего меню элемента управления редактированием (я только что протестировал его, и он сработал). TecMan предоставил ссылку на сообщение VBForums discussion, в котором говорится об этом, однако он получает несколько деталей неправильно. Я получил правильные данные от PureBasic forum discussion.

Правильный подход заключается в следующем:

  1. подкласса управление редактированием, чтобы перехватить WM_CONTEXTMENU сообщений. Можно использовать либо SetWindowSubClass(), либо SetWindowLongPtr(GWL_WNDPROC), хотя the first is preferred.

  2. при получении WM_CONTENTMENU сообщения, вызовите SetWindowsHookEx() установить нити локального крюк (использование 0 для параметра и GetCurrentThreadId()hMod для параметра dwThreadId). Можно использовать крючок WH_CBT или WH_CALLWNDPROC.Затем отправьте WM_CONTENTMENU обработчику сообщений по умолчанию через DefSubclassProc() или CallWindowProc(), чтобы вызвать стандартное всплывающее меню.

  3. внутри процедуры крюка, когда HCBT_CREATEWND (WH_CBT крючка) или WM_CREATE (WH_CALLWNDPROC крюка) уведомление получено, передать HWND при условии, чтобы GetClassName(). Если имя класса #32768 (стандартное окно имя класса для меню, а documented on MSDN) поста (очень важно!) Сообщение пользовательского окна с помощью PostMessage(), указав окно меню, то HWND в сообщении по WPARAM или LPARAM параметру, чтобы любыхHWND, который вы контролируете, например, ваше главное окно, или даже сам элемент редактирования (поскольку он уже подклассифицирован). В следующем шаге вам понадобится HWND. Вы можете опционально удалить девайс в это время или дождаться выхода DefSubclassProc()/CallWindowProc() (он выйдет после того, как меню будет уволено). Вам нужно использовать PostMessage(), потому что окно меню еще не создало его HMENU. PostMessage() задерживает следующий шаг, пока не будет готова HMENU.

  4. при получении сообщения пользовательского окна, отправить на MN_GETMENU сообщений в меню для HWND, что вы получили от крючка с помощью SendMessage(). Теперь у вас есть меню HMENU и вы можете делать с ним все, что хотите.

  5. отключить пункты меню Cut, Copy и Paste, вызовите EnableMenuItem(). Их идентификаторы элементов меню имеют те же значения, что и сообщения WM_CUT, WM_COPY и WM_PASTE (это не документировано Microsoft, но является совместимым в версиях Windows).

Update: Я только что нашел более простое решение (которое также работал, когда я тестировал).

  1. Подкласс управления редактированием для перехвата WM_CONTEXTMENU, как описано выше.

  2. при получении сообщения, вызовите SetWinEventHook() установить внутрипотоковой крючок событий (установите параметр hmodWinEventProc 0, параметр idProcess в GetCurrentProcessId(), параметр idThread к GetCurrentThreadId() и dwFlags параметр 0 - не WINEVENT_INCONTEXT !). Задайте параметры eventMin и eventMax как EVENT_SYSTEM_MENUPOPUPSTART, так что это единственное событие, которое вы получаете. Затем отправьте сообщение обработчику по умолчанию, чтобы вызвать всплывающее меню.

  3. когда ваш обратный вызов события вызывается, меню уже полностью инициализировано, так что вы можете отправить MN_GETMENU сообщений предоставленных HWND, который будет окном в меню для (idObject параметра функции обратного вызова будет OBJID_CLIENT и параметр idChild будет 0).

  4. при необходимости использовать HMENU.

  5. отцепить событие крюк, когда он будет выполнен, как описано выше.


Как вы можете видеть здесь, это работает.

Перед изменением меню:

before modifying the menu

После отключения пунктов меню:

Disabling the menu items

Даже удаление пунктов меню:

Deleting the menu items

+0

См. Мой ответ со ссылкой на vbforums.com. Возможно, вы знаете лучший и/или документированный способ получить дескриптор контекстного меню элемента управления редактированием? – TecMan

+0

@TecMan: один задокументированный способ получить всплывающее меню окна - это сообщение «MN_GETMENU». Хитрость заключается в том, чтобы получить всплывающее меню 'HWND', чтобы вы могли получить его' HMENU'. Подход - единственный способ сделать это. Однако детали, представленные в приведенной вами ссылке VBForums, немного неправильны. Я обновил свой ответ с правильными деталями. –

+0

Что не так с сообщением на VBForums? – TecMan

0

Вы можете оставить видимыми параметры, но заблокировать буфер обмена от использования.
Если это решение подходит вам всем, что вам нужно сделать, это сделать программу, которая открывает буфер обмена, позвонив по номеру OpenClipboard(NULL). Чтобы освободить вызов буфера обмена CloseClipboard().

+0

Остерегайтесь непреднамеренных последствий. Многие приложения рассчитывают на работу с буфером обмена, который документируется. Поэтому блокировка буфера обмена в течение длительных периодов времени вызовет конфликты, сбои и т. Д. Приложения, которые вы даже не ожидаете, например Remote Desktop, могут ошибочно работать. –

0

Один подход (аналогичный идее гипмера, но не такой интрузивный) заключается в том, чтобы просто перезаписать буфер обмена с «ДАННЫМИ, УДАЛЕННЫМИ TecMan» всякий раз, когда он обновляется. Вы можете сделать это как зарегистрированный просмотрщик буфера обмена.
Откройте буфер обмена, очистите все форматы, добавьте CF_TEXT с уведомлением, закройте его. Я бы воспользовался короткой задержкой (возможно, обратным вызовом таймера), чтобы вы сделали свое обновление ПОСЛЕ первого обновления, обработанного другими зарегистрированными буферами обмена в системе. Ваш пробег может отличаться. Злоупотребление буфером обмена, подобным этому, никогда не является хорошей идеей.

0

Я нашел одну интересную мысль о том, как получить дескриптор контекстного меню управления для редактирования на vbforums.com:

http://www.vbforums.com/showthread.php?776385-RESOLVED-Modify-right-click-context-menu-in-standard-controls

Он демонстрирует, как добавлять пользовательские элементы контекстного меню в стандартном контексте OS меню. Я думаю, эту идею можно использовать и для изменения меню. Теоретически мне нужно перечислить пункты меню и отключить элементы, относящиеся к командам копирования/вставки. Вопрос в том, как узнать, связан ли элемент меню с копией/вставкой? Получение текста пункта меню - плохая идея;)

Другой проблемой этого кода является то, что он основан на некоторых функциях Windows, которые не документированы. Я проверил решение, оно все еще работает в Windows 10, но кто знает, как можно изменить контекстное меню управления редактированием в будущих обновлениях ОС ...

+0

Несмотря на то, что обсуждение VBForum обсуждает технику получения стандартного элемента управления «HMENU», некоторые детали неверны. Я обновил свой ответ с правильными деталями. –

 Смежные вопросы

  • Нет связанных вопросов^_^