How to set text on "another" win32 application - winapi

I am using spy++ and see that the control I have has the decimal that matches the hex(after conversion of course) in spy++ and I see the parent window matches as well so I have the IntPtr for a Label and IntPtr for the form/window but my SendMessage is not working to change the text in the target application.
Another approach may be may be to do something like this post but what is the control id and how do I get that
SetText of textbox in external app. Win32 API
I assume the hWnd here needs to be the controls hWnd, correct?
SendMessageCall(hWnd, WM_SETTEXT, (IntPtr)value.Length, value);
I notice that getting the text IS WORKING
SendMessageCall(hWnd, WM_GETTEXT, (IntPtr)sb.Capacity, sb);
and I notice that I get the test, see the correct value, set the text yet it doesn't change and then get the text again using SendMessage AND it is the new value but the application still shows the wrong value....hmmm, do I need to send a repaint message maybe and if so, what is the code for that?
thanks,
Dean

You don't send a window message to force repaint, instead you call InvalidateRect(hWnd, NULL, TRUE).

Related

WinAPI How to Apply Edit field text change?

I'm working with 3d party application. Changing a text in Edit control using
SendMessageW(m_edit_handle,WM_SETTEXT,0,str_address);
And it works fine.. It changes visually in the window. But once I click a button (also programmatically) it works as there is a default value but not the one I set with SendMessageW.
Just wondering if after changing the text in Edit window I have to call some other method to force Windows to update the actual value in the field?
Depending on how the target app is coded, you may need to issue an EN_CHANGE notification to the Edit's parent window. Sending WM_SETTEXT will not send that notification, as it is meant to be sent when the user makes changes to the Edit's content, not when code does.
SendMessageW(m_edit_handle, WM_SETTEXT, 0, str_address);
SendMessageW(GetParent(m_edit_handle), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(m_edit_handle), EN_CHANGE), LPARAM(m_edit_handle));

How to use Win32API SendMessage to change Save Dialog File Location?

I am writing a program that automates saving data to a specific location, based on the common Save/Save As dialog.
There are two attacking approaches. Both approaches require monitoring handles for messages under Spyxx (so essentially we are trying to replicate the SendMessage)
The first approach to set the File Name with target path, using Win32 SendMessage API. The HWnd in this case is the Edit field next to the File name.
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, [MarshalAs(UnmanagedType.LPStr)] string lParam);
SendMessage(HWnd, (int)WindowMessage.WM_SETTEXT, IntPtr.Zero, #"Address: %UserProfile%\Desktop\Target.txt");
The problem with this approach is that, it does not always set the text under Windows 7 and Windows 8.1 (I do have better luck with Windows 10). I tried to set some waiting time, but no matter how long I wait, it doesn't seem to matter (besides SendMessage is synchronous operation, so text should be set, or not set at all)
The second approach is to set the Location at the top of the dialog box. Again, we are using SendMessage to accomplish this, and HWnd in this case, references the ToolbarWindow32 object, which is the child of Breadcrumb Parent object.
SendMessage(HWnd, (int)WindowMessage.WM_SETTEXT, IntPtr.Zero, #"Address: %UserProfile%\Desktop");
or
SendMessage(HWnd, (int)WindowMessage.WM_SETTEXT, IntPtr.Zero, #"Address: Desktop"); // replicated message found on Spyxx
Unfortunately, this approach does not seem to work (i.e. I can send the message, but Dialog doesn't change its location), and I have yet to figure out what steps I am missing.
My question, how do you use Win32 API to interact with the 3rd party app's Save As dialog, so that you can guarantee saving the file in the desired location? Much appreciated and thanks for reading!

Sending WM_HSCROLL to other program

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.

how to send a key stroke window message to a hwnd through JNA

I am just wondering if anyone could please give an example of sending a key press window message to a given hwnd using JNA. I tried to use SendMessageA but it did not work at all.
Thanks a lot.
SendInput() is the officially sanctioned way to fake input. The limitation is that it sends input to the window that has input focus which may not be what you need.
Another option would be to send a WM_SETTEXT, or similar, if the target window responds appropriately.
Exactly what the best option is will depend on exactly what type of window you are targetting, which you have not said.

What Windows message is sent to repaint a partially occluded window?

I know that WM_PAINT tells a window that it needs to repaint itself entirely, but apparently that's not the message that gets sent when it's been covered partially and then the window that was in front of it is no longer in the way and it needs to repaint the dirty portion. Does anyone know what message is sent in this case?
EDIT: Found the problem:
The issue involved a Delphi control I wrote to embed a SDL rendering surface on a Delphi form. SDL has an API to build its renderer on another window's HWND, and it marks it as a "foreign window".
SDL usually handles WM_PAINT internally, so I ended up having to add some code to SDL's WindowProc to forward the message on to the external WindowProc if it's a foreign window. That was working sometimes, but it turns out there was a glitch that was stripping the foreign window flag from the window's data structure, so it was swallowing the message instead of passing it on to my app. Once I fixed that, I started getting the WM_PAINT messages all the time.
Why do you say it's apparently not? WM_PAINT should be called for partial redraws (the updated rect is returned by BeginPaint or GetUpdateRect). If it doesn't appear to be getting called, there may be a bug elsewhere in your app that's preventing it. What are you seeing that leads you to believe that it's not working?
WM_PAINT is sent to indicate that some portion (including the entirity) of the window needs to be repainted.
Call GetUpdateRect() to get a rectangle that bounds the region to be updated. This information is also included in the PAINTSTRUCT (as the rcPaint field) passed to BeginPaint().
The BeginPaint() function returns the rect that requires validation in its 2nd parameter: http://msdn.microsoft.com/en-us/library/dd183362(VS.85).aspx
case WM_PAINT:
{
PAINTSTRUCT psPaint;
HDC hdc = BeginPaint( hwnd, &psPaint );
// psPaint.rcPaint contains invalidated area
EndPaint (hwnd, &psPaint);
}
return 0;
Look at psPaint.rcPaint : http://msdn.microsoft.com/en-us/library/dd162768(VS.85).aspx
I'm pretty certain the Win32 API uses WM_PAINT even for partial repaints. From MSDN:
The WM_PAINT message is sent when the system or another application makes a request to paint a portion of an application's window. [My italics].
That link has the full detail on WM_PAINT but if, as you say, the WM_PAINT message is not being sent for partial redraws, the Spy++ is the tool you need to find out for sure.
Take a look at WM_PRINTCLIENT. There are some circumstances when WM_PAINT is not sent and a WM_PRINTCLIENT message is sent instead. (AnimateWindow for example.)

Resources