Author | Topic: 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 Lee | Re: 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 Kereje | Re: GraBitblt() on Mon, 30 Mar 2020 18:38:14 +0200 | |
Andreas Gehrs-Pahl | Re: GraBitblt() on Wed, 01 Apr 2020 00:28:20 -0400 Diego, >In addition to what Andreas says, you can try it this way. There is a small error in your code. In lines 279-282, the functions Bin2U() must actually be Bin2L(), or the application will crash with an error, if the dialog is moved (even just partially) somewhere to the left or above the default desktop, which results in negative screen coordinates. 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 | |
Jose Antonio Diego Kereje | Re: GraBitblt() on Thu, 02 Apr 2020 00:01:47 +0200 Andreas, You're right, of course. The bad habit of "dragging" old code... Thank you. Regards. Diego | |
Carlos A Beling | Re: GraBitblt() on Sat, 04 Apr 2020 11:41:33 -0300 Hello Diego. Good night. I used the code below for saving a xbpCrt() area and it was saved an area with a border outside the area of XbpCrt() as shown in the attach. Do you know why? Many thanks again. Fraternally Beling On 30/03/2020 13:38, Jose Antonio Diego Kereje wrote: > Hi, > > In addition to what Andreas says, you can try it this way. > > Regards. Diego XbpCrt.png | |
Jose Antonio Diego Kereje | Re: GraBitblt() on Sun, 05 Apr 2020 16:44:55 +0200 Carlos, Window size includes border + border decoration. Try this new sample that includes three different alternatives for what you want. Regards. Diego Test.zip | |
Carlos A Beling | Re: GraBitblt() on Mon, 06 Apr 2020 11:37:47 -0300 Hello Diego. Good day. Again many, many thanks. Great: this function can to be used for users capture screens. Fraternally Beling On 05/04/2020 11:44, Jose Antonio Diego Kereje wrote: > Carlos, > > Window size includes border + border decoration. > > Try this new sample that includes three different alternatives for what > you want. > > Regards. Diego | |
Andreas Gehrs-Pahl | Re: GraBitblt() on Mon, 06 Apr 2020 15:44:16 -0400 Carlos, >Great: this function can to be used for users capture screens. So can the one I posted earlier, and it can also capture the entire desktop, no matter its size or position. Why would you want to use multiple routines, when a single, simpler, one is sufficient for both purposes? Just curious... 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 Tue, 07 Apr 2020 10:17:44 -0300 Hello Andreas. Good day. Many thanks again. I am trying to learn about these functions - and other APIs - and I study each one that is posted here until I understand them. You are right that to use a single and the more simpler function is the best solution. I would like to thank all of you and saying that this our comunication has been so rich for me . Fraternally Beling On 06/04/2020 16:44, Andreas Gehrs-Pahl wrote: > Carlos, > >> Great: this function can to be used for users capture screens. > > So can the one I posted earlier, and it can also capture the entire desktop, > no matter its size or position. Why would you want to use multiple routines, > when a single, simpler, one is sufficient for both purposes? > > Just curious... > > Andreas > | |
Carlos A Beling | Re: GraBitblt() on Tue, 31 Mar 2020 09:50:06 -0300 Hello. Good day. Many thanks to you that helped me sending light in my darkness about the Windows's Api. 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 |