Alaska Software Inc. - GraBitblt()
Username: Password:
AuthorTopic: GraBitblt()
Carlos A Beling GraBitblt()
on Thu, 26 Mar 2020 19:37:45 -0300
Hi.
Good night.
Please, what can to be done for the attached program to copy 
AppDesktop() to a XbpBimap()?.
TIA

Fraternally
Beling


Test.zip
Carlos A Beling Re: GraBitblt() - New Test
on Sat, 28 Mar 2020 13:39:33 -0300
Hi: good day.
I attached a new program Test.prg where I show the tests that I did.
Please desconsider the other one program.
Very strange behaviour.
Testing using Windows 10. Testin in Windows 7 sometimes it does not work

Fraternally
Beling


On 26/03/2020 19:37, Carlos A Beling wrote:
> Hi.
> Good night.
> Please, what can to be done for the attached program to copy 
> AppDesktop() to a XbpBimap()?.
> TIA
> 
> Fraternally
> Beling


Test.zip
Jim LeeRe: GraBitblt() - New Test
on Sun, 29 Mar 2020 01:24:33 +0100
hi,

what do yout to do after got SnapShot of Desktop() ?

i use "PrintScreen" from Xbase++ using
keybd_Event( VK_SNAPSHOT,nWindow,0,0)

attach Sample




---
Diese E-Mail wurde von AVG auf Viren gepruft.
http://www.avg.com


PRNSCR.ZIP
Carlos A Beling Re: GraBitblt() - New Test
on Sun, 29 Mar 2020 12:00:36 -0300
Hello Jim.
Good Day.
When the app gets runtime error I send, by e-mail, for the support 
correction, the file Error.log and the complete screen that I saved at 
the moment of the error.

Fraternally
Beling

On 28/03/2020 21:24, Jim Lee wrote:
> hi,
> 
> what do yout to do after got SnapShot of Desktop() ?
> 
> i use "PrintScreen" from Xbase++ using
> keybd_Event( VK_SNAPSHOT,nWindow,0,0)
> 
> attach Sample
> 
> 
> 
> 
> ---
> Diese E-Mail wurde von AVG auf Viren gepruft.
> http://www.avg.com
>
Andreas Gehrs-Pahl
Re: GraBitblt()
on Sat, 28 Mar 2020 21:15:48 -0400
Carlos,

>Please, what can to be done for the attached program to copy 
>AppDesktop() to a XbpBimap()?.

AppDesktop() is just an XbpIWindow() object with the (DPI-adjusted) size of 
the current/active Dialog's screen area, and dose NOT represent or refer to 
the actual Windows Desktop (which can span multiple monitors)! Neither its 
size nor its content is updated after program start, even if the Desktop 
size, resolution, or content changes while your Xbase++ program is running. 
So trying to copy the current Windows Desktop using AppDesktop() will never 
work.

If you simply want to save a screen shot of the entire Desktop, I recommend 
using the attached code.

Hope that helps,

Andreas

Andreas Gehrs-Pahl
Absolute Software, LLC

phone: (989) 723-9927
email: Andreas@AbsoluteSoftwareLLC.com
web:   http://www.AbsoluteSoftwareLLC.com
[F]:   https://www.facebook.com/AbsoluteSoftwareLLC

Demo.zip
Carlos A Beling Re: GraBitblt()
on Sun, 29 Mar 2020 12:41:05 -0300
Hello Andreas.
Good day.
Many thanks.
Really I can not to capture AppDesktop() this using Grabitblt().
While I was waiting for a help, I sought in the NG for GraBitblt() and 
others and I found out, I do not remember where, the function 
Screen2Bitmap() that is in the attached file Test.zip.
This function seems to work fine.
I will test yours Demo.prg for screen capturing by the user too.

Fraternally
Beling


On 28/03/2020 22:15, Andreas Gehrs-Pahl wrote:
> Carlos,
> 
>> Please, what can to be done for the attached program to copy
>> AppDesktop() to a XbpBimap()?.
> 
> AppDesktop() is just an XbpIWindow() object with the (DPI-adjusted) size of
> the current/active Dialog's screen area, and dose NOT represent or refer to
> the actual Windows Desktop (which can span multiple monitors)! Neither its
> size nor its content is updated after program start, even if the Desktop
> size, resolution, or content changes while your Xbase++ program is running.
> So trying to copy the current Windows Desktop using AppDesktop() will never
> work.
> 
> If you simply want to save a screen shot of the entire Desktop, I recommend
> using the attached code.
> 
> Hope that helps,
> 
> Andreas
>


Test.zip
Andreas Gehrs-Pahl
Re: GraBitblt()
on Sun, 29 Mar 2020 15:55:29 -0400
Carlos,

>This function seems to work fine.

Your function will only work if you use 100% (or no) Scaling and a single 
monitor. If you have a very high resolution screen and select 150% scaling, 
for example, you will get a region that starts on the top left (of your main 
display or primary monitor) that has a size of only 67% of that monitor's 
display area, as the AppDesktop() / XbpIWindow() coordinates and size only 
cover that area.

For your routine to work correctly, you would need to supply it with an area 
that is large enough -- and starts far enough left / top -- to cover all 
your monitors. Even on a single monitor system -- or if you are only 
interested in capturing the main display / primary monitor area -- you need 
to at least get the correct desktop size. 

To get that correct size, you can add the following to your code:

#define HORZSIZE                0x0004
#define HORZRES                 0x0008
#define DESKTOPVERTRES          0x0075
#define DESKTOPHORZRES          0x0076

Function Get_DeskTop_Size(lReal)
LOCAL lVirtual := iif(lReal   == NIL, .t., .not. lReal)
LOCAL nHWnd    := AppDesktop():GetHWnd()
LOCAL nHDC     := DllCall('User32.dll', DLL_STDCALL, 'GetDC', nHWnd)
LOCAL nWidth   := 0
LOCAL nHeight  := 0
   if nHDC # 0
      nWidth  := DllCall('GDI32.dll', DLL_STDCALL, 'GetDeviceCaps', nHDC, ;
                         iif(lVirtual, HORZRES, DESKTOPHORZRES))
      nHeight := DllCall('GDI32.dll', DLL_STDCALL, 'GetDeviceCaps', nHDC, ;
                         iif(lVirtual, VERTRES, DESKTOPVERTRES))
      DllCall('User32.dll', DLL_STDCALL, 'ReleaseDC', nHWnd, nHDC)
   endif
return ({nWidth, nHeight})

And replace the following line:

aSize := Appdesktop():CurrentSize()

with the following two lines:

aSize := Get_DeskTop_Size(.t.)
Appdesktop():SetSize(aSize)

This doesn't cover the possibility of multiple monitors, though. For that, 
you would need to first determine on which monitor your dialog is and what 
the (real) size and coordinates for that monitor are, and then set the 
Size and Position of AppDesktop() accordingly. But it seems that it isn't 
possible to set the Position of AppDesktop() to a negative value, so 
monitors to the left of the primary monitor can't be handled by your 
function at all. So, if your user moves your application to a monitor to 
the left of his primary monitor, you wouldn't be able to capture it at all.

Also, to make your image as big as the entire area, your line:

aRect := {0, 0, (aSize[01] - 1), (aSize[02] - 1)}

Should simply be:

aRect := {0, 0, aSize[1], aSize[2]}

Hope that helps and explains it,

Andreas

Andreas Gehrs-Pahl
Absolute Software, LLC

phone: (989) 723-9927
email: Andreas@AbsoluteSoftwareLLC.com
web:   http://www.AbsoluteSoftwareLLC.com
[F]:   https://www.facebook.com/AbsoluteSoftwareLLC
Carlos A Beling Re: GraBitblt()
on Mon, 30 Mar 2020 11:43:31 -0300
Hi Andreas.
Good day.
Many thanks again.
According to your advice it seems to me to be best to use yours 
Save_Dialog_to_Image_File() function because it does not depend of any 
further work for identifying the AppDesktop area. Is it true?
Fraternally
Beling

On 29/03/2020 16:55, Andreas Gehrs-Pahl wrote:
> Carlos,
> 
>> This function seems to work fine.
> 
> Your function will only work if you use 100% (or no) Scaling and a single
> monitor. If you have a very high resolution screen and select 150% scaling,
> for example, you will get a region that starts on the top left (of your main
> display or primary monitor) that has a size of only 67% of that monitor's
> display area, as the AppDesktop() / XbpIWindow() coordinates and size only
> cover that area.
> 
> For your routine to work correctly, you would need to supply it with an area
> that is large enough -- and starts far enough left / top -- to cover all
> your monitors. Even on a single monitor system -- or if you are only
> interested in capturing the main display / primary monitor area -- you need
> to at least get the correct desktop size.
> 
> To get that correct size, you can add the following to your code:
> 
> #define HORZSIZE                0x0004
> #define HORZRES                 0x0008
> #define DESKTOPVERTRES          0x0075
> #define DESKTOPHORZRES          0x0076
> 
> Function Get_DeskTop_Size(lReal)
> LOCAL lVirtual := iif(lReal   == NIL, .t., .not. lReal)
> LOCAL nHWnd    := AppDesktop():GetHWnd()
> LOCAL nHDC     := DllCall('User32.dll', DLL_STDCALL, 'GetDC', nHWnd)
> LOCAL nWidth   := 0
> LOCAL nHeight  := 0
>     if nHDC # 0
>        nWidth  := DllCall('GDI32.dll', DLL_STDCALL, 'GetDeviceCaps', nHDC, ;
>                           iif(lVirtual, HORZRES, DESKTOPHORZRES))
>        nHeight := DllCall('GDI32.dll', DLL_STDCALL, 'GetDeviceCaps', nHDC, ;
>                           iif(lVirtual, VERTRES, DESKTOPVERTRES))
>        DllCall('User32.dll', DLL_STDCALL, 'ReleaseDC', nHWnd, nHDC)
>     endif
> return ({nWidth, nHeight})
> 
> And replace the following line:
> 
> aSize := Appdesktop():CurrentSize()
> 
> with the following two lines:
> 
> aSize := Get_DeskTop_Size(.t.)
> Appdesktop():SetSize(aSize)
> 
> This doesn't cover the possibility of multiple monitors, though. For that,
> you would need to first determine on which monitor your dialog is and what
> the (real) size and coordinates for that monitor are, and then set the
> Size and Position of AppDesktop() accordingly. But it seems that it isn't
> possible to set the Position of AppDesktop() to a negative value, so
> monitors to the left of the primary monitor can't be handled by your
> function at all. So, if your user moves your application to a monitor to
> the left of his primary monitor, you wouldn't be able to capture it at all.
> 
> Also, to make your image as big as the entire area, your line:
> 
> aRect := {0, 0, (aSize[01] - 1), (aSize[02] - 1)}
> 
> Should simply be:
> 
> aRect := {0, 0, aSize[1], aSize[2]}
> 
> Hope that helps and explains it,
> 
> Andreas
>
Jose Antonio Diego KerejeRe: GraBitblt()
on Mon, 30 Mar 2020 18:38:14 +0200
Hi,

In addition to what Andreas says, you can try it this way.

Regards. Diego


Test.zip