listbox not populating correctly - c++

This is my first posting here, i am trying to learn to program a win32 GUI in code blocks 12.11, but here is the problem,
I have got 2x list boxes on a dialog box window(IDC_LISTP > Personal Project Notes) and (IDC_LISTS > Shared Project Notes),
The (personal project notes) auto populates on the dialog been created, i can also get the (Shared project notes) to populate from the correct folder too(update shared).
The problem arises when i click the button(update personal) after clicking the(update shared ), it loads the contents of (shared project notes) into the(personal project notes) list box, even after using the clear button too, this still populates (the personal project notes) when clicking the (update personal)button,
how do i stop from this from happening???
please could someone help me resolve this problem, has i have been banging my head against a wall for days now,
This is the code i have been currently experimenting with, please excuse the messy code, as most of it is from examples that i have converted to suit my GUI.
additional posts http://forums.codeguru.com/showthread.php?540733-win32-listbox-not-populating-right with pics too
BOOL CALLBACK DlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam){
switch(Message){
case WM_INITDIALOG:
CheckRadioButton(HWND (hwnd),IDRADIO, IDRADIO2, IDRADIO);
{
DlgDirList(HWND (ID_PROJECT_PROJECT_NOTES), pbuffer, IDC_LISTP, 0, DDL_EXCLUSIVE);
HWND hListBox = GetDlgItem(hwnd, IDC_LISTP);
SendMessage(hListBox, LB_DIR, 0, (LPARAM)("*.txt*"));
}
break;
case WM_COMMAND:
switch(LOWORD(wParam)){
case ID_UPDATEP:{
SendDlgItemMessage(HWND(hwnd), IDC_LISTP, LB_RESETCONTENT, 0, 0);
DlgDirList(HWND (ID_PROJECT_PROJECT_NOTES), pbuffer, IDC_LISTP, 0, DDL_EXCLUSIVE);
HWND hListBox = GetDlgItem(hwnd, IDC_LISTP);
SendMessage(hListBox, LB_DIR, 0, (LPARAM)("*.txt"));
}
break;
case ID_UPDATES:{
SendDlgItemMessage(HWND(hwnd), IDC_LISTS, LB_RESETCONTENT, 0, 0);
DlgDirList(HWND (ID_PROJECT_PROJECT_NOTES), sbuffer, IDC_LISTS, 0, DDL_EXCLUSIVE);
HWND hList = GetDlgItem(hwnd, IDC_LISTS);
SendMessage(hList, LB_DIR, 0, (LPARAM)("*.txt"));
}
break;
case IDCLEAR:
SendDlgItemMessage(HWND(hwnd), IDC_LISTP, LB_RESETCONTENT, 0, 0);
SendDlgItemMessage(HWND(hwnd), IDC_LISTS, LB_RESETCONTENT, 0, 0);
break;
case IDCREATE:{
DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDPAD), NULL, DlgProc);
}
break;
case IDOK:
EndDialog(hwnd, IDOK);
break;
case IDCANCEL:
EndDialog(hwnd, IDCANCEL);
break;
}
break;
case WM_CLOSE:
EndDialog(hwnd, 0);
break;
default:
return FALSE;
}
return TRUE;
}

There are several things wrong with your code, take a look at the MSDN Docs for DlgDirList():
a) The first parameter to DlgDirList() needs to be the handle to the dialog box that contains the list box; there is no error checking in the code, I suspect that the call to DlgDirList() fails with an error
b) the docs say that DlgDirList sends the LB_RESETCONTENT and LB_DIR messages to the list box
So all you need to do is
int nResult;
nResult = DlgDirList(hwnd, pbuffer, IDC_LISTP, 0, 0);
TRACE("Filling P (ID %d) from %s: result = %d\n", IDC_LISTP, pbuffer, nResult);
nResult = DlgDirList(hwnd, sbuffer, IDC_LISTS, 0, 0);
TRACE("Filling S (ID %d) from %s: result = %d\n", IDC_LISTS, sbuffer, nResult);
Make sure that pbuffer and sbuffer each contain a path and a wildcard-string, like "C:\personal\*.txt" and "C:\shared\*.txt".
This link contains a sample of how to use DlgDirList.

Related

How to add mouse double click to ListBox

To this code: https://www.dreamincode.net/forums/topic/163804-microsoft-working-with-listboxes-part-i/
It is displaying list and looping nicely.
Sadly my guru never finished his code.
So plan would be adding double click detection on a name. How?
case WM_COMMAND:
{
return 0;
}
Something like this? 11 is this child window where names are.
case WM_COMMAND:
{
if (LOWORD(wparam) == 11) {
if ((message) == LBN_DBLCLK) {
cout << "double click" << endl;
}
}
return 0;
}
Doesn't work
First, according to the documentation:
Parameters
wParam
The LOWORD contains the identifier of the list box. The HIWORD specifies the notification code.
lParam
Handle to the list box.
Remarks
This notification code is sent only by a list box that has the LBS_NOTIFY style.
So in the first step you need to add this style and use HIWORD (wParam) to determine whether to double-click the list.
Then if you need to get the elements of the list, you should not send LB_GETCURSEL to window_handle, but should send it to This->listbox_handle, which is the window handle of the listbox. Then you can get it by sending LB_GETTEXT Text content.
Here is the code:
case WM_COMMAND:
{
if (HIWORD(wparam) == LBN_DBLCLK) {
TCHAR temp[100]{};
int index = SendMessageW(This->listbox_handle, LB_GETCURSEL, 0, 0L);
SendMessageW(This->listbox_handle, LB_GETTEXT, index, (LPARAM)temp);
MessageBox(window_handle, temp, L"test", 0);
}
return 0;
}
And it works for me:
Try replacing:
if ((message) == LBN_DBLCLK)
with:
if (HIWORD (wParam) == LBN_DBLCLK)
Documentation here.

Detect when any application Window is dragged to top of screen

On Windows 10 I have been experimenting with replacing the "Window snap" feature to work better with ultra wide monitors. While I have had no problem capturing the Windows Key+arrow cursors to handle the keyboard shortcut, I now want to detect when another application Window has been dragged to the top/right/left/bottom of the current monitor.
Current code:
#include <iostream>
#include <Windows.h>
HHOOK _hook_keyboard;
KBDLLHOOKSTRUCT kbdStruct;
CONST int HORIZONTAL_SLOTS = 4;
CONST int VERTICAL_SLOTS = 1;
// horizontalPosition/verticalPosition specifies which "slot" starting at 0 to place Window in
// horizontalSlots/verticalSlots specifies how many slots to divide the screen into
void MoveAndResizeActiveWindow(int horizontalPosition, int verticalPosition, int horizontalSlots, int verticalSlots)
{
// get work area on primary monitor
HWND currentWindow = GetForegroundWindow();
if (currentWindow != NULL)
{
HMONITOR currentMonitor = MonitorFromWindow(currentWindow, MONITOR_DEFAULTTONEAREST);
MONITORINFO monitorInfo;
monitorInfo.cbSize = sizeof(MONITORINFO);
if (GetMonitorInfo(currentMonitor, &monitorInfo))
{
long width = monitorInfo.rcWork.right - monitorInfo.rcWork.left;
long height = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;
long snappedWidth = width / horizontalSlots;
long snappedHeight = height / verticalSlots;
long snappedLeft = (snappedWidth * horizontalPosition) + monitorInfo.rcWork.left;
long snappedTop = (snappedHeight * verticalPosition) + monitorInfo.rcWork.top;
MoveWindow(currentWindow, snappedLeft, snappedTop, snappedWidth, snappedHeight, true);
}
}
}
LRESULT __stdcall HookCallbackKeyboard(int nCode, WPARAM wParam, LPARAM lParam)
{
BOOL bEatkeystroke = false;
short keyState;
if (nCode >= 0)
{
kbdStruct = *((KBDLLHOOKSTRUCT*)lParam);
switch (wParam)
{
case WM_KEYDOWN:
keyState = GetAsyncKeyState(VK_LWIN);
if (keyState)
{
switch (kbdStruct.vkCode)
{
case VK_LEFT:
bEatkeystroke = true;
break;
case VK_RIGHT:
bEatkeystroke = true;
break;
case VK_UP:
bEatkeystroke = true;
break;
case VK_DOWN:
bEatkeystroke = true;
break;
};
};
break;
case WM_KEYUP:
keyState = GetAsyncKeyState(VK_LWIN);
if (keyState)
{
switch (kbdStruct.vkCode)
{
case VK_LEFT:
MoveAndResizeActiveWindow(0, 0, 4, 1);
bEatkeystroke = true;
break;
case VK_RIGHT:
MoveAndResizeActiveWindow(3, 0, 4, 1);
bEatkeystroke = true;
break;
break;
case VK_UP:
MoveAndResizeActiveWindow(1, 0, 4, 1);
bEatkeystroke = true;
break;
case VK_DOWN:
MoveAndResizeActiveWindow(2, 0, 4, 1);
bEatkeystroke = true;
break;
};
}
break;
};
}
if (bEatkeystroke)
{
return 1;
}
else
{
return CallNextHookEx(_hook_keyboard, nCode, wParam, lParam);
}
}
void SetHook()
{
if (!(_hook_keyboard = SetWindowsHookEx(WH_KEYBOARD_LL, HookCallbackKeyboard, NULL, 0)))
{
MessageBox(NULL, L"Failed to install hook on keyboard!", L"Error", MB_ICONERROR);
}
}
int main(int argc, char** argv[])
{
SetHook();
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
Any suggestions how to identify when Windows have been dragged to a particular location on the screen?
As per advice in replies to original question I have tried used SetWinEventHook with the following code, planning to restrict EVENT_MIN and EVENT_MAX once correct events to watch for worked out.
g_hook_winevent = SetWinEventHook(
EVENT_MIN, EVENT_MAX,
NULL, // Handle to DLL.
HandleWinEvent, // The callback.
0, 0, // Process and thread IDs of interest (0 = all)
WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS); // Flags.
}
void CALLBACK HandleWinEvent(HWINEVENTHOOK hook, DWORD event, HWND hwnd,
LONG idObject, LONG idChild,
DWORD dwEventThread, DWORD dwmsEventTime)
{
// process event here
}
While this easily tracks start or end of a Windows move with EVENT_SYSTEM_MOVESIZESTART and EVENT_SYSTEM_MOVESIZEEND I can't see an event here that tracks the moving of Window prior to EVENT_SYSTEM_MOVESIZEEND.
While that will work if only good option, ideally I want to be able to detect Window location from start of EVENT_SYSTEM_MOVESIZESTART until EVENT_SYSTEM_MOVESIZEEND completes. Testing with notepad the only event getting raised during the move is EVENT_OBJECT_NAMECHANGE, which seems to constantly trigger during Window move, at least with Notepad. However based on description in documentation I'm not sure if this is suitable for my use case: "An object's Name property has changed. The system sends this event for the following user interface elements: check box, cursor, list-view control, push button, radio button, status bar control, tree view control, and window object. Server applications send this event for their accessible objects."

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.

GetWindowText() doesn't work

Initially I have to say that I know nothing about WinAPI. I'm learning from quite old tutorial, which seems to be a little bit outdated. I'm trying to make a dialog box where user would type in size of a next window. I've made it in Visual Studio using Resource Editor (or whatever it is called). I'm trying to retrieve data from Edit Controls, but GetWindowText doesn't work well.
So I made global LPTSTR named SizeX and SizeY (I know I could made them local and later pass them to a function that creates the second window, but I've got then problems with hInstance... nevermind).
BOOL CALLBACK SettingsProcedure(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_INITDIALOG:
{
SetWindowTextA(GetDlgItem(hwnd, IDC_EDIT1), "20"); //I'm setting default input in case the user doesn't want to write anything
SetWindowTextA(GetDlgItem(hwnd, IDC_EDIT2), "20");
}
break;
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDC_BUTTON1:
{
GetWindowText(GetDlgItem(hwnd, IDC_EDIT1), sizeX, GetWindowTextLength(GetDlgItem(hwnd, IDC_EDIT1)) + 1);
if (sizeX == NULL)
break; //breaks every time
GetWindowText(GetDlgItem(hwnd, IDC_EDIT2), sizeY, 10);
EndDialog(hwnd, IDC_BUTTON1);
}
break;
}
}
break;
default: return FALSE;
}
return TRUE;
}
I'm sure I have a lot of basic mistakes in this code, so please don't blame me :P
I have no idea how to make it work. The fantastic tutorial I use tells nothing about Edit Controls, it even has an information that it might be too old. Unfortunately that is the only WinAPI tutorial I've found in my language, if you know any good one in English I'd be glad.
the thing that you should do is use directly GetDlgItemInt to retrieve sizeX and sizeY otherwise you should get text as a string then convert it into int:
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDC_BUTTON1:
{
BOOL bCheck = FALSE;
sizeX = GetDlgItemInt(hwnd, IDC_EDIT1, &bCheck, false);
sizeY = GetDlgItemInt(hwnd, IDC_EDIT2, &bCheck, false);
// or text then convert:
int textLengthX = SendDlgItemMessage(hwnd, IDC_EDIT1, WM_GETTEXTLENGTH, 0, 0);
int textLengthY = SendDlgItemMessage(hwnd, IDC_EDIT2, WM_GETTEXTLENGTH, 0, 0);
LPSTR lpTextX = (LPSTR)GlobalAlloc(GPTR, textLengthX + 1);
LPSTR lpTextY = (LPSTR)GlobalAlloc(GPTR, textLengthY + 1);
SendDlgItemMessage(hwnd, IDC_EDIT1, WM_GETTEXT, (WPARAM)textLengthX + 1, (LPARAM)lpTextX);
SendDlgItemMessage(hwnd, IDC_EDIT1, WM_GETTEXT, (WPARAM)textLengthY + 1, (LPARAM)lpTextY);
// now you have sizeX and sizeY as strings so convert them to int:
int sizeX = atoi(lpTextX);
int sizeY = atoi(lpTextY);
GlobalFree(lpTextX);
GlobalFree(lpTextY);
}
break;
}
break;
}

How to change menu item text?

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