c++ - Winapi 创建标签菜单

标签 c++ winapi tabs

I'm trying to make a tab menu, it should have an active state with different styling when a tab is selected, the problem is when starting the program the tabs get selected after two clicks.甚至在WM_DRAWITEM中显示buttonPressed数组的内容时,是延迟改变事件状态的值

case WM_CREATE:

    buttonPressed[0] = 1;
    buttonPressed[1] = 0;
    buttonPressed[2] = 0;
    buttonPressed[3] = 0;

    button1 = CreateWindow("BUTTON","Overview",WS_VISIBLE | WS_CHILD | BS_OWNERDRAW, 0,0,200,50, hwnd , (HMENU) 1 , NULL, NULL);
    button2 = CreateWindow("BUTTON","Send",WS_VISIBLE | WS_CHILD | BS_OWNERDRAW, 200,0,200,50, hwnd , (HMENU) 2, NULL, NULL);
    button3 = CreateWindow("BUTTON","Receive",WS_VISIBLE | WS_CHILD | BS_OWNERDRAW, 400,0,200,50, hwnd , (HMENU) 3, NULL, NULL);
    button4 = CreateWindow("BUTTON","Transactions",WS_VISIBLE | WS_CHILD | BS_OWNERDRAW, 600,0,200,50, hwnd , (HMENU) 4, NULL, NULL);

break;

case WM_DRAWITEM:
        {
            if((wParam == 1 && buttonPressed[0] == 1) ||  (wParam == 2 && buttonPressed[1] == 1) || (wParam == 3 && buttonPressed[2] == 1) || (wParam == 4 && buttonPressed[3] == 1)   ){
                FillRect(Item->hDC, &Item->rcItem, CreateSolidBrush(0x6C6C6C) );
                SetBkMode(Item->hDC, 0x6C6C6C);
                SetTextColor(Item->hDC, RGB(0,0,255));
            }else{
                FillRect(Item->hDC, &Item->rcItem, CreateSolidBrush(0x6C6C6C) );
                SetBkMode(Item->hDC, 0x6C6C6C);
                SetTextColor(Item->hDC, RGB(255,255,255));
            }
                int len;
                len = GetWindowTextLength(Item->hwndItem);
                LPSTR lpBuff;
                lpBuff = new char[len+1];
                GetWindowTextA(Item->hwndItem, lpBuff, len+1);
                DrawTextA(Item->hDC, lpBuff, len, &Item->rcItem, DT_CENTER | DT_VCENTER | DT_WORDBREAK);
        }
break;
case WM_COMMAND:

            switch ( LOWORD(wParam) ){
                case 1:
                   buttonPressed[0] = 1;
                   buttonPressed[1] = 0;
                   buttonPressed[2] = 0;
                   buttonPressed[3] = 0;
                break;
                case 2:
                    buttonPressed[0] = 0;
                   buttonPressed[1] = 1;
                   buttonPressed[2] = 0;
                   buttonPressed[3] = 0;
                break;
                case 3:
                   buttonPressed[0] = 0;
                   buttonPressed[1] = 0;
                   buttonPressed[2] = 1;
                   buttonPressed[3] = 0;
                break;
                case 4:
                   buttonPressed[0] = 0;
                   buttonPressed[1] = 0;
                   buttonPressed[2] = 0;
                   buttonPressed[3] = 1;
                break;

            }

break;

最佳答案

在更改 buttonPressed 数组中的状态后,您的 WM_COMMAND 处理程序不会触发按钮的任何重绘。在每个按钮上调用 InvalidateRect() 为每个按钮触发新的 WM_PAINT 消息。

此外,您在此代码中犯了与您在 earlier code 中犯的相同错误(内存和资源泄漏、SetBkMode() 的无效参数等) .您只使用了已接受答案中的很少一部分代码,并且忽略了答案向您指出的所有错误。

尝试更像这样的东西:

struct ButtonInfo {
    HWND Wnd;
    bool Pressed;
};

ButtonInfo button[4];

...

case WM_CREATE:
    {
        LPCTSTR captions[4] = {TEXT("Overview"), TEXT("Send"), TEXT("Receive"), TEXT("Transactions")};

        for (int i = 0; i < 4; ++i) {
            button[i].Pressed = false;
            button[i].Wnd = CreateWindow(TEXT("BUTTON"), captions[i], WS_VISIBLE | WS_CHILD | BS_OWNERDRAW, i * 200, 0, 200, 50, hwnd, reinterpret_cast<HMENU>(i+1), NULL, NULL);
        }

        button[0].Pressed = true;
    }
    break;

case WM_DRAWITEM:
    {
        LPDRAWITEMSTRUCT Item = reinterpret_cast<LPDRAWITEMSTRUCT>(lParam);

        HFONT hFont = CreateFont(17, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, TEXT("Arial Black"));
        HFONT hOldFont = (HFONT) SelectObject(Item->hDC, hFont);

        HBRUSH hBrush = CreateSolidBrush(RGB(0x6C, 0x6C, 0x6C));
        FillRect(Item->hDC, &Item->rcItem, hBrush);
        DeleteObject(hBrush);

        SetBkMode(Item->hDC, TRANSPARENT);

        int buttonID = wParam;
        if (button[buttonID - 1].Pressed) {
            SetTextColor(Item->hDC, RGB(0,0,255));
        } else {
            SetTextColor(Item->hDC, RGB(255,255,255));
        }

        int len = GetWindowTextLength(Item->hwndItem) + 1;
        LPTSTR lpBuff = new TCHAR[len];
        len = GetWindowText(Item->hwndItem, lpBuff, len);
        DrawText(Item->hDC, lpBuff, len, &Item->rcItem, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
        delete[] lpBuff;

        SelectObject(Item->hDC, hOldFont);
        DeleteObject(hFont);
    }
    break;


case WM_COMMAND:
    {
        int buttonID = LOWORD(wParam);

        int buttonIdx = buttonID - 1;
        for (int i = 0; i < 4; ++i) {
            button[i].Pressed = (i == buttonIdx);
            InvalidateRect(button[i].Wnd, NULL, TRUE);
        }

        switch (buttonID) {
            // perform whatever actions you need based on which button was clicked....
        }
    }
    break;

关于c++ - Winapi 创建标签菜单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51449093/

相关文章:

c++ - 如何在 cocos2dx v3.7 中将一些 Sprite 放入 Valuemap

c++ - vector 。检查它是否包含 "Key"。 C++

winapi - VB6:子类窗体未收到 MF_OWNERDRAW 菜单项的 WM_DRAWITEM 消息

windows - 向 WM_PAINT 发送消息

css - Orbeon Forms 2017 - 如何将部分制作成标签页

javascript - 我无法使用 javascript 更改内容选项卡

c++ - switch 语句中的控制结构

c++ - 在构造函数中将指针/引用传递给现有对象的首选方式是什么?

c# - CryptFindLocalizedName 在多次调用时返回无效字符串

javascript - jQuery UI 选项卡错误 : Mismatching fragment identifier.