News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Watchingdows DC

Started by oex, April 03, 2011, 04:19:14 AM

Previous topic - Next topic

oex

I am not fully understanding DC stuff.... What I want to do is grab a Bitmap of a window that isnt 'on top'.... I can snapshot the screen with no problem however how do I get the images of what's behind the visible in the z-order.... Transparency is an issue :lol.... I'm sure I did something similar with clip regions and window transparency before but specifically now I want to get bitmaps of all windows I cant see (That are actually visible windows).... I also want the whole window painted to the bitmap and not just the 'visible portion'

If I snapshot a window behind another the bitmap is black....
We are all of us insane, just to varying degrees and intelligently balanced through networking

http://www.hereford.tv

MichaelW

One method would be to bring the target window to the top of the Z-order.

invoke SetForegroundWindow, hwndTarget
eschew obfuscation

oex

Yeah.... Not a method I'm happy with.... I want to be able to use the computer while it's happening.... Also as far as I understand it (I havent checked it yet) the area that's visible would be the only area copied so if the window was half off the screen I would get a clipped BMP.... This is OK if I can set a fixed size however if it's a half a 1024x768 window on 1024x768 bmp image with a load of random screen that's just annoying :lol....

What exactly are DCs drawn to? ie if my screen is 1024x768 does this mean that this is the largest image I can get of the IE window I'm currently viewing?

I'd like to create a rolling windows effect with the mousewheel however to do this I need to generate some thumbs.... To generate the thumbs I need to pre-draw the DCs resized to images for a reasonable effect speed and flicking between windows is unacceptable....
We are all of us insane, just to varying degrees and intelligently balanced through networking

http://www.hereford.tv

MichaelW

I have never found a way to capture the off-screen portion of a window (short of moving it on-screen). AFAIK at least by default the window DC bitmap object is the size of the screen, and if my understanding of this is correct (and I'm not sure that it is) the off-screen portion does not exist as a bitmap.

eschew obfuscation

oex

Quote from: MichaelW on April 03, 2011, 05:10:47 AM
I have never found a way to capture the off-screen portion of a window (short of moving it on-screen). AFAIK at least by default the window DC bitmap object is the size of the screen, and if my understanding of this is correct (and I'm not sure that it is) the off-screen portion does not exist as a bitmap.

I dont think it is exists as a BMP.... I think it must be 'forced' ie by getting something to fire the WM_PAINT messages or 'fool' the application into believing it is actually visible and maximised :lol....

I have read somewhere that 'PrintWindow' might do something near what I wanted....
We are all of us insane, just to varying degrees and intelligently balanced through networking

http://www.hereford.tv

donkey

GDI objects, as far as I know are system wide objects, at least it would not make any sense to have them local to an application since the system needs access to them to display them. In that case you should be able to use the handle returned from GetCurrentObject, hDC, OBJ_BITMAP and clone it. I've never tried it but can't see a reason it would not work. It would be the actual bitmap so there would be no issues of it being obscured by other windows.

If that doesn't work I would try to read the bitmap memory directly using ReadProcessMemory, you can get the pId of the process using GetWindowThreadProcessId, open the process then send a GetObject with memory allocated in the remote process using VirtualAllocEx, read the memory into your process and tada, you have the bitmap data. A bit of work but I've used it successfully in the past for other things like getting information from the desktop.

Here's an example of using an interprocess read/write to get information from an LVITEM structure of a desktop item, the bitmap version would be close to the same:


; Get the ID of the process that created the desktop listview
invoke GetWindowThreadProcessId,[hlv],OFFSET PID

; Open the process with Virtual memory priviledges
invoke OpenProcess,PROCESS_VM_OPERATION \
+ PROCESS_VM_READ + PROCESS_VM_WRITE,0,[PID]
mov [hProcess],eax

mov edi,[pLVItem]

; Calculate the size of buffer needed
mov ecx,SIZEOF LV_ITEM
add ecx,[edi+LV_ITEM.cchTextMax]
inc ecx

; Create a buffer inside the process space of the desktop listview
invoke VirtualAllocEx,eax,0,ecx,MEM_COMMIT,PAGE_READWRITE
mov [pMem],eax

; Substitute the address of the local pszText buffer for the remote one
mov esi,eax
add esi,SIZEOF LV_ITEM

mov ebx,[edi+LV_ITEM.pszText]
mov [edi+LV_ITEM.pszText],esi

; Write the LV_ITEM structure to the remote process buffer
invoke WriteProcessMemory,[hProcess],[pMem],\
[pLVItem],SIZEOF LV_ITEM,OFFSET cbWritten

; Get the item info, using the remote buffer
invoke SendMessageA,[hlv],LVM_GETITEM,0,[pMem]

; Copy the remote LV_ITEM into our local LV_ITEM
invoke ReadProcessMemory,[hProcess],[pMem],\
[pLVItem],SIZEOF LV_ITEM,OFFSET cbWritten

; Reset the address of the pszText buffer
mov [edi+LV_ITEM.pszText],ebx

; Copy the text from the remote buffer
invoke ReadProcessMemory,[hProcess],esi,ebx,\
[edi+LV_ITEM.cchTextMax],OFFSET cbWritten

; Free the memory and close the remote process
invoke VirtualFreeEx,[hProcess],[pMem],0,MEM_RELEASE
invoke CloseHandle,[hProcess]
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

oex

Thanks Edgar, I will work out what you just said and then see if it works :lol....

I'll probably not reply again this er morning I have to feed the virus checker and get some sleep but I'll check back later most probably with any results (or lack tada thereof)....
We are all of us insane, just to varying degrees and intelligently balanced through networking

http://www.hereford.tv

MichaelW

The attachment is a quick and dirty test that captures the bitmap object for its own DC and copies it to a file. Any off-screen portion of the window is clipped.
eschew obfuscation

dedndave

i was thinking that you might be able to move a window off-screen, put it on top, and get a snapshot   :bg
of course, you would want some way to discover the original z-order for all the windows, so you can restore it

oex

I am getting the impression that the only way is either *possibly* to load it to another desktop view (which might work but is annoying and a tacky way to do this).... Or to cache opened windows as they are visible....

I'm sure I have seen on Vista/7, or somesuch thumbs of the windows so there must be a way.... Maybe it is not possible version wise....

The hDC is the handle to the device context ie the screen so the window drawing is in some measure dictated by the application ie controls etc might not be updated when the window is minimised....
We are all of us insane, just to varying degrees and intelligently balanced through networking

http://www.hereford.tv

oex

We are all of us insane, just to varying degrees and intelligently balanced through networking

http://www.hereford.tv

Gunner

2 things for you to look into:
See if PrintWindow will do what you want... or check out WinCap
~Rob (Gunner)
- IE Zone Editor
- Gunners File Type Editor
http://www.gunnerinc.com

oex

Quote from: Gunner on April 03, 2011, 06:50:59 PM
2 things for you to look into:
See if PrintWindow will do what you want... or check out WinCap

Nice 1 :bg

"WinCap is based on the work by Feng Yuan. It injects a DLL into
whatever process owns the specified window. The DLL hooks the
BeginPaint and EndPaint APIs in the remote process. It then sends
a WM_PAINT in the hope that the window will call BeginPaint/EndPaint
when it processes this message.

The hook for Begin/EndPaint modifies the return value of these
functions and causes the application to paint into a private off-screen DC
instead of a regular screen DC.

In addition to WM_PAINT, the WM_NCPAINT and WM_ERASEBKGND are simulated
to provide the complete window painting cycle.

To capture an entire window (and it's children), WinCap has to enumerate
all child windows and repeatedly capture each one, copying each bitmap
into one big bitmap, ready to be copied to the clipboard."

Damned annoying! But sounds like just was I was looking for :lol

Also:

"PrintWindow takes a window handle, an hdc, and a reserved flag. The API uses window redirection to paint a snapshot of the window into the hdc."
We are all of us insane, just to varying degrees and intelligently balanced through networking

http://www.hereford.tv

oex

Just a quick update.... The code seems to work ok.... Here is the basic code before it degrades into a jumbled mess of tests :lol....


.if rv(GetWindowDC, oexhWnd)
mov hdc, eax
.if rv(CreateCompatibleDC, hdc)
mov hdcMem, eax

; invoke GetWindowRect, oexhWnd, &rc

.if rv(CreateCompatibleBitmap, hdc, 1280, 1024)
mov hBitmap, eax

invoke SelectObject, hdcMem, hBitmap

invoke PrintWindow, oexhWnd, hdcMem, 0

invoke DeleteObject, hBitmap
.endif

invoke DeleteObject, hdcMem
.endif

invoke ReleaseDC, oexhWnd, hdc
.endif


If I wasnt a paid up member of Baltoro's Counter Intelligence Administration (CIA) I'd post a screenshot to prove it :lol
We are all of us insane, just to varying degrees and intelligently balanced through networking

http://www.hereford.tv

oex

The webpage must not be minimised otherwise you will see only a silly taskbar item....
We are all of us insane, just to varying degrees and intelligently balanced through networking

http://www.hereford.tv