Finding screen co-ordinates of DrawText output.

I have written a DLL that intercepts calls to DrawTextA to read text sent by
another program to the screen, and to get the text coordinates. My problem
is that the coordinates passed to DrawTextA() are relative to the specific
device context, and I need the screen coordinates.

DrawTextA must use the HDC parameter to determine the screen coordinates at
which the text is to be printed – it has no other way of knowing. So how can
I find out? I have tried calling WindowFromDC, but it returns NULL. Calls to
GetCurrentPositionEx, GetViewportOrg and GetWindowOrg give inconsistent and
apparently meaningless results, and passing their output to LPtoDP or DPtoLP
doesn’t help. What should I do?
Halan2Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Jaime OlivaresSoftware ArchitectCommented:
Maybe you can intercept the window's sizing event (WM_SIZE) before, to know corners coordinates. This information will help you in client to screen coordinates calculus.
0
Halan2Author Commented:
This does not solve the problem, as there is more than 1 window to which the
text may be directed. I want to find the target window for each text string intercepted.
 
I need to know the text screen coordinates so that I can use
WindowFromPoint(Pt)->GetTopLevelWindow().
0
Halan2Author Commented:
More details:
The application I'm intecepting opens 2 or more windows.
To give some code example:

BOOL ReadDrawTextStrings()
{
    GetDrawTextA(Buffer);
    for(Index = 0; Index < BUFF_COUNT ;Index++) {
        if(_tcslen(Buffer[Index].Buffer) == 0) {
            return TRUE;
            }
    Text.Format("[%d, %d] %s\n", Buffer[Index].Location.x, Buffer[Index].Location.y, Buffer[Index].Buffer);
    LogFile.WriteString(Text);
    }
...
...
}

From this I get:
[510,80] Hello world
[510,80] Hello there

The problem is that the first line is from one of the windows and the next (might be) from the other but I cannot tell which is which.
0
Cloud Class® Course: SQL Server Core 2016

This course will introduce you to SQL Server Core 2016, as well as teach you about SSMS, data tools, installation, server configuration, using Management Studio, and writing and executing queries.

SteHCommented:
Is the DC perhaps released when you try the call WindowFromDC? Can you try it earlier on in your interception routine?
0
MadshiCommented:
WindowFromDC will work only if the DC belongs to a window (doh!). When an application uses double buffering (drawing the text into a bitmap and blitting the bitmap to the window DC) then WindowFromDC can't work, because the DC is a bitmap DC and no window DC.

I guess that's the problem you're facing here. Probably you're catching draw events on a bitmap DC. In the moment of drawing there's no way to know onto which screen position the bitmap will later be blitted. Maybe it won't be blitted at all but is just used internally for some strange reason?
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
BeyondWuCommented:
You also need to hook all DC creation/destroy APIs, such as BeginPaint,GetDC,GetDCEx, GetWindowDC ,CreateCompatibleDC,CreateDC,ReleaseDC,DeleteDC,EndPaint etc.,
You only need to save the array such as:
struct DCinfo
{
      HDC hdc;
      HWND hwnd;
}mydcinfo[1024];  you'd better make it dynamical expandable, here just a demo
each time you hook the DC-creation APIs, you can simply search the list and if the hdc hasn't been inserted just add the new hdc and hwnd into your list, when the DC-destroy APIs are called, just delete it from you list....
OK, then when you catch the DrawTextA APIs, you just search your HDC from the list and find the corresponding HWND handle....

Hope this can help you.
0
Halan2Author Commented:
Madshi, it was the double-buffering and it was a bit difficult to sort out, but is all working now.

Thanks for your advice.
0
devoured_elysiumCommented:
Hello. Could you share with us the way you did sort this thing out?
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.