Reputation:
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. When displaying the contents of the buttonPressed array in WM_DRAWITEM even, is a delay in changing the value of the active state
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;
Upvotes: 0
Views: 84
Reputation: 595402
Your WM_COMMAND
handler is not triggering any repaints of the buttons after changing the states in the buttonPressed
array. Call InvalidateRect()
on each button to trigger a new WM_PAINT
message for each button.
Also, you are making the same mistakes in this code (leaking memory and resources, invalid parameter to SetBkMode()
, etc) that you made in your earlier code. You are using very few portions of code from the accepted answer, and you are ignoring all of the mistakes that answer pointed out to you.
Try something more like this:
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;
Upvotes: 1