Winapi创建选项卡菜单

时间:2018-07-20 19:20:09

标签: c++ winapi tabs

我正在尝试制作一个选项卡菜单,当选择一个选项卡时,它应该处于活动状态并具有不同的样式,问题是在启动程序时,在单击两次后选择了选项卡。在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;

1 个答案:

答案 0 :(得分:1)

更改WM_COMMAND数组中的状态后,您的buttonPressed处理程序不会触发按钮的重新绘制。在每个按钮上调用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;