Ответы с форумов MSDN

WINAPI - Добавление своего элемента в системное меню

Date: 16.12.2019 10:02:10

Какой элемент управления вы используете, чтобы отображать текст? В общем случае, вам нужно установить с помощью SetWinEventHook хук на событие появления меню EVENT_SYSTEM_MENUPOPUPSTART и в обработчике этого события добавить в меню элемент через AppendMenu. Вот так будет выглядеть код для стандартного Edit Control:

#include <stdlib.h> 
#include <stdio.h>
#include <windows.h>

bool Enabled = false;
UINT CurrentItemID;

HWND GetMenuOwner(DWORD thid) { //получает владельца активного меню UI-потока
	GUITHREADINFO info;
	memset(&info, 0, sizeof(info));
	info.cbSize = sizeof(info);
	GetGUIThreadInfo(thid, &info);
	if ((info.flags & GUI_POPUPMENUMODE) != 0) {		
		return info.hwndMenuOwner;
	}
	else {		
		return NULL;
	}
}

//Обработка появления меню
void CALLBACK HandleMenuPopup(HWINEVENTHOOK hook, DWORD event, HWND hwnd,
	LONG idObject, LONG idChild,
	DWORD dwEventThread, DWORD dwmsEventTime)
{
	HWND hOwner = GetMenuOwner(dwEventThread);

	//получаем имя класса окна
	WCHAR buf[100] = L"";
	GetClassNameW(hOwner, buf, 100);
	
	if (wcscmp(buf, L"Edit") == 0) {
		//если это Edit Control, получаем меню
		HMENU hMenu = (HMENU)SendMessage(hwnd, MN_GETHMENU, 0, 0);
		int c = GetMenuItemCount(hMenu);
		UINT id_max = 0;

		//найдем максимальный ID элемента...
		for (int i = 0; i < c; i++) {
			UINT id = GetMenuItemID(hMenu, i);

			//Значения больше 10000, видимо, зарезервированы для особых целей - с ними не работает
			if (id >= 10000) continue; 

			if (id > id_max) id_max = id;
		}
		CurrentItemID = id_max + 1; //получаем уникальный ID для нового элемента

		//добавляем новый элемент Test
		BOOL res = AppendMenu(hMenu, MF_STRING | MF_POPUP, CurrentItemID, L"Test");
		if (res == FALSE) {
			printf("AppendMenu error %d", GetLastError());
			Enabled = false;
			return;
		}
		Enabled = true;
	}
	else Enabled = false;
}

//обработка нажатия элемента
void CALLBACK HandleMenuClick(HWINEVENTHOOK hook, DWORD event, HWND hwnd,
	LONG idObject, LONG idChild,
	DWORD dwEventThread, DWORD dwmsEventTime)
{	
	if (Enabled && idChild == CurrentItemID) {		
				
		HWND hOwner = GetMenuOwner(dwEventThread);
		
		//выполнить необходимые действия...
	}
}

void InitializeHook()
{
	CoInitialize(NULL);
	HWINEVENTHOOK hook = SetWinEventHook(
		EVENT_SYSTEM_MENUPOPUPSTART, EVENT_SYSTEM_MENUPOPUPSTART,  // Range of events
		NULL,                                          // Handle to DLL.
		HandleMenuPopup,                                // The callback.
		GetCurrentProcessId(), 0,              // Process and thread IDs of interest (0 = all)
		WINEVENT_OUTOFCONTEXT); // Flags.
	if (hook == 0) printf("SetWinEventHook HandleMenuPopup error %d", GetLastError());

	hook = SetWinEventHook(
		EVENT_OBJECT_INVOKED, EVENT_OBJECT_INVOKED,  // Range of events
		NULL,                                          // Handle to DLL.
		HandleMenuClick,                                // The callback.
		GetCurrentProcessId(), 0,              // Process and thread IDs of interest (0 = all)
		WINEVENT_OUTOFCONTEXT); // Flags.
	if (hook == 0) printf("SetWinEventHook HandleMenuClick error %d", GetLastError());
}

 

Основано на ответе https://stackoverflow.com/a/32998022/8674428



Message 155

Date: 17.12.2019 3:19:02

Текст через сообщение WM_GETTEXT, выделение - через EM_GETSEL.

WCHAR buf[256]=L"";
SendMessage(hOwner, WM_GETTEXT, sizeof(buf)/sizeof(WCHAR), (LPARAM)buf);
DWORD start, end;
SendMessage(hOwner, EM_GETSEL, (WPARAM)&start, (LPARAM)&end);
WCHAR selection[256] = L"";
wcsncpy_s(selection, sizeof(selection) / sizeof(WCHAR), &(buf[start]), end - start);


Автор: VadimTagil

Главная страница - Список тем - Репозиторий на GitHub