Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
Home
Discussion GroupsVB SyntaxEnterprise DevelopmentDatabase AccessControlsCOMWin APICrystal ReportDeploymentGeneralGeneral 2
Related Topics
VB.NET / ASP.NETMS SQL ServerMS AccessOther Database ProductsMore Topics ...

VB Forum / Win API / July 2007



Tip: Looking for answers? Try searching our database.

Strange DC handling difference with VB apps in 9x/XP

Thread view: 
Enable EMail Alerts  Start New Thread
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.
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.