Author Topic: _SCREENIMAGE bug?  (Read 7849 times)

0 Members and 1 Guest are viewing this topic.

Offline LM

  • Newbie
  • Posts: 28
    • View Profile
_SCREENIMAGE bug?
« 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?

Offline 191Brian

  • Newbie
  • Posts: 91
    • View Profile
    • My Itch page
Re: _SCREENIMAGE bug?
« Reply #1 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.   
Brian ...

Marked as best answer by LM on March 29, 2021, 01:37:56 pm

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: _SCREENIMAGE bug?
« Reply #2 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
« Last Edit: March 22, 2021, 11:37:38 am by SpriggsySpriggs »
Shuwatch!

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: _SCREENIMAGE bug?
« Reply #3 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.

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: _SCREENIMAGE bug?
« Reply #4 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.
« Last Edit: March 22, 2021, 07:27:12 pm by SpriggsySpriggs »
Shuwatch!

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: _SCREENIMAGE bug?
« Reply #5 on: March 22, 2021, 12:34:20 pm »
@SpriggsySpriggs  Oh, thank you for the information :)

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: _SCREENIMAGE bug?
« Reply #6 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.
Shuwatch!

Offline LM

  • Newbie
  • Posts: 28
    • View Profile
Re: _SCREENIMAGE bug?
« Reply #7 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.


Offline George McGinn

  • Global Moderator
  • Forum Regular
  • Posts: 210
    • View Profile
    • Resume
Re: _SCREENIMAGE bug?
« Reply #8 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.
____________________________________________________________________
George McGinn
Theoretical/Applied Computer Scientist
Member: IEEE, IEEE Computer Society
Technical Council on Software Engineering
IEEE Standards Association
American Association for the Advancement of Science (AAAS)

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: _SCREENIMAGE bug?
« Reply #9 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.
« Last Edit: March 22, 2021, 07:25:28 pm by SpriggsySpriggs »
Shuwatch!

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: _SCREENIMAGE bug?
« Reply #10 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.
Shuwatch!

Offline George McGinn

  • Global Moderator
  • Forum Regular
  • Posts: 210
    • View Profile
    • Resume
Re: _SCREENIMAGE bug?
« Reply #11 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.
____________________________________________________________________
George McGinn
Theoretical/Applied Computer Scientist
Member: IEEE, IEEE Computer Society
Technical Council on Software Engineering
IEEE Standards Association
American Association for the Advancement of Science (AAAS)

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: _SCREENIMAGE bug?
« Reply #12 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.
Shuwatch!

Offline LM

  • Newbie
  • Posts: 28
    • View Profile
Re: _SCREENIMAGE bug?
« Reply #13 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!

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: _SCREENIMAGE bug?
« Reply #14 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
« Last Edit: March 22, 2021, 10:28:16 pm by SpriggsySpriggs »
Shuwatch!