Strange DC handling difference with VB apps in 9x/XP
|
|
Thread rating:  |
Thorsten Albers - 18 Jul 2007 18:07 GMT Hi, folks!
I have made a (to me) strange observation of different handling of DCs when executing 2 VB 6 apps on 9x and XP.
The test scenario: App A has one single form with a VB PictureBox on it (AutoRedraw = True). When startet it loads a JPEG image file into the PictureBox which is larger then the PictureBox so that some parts of the JPEG image isn't visible. App B has one single form with no controls. When startet (after App A has been startet) it searches for the main window handle of App A, then for the handle of the PictureBox of App A. If successfull, App B sends (SendMessage()) a WM_PAINT message to the PictureBox of App A together with the DC handle of the main form of App B.
Aim: App B shall get the >full< image loaded into the PictureBox of App A. Simple blitting doesn't help since this copies only the parts of the image visible in the PictureBox. As far as I can see there is no other method to get the image from a PictureBox of a foreign VB process (both STM_GETIMAGE and BM_GETIMAGE are not supported by the PictureBox, and AFAIK there is no other window message available for this purpose).
Result: - On Win 9x the PictureBox of >>App A<< correctly draws its contents on the main form of >>App B<<; the image then can be saved in >>App B<<. - On Win XP nothing happens and the DC remains unchanged.
The MSDN doesn't state anything about differences in DC handling on Win 9x and Win XP (on Win 2K/XP there only seems to be a certain thread dependence of DCs, but this doesn't seem to apply in this case).
Does anyone here have any experience with and maybe also a solution for this problem?
Thanks in advance for all replies, Thorsten Albers
 Signature ---------------------------------------------------------------------- THORSTEN ALBERS Universität Freiburg albers@ uni-freiburg.de ----------------------------------------------------------------------
Mark Yudkin - 19 Jul 2007 08:53 GMT The Windows 95 and Windows NT product ranges are only very loosely related - many have quipped that about the only thing they have in common is the first 7 letters of their names. Information on 95 -> NT migration used to be in old MSDNs, but it's probably been removed in the meantime; for the most part it was any a "rewrite" guide.
Almost all code that deals with the GDI will need significant effort to move from the 16-bit (yes!) W95/98/ME APIs to the 32-bit WNT/2K/XP/2K3/Vista versions. Other differences between the two families involves memory protection (W9x has none) - which seems to be part of your issue.
> Hi, folks! > [quoted text clipped - 39 lines] > Thanks in advance for all replies, > Thorsten Albers Thorsten Albers - 19 Jul 2007 10:57 GMT Mark Yudkin <DoNotContactMe@boingboing.org> schrieb im Beitrag <#vDbNndyHHA.1168@TK2MSFTNGP02.phx.gbl>...
> Almost all code that deals with the GDI will need significant effort to move > from the 16-bit (yes!) W95/98/ME APIs to the 32-bit WNT/2K/XP/2K3/Vista > versions. Other differences between the two families involves memory > protection (W9x has none) - which seems to be part of your issue. It is rather doubtfull to me whether it is a matter of memory protection. A device context like other GDI objects is a global object which might be shared between processes both on Win 9x and Win NT.
 Signature ---------------------------------------------------------------------- THORSTEN ALBERS Universität Freiburg albers@ uni-freiburg.de ----------------------------------------------------------------------
Schmidt - 19 Jul 2007 12:44 GMT > > Other differences between the two families involves memory > > protection (W9x has none) - which seems to be part of your issue. > > It is rather doubtfull to me whether it is a matter of memory protection. > A device context like other GDI objects is a global object which might > be shared between processes both on Win 9x and Win NT. I'd say, it is exactly this - a matter of memory-protection.
I've tested the scenario with the two processes A and B and found, that you can raise SendMessage from App A and trigger the "wm_paint-copy" inside the other App B (e.g. from the app-internal PictureBox.hWnd to its internal Form.hdc) by specifiying these Handles (of the foreign App B) in the SendMessage-Call (raised by App A). So the SendMessage-Call from the other process "goes through and works", showing that this is not a "message-blocking or -ignoring" issue.
Not started yet, to try to enhance process-rights or something like this - or to use VirtualAllocEx, to allocate additional memory inside the foreign process using its Process-Handle and "establish a paintable DC there (including a writable DIB, selected into this DC) - don't even know, if that's possible. What I've tested was, to use GetDC(0) (a "global" Screen-DC), to force the paint to write into this (hopefully) "globally seen DC", but to no avail - even GetDC(0)-DCHandles as the "Paint-Target" work only internally, inside the process wich aquired these handles.
Not tested, if maybe a DirectX-(Primary)Surface (mapped as GDI-DC) would be a valid (Cross-Process-)Render-Target.
Olaf
Juergen Thuemmler - 19 Jul 2007 14:52 GMT Hi Olaf & Thorsten,
> Not started yet, to try to enhance process-rights or something > like this - or to use VirtualAllocEx, to allocate additional memory > inside the foreign process using its Process-Handle and "establish > a paintable DC there (including a writable DIB, selected into > this DC) - don't even know, if that's possible. I've added a second Picturebox Picture1 to app A and a command button: Private Sub Command1_Click() Call SendMessageLong(picTest.hwnd, WM_PAINT, Picture1.hDC, 0) End Sub This works; the picture is drawn. Then I did this from the app B (hDC2 = GetDC(hWndChild2), where hWndChild1 is the PB in A with Picture, hWndChild2 is the new Picturebox in A): Call SendMessageLong(hWndChild1, WM_PAINT, hDC2, 0) This doesnt work; nothing happens...Why???
Juergen.
Schmidt - 19 Jul 2007 15:53 GMT > I've added a second Picturebox Picture1 to app A and a command button: > Private Sub Command1_Click() [quoted text clipped - 6 lines] > Call SendMessageLong(hWndChild1, WM_PAINT, hDC2, 0) > This doesnt work; nothing happens...Why??? This doesn't work, because with: hDC2 = GetDC(hWndChild2) you create a (mapped) Process-lokal DC in B (from a WindowHandle in A).
What works for me is, if you set hDC2 in B to the "original Value" of Picture1.hdc from A. (I've done this, typing the Picture1.hdc-Value from A (A_MainForm.Caption = Picture1.hdc) into a TextBox of the running App B "by hand").
Olaf
Juergen Thuemmler - 19 Jul 2007 15:59 GMT > I've added a second Picturebox Picture1 to app A and a command button: > Private Sub Command1_Click() [quoted text clipped - 6 lines] > Call SendMessageLong(hWndChild1, WM_PAINT, hDC2, 0) > This doesnt work; nothing happens...Why??? Next "discovery": I print the "Picture1.hDC" value in the command button sub. It is always the same, on each button click (while the app A is running). I DPrint the values of Debug.Print CLng(GetDC(hWndChild2)) Debug.Print CLng(GetWindowDC(hWndChild2)) Debug.Print CLng(GetDC(0)) in app B. Each value is different from the other, different each time the function is called and completely different to the Picture1.hDC value. Whe I use the Picture1.hDC value in app B in Call SendMessageLong(hWndChild1, WM_PAINT, hDC2, 0) for "hDC2", it works. Can someone explain it?
Juergen.
Schmidt - 19 Jul 2007 16:04 GMT > Whe I use the Picture1.hDC value in app B in > Call SendMessageLong(hWndChild1, WM_PAINT, hDC2, 0) > for "hDC2", it works. Funny, we posted at the same time.
> Can someone explain it? The DCs retrieved by GetDC(hWndFromOtherProcess) are something like "inherited DCs", mapped into the calling process and usable only there in its context.
Olaf
Juergen Thuemmler - 19 Jul 2007 17:44 GMT Hi Olaf & Thorsten,
> The DCs retrieved by GetDC(hWndFromOtherProcess) > are something like "inherited DCs", mapped into the > calling process and usable only there in its context. well, meanwhile I've written a little Dll, to which I pass the target handle of app A and the handle of the window in app B, where the picture should be painted. The Dll hooks into the app A, calls there PostMessage(wnd, WM_PAINT, (WPARAM) GetDC(hdest), 0); where wnd is the target window, which contains the picture, and hdest ist the window in app B. It works perfectly (have tested it only with VB programs...:)
Juergen.
Schmidt - 19 Jul 2007 18:35 GMT > well, meanwhile I've written a little Dll, to which I pass the target > handle of app A and the handle of the window in app B, where > the picture should be painted. The Dll hooks into the app A, ... Ah, thats the glue, wich makes the decisive difference - good to know...:-)
Olaf
Juergen Thuemmler - 19 Jul 2007 18:43 GMT > Ah, thats the glue, wich makes the decisive difference - > good to know...:-) The bad news is: You cannot reach the "painted" by the Image-Property (no matter whether form or picturebox) and therefore also not save using "SavePicture()". Also "AutoRedraw = True" doesn't work. It seems, that VB doesn't realize the painting... Any ideas?
Juergen.
Schmidt - 20 Jul 2007 07:18 GMT > > Ah, thats the glue, wich makes the decisive difference - > > good to know...:-) [quoted text clipped - 5 lines] > doesn't work. It seems, that VB doesn't realize the > painting... Then simply do an additional BitBlt (inside the process) - or use a MemoryDC (with your own DIB selected into).
Maybe you can also paint into the memoryDC directly, if you somehow change GetDC(hdest) to your MemDC- Parameter.
Olaf
Juergen Thuemmler - 20 Jul 2007 08:23 GMT > Then simply do an additional BitBlt (inside the process) - > or use a MemoryDC (with your own DIB selected into).
> Maybe you can also paint into the memoryDC directly, > if you somehow change GetDC(hdest) to your MemDC- > Parameter. I've tested it too - no success. And: The target where is to paint must be visible. I can blit from the target to a MemDC and create a picture using OleCreatePictureIndirect() and save it, but then, the picture file contains again only the visible part of the target - the same situation like at starting point.
Juergen.
Schmidt - 20 Jul 2007 08:54 GMT > I've tested it too - no success. > And: The target where is to paint must be visible. > I can blit from the target to a MemDC and create a picture using > OleCreatePictureIndirect() and save it, but then, the picture file > contains again only the visible part of the target - the same situation > like at starting point. Arrgh ;-) Maybe a workaround is, if you determine this visible part - and then use SetDCOrg or the ViewPort-APIs, to shift the origin of your Destination- (Memory-)DC and force then a second wm_paint-copy.
Olaf
Juergen Thuemmler - 20 Jul 2007 09:18 GMT > Maybe a workaround is, if you determine this visible part - > and then use SetDCOrg or the ViewPort-APIs, to shift the > origin of your Destination- (Memory-)DC and force then > a second wm_paint-copy. This wouldn't solve the original problem - to get a picture larger than the screen from a foreign app and save it to a file. In any case where BitBlt() must be used, this is impossible. I think, the better way is to ask the window which contains the picture to copy it into the clipboard...
Juergen.
Schmidt - 20 Jul 2007 09:23 GMT > I think, the better way is to ask the window which contains the > picture to copy it into the clipboard... Ok, if you can restore the original Clipboard-Content after you're done with your "Copy-Operation" - why not.
Olaf
Mark Yudkin - 20 Jul 2007 08:14 GMT > A device context like other GDI objects is a global object which might be > shared between processes both on Win 9x and Win NT. A device context on NT is very definitely not a shared object. In addition, there is no means in Windows for sharing a device context across processors. This is one of the differences to 95/98/ME.
> Mark Yudkin <DoNotContactMe@boingboing.org> schrieb im Beitrag > <#vDbNndyHHA.1168@TK2MSFTNGP02.phx.gbl>... [quoted text clipped - 8 lines] > device context like other GDI objects is a global object which might be > shared between processes both on Win 9x and Win NT.
|
|
|