Currently there are several ways to get a ChildWindow handle; FindWindowEx (uses parent handle, plus window caption), GetWindow (uses parent handle, and Z-Order), and EnumChildWindows. None are satisfactory for my application.
Would like to use something like FindWindowEx, but this requires knowledge of the contents of the TextBox (caption) that's used by FindWindowsEx. This works if the TextBox contents is static, but in most cases the contents change and and would be unknown to the Application trying to find the TextBox handle.
Does anyone know of a Win32 API that would function like FindWindowEX, using the Parent Handle, but instead of the ChildWindow caption, looks for a user specified TAG property for the ChildWindow that would remain static?
The GetDlgItem function accepts the parent window handle and child item ID.
It is not limited to dialog boxes despite the name.
You can use the GetDlgItem function with any parent-child window pair, not just with dialog boxes.
Related
I've created a combobox manually in my main window using CreateWindow(). Because of this it has no ID associated with it only the handle returned by CreateWindow(). When the user makes a selection from the combobox list and the combobox throws a message, how do I handle that in the WinProc WM_COMMAND code since there is no ID associated with the combobox? As far as I can tell, I must know the combobox ID to handle the message. This is especially problematic once I have more than one combobox in the main window. Surely there is something I am missing and there is a simple answer.
Okay. So what Igor Tandetnik stated is the answer.
It does have an ID - whatever you passed for hMenu parameter of CreateWindow...
This is also discussed in the following link.
What is winapi HMENU and how do i use it?
From the above link:
HMENU is a handle to a menu, e.g. as created by LoadMenu (which creates a menu from a specification in a resource).
But, the CreateWindow function re-uses the same argument for two different purposes. With a top-level window it's a menu handle, but with a child window it's the child window id, which should be in 16-bit integer range...
When creating a child window, just cast the id to HMENU.
I've got a few questions here about control IDs:
Can they be changed at runtime by setting GWL(P)_ID? Or will the dialog manager not be fooled? Since this is a framework, I need to generate them at runtime; initially they are 0.
What is the uniqueness scope of control IDs, the whole toplevel window or just the immediate parent of a control? Controls in my framework are stored in a custom container window, there are multiple such in each toplevel window.
Thanks.
Question 1
Control IDs can be changed by calling SetWindowLongPtr:
SetWindowLongPtr(hwndChild, DWL_ID, new_id);
Question 2
From the documentation for CreateWindow, with my emphasis:
hMenu [in, optional]
A handle to a menu, or specifies a child-window identifier depending
on the window style. For an overlapped or pop-up window, hMenu
identifies the menu to be used with the window; it can be NULL if the
class menu is to be used. For a child window, hMenu specifies the
child-window identifier, an integer value used by a dialog box control
to notify its parent about events. The application determines the
child-window identifier; it must be unique for all child windows with
the same parent window.
Or from the documentation of GetDlgItem:
You can use the GetDlgItem function with any parent-child window pair,
not just with dialog boxes. As long as the hDlg parameter specifies a
parent window and the child window has a unique identifier (as
specified by the hMenu parameter in the CreateWindow or CreateWindowEx
function that created the child window), GetDlgItem returns a valid
handle to the child window.
So the scope for IDs is the parent window. But this also tells you that you can specify the ID when you create the child window via the re-purposed hMenu parameter.
I have a VB6 application with a ListView (MSCOMCTL.OCX). I need to get the window handle (hwnd) for a listviewitem, or preferably (if something like that exists) - of a specific subitem.
I know I can get the handle for the column headers using FindWindowEx and looking for the class msvb_lib_header, but I don't know how to get the handle for the item. Spy++ shows a msvb_lib_header window as the child of the listview, but does not show any other windows.
List view items and subitems are not window handles. They are internal children of the list view, exposed using the LVM_GETITEM and LVM_SETITEM messages and the LVITEM structure. (Subitems use the same interface; the iSubItem member of LVITEM would be nonzero in this case.)
ListView.ListItem object has not hwnd.
You should search ListView by class name, next use SendMessage() to send the message LVM_GETITEM and using the LVITEM structure to get info about items:
LVM_GETITEM message (Windows)
https://msdn.microsoft.com/en-us/library/windows/desktop/bb774953(v=vs.85).aspx
LVITEM structure (Windows)
https://msdn.microsoft.com/en-us/library/windows/desktop/bb774760(v=vs.85).aspx
this reference page may help you:
List-View Control Reference (Windows)
https://msdn.microsoft.com/en-us/library/windows/desktop/ff485973(v=vs.85).aspx
In an MFC program I am trying to access controls that are in one window (class) from another (sibling or daughter) window with code in a different .cpp file. Typically you access a control with a DDX_Control variable defined in the class .cpp file.
DDX_Control(pDX, IDC_STATUS, m_Status);
The code for the other window is in a different file, so I don’t have access to the control variable (m_Status). What I have done is used FindWindow to find the main window, then GetDlgItem to find the control I am interested in:
CWnd * tmpWnd = CWnd::FindWindow(NULL,"MainWindow"); // find the main dialog box
CStatic * tmpStatus = (CStatic*) tmpWnd->GetDlgItem(IDC_Status);
tmpStatus->SetWindowText(“Status Report);
This works fine in the debugger, but fails when executed outside the debugger. FindWindow gets the window ID correctly, but GetDlgItem returns null.
Ideally I’d like to access the control variable (m_Status) from the other window, but I don’ know how to do so. I understand the GetDlgItem is less than ideal under any circumstance.
One solution would be to send a message to the main window class and tell it what to do, but I’d have to have a routine to handle each control and know how to handle whatever kind of data I am sending.
Is there a “right” way to do this?
Thank you
The ultimate answer is to cast to the original class:
((CspDlg *)AfxGetMainWnd())->m_Status.SetWindowText("Report");
Since you created the "main" window you have an object or pointer for it. Or, you can call AfxGetMainWnd() to get a pointer to it. Then you can use that to access a public member such as m_Status. All of your windows are interconnected and it should not be necessary to use FindWindow to find any window in your own program.
The fact that some variables may be defined in another file is not relevant. That can be handled with suitable use of #include "theotherfile.h" and object pointers/references.
I'm learning Win32 assembly. Have some question I search but not suitable result.
Anyone can explain for me What difference between control's window handle and controlID.
They have nothing in common. Every window has a handle, returned by CreateWindowEx(). Such a window can have a few extra properties attached, like a menu handle. The hMenu argument in CreateWindowEx(). If the window doesn't have a menu, a child window won't have one, then you can use that argument to pass an arbitrary other bit of data. It will be assigned to the GWLP_ID property (see GetWindowLongPtr). Also note the GWLP_USERDATA, an extra property that's entirely yours to use as you see fit.
Dialogs take advantage of this, a dialog template that you create in the resource editor gives you a way to number the child controls. With a helper function like GetDlgItem() to get the handle back for a control with a specific number. Which is pretty necessary for dialogs since it is Windows that create the child controls from the dialog template so you don't know the window handles for them yourself.