为什么 WinAPI 中的上下文(弹出)菜单没有出现?

Why my context (popup) menu in WinAPI doesn't appear?

本文关键字:菜单 弹出 WinAPI 上下文 为什么      更新时间:2023-10-16

我正试图在应用程序中使用WinAPI设置上下文菜单,但由于某些原因,我没有成功。将弹出菜单的代码放在WM_RBUTTONUP的情况下。但是,右键单击后不会发生任何事情。有人能告诉我我做错了什么吗?

.cpp:

#include "stdafx.h"
#include "Growing_children_PAWEL_MICHNA.h"
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst;                                // current instance
TCHAR szTitle[MAX_LOADSTRING];                  // The title bar text
//TCHAR szChild1Title[MAX_LOADSTRING];
//TCHAR szChild2Title[MAX_LOADSTRING];
TCHAR szWindowClass[MAX_LOADSTRING];            // the main window class name
TCHAR szChild1WindowClass[MAX_LOADSTRING];
TCHAR szChild2WindowClass[MAX_LOADSTRING];
HWND hWnd, child1hWnd, child2hWnd;
HMENU hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_CONTEXT_MENU));
int mywidth = 25;
int myheight = 25;
bool greater = true;
// Forward declarations of functions included in this code module:
ATOM                MyRegisterClass(HINSTANCE hInstance);
ATOM                Child1RegisterClass(HINSTANCE hInstance);
ATOM                Child2RegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);
    MSG msg;
    HACCEL hAccelTable;
    // Initialize global strings
    LoadString(hInstance, IDS_APP_TITLE, NULL, MAX_LOADSTRING);
    LoadString(hInstance, IDC_GROWING_CHILDREN_PAWEL_MICHNA, szWindowClass, MAX_LOADSTRING);
    LoadString(hInstance, IDC_CHILD1, szChild1WindowClass, MAX_LOADSTRING);
    LoadString(hInstance, IDC_CHILD2, szChild2WindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);
    Child1RegisterClass(hInstance);
    Child2RegisterClass(hInstance);
    // Perform application initialization:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }
    hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_GROWING_CHILDREN_PAWEL_MICHNA));
    // Main message loop:
    while (GetMessage(&msg, NULL, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    return (int) msg.wParam;
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;
    HBRUSH redBrush = CreateSolidBrush(RGB(255, 0, 0));
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style          = NULL; //CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_GROWING_CHILDREN_PAWEL_MICHNA));
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground  = redBrush;
    wcex.lpszMenuName   = MAKEINTRESOURCE(NULL);
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
    return RegisterClassEx(&wcex);
}
ATOM Child1RegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;
    HBRUSH blueBrush = CreateSolidBrush(RGB(0, 0, 255));
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style          = CS_PARENTDC; //CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_GROWING_CHILDREN_PAWEL_MICHNA));
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground  = blueBrush;
    wcex.lpszMenuName   = MAKEINTRESOURCE(NULL);
    wcex.lpszClassName  = szChild1WindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
    return RegisterClassEx(&wcex);
}
ATOM Child2RegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;
    HBRUSH greenBrush = CreateSolidBrush(RGB(0, 255, 0));
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style          = CS_PARENTDC; //CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_GROWING_CHILDREN_PAWEL_MICHNA));
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground  = greenBrush;
    wcex.lpszMenuName   = MAKEINTRESOURCE(NULL);
    wcex.lpszClassName  = szChild2WindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
    return RegisterClassEx(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // Store instance handle in our global variable
   hWnd = CreateWindowEx(WS_EX_TOPMOST | WS_EX_LAYERED, szWindowClass, NULL, WS_POPUPWINDOW, CW_USEDEFAULT, 0, 500, 500, NULL, NULL, hInstance, NULL);
   if (!hWnd)
   {
      return FALSE;
   }
   // Set windows transparency to 70%
   SetLayeredWindowAttributes(hWnd, 0, (255 * 70) / 100, LWA_ALPHA);
   RECT rc; 
   // get the center of the work area of the system 
   SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0); 
   int centerX = (rc.left + rc.right + 1) / 2; 
   int centerY = (rc.top + rc.bottom + 1) / 2; 
   //move the main windows to the center
   MoveWindow(hWnd, centerX-250, centerY-250, 500, 500, true);
   child1hWnd = CreateWindow(szChild1WindowClass, NULL, WS_CHILD, 0, 0, 25, 25, hWnd, NULL, hInstance, NULL);
   SetLayeredWindowAttributes(child1hWnd, 0, (255 * 70) / 100, LWA_ALPHA);
   child2hWnd = CreateWindow(szChild2WindowClass, NULL, WS_CHILD, 475, 476, 25, 25, hWnd, NULL, hInstance, NULL);
   SetLayeredWindowAttributes(child2hWnd, 0, (255 * 70) / 100, LWA_ALPHA);
   ShowWindow(hWnd, nCmdShow);
   ShowWindow(child1hWnd, nCmdShow);
   ShowWindow(child2hWnd, nCmdShow);
   UpdateWindow(hWnd);
   UpdateWindow(child1hWnd);
   UpdateWindow(child2hWnd);
   return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;
    POINT point;
    switch (message)
    {
    case WM_COMMAND:
        wmId    = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        // Parse the menu selections:
        switch (wmId)
        {
        case IDM_ABOUT:
            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            break;
        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        break;
    case WM_CREATE:
    {
        SetTimer(hWnd, 1, 100, NULL);
        return 0; 
    }
        break;
    case WM_RBUTTONUP: 
    {
        point.x = LOWORD(lParam); 
        point.y = HIWORD(lParam); 
        ClientToScreen(hWnd, &point); 
        TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, point.x, point.y, 0, hWnd, NULL); 
        return 0;
    }
    case WM_TIMER:
        if(mywidth < 250 && greater == true)
        {
            MoveWindow(child1hWnd, 0, 0, ++mywidth, ++myheight, true);
            MoveWindow(child2hWnd, 500-mywidth, 500-myheight, mywidth, myheight, true);
            if(mywidth == 250)
                greater = false;
        }
        else
        {
            MoveWindow(child1hWnd, 0, 0, --mywidth, --myheight, true);
            MoveWindow(child2hWnd, 500-mywidth, 500-myheight, mywidth, myheight, true);
            if(mywidth == 0)
                greater = true;
        }
        break;
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        EndPaint(hWnd, &ps);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    case WM_NCHITTEST:
        if (hWnd == child1hWnd || hWnd == child2hWnd) return HTTRANSPARENT;
        return HTCAPTION; 
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;
    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}

.rc片段:

IDR_CONTEXT_MENU MENU
BEGIN
    MENUITEM "Color",                       ID_COLOR32778
    POPUP "Figures"
    BEGIN
        MENUITEM "None",                        ID_FIGURES_NONE, CHECKED
        MENUITEM "Square",                      ID_FIGURES_SQUARE
        MENUITEM "Triangle",                    ID_FIGURES_TRIANGLE
        MENUITEM "Circle",                      ID_FIGURES_CIRCLE
    END
    MENUITEM "Exit",                        ID_EXIT
END

您的hMenu是一个静态变量,它在hInst有值之前加载。我认为LoadMenu呼叫失败。

您还将在TrackPopupMenu文档中注意到,不仅可以使用任何菜单句柄,它还必须是一个弹出菜单句柄。在资源中,为顶级菜单创建一个元素,并将弹出菜单放在它下面;然后使用LoadMenu加载顶级菜单,使用GetSubMenu获取下拉菜单的句柄。