QB64.org Forum

Active Forums => QB64 Discussion => Topic started by: LM on March 22, 2021, 09:40:37 am

Title: _SCREENIMAGE bug?
Post by: LM on March 22, 2021, 09:40:37 am
I thought I'd throw this out there to see if anyone has any ideas.

Trying to do a screenshot using image& = _SCREENIMAGE.  My screen is set to 1920x1080, but I only get a partial image of the screen.  This is what I get:
_Width(image&) reports 1536 instead of 1920
_Height(image&) reports 864 instead of 1080

I am wondering if it could have to do with the font/text size zoom in Windows 10?  I have the resolution at 1920x1080 but have the Windows font/text size set at 125%.  1920 /1.25 = 1536 and 1080 / 1.25 = 864.  Not certain yet whether the text size is the issue as I have not had a chance to test my hypothesis.  I need to keep the Windows text size at 125% while still being able to get a full screenshot.

What do people think?  Any other ideas?  If that is the issue, how can I get a full screenshot instead of a partial screenshot?
Title: Re: _SCREENIMAGE bug?
Post by: 191Brian on March 22, 2021, 10:14:41 am
Hi

Your calculations seem to indicate you have correctly identified the cause, as far as I can tell the windows 10 is slightly misleading when it describes that setting as the the size of text as it scales the whole screen not just text.  That said I don't know what the solution would be.   
Title: Re: _SCREENIMAGE bug?
Post by: SpriggsySpriggs on March 22, 2021, 10:19:54 am
This is the code block that performs the _SCREENIMAGE function. I'll do some looking online about fixes or workarounds
Code: C++: [Select]
  1. int32 func__screenimage(int32 x1,int32 y1,int32 x2,int32 y2,int32 passed){
  2.    
  3.     #ifdef QB64_WINDOWS
  4.        
  5.         static int32 init=0;
  6.         static int32 x,y,w,h;
  7.        
  8.         static HWND hwnd;
  9.         static RECT rect;
  10.         static HDC hdc;
  11.        
  12.         if (!init){
  13.             hwnd=GetDesktopWindow();
  14.             GetWindowRect(hwnd,&rect);
  15.             x=rect.right-rect.left; y=rect.bottom-rect.top;
  16.         }
  17.        
  18.         hdc=GetDC(NULL);
  19.        
  20.         static HDC hdc2=NULL;
  21.         static HBITMAP bitmap;
  22.         static int32 bx,by;
  23.        
  24.         if (passed){
  25.             if (x1<0) x1=0;
  26.             if (y1<0) y1=0;
  27.             if (x2>x-1) x2=x-1;
  28.             if (y2>y-1) y2=y-1;
  29.             w=x2-x1+1; h=y2-y1+1;
  30.             }else{
  31.             x1=0; x2=x-1; y1=0; y2=y-1; w=x; h=y;
  32.         }
  33.        
  34.        
  35.        
  36.         if (hdc2){
  37.             if ((w!=bx)||(h!=by)){
  38.                 DeleteObject(bitmap);
  39.                 ReleaseDC(NULL,hdc2);
  40.                 hdc2=CreateCompatibleDC(hdc);
  41.                 bitmap=CreateCompatibleBitmap(hdc,w,h); bx=w; by=h;
  42.                 SelectObject(hdc2,bitmap);
  43.             }
  44.             }else{
  45.             hdc2=CreateCompatibleDC(hdc);
  46.             bitmap=CreateCompatibleBitmap(hdc,w,h); bx=w; by=h;
  47.             SelectObject(hdc2,bitmap);
  48.         }
  49.        
  50.         init=1;
  51.        
  52.         BitBlt(        hdc2,
  53.         0,0,
  54.         w,h,
  55.         hdc,
  56.         x1,y1,
  57.         SRCCOPY);
  58.        
  59.         static BITMAPFILEHEADER   bmfHeader;  
  60.         static BITMAPINFOHEADER   bi;
  61.         bi.biSize = sizeof(BITMAPINFOHEADER);    
  62.         bi.biWidth = w;    
  63.         bi.biHeight = -h; //A bottom-up DIB is specified by setting the height to a positive number, while a top-down DIB is specified by setting the height to a negative number. The bitmap color table will be appended to the BITMAPINFO structure.
  64.         bi.biPlanes = 1;    
  65.         bi.biBitCount = 32;    
  66.         bi.biCompression = BI_RGB;    
  67.         bi.biSizeImage = 0;  
  68.         bi.biXPelsPerMeter = 0;    
  69.         bi.biYPelsPerMeter = 0;    
  70.         bi.biClrUsed = 0;    
  71.         bi.biClrImportant = 0;
  72.        
  73.         static int32 i,i2;
  74.         i2=func__dest();
  75.         i=func__newimage(w,h,32,1);
  76.         sub__dest(i);
  77.        
  78.         GetDIBits(hdc2,bitmap,0,h,write_page->offset,(BITMAPINFO*)&bi, DIB_RGB_COLORS);
  79.         sub__setalpha(255,NULL,NULL,NULL,0);
  80.         sub__dest(i2);
  81.        
  82.         ReleaseDC(NULL,hdc);
  83.         return i;
  84.         #else
  85.         return func__newimage(func_screenwidth(), func_screenheight(), 32, 1);
  86.     #endif
  87. }

Try running this below code and let me know your results:
Code: QB64: [Select]
  1.  
  2. Type RECT
  3.     As Long left, top, right, bottom
  4.  
  5.     Function SetProcessDPIAware%% ()
  6.  
  7.     Function GetDesktopWindow%& ()
  8.     Function GetWindowRect%% (ByVal hWnd As _Offset, Byval lpRect As _Offset)
  9.     Function GetClientRect%% (ByVal hWnd As _Offset, Byval lpRect As _Offset)
  10.  
  11. Print SetProcessDPIAware
  12. Dim As _Offset desktop
  13. Dim As RECT rect, rect2
  14. desktop = GetDesktopWindow
  15. If desktop Then
  16.     If GetWindowRect(desktop, _Offset(rect)) Then
  17.         Print rect.left, rect.top, rect.right, rect.bottom
  18.         If GetClientRect(desktop, _Offset(rect2)) Then
  19.             Print rect2.left, rect2.top, rect2.right, rect2.bottom
  20.         End If
  21.     End If
Title: Re: _SCREENIMAGE bug?
Post by: Petr on March 22, 2021, 12:27:54 pm
Just for test: What returns functions _DESKTOPWIDTH and _DESKTOPHEIGHT? If 1920 to 1080, try use image& =  _SCREENIMAGE(0, 0, _DESKTOPWIDTH, _DESKTOPHEIGHT), what it do.
Title: Re: _SCREENIMAGE bug?
Post by: SpriggsySpriggs on March 22, 2021, 12:32:04 pm
@Petr Without the program being DPI aware the results will be the scaled resolution, not 1920 x 1080 (I tested your above code and the image is 1536 x 864). I found a fix and I've made a pull request on GitHub.
Title: Re: _SCREENIMAGE bug?
Post by: Petr on March 22, 2021, 12:34:20 pm
@SpriggsySpriggs  Oh, thank you for the information :)
Title: Re: _SCREENIMAGE bug?
Post by: SpriggsySpriggs on March 22, 2021, 04:11:46 pm
@LM I have found the bug and squashed it, looks like. I am just waiting for the pull request on GitHub to be approved. Once it is, I'll let you know and you can download the Dev build and be A-OK.
Title: Re: _SCREENIMAGE bug?
Post by: LM on March 22, 2021, 05:29:55 pm
@LM I have found the bug and squashed it, looks like. I am just waiting for the pull request on GitHub to be approved. Once it is, I'll let you know and you can download the Dev build and be A-OK.

@SpriggsySpriggs
Thanks!  It sounds great that you found the bug.  I appreciate that you are looking in to it!  Please let me know once it is available.

Unfortunately I have not yet had a chance to test the code you asked me to run earlier and probably can't get to it yet for a few hours.  It sounds like you have found the issue/solution so I assume you don't need me to run it anymore, but please let me know if my assumption is incorrect.

Title: Re: _SCREENIMAGE bug?
Post by: George McGinn on March 22, 2021, 06:37:39 pm
I will give this code a test on both macOS (Big Sur) and Linux to see if I get the same results.

My guess is that it could be the Windows OS (which is why I don't run it anymore!

I'll do this sometime tonight and post my results here.
Title: Re: _SCREENIMAGE bug?
Post by: SpriggsySpriggs on March 22, 2021, 07:17:24 pm
@George McGinn This shouldn't apply to Linux or Mac at all. LM mentioned he is running the code in Windows 10.
Title: Re: _SCREENIMAGE bug?
Post by: SpriggsySpriggs on March 22, 2021, 07:29:42 pm
It sounds like you have found the issue/solution so I assume you don't need me to run it anymore, but please let me know if my assumption is incorrect.

@LM I'd be interested to know that it does rectify the issue on your end. If you get a chance to run it, please do. I know it worked for me because I was setting the environment to be aware of the DPI scaling which resulted in correct screenshots. I know it should work on your machine but it would be good to see if it works on yours. Don't feel like you absolutely must, though. Chances are, the bug fix will work and you won't have to worry at all.
Title: Re: _SCREENIMAGE bug?
Post by: George McGinn on March 22, 2021, 08:27:20 pm
I tried to run the second program in your post and I get a DYNAMIC LIBRARY not found on line 7 for the statement:
   DECLARE DYNAMIC LIBRARY "User32",6

I think this is a Windows feature, as any program the declares a DYNAMIC LIBRARY will not work on Linux.

I tried. I think this will also be a problem in macOS, so I will not try it there.

George


@LM I'd be interested to know that it does rectify the issue on your end. If you get a chance to run it, please do. I know it worked for me because I was setting the environment to be aware of the DPI scaling which resulted in correct screenshots. I know it should work on your machine but it would be good to see if it works on yours. Don't feel like you absolutely must, though. Chances are, the bug fix will work and you won't have to worry at all.
Title: Re: _SCREENIMAGE bug?
Post by: SpriggsySpriggs on March 22, 2021, 08:31:30 pm
@George McGinn This shouldn't apply to Linux or Mac at all. LM mentioned he is running the code in Windows 10.
@George McGinn As LM mentioned in his post, he's using Windows. The code I mentioned you could try running was his code in the original post, not mine. Mine is Windows only since this is a Windows issue. User32 is a Windows DLL.
Title: Re: _SCREENIMAGE bug?
Post by: LM on March 22, 2021, 09:50:16 pm
@LM I'd be interested to know that it does rectify the issue on your end. If you get a chance to run it, please do. I know it worked for me because I was setting the environment to be aware of the DPI scaling which resulted in correct screenshots. I know it should work on your machine but it would be good to see if it works on yours. Don't feel like you absolutely must, though. Chances are, the bug fix will work and you won't have to worry at all.

@SpriggsySpriggs
I did not have a chance to run it on the Win 10 machine but I was able to reproduce the issue on a Windows 8.0 machine (resolution 1920x1080, but set to enlarge text).  This is the output from your code:
1
0     0     1536    864
0     0     1536    864

When I do a screenshot with _SCREENIMAGE, I only get part of the screen.  What I get is a 1536 x 864 image that represents the upper left portion of the screen.  The lower right portion that I see on my actual computer screen is not included.

When I change the Windows settings back to not enlarge the text, _SCREENIMAGE grabs the whole screen correctly (1920x1080 image), and the output of your code is: 
1
0     0     1920   1080
0     0     1920   1080

I assume it will work exactly the same on the Windows 10 machine, but I am not able to get to that machine right now.

Does this help?  Thanks!
Title: Re: _SCREENIMAGE bug?
Post by: SpriggsySpriggs on March 22, 2021, 10:07:43 pm
Hmmmmm.... That does make me curious..... It should have made the program report back 1920 x 1080. Very curious. Something I haven't asked you yet is if you are on 32 or 64 bit.... Which are you on? It works fine for me in Windows 10 20H2 64 bit with QB64 x64 and with QB64 x32. If you can, try running this code in both your Windows 8 and Windows 10 environments.
@LM
Code: QB64: [Select]
  1.  
  2. Type RECT
  3.     As Long left, top, right, bottom
  4.  
  5.     Function SetProcessDPIAware%% ()
  6.  
  7.     Function SetProcessDpiAwareness%& (ByVal value As Long)
  8.  
  9.     Function GetDesktopWindow%& ()
  10.     Function GetWindowRect%% (ByVal hWnd As _Offset, Byval lpRect As _Offset)
  11.     Function GetClientRect%% (ByVal hWnd As _Offset, Byval lpRect As _Offset)
  12.  
  13. 'Print SetProcessDPIAware
  14. Print SetProcessDpiAwareness(1)
  15.  
  16. Dim As _Offset desktop
  17. Dim As RECT rect, rect2
  18. desktop = GetDesktopWindow
  19. If desktop Then
  20.     If GetWindowRect(desktop, _Offset(rect)) Then
  21.         Print rect.left, rect.top, rect.right, rect.bottom
  22.         If GetClientRect(desktop, _Offset(rect2)) Then
  23.             Print rect2.left, rect2.top, rect2.right, rect2.bottom
  24.         End If
  25.     End If
Title: Re: _SCREENIMAGE bug?
Post by: LM on March 22, 2021, 10:26:37 pm
Hmmmmm.... That does make me curious..... It should have made the program report back 1920 x 1080. Very curious. Something I haven't asked you yet is if you are on 32 or 64 bit.... Which are you on?

@SpriggsySpriggs
64 bit in both cases (both the Win 10 and Win 8.0 machines).
Title: Re: _SCREENIMAGE bug?
Post by: SpriggsySpriggs on March 22, 2021, 10:29:33 pm
@LM Apologies, I edited my reply just as you were replying to it. Please review the code I posted and try running it in both of your environments.
Title: Re: _SCREENIMAGE bug?
Post by: LM on March 22, 2021, 10:37:00 pm
@LM Apologies, I edited my reply just as you were replying to it. Please review the code I posted and try running it in both of your environments.

@SpriggsySpriggs
I can only do Win 8 at the moment.  This is what I get with no text enlargement:
0
0     0     1920   1080
0     0     1920   1080

This is what I get with text enlargement:
0
0     0     1536   864
0     0     1536   864

And this is what I get with even more text enlargement:

This is what I get with text enlargement (largest):
0
0     0     1280   720
0     0     1280   720

In all cases, the actual screen that I see on the computer still appears to be 1920x1080 but windows and text are enlarged.  I mean, things like the clock, date and small icons in the task bar are still 1920x1080 type resolution regardless of the text enlargement setting.

LM


Title: Re: _SCREENIMAGE bug?
Post by: SpriggsySpriggs on March 22, 2021, 10:38:14 pm
You keep saying "Text enlargement". Are you doing something other than just scaling your resolution? I'd almost ask you to download my fork from GitHub and compile it to see if you can get the right results before we do a merge. I've not had one instance of it not working with my code so it is strange that yours is behaving like this, especially since the first function I gave you works in Vista and up and the second one starts with Windows 8.1. If you are only doing a text enlargement then that's probably why you aren't seeing a change. Resolution scaling != text size increase.

@Petr Can you run my last code snippet on your machine after changing your resolution scaling to something other than 100%?  If you can run it once with SetProcessDPIAware and once with SetProcessDpiAwareness then that will be great. A success with SetProcessDPIAware is anything nonzero and a success with SetProcessDpiAwareness is zero.
Title: Re: _SCREENIMAGE bug?
Post by: LM on March 22, 2021, 10:50:25 pm
You keep saying "Text enlargement". Are you doing something other than just scaling your resolution? I'd almost ask you to download my fork from GitHub and compile it to see if you can get the right results before we do a merge. I've not had one instance of it not working with my code so it is strange that yours is behaving like this, especially since the first function I gave you works in Vista and up and the second one starts with Windows 8. If you are only doing a text enlargement then that's probably why you aren't seeing a change. Resolution scaling != text size increase.

@SpriggsySpriggs
I have attached images of my settings.  The only thing I changed in the different scenarios is sliding the slider to the different positions (smaller -> larger) (see text_enlargement_settings_Win8.jpg).  I will try to check on Win 10 tomorrow - probably can't get to that machine tonight.

Again, in all cases the true resolution of my computer screen remains 1920x1080, but the size of text and windows vary.
Title: Re: _SCREENIMAGE bug?
Post by: SpriggsySpriggs on March 22, 2021, 10:55:56 pm
@LM I am seeing something in the settings that grabs my attention. In your second screenshot, the note at the bottom that mentions that the settings may not be applied until next time you sign out and sign in. I've seen posts online saying that people in 8 and above have had issues with SetProcessDPIAware and SetProcessDpiAwareness because they had not signed out and signed back in, finalizing the settings. In Windows 10, a log out and log in is not required as the settings can be finalized immediately.
Title: Re: _SCREENIMAGE bug?
Post by: LM on March 23, 2021, 12:03:07 am
@LM I am seeing something in the settings that grabs my attention. In your second screenshot, the note at the bottom that mentions that the settings may not be applied until next time you sign out and sign in. I've seen posts online saying that people in 8 and above have had issues with SetProcessDPIAware and SetProcessDpiAwareness because they had not signed out and signed back in, finalizing the settings. In Windows 10, a log out and log in is not required as the settings can be finalized immediately.

@SpriggsySpriggs
Great catch!  It seems to work after I restarted the Win 8 machine.  I get this with the "medium" setting now:
0
0     0     1920   1080
0     0     1920   1080

With your code preceding the image& = _SCREENIMAGE statement, it appears that it is now grabbing the full screen like I want.  I will try it on the Win 10 machine tomorrow.

I appreciate your effort on this.  Sorry for the back and forth tonight.  Great catch on the restart required in Win 8.

LM

Title: Re: _SCREENIMAGE bug?
Post by: LM on March 23, 2021, 07:43:06 am
@SpriggsySpriggs
Great catch!  It seems to work after I restarted the Win 8 machine.  I get this with the "medium" setting now:
0
0     0     1920   1080
0     0     1920   1080

With your code preceding the image& = _SCREENIMAGE statement, it appears that it is now grabbing the full screen like I want.  I will try it on the Win 10 machine tomorrow.

I appreciate your effort on this.  Sorry for the back and forth tonight.  Great catch on the restart required in Win 8.

LM

@SpriggsySpriggs
It works now on the Win 10 machine too (with your code).  Thanks!
Title: Re: _SCREENIMAGE bug?
Post by: SpriggsySpriggs on March 23, 2021, 09:16:23 am
@LM Glad to hear it worked! It sure had me baffled! Well, I guess the fact that it fixed your issue along with hanness' makes it a good evidence for a new merge on GitHub! Thank you for trying it out.
Title: Re: _SCREENIMAGE bug?
Post by: George McGinn on March 23, 2021, 01:51:58 pm
I'm on 64-bit
Title: Re: _SCREENIMAGE bug?
Post by: SpriggsySpriggs on March 24, 2021, 12:45:30 pm
@LM The latest dev build contains the bug fix and makes the program DPI aware. Download it at your convenience and let us know how it goes for you!
Title: Re: _SCREENIMAGE bug?
Post by: LM on March 24, 2021, 11:35:39 pm
@LM The latest dev build contains the bug fix and makes the program DPI aware. Download it at your convenience and let us know how it goes for you!

@SpriggsySpriggs
Thanks!  Much appreciated.  I will check it out.