I am creating an application that can get text from the selected rectangle on any window. So I am doing this by hooking the ExtTextOut(A/W), TextOut(A/W), DrawText(A/W) apis.
I am able to retrieve the text from windows but in some special cases I am not able to get the text properly.
When I tried to debug it I saw that the HDC parameter of ExtTextOutW can not been used to get the HWND, because when I try to call WindowFromDC(hdc), it returns NULL HWND.
I tried to find out the reason then I found that this HDC is memoryDC so is there any way to get the HWND from that memory DC.
So Please somebody help me to get the actual HWND from the HDC.
I think you will have to follow that HDC as it is likely that it will be BitBlt(), or similar, to a HDC that is associated with an actual HWND:
cache the text written to memory HDCs
hook BitBlt(), and others, and check if the the source HDC of the BitBlt() is one of the memory HDCs that has had text written to it. If it is, check if the destination HDC has a HWND and if not then it is a memory HDC which must again be followed
Related
Every example code I have seen are GetDC and ReleaseDC being called again and again. Or BeginPaint and EndPaint.
But I think drawing on the screen happens very frequently (especially in a game), so storing the drawing in memory is better than getting and releasing device contexts all time.
So I went the route of getting a DC and "keeping it", only releasing it when the program ends. But why don't people do it like this? Is it because GetDC and ReleaseDC cost very little?
case WM_CREATE:
hdc = GetDC(hWnd); //hdc is declared as global HDC
MyBitmap = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BITMAP1));
return 0;
case WM_PAINT:
MemDC = CreateCompatibleDC(hdc);
OldBitmap = (HBITMAP)SelectObject(MemDC, MyBitmap);
BitBlt(hdc, 0, 0, 300, 300, MemDC, 0, 0, SRCCOPY);
SelectObject(MemDC, OldBitmap);
DeleteDC(MemDC);
return 0;
The code you presented here is wrong. First off, you need to read a little more of the documentation. Here is a useful link: Painting and Drawing. Basically there are two ways to update a window:
In response to the WM_PAINT message. Use the BeginPaint and EndPaint functions to paint the client area properly. This message is sent by the system when a part of the client area is "invalidated" (as a result of resizing, restoring from minimized state, moving a window previously obscured, or programmatically invalidating it.) WM_PAINT is a low-priority message, received just before the message-queue gets empty.
Specifically drawing a part or the whole client area without having an invalidated region on it. Use GetDC and ReleaseDC for this. Useful if you want to make changes immediately visible, when the application (CPU) is busy.
Writing some code to process the WM_PAINT message is normally almost mandatory, while specifically drawing as well is optional, depending on the requirements of your application.
Never send or post a WM_PAINT message yourself, instead invalidate a part or the client area - the application will receive a WM_PAINT message before becoming idle. If you want the painting to occur immediately call UpdateWindow - this bypasses the message queue.
A recent (Aug 2016) security update in Windows 10 prevents the reuse of printer device contexts. After printing one document Windows 10 will refuse to print again with that same DC. It has always been a preferred practice to create a new DC for each document, but now it seems to be a requirement in Windows 10.
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!
I'm a bit confused by the MSDN page for WM_PRINTCLIENT and related functionality in a few ways:
What value should I return from my window procedure? The documentation is missing a "Return value" section entirely. (It is also missing in the Visual Studio 2012 offline documentation disc's version of the page.) Raymond Chen's original scratch program returns zero; is this the preferred option?
The summary and Remarks section for WM_PRINTCLIENT indicates that I should only draw the client area, but the LPARAM lists all the possible WM_PRINT flags — so what should I do, ignore it and unconditionally draw just the client area or draw everything requested? (My intention with this question is not to second-guess the documentation; I'm just looking to implement this message correctly.)
I want to, as a convenience/kindness, provide the WM_PAINT with DC in wParam functionality mentioned in the WM_PAINT documentation as an option as well. How should I interpret LPARAM in this case? Or is there a reason I shouldn't provide this alternative route? (Corollary: if LPARAM is to be ignored, should I draw the entire client area unconditionally?)
Thanks.
Update Rephrasing the third part:
The documentation for WM_PAINT includes the paragraph
For some common controls, the default WM_PAINT message processing checks the wParam parameter. If wParam is non-NULL, the control assumes that the value is an HDC and paints using that device context.
I would like to provide this behavior in my control in addition to WM_PRINTCLIENT for completeness's sake. Is there a reason I should NOT do so? And if doing so wouldn't hurt, how should I interpret the lParam, and should I draw the entire client rect?
What value should I return from my window procedure?
You return 0 to indicate that the message was handled. Do not call DefWindowProc().
but the LPARAM lists all the possible WM_PRINT flags
That was a bit sloppy, a copy/paste fumble from the WM_PRINT article. The only flags you should test are PRF_ERASEBKGND, but only if you draw method requires having the background painted, and PRF_CLIENT, which will always be set in common usage of the message.
How should I interpret LPARAM in this case?
Hard to decode that question, WM_PAINT doesn't use the lparam argument. But yes, you want a common function that implements the painting so you can call it both from your WM_PAINT and your WM_PRINTCLIENT message handlers. Boilerplate code in your window procedure ought to look like:
case WM_PAINT: {
HDC hdc = BeginPaint(hWnd, &ps);
Draw(hdc);
EndPaint(hWnd, &ps);
break;
}
case WM_PRINTCLIENT: {
HDC hdc = (HDC)wParam;
DWORD flags = (DWORD)lParam;
if (flags & PRF_ERASEBKGND) SendMessage(hWnd, WM_ERASEBKGND, (WPARAM)hdc, NULL);
if (flags & PRF_CLIENT) Draw(hdc);
break;
}
Where void Draw(HDC hdc) is your common paint function.
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.)
I have an HDC object and I'd like to use it to get the name of the program that created it (such as Notepad or Firefox). Is there a way to do this?
If not, how can I do this?
WindowFromDC to get the window handle from the HDC
GetWindowThreadProcessId to get the process ID from the window handle
OpenProcess to obtain a process handle from the process ID
GetProcessImageFileName to obtain the program's path from the process handle
Or, once you have the window handle, GetWindowText to get the window title.