How to change menu item text? - c++

I need to change menu item text on runtime. I've try to use GetMenuItemInfo() and SetMenuItemInfo():
case WM_NOTIFYICONMSG:
switch (lParam) {
case WM_LBUTTONDBLCLK:
someAction();
break;
case WM_RBUTTONDOWN:
{
POINT point;
GetCursorPos(&point);
HMENU hMenu;
HMENU hMenuTrackPopup;
hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_MENU));
if (hMenu) {
MENUITEMINFOA menuitem = { sizeof(MENUITEMINFOA) };
GetMenuItemInfoA(hMenu, IDM_EXIT, false, &menuitem);
menuitem.dwTypeData = "New text here";
SetMenuItemInfoA(hMenu, IDM_EXIT, false, &menuitem);
hMenuTrackPopup = GetSubMenu(hMenu, 0);
TrackPopupMenu(hMenuTrackPopup, 0, point.x, point.y, 0, hWnd, NULL);
DestroyMenu(hMenu);
}
}
break;
default:
break;
}
break;
But it doesn't work, text doesn't changed. What I am doing wrong? How to implement it?

As #HansPassant pointed out the solution is:
You are not using MENUITEMDATA correctly, you forgot to set the fMask member. Read the MSDN article for the struct for details
and then:
add menuitem.fMask = MIIM_TYPE | MIIM_DATA; and it works well
I can't take credit for this solution but am providing it here so that the next person that needs an answer to that question can easily find it without parsing the comments' section

Related

Handling the hotkey for menu item

I have created a new menu item "Extra" and add it to the window's main menu.
HMENU menu = GetMenu(hWnd);
HMENU popup = CreatePopupMenu();
AppendMenu(menu, MF_STRING | MF_POPUP, (UINT)popup, L"Extra");
SetMenu(hWnd, popup);
Next I inserted new item to "Extra" item with hotkey:
#define IDM_ITEM1 12310
and:
MENUITEMINFOW mmi;
mmi.cbSize = sizeof(MENUITEMINFOW);
mmi.fMask = MIIM_STRING | MIIM_ID;
mmi.fType = MFT_STRING;
mmi.dwTypeData = L"First item\tCtrl+N";
mmi.wID = IDM_ITEM1;
InsertMenuItemW(popup, 1, true, &mmi);
And handle "First item" click:
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case IDM_ITEM1:
{
MessageBox(0, L"First", L"", MB_OK);
break;
}
}
break;
}
And now when I click on "First item" a message box is appeared.
But when I press Ctrl+N hotkey - nothing happens. Why? How to fix this (without using accelerator resources)?
without using accelerator resources ?
You need to create an array of ACCEL and then call the CreateAcceleratorTable function:
ACCEL s_accel[2] = {{FCONTROL | FVIRTKEY, TEXT('C'), IDM_COLOR},
{FCONTROL | FVIRTKEY, TEXT('Q'), IDM_QUIT}};
HACCEL h_accel = CreateAcceleratorTable(s_accel, 2);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(hwnd, h_accel, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
DestroyAcceleratorTable(h_accel);

Button not updating

I have an application, a game, that I've been working on and I stuck with a button not been (visually) updated.
The button is a pause button. When the app starts it is disabled (has WS_DISABLED style), but when the user starts a game, I simply remove that style responsable to disable it (WS_DISABLED).
The problem is: the button remains (visually) with the disabled style (when removing the style).
Or remains (visually) with the enable style (when adding the style).
However, the button is correctly updated when I click in it. I assume that this is a repaint/update issue.
I tried to repaint the window (no sucess):
RedrawWindow(hWnd,NULL,NULL,RDW_ALLCHILDREN | RDW_UPDATENOW);
Here is the code fragment located in WinProc function:
switch (message) {
case WM_CREATE:
CreateControls(hWnd);
break;
case WM_COMMAND:
{
switch (HIWORD(wParam)) {
case BN_CLICKED:
switch (LOWORD(wParam)) {
case 3:
{
char text[50];
GetDlgItemTextA(hWnd, 3, text, 50);
HWND pauseB = GetDlgItem(hWnd, 4);
LONG style = GetWindowLong(pauseB, GWL_STYLE);
if (strncmp(text, "Start", strlen(text)) == 0) {
SetDlgItemTextA(hWnd, 3, "Stop");
SetWindowLong(pauseB, GWL_STYLE, style & ~WS_DISABLED);
std::thread bt(RunGame, hWnd);
bt.detach();
} else {
SetDlgItemTextA(hWnd, 3, "Start");
SetWindowLong(pauseB,GWL_STYLE,style | WS_DISABLED);
}
RedrawWindow(hWnd,NULL,NULL,RDW_ALLCHILDREN | RDW_UPDATENOW);
//SendMessage(hWnd, WM_PAINT, NULL, NULL);
}
default:
break;
}
break;
default:
break;
}
}
break;
// other cases...
}
I may confess that I don't know much about c++. So sorry for my mistakes.

SendMessage in win32 project has different result

I have a win32 project that has 2 text windows(inputArea, outputArea) and 2 buttons(sendButton and ResetButton).
My problem is that when I press Reset I want to clear the text from both areas, and the inputArea gets cleared but the outputArea gets colored.
Here is the code I have tried:
case IDC_ResetButton:
{
SendMessage(hwndInputArea, WM_SETTEXT, NULL, NULL);
SendMessage(hwndOutputArea, WM_SETTEXT, NULL, NULL);
break;
}
my intial inputArea:
my initial outputArea:
And here is what happens to outputArea when I press Reset:
Also, I tried each line of code separately and they work, but when I put both of them I get this result of the outputArea and I can't find out why.
Thank you in advance.
I guess that is editcontrol.
There are three options of color for that.
・text color
・background color
・drawing brush
HBRUSH CXxxDlg::OnCtlColor( CDC* pDC, CWnd* pWnd, UINT nCtlColor ) {
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
pDC->SetTextColor(RGB(0,0,0));
pDC->SetBkColor(RGB(192,192,192)); // …(1)
HBRUSH hbrOrg = static_cast<HBRUSH>(GetStockObject(GRAY_BRUSH)); // …(2)
return hbrOrg;
}
(1)(2)… make the same color
try to get the handle of you edit control each time on your button case like this (Change IDC_EDIT1 and 2 to your edit control ID):
case IDC_ResetButton:
{
hwndInputArea = GetDlgItem(hwndDlg,IDC_EDIT1);
hwndOutputArea = GetDlgItem(hwndDlg,IDC_EDIT2);
SendMessage(hwndInputArea, WM_SETTEXT, 0, NULL);
SendMessage(hwndOutputArea, WM_SETTEXT, 0, NULL);
break;
}

Using WINAPI how do I change the value of a checkbox button?

Currently I have a checkbox created in WM_CREATE:
hwndButtonPollFlag =
CreateWindow(
TEXT("BUTTON"),
TEXT(sA.getMonitor(monitorSelected)->szDevice),
WS_CHILD | WS_VISIBLE | SS_WHITERECT | BS_CHECKBOX,
0,
0,
0,
0,
hwnd,
(HMENU)IDB_PollFlag,
hInstance,
NULL);
I am trying to change it's value whenever another button is clicked with:
if (sA.getScreenArray(monitorSelected)->getPollFlag())
{
SetWindowLongPtr(hwndButtonPollFlag, GCL_STYLE, WS_VISIBLE | BST_CHECKED);
}
else
{
SetWindowLongPtr(hwndButtonPollFlag, GCL_STYLE, WS_VISIBLE | BST_UNCHECKED);
}
SetWindowText(hwndButtonPollFlag, TEXT(sA.getMonitor(monitorSelected)->szDevice));
This does change the text displayed next to the checkbox but not the actual state of the button. Also I would like the checkbox to have only two states (checked or unchecked) is there any other way to create that effect other than in the button return have something along the lines of:
switch (HIWORD(wParam))
{
case BST_CHECKED:
sA.getScreenArray(monitorSelected)->setPollFlag(true);
return 0;
case BST_INDETERMINATE:
if (sA.getScreenArray(monitorSelected)->getPollFlag())
{
SetWindowLongPtr(hwndButtonPollFlag, GCL_STYLE, WS_VISIBLE | BST_UNCHECKED);
}
else
{
SetWindowLongPtr(hwndButtonPollFlag, GCL_STYLE, WS_VISIBLE | BST_CHECKED);
}
return 0;
case BST_UNCHECKED:
sA.getScreenArray(monitorSelected)->setPollFlag(false);
return 0;
}
EDIT: As Mark Ransom said I used messages with the BM_GETCHECK and BM_SETCHECK flag as so:
case IDB_MONITOR:
monitorSelected = LOWORD(lParam);
if (sA.getScreenArray(monitorSelected)->getPollFlag())
{
SendMessage(hwndButtonPollFlag, BM_SETCHECK, BST_CHECKED, NULL);
}
else
{
SendMessage(hwndButtonPollFlag, BM_SETCHECK, BST_UNCHECKED, NULL);
}
SetWindowText(hwndButtonPollFlag, TEXT(sA.getMonitor(monitorSelected)->szDevice));
return 0;
case WM_COMMAND:
//sA.getScreenArray(monitorSelected)->setPollFlag(LOWORD(lParam));
switch (LOWORD(wParam))
{
case IDB_PollFlag:
if (SendMessage(GetDlgItem(hwnd, IDB_PollFlag), BM_GETCHECK, 0, 0) == BST_CHECKED)
{
SendMessage(hwndButtonPollFlag, BM_SETCHECK, BST_CHECKED, NULL);
sA.getScreenArray(monitorSelected)->setPollFlag(true);
}
else {
SendMessage(hwndButtonPollFlag, BM_SETCHECK, BST_UNCHECKED, NULL);
sA.getScreenArray(monitorSelected)->setPollFlag(false);
}
break;
}
return 0;
You need to send the BM_SETCHECK message.
SendMessage(hwndButtonPollFlag, BM_SETCHECK, BST_CHECKED, 0);
BST_CHECKED and BST_UNCHECKED aren't window styles, they're simply flag values used by the CheckDlgButton and IsDlgButtonChecked API functions. CheckDlgButton is the function to call to change its state.
(Or, you can send BM_SETCHECK and BM_GETCHECK messages directly to the button for the same effect).

Right Click on ListView WinAPI C++

I have a window with a listview which I would like to right click an entry in the listview and have certain options displayed in a context menu. I cant find any examples for C++. The similar question is here but this is for listbox and i cant make it work in my program
So far I could not find any examples for c++ online. I could make it work for WM_LBUTTONDOWN on my main window but not on listview. Anyway, this is my code which i cant make it work:
case WM_CONTEXTMENU:
if ((HWND)wParam == hWndListView) {
POINT cursor;
GetCursorPos(&cursor);
TrackPopupMenu((HMENU)GetSubMenu(LoadMenu(hInst, MAKEINTRESOURCE(IDR_CONTEXT)), 0), TPM_LEFTALIGN | TPM_RIGHTBUTTON, cursor.x, cursor.y, 0, hWnd, NULL);
}
break;
Any advise? Thanks
Answer:
case WM_NOTIFY:
// When right button clicked on mouse
if ((((LPNMHDR)lParam)->hwndFrom) == hWndListView)
{
switch (((LPNMHDR)lParam)->code)
{
case NM_RCLICK:
{
POINT cursor; // Getting the cursor position
GetCursorPos(&cursor);
// Creating the po-up menu list
TrackPopupMenu((HMENU)GetSubMenu(LoadMenu(hInst, MAKEINTRESOURCE(IDR_CONTEXT)), 0), TPM_LEFTALIGN | TPM_RIGHTBUTTON, cursor.x, cursor.y, 0, hWnd, NULL);
}
break;
}
break;
}
break;
This works under WndProc