RFR: 8348760: RadioButton is not shown if JRadioButtonMenuItem is rendered with ImageIcon in WindowsLookAndFeel [v24]

Prasanta Sadhukhan psadhukhan at openjdk.org
Mon Mar 17 12:40:07 UTC 2025


On Wed, 12 Mar 2025 11:00:30 GMT, Prasanta Sadhukhan <psadhukhan at openjdk.org> wrote:

>> When JRadioButtonMenuItem is called with imageIcon, then only imageIcon is shown without radiobutton in WIndowsLookAndFeel as there was no provision of drawing the radiobutton alongside icon.
>> If icon is not there, the radiobutton is drawn. Added provision of drawing the radiobutton windows Skin even when imageIcon is present.
>
> Prasanta Sadhukhan has updated the pull request incrementally with one additional commit since the last revision:
> 
>   Review comments fix

Native program to render radiobutton with image (bitmap) icon


#include <windows.h>
#include <string>

#define IDM_RADIO1 1001
#define IDM_RADIO2 1002
#define IDM_RADIO3 1003

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {
    static TCHAR szAppName[] = TEXT("RadioMenuDemo");
    HWND hwnd;
    MSG msg;
    WNDCLASS wndclass;

    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = szAppName;

    RegisterClass(&wndclass);

    hwnd = CreateWindow(szAppName, TEXT("Radio Menu Demo"),
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT,
        400, 300,
        NULL, NULL, hInstance, NULL);

    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);

    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
    static HMENU hMainMenu, hRadioSubMenu;

    switch (message) {
    case WM_CREATE: {
        // Create main menu
        hMainMenu = CreateMenu();
        hRadioSubMenu = CreatePopupMenu();

        // Configure menu items using MENUITEMINFO
        MENUITEMINFO mii = { 0 };
        mii.cbSize = sizeof(MENUITEMINFO);
        mii.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_ID | MIIM_BITMAP | MIIM_CHECKMARKS;

        // First radio item
        mii.fType = MFT_RADIOCHECK;
        std::wstring wstr1 = L"Radio Option 1";
        LPWSTR lp1 = (LPWSTR)wstr1.c_str();
        mii.dwTypeData = lp1;
        mii.cch = (UINT)strlen((const char *)lp1);
        mii.wID = IDM_RADIO1;
        mii.fState = MFS_CHECKED;

        HDC hdc = GetDC(hwnd);
        HBITMAP hBitmap = CreateCompatibleBitmap(hdc, 16, 16);
        HDC memDC = CreateCompatibleDC(hdc);
        //HGDIOBJ oldObj = SelectObject(memDC, hBitmap);
        HBRUSH hBrush = CreateSolidBrush(RGB(255, 0, 0));
        RECT rect = { 0, 0, 16, 16 };
        FillRect(memDC, &rect, hBrush);
        mii.hbmpItem = hBitmap;
        InsertMenuItem(hRadioSubMenu, 0, TRUE, &mii);

        // Second radio item
        std::wstring wstr2 = L"Radio Option 2";
        LPWSTR lp2 = (LPWSTR)wstr2.c_str();
        mii.dwTypeData = lp2;
        mii.cch = (UINT)strlen((const char *)lp2);
        mii.wID = IDM_RADIO2;
        InsertMenuItem(hRadioSubMenu, 1, TRUE, &mii);

        // Third radio item
        std::wstring wstr3 = L"Radio Option 3";
        LPWSTR lp3 = (LPWSTR)wstr3.c_str();
        mii.dwTypeData = lp3;
        mii.cch = (UINT)strlen((const char *)lp3);
        mii.wID = IDM_RADIO3;
        mii.hbmpItem = NULL;
        InsertMenuItem(hRadioSubMenu, 2, TRUE, &mii);

        // Add submenu to main menu
        AppendMenu(hMainMenu, MF_POPUP, (UINT_PTR)hRadioSubMenu, L"Options");
        SetMenu(hwnd, hMainMenu);

        // Set initial checked item using CheckMenuRadioItem
        CheckMenuRadioItem(hRadioSubMenu,
            IDM_RADIO1, IDM_RADIO3,  // Group range
            IDM_RADIO1,              // Initial selection
            MF_BYCOMMAND);           // Identifier type
        return 0;
    }

    case WM_COMMAND:
        switch (LOWORD(wParam)) {
        case IDM_RADIO1:
        case IDM_RADIO2:
        case IDM_RADIO3:
            // Update radio selection
            CheckMenuRadioItem(hRadioSubMenu,
                IDM_RADIO1, IDM_RADIO3,
                LOWORD(wParam), MF_BYCOMMAND);
            break;
        }
        return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}




It shows either icon or radio bullet in this program in WIndows 11

![image](https://github.com/user-attachments/assets/860022da-91c4-4c68-b39e-b5a543cfc2b2)

-------------

PR Comment: https://git.openjdk.org/jdk/pull/23324#issuecomment-2729336165


More information about the client-libs-dev mailing list