What Windows API function can I use to get text within a dialog? For example, if I had the handle of an error message dialog, how could I get the displayed error message?
If I correctly understand your question, your problem is very easy. Open Spy++ from the Visual Studio Tools menu. Then press Ctrl + F to receive a dialog for finding windows. Drag & drop the "Finder tool" on the control inside the dialog box from which you want to read the text; look at properties of the window, the field "Control ID" is what you need.
If you have a handle of the Dialog Window (HWND hDlg) you should use the GetDlgItemText function (see http://msdn.microsoft.com/en-us/library/ms645489(VS.85).aspx)
UINT GetDlgItemText(HWND hDlg,
int nIDDlgItem,
LPTSTR lpString,
int nMaxCount
);
to read the text. As a nIDDlgItem parameter you should place the identifier of the control. It is the value which you have found using Spy++.
Dialog boxes don't actually contain text - they contain other controls which contain the text. You must enumerate or otherwise find the appropriate child window of the dialog box, and get its text with GetWindowText.
Related
Something I thought would be easy I can't get to work. How do I get a ComboBox to show on the CMFCToolBar? Here's what I have done that doesn't work (meaning it just shows the original placeholder button with the circle (grayed out)).
1 - I added a button to the toolbar in resource editor giving it the id ID_EDIT_FIND_COMBO (I also put a circle in it just to know it's in use).
2- in CMainFrame I added ON_REGISTERED_MESSAGE(AFX_WM_RESETTOOLBAR, OnToolbarReset) to message map and the OnToolbarReset() function below:
afx_msg LRESULT CMainFrame::OnToolbarReset(WPARAM wparm, LPARAM )
{
UINT uitoolbarid = (UINT) wparm;
if (uitoolbarid == IDR_MAINFRAME) {
CMFCToolBarComboBoxButton btncombo(ID_EDIT_FIND_COMBO, GetCmdMgr()->GetCmdImage(ID_EDIT_FIND));
m_wndToolBar.ReplaceButton(ID_EDIT_FIND_COMBO, btncombo);
}
return 0;
}
The ReplaceButton() returns 1 saying it replaced it.
What am I missing?
To be clear, here's what MS says to do which is what is done above:
1 - Reserve a dummy resource ID for the button in the parent toolbar resource. For more information about how to create buttons by using the Toolbar Editor in Visual Studio, see the Toolbar Editor article.
2 - Reserve a toolbar image (button icon) for the button in all bitmaps of the parent toolbar.
3 - In the message handler that processes the AFX_WM_RESETTOOLBAR message, do the following steps:
a. Construct the button control by using a CMFCToolbarButton-derived class.
b. Replace the dummy button with the new control by using CMFCToolBar::ReplaceButton. You can construct the button object on the stack, because ReplaceButton copies the button object and maintains the copy.
TIA!!
Here's a sample project where it doesn't work. Just the button on the toolbar, not a combobox. Even took code sample from MS sample.
Sample Project
The answer is that MFC caches the toolbar so if you ever run it without the combo, once you replace the button to use the combo it still doesn't use it. You can make it pick up the change by either going to customize for the toolbars (if you have that option enabled) and choose Reset All, otherwise, you'll find under Computer\HKEY_CURRENT_USER\Software\{NameAsUsedInSetRegistryCall}\{appname}\Workspace all the cache items, of which the various MFCToolBar entries. Delete the key and run app again, then it works. Why they wouldn't make it smart and have a timestamp to know if to automactially update, not sure?
I am a newbie in Xlib world. In my project,I want to share my window to another via Remote desktop protocol, but they only saw content of window and didn't see anything if click on menu item of window. I used XGetImage to get data of specifies window. But If that window contain dialog ( see image here) I couldn't get data of dialog .
I use freeRDP source code, I modify in X11_shadow.c
function:
int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem){
...
image = XGetImage(subsystem->display, 58720435, 0, 0, surface->width,
surface->height, AllPlanes,ZPixmap); //with 58720435 is window id of chrome
... }
In my opinion, the most important here is how can I get data of dialog in Window. I have a solution :
1. get window id of that dialog ( I am not sure the dialog has owner Window ID)
2. Use XGetImage get data of that dialog.
But It's not working.
I works on Linux environment.
Are there any solutions for my problems?
Thank you very much
In most applications, when you click some MenuItem, a WindowsMessage is sent (usually WM_COMMAND), with a wParam representing the ID of the chosen MenuItem.
There is a certain program that has a Window Menu (the menu accessible via clicking the program's icon on the title-bar),
and I want to find what is the WindowsMessage that is sent when I choose a specific MenuItem from that Menu.
The program is soething you all know - the Command Prompt window, in Windows XP:
(cmd.exe)
And here is the Window Menu:
I want to capture the WindowsMessage and wParam for a MenuItem there,
for example the "Paste" MenuItem.
(but not just it.. any other might be as well)
Here is what I tried:
Method 1:
The first method I always try is to use Spy++.
The problem is that when I try to Log Messages for this specific program (the DOS window), Spy++ gives me this messagebox:
For some reason Spy++ won't capture WindowsMessages for this program.
So I went on to the second method that I use..
Method 2:
Resource Hacker (ResHacker.exe) is also good for finding the WindowsMessage that is sent from clicked MenuItems, and it does it quite easily.
If you run Resource Hacker, and then Open some EXE file with it,
you usually see these trees, which one of them is called "Menu",
and it contains all the details including the wParam:
The problem is, that when I try to use Resource Hacker on cmd.exe,
I get this:
As it can be seen, no "Menu" tree there.
My question:
Are there other ways, in addition to the 2 methods that I usually use,
that can be used to find the WindowsMessage (and wParam) that is sent for the "Paste" MenuItem in the Window Menu of the DOS window?
0xfff1 is the wParam, so in C# (you didn't specify the language you were using, but it should be easy enough to translate it):
[DllImport("User32.dll")]
public static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, uint lParam);
public const int WM_KEYDOWN = 0x01000;
void PasteInCommandPrompt(IntPtr hWnd)
{
SendMessage(handle, WM_COMMAND, 0xfff1, 0);
}
http://blogs.msdn.com/b/bill/archive/2012/06/09/programmatically-paste-clipboard-text-to-a-cmd-window-c-or-c.aspx
Edit: 22 September 2019
In the comments of Console window - programmatic command code (wParam of WM_COMMAND) (a question where a user was using the above link to Bill Lin's blog, but having trouble getting it working), #eryksun gave me the idea of looking for a ConvhostV2.dll.mui to find the all available menu commands. I couldn't find ConvhostV2.dll.mui...
But on my system I found C:\Windows\System32\en-US\ConhostV1.dll.mui, which when viewed with Resource Hacker (as #spaceman tried with cmd.exe), contains all the menu items available for cmd.exe.
The complete list of commands cmd.exe has are:
0xfff0: Copy
0xfff1: Paste
0xfff2: Mark
0xfff3: Scroll
0xfff4: Find
0xfff5: Select all
Besides paste (which allows you to execute arbitrary commands), select all and copy are very useful, as they let you get console output (albeit, stripping all virtual terminal sequences, the characters that specify text color).
If you are going deep into the route of manipulating command windows you may also be interested in the new "Windows Pseudo Console", which can let you have full control over cmd.exe, or any command line based application. See https://devblogs.microsoft.com/commandline/windows-command-line-introducing-the-windows-pseudo-console-conpty/ .
I did a SetFocus to a button in a dialog. The button gets the dashed outline. When the user presses the return key, the dialog get a IDOK message rather than a message from the button were I set the focus. The same thing happens under other circumstances.
Why is this happening? And how can I cause the return to act as a button press?
Plain c++ windows app, no MFC, no NET.
Feature, not a bug. The [Enter] key operates the button that's marked as the default button for a dialog. Either with the DEFPUSHBUTTON in the .rc file or the BS_DEFPUSHBUTTON style flag. Which is typically the "OK" button so getting IDOK back is expected. The [Escape] key is special that way too, typically the [Cancel] button. This is bound to ring a bell if you think back on how you used dialogs before.
You click a button that has the focus by pressing the space bar instead.
In another SO question I found KB article that might help you:
If a dialog box or one of its controls currently has the input focus,
then pressing the ENTER key causes Windows to send a WM_COMMAND
message with the idItem (wParam) parameter set to the ID of the
default command button. If the dialog box does not have a default
command button, then the idItem parameter is set to IDOK by default.
When an application receives the WM_COMMAND message with idItem set to
the ID of the default command button, the focus remains with the
control that had the focus before the ENTER key was pressed. Calling
GetFocus() at this point returns the handle of the control that had
the focus before the ENTER key was pressed. The application can check
this control handle and determine whether it belongs to any of the
edit controls in the dialog box. If it does, then the user was
entering data into one of the edit controls and after doing so,
pressed ENTER. At this point, the application can send the
WM_NEXTDLGCTL message to the dialog box to move the focus to the next
control.
According to MSDN,
Dialog Box Keyboard Interface
The system provides a special keyboard interface for dialog boxes that carries out special processing for several keys. The interface generates messages that correspond to certain buttons in the dialog box or changes the input focus from one control to another. Following are the keys used in this interface and their respective actions.
...
ENTER: Sends a WM_COMMAND message to the dialog box procedure. The wParam parameter is set to IDOK or control identifier of the default push button.
Since the system intercepts and processes ENTER key pressed directly through the dialog, you'll need to handle it in your dialog box procedure by calling GetFocus() to first see which control has the focus, and perform the appropriate action for that particular control.
Im trying to scroll other program (PowerPoint 2013) by sending WM_HSCROLL,
and it will work only if I offer the correct LPARAM (not NULL) to SendMessage.
The value of LPARAM is dynamic, it will change if you close and open a new program.
Now I can only get its value by hooking WM_HSCROLL and clicking scroll bar manually.
// This is my code:
LPARAM lParam = 0x0a616c38; // Found by hooking WM_HSCROLL
SendMessage(hTarget, WM_HSCROLL, SB_LINERIGHT, lParam);
So is it possible to get the correct LPARAM programatically?
Many thanks!
p.s. The scroll bar is not a real window in PowerPoint 2013.
p.s. It returns 1 if I use GetScrollInfo(hTarget, SB_CTL, &scrollinfo), but all values inside scrollinfo are zero.
p.s. Office Home and Student 2013 Official Site
Did you try to call GetLastError?
GetScrollInfo will probably not work across process boundaries, so I would say that's why you're not getting valid values back.
The lParam value of a WM_HSCROLL message is either NULL for the standard window scroll bar, or the handle of the scroll control. The handle of the scroll control will obviously change every time the program is run, so you need to find that out yourself before you can reliably simulate scroll input.
To do this, you can use the FindWindowEx function to search the parent window (hTarget in your example) for child windows of class "SCROLLBAR". As you will probably find more than one scrollbar child window you'll need some way to tell them apart - most probably, via the window's GWL_ID value as this will probably not change from run to run.