如何在Win32 API中知道选定的菜单项

How to know selected menu item in Win32 API

本文关键字:菜单项 Win32 API      更新时间:2023-10-16

在窗口API中,我有一个弹出菜单,该菜单分别包含3个项目","圆圈"answers"退出"。

我的程序是让用户选择一个要绘制的形状,然后采用点,参数(即行的起点和终点,...(。这是我到目前为止写的代码的一部分。

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
    WPARAM wParam, LPARAM lParam) {
    HMENU hMenu;
    POINT point;
    HDC hdc;
    hdc = GetDC(hwnd);
    static int x1, y1,x2,y2,count = 0;
    switch (msg) {
    case WM_LBUTTONDOWN:
        count++;
        if (count == 1)
        {
            x1 = LOWORD(lParam);
            y1 = HIWORD(lParam);
        }
        else
        {
            x2 = LOWORD(lParam);
            y2 = HIWORD(lParam);
            // I think the problem goes here, it never execute else part 
            //even if global_ID ==2, Am I missing something?
            if (global_ID == 1)//Line
            {DirectMethod(hdc, x1, y1, x2, y2, RGB(0, 0, 0));}
            else if (global_ID == 2)//Circle
            {Ellipse(hdc, x1, y1, x2, y2);}
            count = 0;
        }
    case WM_COMMAND:
        switch (LOWORD(wParam)) {
        case IDM_FILE_LINE:
            global_ID = 1;
            break;
        case IDM_FILE_CIRCLE:
            global_ID = 2;//Global Variable
            break;
        case IDM_FILE_QUIT:
            SendMessage(hwnd, WM_CLOSE, 0, 0);
            break;
        }
        break;
    case WM_RBUTTONUP:
        point.x = LOWORD(lParam);
        point.y = HIWORD(lParam);
        hMenu = CreatePopupMenu();
        ClientToScreen(hwnd, &point);
        AppendMenuW(hMenu, MF_STRING, IDM_FILE_LINE, L"&line");
        AppendMenuW(hMenu, MF_STRING, IDM_FILE_CIRCLE, L"&Circle");
        AppendMenuW(hMenu, MF_SEPARATOR, 0, NULL);
        AppendMenuW(hMenu, MF_STRING, IDM_FILE_QUIT, L"&Quit");
        TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, point.x, point.y, 0, hwnd, NULL);
        DestroyMenu(hMenu);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    }
    return DefWindowProcW(hwnd, msg, wParam, lParam);
}

我想做的是,基于选定的菜单项(行,圈子,...(我执行了特定的代码,这也取决于从用户点击鼠标(wm_lbuttondown(。

例如:如果用户选择"行",我应该取两个分绘制该行。

您的代码中有逻辑孔:

  1. 即使您不应该,您也在计数鼠标点击。当您的WM_COMMAND处理程序设置global_ID时,您也不会将count重置为0,因此随后的单击最终可能会跳过x1/y1的分配,因为count可能已经是> 0

  2. global_ID不是1或2时,您的WM_LBUTTONDOWN处理程序不应做任何事情。

  3. 拨打DirectMethod()/Ellipse()之后,您不会重置global_ID,因此WM_LBUTTONDOWN将只能保持无限点击并在每次点击时执行其图纸。

  4. 您的WM_LBUTTONDOWN缺少所需的break语句,因此每个WM_LBUTTONDOWN消息都将落到WM_COMMAND代码中。

而是尝试一下:

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static int x1, y1, x2, y2, count = 0, global_ID = 0;
    switch (msg)
    {
        case WM_LBUTTONDOWN:
        {
            switch (global_ID)
            {
                case 1: //Line
                case 2: //Circle
                {
                    ++count;
                    if (count == 1)
                    {
                        x1 = GET_X_LPARAM(lParam);
                        y1 = GET_Y_LPARAM(lParam);
                    }
                    else
                    {
                        x2 = GET_X_LPARAM(lParam);
                        y2 = GET_Y_LPARAM(lParam);
                        HDC hdc = GetDC(hwnd);
                        if (global_ID == 1) {
                            DirectMethod(hdc, x1, y1, x2, y2, RGB(0, 0, 0));
                        }
                        else {
                            Ellipse(hdc, x1, y1, x2, y2);
                        }
                        ReleaseDC(hwnd, hdc);
                        global_ID = 0;
                    }
                    break;
                }
            }
            break;
        }
        case WM_COMMAND:
        {
            switch (LOWORD(wParam))
            {
                case IDM_FILE_LINE:
                    global_ID = 1;
                    count = 0;
                    break;
                case IDM_FILE_CIRCLE:
                    global_ID = 2;
                    count = 0;
                    break;
                case IDM_FILE_QUIT:
                    SendMessage(hwnd, WM_CLOSE, 0, 0);
                    break;
            }
            break;
        }
        case WM_RBUTTONUP:
        {
            POINT point;
            point.x = GET_X_LPARAM(lParam);
            point.y = GET_Y_LPARAM(lParam);
            ClientToScreen(hwnd, &point);
            HMENU hMenu = CreatePopupMenu();        
            AppendMenuW(hMenu, MF_STRING, IDM_FILE_LINE, L"&line");
            AppendMenuW(hMenu, MF_STRING, IDM_FILE_CIRCLE, L"&Circle");
            AppendMenuW(hMenu, MF_SEPARATOR, 0, NULL);
            AppendMenuW(hMenu, MF_STRING, IDM_FILE_QUIT, L"&Quit");
            TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, point.x, point.y, 0, hwnd, NULL);
            DestroyMenu(hMenu);
            break;
        }
        case WM_DESTROY:
        {
            PostQuitMessage(0);
            break;
        }
    }
    return DefWindowProcW(hwnd, msg, wParam, lParam);
}