简体   繁体   中英

How to know selected menu item in Win32 API

In window API, I have a popup menu which contains 3 items "Line","Circle" and "Exit" respectively.

My program is to let the user select a shape to draw then takes the points, parameters (ie start and end points of the line,...). This is part of the code i've written so far.

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);
}

What I wanna do is, based on selected menu item (Line, Circle,...) I execute specific piece of code which depends also on getting mouse clicks from user (WM_LBUTTONDOWN).

For example: If the user selected "Line", I should take two points to draw that line.

There are logic holes in your code:

  1. you are counting mouse clicks even when you shouldn't be. When your WM_COMMAND handler sets global_ID , you are not also resetting count to 0, so a subsequent click may end up skipping the assignment of x1 / y1 since count may already be > 0 .

  2. your WM_LBUTTONDOWN handler should not be doing anything at all when global_ID is not 1 or 2.

  3. you are not resetting global_ID after calling DirectMethod() / Ellipse() , so WM_LBUTTONDOWN will just keep counting clicks endlessly and performing its drawings on every other click.

  4. your WM_LBUTTONDOWN is missing a required break statement, so every WM_LBUTTONDOWN message will fall through to the WM_COMMAND code.

Try this instead:

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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM