I've just got a fresh device context (DC):
GetDC(someForeignHwnd)
Most normal people now want to paint on this. I don't. I want to display the context in my own program. Or duplicate, I wouldn't even mind the window I stole the context from beeing empty.
In my case, I want it in a TPanel in Delphi, but anything else helping me understanding goes.
Afterwards, I'll probably find the DC invalid by the time I get to display it.
My main problem is: Showing the content of another window in my own. But that isn't important. First of all, I want to know how these DC are of any use. Can I do something like the following?
Canvas.Draw(0, 0, MyNewDC);
The answer can be in Java, C, or Pascal. Is it just not possible or just a stupid idea?
While it's possible to use a device context that you retrieve via GetDC() as the SOURCE for BitBlt(), etc., you will likely not get the results that you're looking for. When you call GetDC() for a specific window, Windows essentially returns a device context for the screen, but with a clipping region set to exclude any portions of the screen where the window is not visible. For example, if there happens to be another window overlapping the source window, the portion of the source window that is covered is clipped from the device context. Therefore, you can only "retrieve" the bits that are actually visible.
You may have better luck sending a WM_PRINT or WM_PRINTCLIENT message to the window. However, not all windows respond to these messages, so this isn't a universal solution.
Related
So I`m very new to win32ui, basically just starting. I was once using BitBlt wit python win32api module and as far as I remember to draw on top of display (so any application - if they are opened) I had to get specific context handle. But my memory is hazy on whether it simply was NULL or was it some specific context? Null doesn't seem to work, so I wonder how to obtain that general context? I really want to avoid to create fully transparent un blocking window.
The GetDC API allows you to get a device context for any given window. Alternatively,
If [hWnd] is NULL, GetDC retrieves the DC for the entire screen.
You can use the device context for the entire screen to read from, reliably (with restrictions). Rendering into a device context for a window you do not own won't be reliable, though. While it won't fail straight away, the window owner can overwrite your rendering at any point. There's no way for you to even be notified about this.
If you need to render on top of the screen you will have to create a top-most (transparent) window yourself, and use its device context. Make sure you ask the question: What if two programs did this?
My goal is to screen-scrape a portion of a program which constantly updates with new text. I have tried OCR with Tesseract but I believe it would be much more efficient to somehow intercept the text if possible. I have attempted using the GetWindowText() function, but it only returns the window title. Using Window Detective I have determined that whenever the window updates in the way I wish to capture, a WM_PAINT message is reliably sent to the window.
I have looked a bit into Windows API Hooks, but it seems that most of these techniques involving DLL injection are intended at sending new messages, not accessing the content of already sent messages.
How should I approach this problem?
When you say 'screen-scrape', is that what you really mean? Reading your post, it sounds like you actually want to get at the text in the child window or control in question - as text, and not just as a bitmap. To do that, you will need to:
Determine which child window or control actually contains the text you want to get at. It sounds like you may have already done that but if not, the tool of choice is generally Spy++. (Please note: the version of Spy that you use must match the 'bitness' of your application.)
Then, firstly, try to figure out whether the text in that window can be retrieved somehow. If it's a standard Windows control (specifically EDIT or RICHEDIT) then there are documented ways to do that, see MSDN.
If that doesn't pan out, you might have some success hooking calls to ExtTextOut(), although that's not a pleasant proposition and I think you might struggle to achieve it. That said, I believe the accepted way (in some sense of the word 'accepted') is here.
With reference to point 3, even if you achieve it, how would you know whether any particular call to ExtTextOut() was drawing to the window you're interested in? Answer, most likely, HWND WindowFromDC().
I hope that helps a little. Please don't come back at me with a bunch of detailed questions about how this might apply to your particular use-case. I'm not really interested in that, these are just intended as a few signposts.
The normal way to capture an image of a window is to call:
HDC SharedWndDC = GetWindowDC(SharedWnd);
BitBlt(BitmapDC, 0, 0, width, height, SharedWndDC, 0, 0, SRCCOPY /* |CAPTUREBLT */);
ReleaseDC(SharedWnd, SharedWndDC);
Which on a system running DWM, nicely grabs just the window in question, even if it's being overlapped by other windows or partly off the screen, or whatnot.
But, it doesn't work right on some windows (presumably those that use WPF), and does funny things with the glass areas. Basically, the GDI capture doesn't work on non-GDI things.
I understand what I really want is to grab the Direct3D "back buffer" or "front buffer", but the numerous examples I've seen for that are for capturing the entire screen or desktop. Not knowing Direct3D, I can't find an example or simple statement of how to obtain the proper object for an existing window, which I could then grab the buffers from.
Can some kind soul at least show that missing piece?
—John
I don't believe there is a way to capture the front buffer contents without capturing the whole screen, and the back buffer is private to the application running Direct3D. The front buffer's content can only be seen when the graphics card actually presents the data to the monitor. With GDI, Windows has access to the front and back buffers, because it is managing them itself. But with Direct3D (and I'm presuming WPF), this is no longer the case. Windows does not have access to the buffers, and as such, can't obtain the data unless the application gives it to Windows, which is impossible (there's no message defined to do so).
EDIT:
This looks like a dead question, but I'll add this anyway in case someone else comes along looking for answers. The aforementioned issues still apply to getting the window contents programmatically. However, it is possible in Windows to get the contents of a single window by utilizing the shortcut ALT+Print Screen when the window you want to capture has the keyboard focus (a.k.a. it's the active window). This may or may not help you, but it does capture the contents of just the window in question, even with DirectX stuff.
I previously asked a question about changing the cursor system-wide on OSX. I used NSCursor to change the cursor, but the effects are only as long as the application is active. When another application becomes active, the custom cursor is lost.
Here is a related, more general question. How can you write an application to have system-wife effects? For example drawing an image on-screen even when your application is not active, and something else is?
I understand I probably need to go at a lower level than the Cocoa APIs. I just cannot figure out where to start looking? Any specific Carbon APIs that I need to be looking at? Or even lower?
Any pointers would be appreciated! If you specifically know how to change the cursor system-wide or how to draw an image and move it around (no matter what application is active), that would solve my current problem as well! Can I write an application that can achieve this when its installed on the system?
Thanks!
You can achieve the effect you want, but not the way you're thinking about doing it.
You say,
I am writing a presentation aid application that shows the equivalent of the "laser pointer" on screen, programmatically. My first idea was to use the mouse cursor itself as the pointer, and change its appearance as a red circle.
Then fake that. Create an application, perhaps of type LSUIElement, perhaps not, depending on the behavior you want. Create a borderless window (type NSBorderlessWindowMask) and fill it with a clear color. Set its window level high enough so that it floats over everything (using -[NSWindow setLevel:], though I can't think of what the best level would be off-hand), and draw into it.
It's true that you cannot set the cursor when you are not the foremost app. It's true that you cannot just scribble on the screen. But you can get the same effects if you're clever.
This behaviour is not provided by any APIs on Mac OS X. You would have to modify the resource files in the OS, and that's a very dangerous operation that could brick the target computer. You have to know what you're doing.
Are you trying to implement a theming app or something like that? What's your goal? If you tell us what you are trying to do, we may be able to suggest alternate approaches.
We have a fairly complex GUI, so when certain windows are resized their Redraw() is set to false till the operation is completed. The problem with this is that if the OS "Show window content while dragging" setting is checked, when decreasing the window's size the windows behind it are not repainted. This means I have to force the repaint myself so the remains of the resized window are deleted. I have no problem getting the dimensions of the region that was uncovered. What I'm looking for is best way to cause all windows within that region to repaint their part.
Not being much of a GUI programmer, I can traverse the uncovered region and list the windows in it. Then, I can ask each one of them to repaint its part. But I'm quite certain there has to be a better way to do this...
It is worth mentioning the app is written in PowerBuilder. This means I can call whatever Win32 function I'd like, but have limited control over the GUI behavior and the message handling. If there's a better way to prevent the window's content resize from being visible, or there's a way to make a non-redrawn window clean after itself, I'd love to hear it (just have the limitations above in mind).
I'm curious what version of PowerBuilder you are working in? I do resizing all the time and never run into issues like you are describing.
Maybe you can lay out some more detail on why you need to set your redraws to false within the PowerBuilder environment.
Hope I can help.