The problem background

In Windows C++ client program development, often encounter the development of custom right menu function point. At this point, we usually only need to process the WM_CONTEXTMENU message in the window’s event procedure. When processing, according to the need can use CreatePopupMenu to create pop-up menu, and insert the specified sub-menu items, and finally process the corresponding menu item message such a process to achieve a custom right-click menu list. You can also override some implemented or defined menu lists by getting a handle to a menu item, enumerating and modifying the form of the menu list. There was a need to inherit the default right-click menu from Edit and add some custom right-click menu items. However, when WM_CONTEXTMENU message is fired, it cannot get the default right-click menu handle information, so it cannot get the menu list items in the right-click menu. Therefore, you cannot continue to customize the right-click menu item. The following code demonstrates the common method of customizing the right-click menu and implementing the method of overloading the default Context in the Editbox.

Custom right click menu

Here with code to represent the general right-click menu creation and processing process:

#define EDIT_NEW_MENU_ITEM WM_USER + 800 static LRESULT CALLBACK wndProcForditCtrl (HWND HWND, UINT message, HWND) WParam wParam, lParam lParam) {switch (message) {case WM_ContextMenu: {hMenu popup = createPapupMenu (); WCHAR temp[50] = {0}; Wcscpy (temp, L" custom menu "); AppendMenu(popup, MF_STRING, (UINT_PTR)EDIT_NEW_MENU_ITEM, tmp); POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)}; TrackPopupMenu(popup, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, pt.x, pt.y, 0,hwnd, nullptr); return true; } break; Case EDIT_NEW_MENU_ITEM:{// handle the message as needed} break; default: break; } return DefWindowProc(hwnd, message, wParam, lParam); }

Overload the system default right-click menu

// Get MenuItemInfo getMenuInfoByPosition (hMenu menu, UINT nPos) {TCHAR szMenustr [256] = {0}; MENUITEMINFO mInfo = {0}; mInfo.cbSize = sizeof(mInfo); mInfo.fMask = 0 |MIIM_CHECKMARKS | MIIM_DATA | MIIM_ID | MIIM_STATE | MIIM_SUBMENU| MIIM_TYPE| 0; mInfo.dwTypeData = szMenuStr; mInfo.cch = _countof(szMenuStr); GetMenuItemInfo(menu, nPos, TRUE, &mInfo); return mInfo; } #define EDIT_NEW_MENU_ITEM WM_USER + 800 static bool isInitMenu = true; static LRESULT CALLBACK WndProcForEditCtrl(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_CONTEXTMENU: { isInitMenu = true; } break; case WM_ENTERIDLE: {if (wParam == MSGF_MENU) {// Represent a menu message, If (isInitMenu) {isInitMenu = false; if (isInitMenu) {isInitMenu = false; MENUBARINFO mbi; memset(&mbi, 0, sizeof(MENUBARINFO)); mbi.cbSize = sizeof(MENUBARINFO); GetMenuBarInfo((HWND)lParam, OBJID_CLIENT, 0, &mbi); if (::IsMenu((HMENU)mbi.hMenu)) { for (int i = 0; i < GetMenuItemCount(mbi.hMenu) - 1; i++) { MENUITEMINFO menuInfo = GetMenuInfoByPosition(mbi.hMenu, i); auto aa = menuInfo.dwTypeData; if (str::Len(menuInfo.dwTypeData)) { WCHAR menuName[50] = {0}; wcscpy(menuName, menuInfo.dwTypeData); win::menu::SetText(mbi.hMenu, menuInfo.wID, menuName); } } WCHAR menuStr[50] = {0}; Wcscpy (menuStr, L" custom menu "); AppendMenu(mbi.hMenu, MF_STRING, (UINT_PTR)9000, menuStr); } } } } break; default: break; } return DefWindowProc(hwnd, message, wParam, lParam); }

The resources……

Important note

= =Welcome everyone to pay attention to my personal WeChat public account, together to discuss and learn C++ back-end, client development knowledge!= =