[Webinar] Streamline your web hosting managementRegister Today

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 231
  • Last Modified:

Get window's image.

  Hi.
 I want to write a program , that by handle to window will get it's image,
not matter the state of the window(VISIBLE, INVISIBLE, MINIMAZED, etc.).
    Actually I have two questions.
1. Does it possible?
2. If it's then what is the best way to do it?

Thanks.
0
dpodvaln
Asked:
dpodvaln
  • 9
  • 7
  • 7
  • +1
1 Solution
 
MichaelSCommented:
You can try to do it by sending WM_PAINT message and providing your own DC. For that you have to be in the context of process of this window (you can set global hook and in such way catch it).
0
 
dpodvalnAuthor Commented:
MichaelS :what do you mean by saying "you have to be in the context of process of this window"? Does it mean that this window has to be created by my process? If it's then it's not good solution for me. I need to be able to do that on _any_ window in the system.
Thanks.
0
 
MichaelSCommented:
It can be any window but you have to send WM_PAINT and provide device context. This you can do only from the same process so you have to be there. For this you can use global hook. You write all the stuff in the dll and this dll will loaded in each process.
0
Receive 1:1 tech help

Solve your biggest tech problems alongside global tech experts with 1:1 help.

 
dpodvalnAuthor Commented:
I think it's some missunderstanding... I'm not a windows programmer but as i understand from your answer i have to change something in the program that creates window. I DON'T want to do that. I want to write completely separate program that will be able to catch image of any other window, doesn't matter of the process that own that window.
    If i understood wrong your answer, can you explain it once more? Example will be great.

Thanks.
0
 
MichaelSCommented:
Well, let's do it again. You write dll (separate file). In that dll you will have all your stuff (hook functions). After that you have to set global hook. See function SetWinodwsHookEx(). Your dll will be loaded in all existing processes.
0
 
WynCommented:
http://www.codeguru.com/bitmap/window_to_file.shtml

Writing a window image to a BMP file
0
 
WynCommented:
the key code is:

CreateCompatibleDC()
/*this creates a memdc compatible with the window dc,you can get from
GetDC()*/
GetWindowRect()
CreateCompatibleBitmap()
SelectObject();
//prepare to draw image you want to memdc
BitBlt()
//you get it!!!

Regards
Wyn
0
 
MichaelSCommented:
Wyn, it's not a good idea to make a wrong answer. Read the question and history again.
0
 
WynCommented:
MichaelS , I think you misunderstand .
Please read the question again.
However , dpodvaln, if you dont want to write it to file.Simple do the first part of the coding in the article I propose.(exactly the code I extract out).

MichaelS , If I 'm wrong .Please in details.I can not understand your comment to dpodvaln and me.
0
 
WynCommented:
There is no big diffenece of getting the image of window between different processes if you have the handle.
0
 
WynCommented:
dpodvaln ,is this your need?

As my understanding,dpodaln wants to get the image of any window exist with a handle.
Is this right?
0
 
nietodCommented:
Sending a WM_PAINT is very very unreliable for this.  You should send the window a WM_PRINT or WM_PRINTCLIENT instead.  The message was created for this purpose.
0
 
dpodvalnAuthor Commented:
wyn : The answer is not good for me. As i wrote in my question i need to get image of the window, not matter of the state of the window.
    On the URL that you gave it wrote :
"You should note that if the window is partially or completely covered by other windows then the saved bitmap will show parts of these other windows too."
 But thanks anyway .
0
 
nietodCommented:
dpodvaln, look at the WM_PRINT and WM_PRINTCLIENT messages.  They are provided expressly for this purpose.  They will show portions of the window that are covered by other windows or that are positioned of the screen.

You just obtain a DC that you want the window image to appear (usually a DC for memory based bitmap) then you send the window a WM_PRINT or WM_PRINTCLIENT message and specify this DC in the wParam and the appropriate flags in the lParam.

Let me know ifyou have any questions.
0
 
dpodvalnAuthor Commented:
I have a couple questions :
1. Will it work with all windows, or only with windows that has reactions to this message (WM_PRINT)?
2. Will it work for invisible, minimized, etc. windows?
3. Do i need as MichaelS wrote to be in the owner procees address space?

Thanks.
0
 
nietodCommented:
>>  Will it work with all windows, or only with
>> windows that has reactions to this message
>> (WM_PRINT
Only windows that handle this message.  But most windows will handle the message.  The built-in window types (windows that are part of the OS, like the standard controls) should all handle it, the MFC windows should all handle it.  The only problem might be windows written by programs that didn't know to handle this message.  Most programmers that don't know to handle it, also don't knwo how to write their own window classes so they use the built-in windows and/or MFC, so this shouldn't occur to often

If it doesn't work for a particular window, you are out of luck, there isn't any solution that is going to work for all windows, this is one that is like to work with almost all windows

>> 2. Will it work for invisible, minimized, etc. windows?
I suspect it will work fine for invisible windows, and probalby will work fine for minimized ones to.

>> 3. Do i need as MichaelS wrote to be in the
>> owner procees address space?
No.  (fortunately.)  You just send the message to the window--any window at all.
0
 
dpodvalnAuthor Commented:
I wrote program that does it. It doesn't seems to work . Here it's
      HANDLE hnd = (void *) 0x00105f8; // handle of paintbrash window
      HDC original_dc = GetDC(hnd);
      HDC new_dc = CreateCompatibleDC(original_dc);
      HDC dest_dc = GetDC(hWnd);
      SendMessage(hnd, WM_PRINT, (unsigned int) new_dc , PRF_CLIENT );
      BitBlt(dest_dc, 0, 0, 200, 200, new_dc, 0, 0, SRCCOPY | WHITENESS);

        I checked with Spy++ and it seems that window receive this message with correct dc. But i don't see anything on my window. If you can please take a look at this code.
Thanks.
0
 
nietodCommented:
>> HANDLE hnd = (void *) 0x00105f8; // handle of paintbrash window
Are you sure that is the correct value?  It would be unusual t be able to rely on a hard-coded window handle

When you create a DC with CreateCompatibleDC() is creates the DC, but the DC will store a 1 pixel by 1 pixel monochrome bitmap.  so the results of your bitblt() should be to set a single pixel on the window to black or white.

You can use the WM_PRINT message to draw directly to your window's DC, like

SendMessage(hnd, WM_PRINT, (WPARAM) dest_dc , PRF_CLIENT );

or you can create a bitmap and select it into the destination DC, like

RECT WndRct;

GetWindowRect(hnd,&WndRct);

int Wdt = WndRct.right - WndRct.left;
int Hgt = WndRct.bottom - WndRct.top;
HBITMAP BmpHnd = CreateCompatibleBitmap(dest_dc,Wdt,Hgt);
HBITMAP OldBmp = SelectObject(new_dc,BmpHnd);

// now draw to the DC and bitblt()

SelectObject(new_dc,OldBmp); // select back the original bitmap
              // This must be done.
DeleteObject(BmpHnd); // Delete the bitmap.

Note that CreateComaptibleBitmap() must be done with dest_dc as the parameter, not with new_dc.  The bitmap it creates uses the color format of the bitmal currently in the specified DC.  Since the bitmap in new_dc is monochrome, you would get a monochrome bitmap if you specified it.
0
 
dpodvalnAuthor Commented:
nietod : I tried to do SendMessage(hnd, WM_PRINT, (WPARAM) dest_dc , PRF_CLIENT );  It still doesn't work. In my example, when i do BitBlt(dest_dc, 0, 0, 200, 200, original_dc, 0, 0, SRCCOPY); then i can see a window if it not overlapped by another.That's means that window handler is correct one.
0
 
nietodCommented:
>> I tried to do SendMessage(hnd, WM_PRINT,
>> (WPARAM) dest_dc , PRF_CLIENT );  It still
>> doesn't work
What happened?

>> when i do BitBlt(dest_dc, 0, 0, 200, 200,
>> original_dc, 0, 0, SRCCOPY); then i can
>> see a window if it not overlapped by another.
>> That's means that window handler is correct one.
I don't understand what you meant by this.

Can you post the code again?  (However, I might be done for the day.)
0
 
MichaelSCommented:
As I already told you have to send this message from the process to which belong target window. Use hooks for it.
0
 
dpodvalnAuthor Commented:
nietod :
>> What happened?
   Nothing happened.I just didn't see anything.

     Here two programs that I have now.
1.
      HANDLE src_handle = (void *) 0x00030174;
      HDC dest_dc = GetDC(hWnd);
      SendMessage(src_handle, WM_PRINT , (WPARAM) dest_dc ,PRF_OWNED);
________________________________

2.       HANDLE src_handle = (void *) 0x00030174;
      HDC src_dc = GetDC(src_handler);
      HDC dest_dc = GetDC(hWnd);
        BitBlt(dest_dc, 0, 0, 200, 200, src_dc, 0, 0, SRCCOPY);

___________________________________

  In the first program nothing happened.
  In the second one i can see image of the source window in my window, but if the source window is overlapped by another one then i get this window too that isn't good for me.


MichaelS : I would try yours suggestion, but i don't have a clue how to write it. I wrote a hook dll. I wrote empty hook function. In my program i did SetWindowsHookEx(WH_CALLWNDPROCRET, hook_f, lib, 0);
What should i do next?


Thanks.
0
 
MichaelSCommented:
you can figure out ProcessID of target window. After that on the DLLATTACH you just check if you are in the right process or not, if yes you send WM_PRINT, WM_PAINT or whatever to target window and got a bitmap. After that you have to transfer this bitmap to your app somehow, messages, memory mapped file, file, pipes, sockets ...
0
 
dpodvalnAuthor Commented:
michaelS : Would bitmap that i'll receive in that way show also covered part parts of the window(if it's covered by another windows), or it will contain insteed parts of that other windows?

   Why can't i do that as nietod suggested? I mean the only difference between yours and the nietod suggestion is that you are saying that i have to be in the process address space, and nietod says that not necessarily.If it works as nietod described it why do i have to be in the process's address space?


    Thanks.
0
 
MichaelSCommented:
Ok, so the problem I see is that DC you have will not valid in other process. Look, you have HANDLE of DC. Then you call SendMessage() and transfer that handle to another process. Are you sure that in another process DC handle will be valid? If yes, forget about hooks, if no - than you have something additional to programm.
0
 
nietodCommented:
That should not be a problem  DC handles are global, just like window handles.  

I'll have to give it a try a little later.  
0
 
nietodCommented:
It appears at the moment lik MichaelS is right.  The DC handles cannot be passed between apps (at least not in win32).  So even with WM_PRINTCLIENT you will need to inject your program into the target process's address space.

I'd like to do a little more research on that though, because that means that WM_PRINTCLIENT is really a lot less useful.
0
 
dpodvalnAuthor Commented:
 It seems for me that posting messages like WM_PRINT or WM_PAINT will not work.
I think that the "correct" way to do this is to  hook api of gdi32 and user32.I didn't try it yet.
  No answer or comment didn't give answer on the asked question, but comments of MichaelS opened my eyes on possibility to enter to other process address space(yes, i know, i stupy if i didn't know it before -)), so i decided to give points to MichaelS.
    Thanks to everybody.
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 9
  • 7
  • 7
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now