Author Topic: Program code ScreenShot non QB64 program fullscreen *** SOLVED = [⊞] + [PrtSc]  (Read 2879 times)

0 Members and 1 Guest are viewing this topic.

Offline Richard

  • Seasoned Forum Regular
  • Posts: 364
    • View Profile
I am trying to in a program take a ScreenShot of a Windows Screen (the QB64 program window is not visible).

I have tried Auto Hot Key which using ^J (CHR$(10)) as the hotkey for PrintScreen and this takes a screenshot when I manually use it (i.e. Ctrl J), but when I attempt to script it for program control - the external program does not seem to accept the ^J for the screenshot via the

SHELL _DONTWAIT "START /MAX MyExternalProgram.exe filename.ext"

_CLIPBOARD$ = CHR$(10)  ' Ctrl + J     .ahk file  ^-^-#{PrintScreen}   reduce screen elements a few times THEN take a ScreenShot

PRINT _CLIPBOARD$

_SCREENPRINT CHR$(22)  ' Ctrl + V paste from clipboard

_DELAY 5

Since it is not a QB64 program screen, I cannot use my program screenshot routine. Any way (program-wise) to get a ScreenShot?
« Last Edit: November 15, 2020, 08:07:59 pm by Richard »

Offline RhoSigma

  • QB64 Developer
  • Forum Resident
  • Posts: 565
    • View Profile
Re: Program code to ScreenShot non QB64 program full screen
« Reply #1 on: November 15, 2020, 09:06:28 am »
My Projects:   https://qb64forum.alephc.xyz/index.php?topic=809
GuiTools - A graphic UI framework (can do multiple UI forms/windows in one program)
Libraries - ImageProcess, StringBuffers (virt. files), MD5/SHA2-Hash, LZW etc.
Bonus - Blankers, QB64/Notepad++ setup pack

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Program code to ScreenShot non QB64 program full screen
« Reply #2 on: November 15, 2020, 09:08:05 am »
_SCREENIMAGE
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Richard

  • Seasoned Forum Regular
  • Posts: 364
    • View Profile
Re: Program code to ScreenShot non QB64 program full screen
« Reply #3 on: November 15, 2020, 10:02:47 am »
@RhoSigma
@Steve

Thanks for your replies.

Based on the Wiki example, I inserted the following Code fragment at the beginning of the program:-

desktop& = _SCREENIMAGE
MaxScreenx& = _WIDTH(desktop&)
MaxScreeny& = _HEIGHT(desktop&)
_FREEIMAGE desktop ' free image after measuring screen (it is not displayed)
SCREEN _NEWIMAGE(MaxScreenx&, MaxScreeny&, 32) ' program window is sized to fit
_SCREENMOVE 0, 0

PRINT "..."


then had my stuff calling my externalprogram

and then used my simple .BMP format screendump


open "A:\screen32.bmp" for binary as #1

... 56 byte header

FOR y% = 1799 TO 0 STEP -1
    FOR x% = 0 TO 3199

        c& = POINT(x%, y%)

        r$ = CHR$(_RED32(c&))
        g$ = CHR$(_GREEN32(c&))
        b$ = CHR$(_BLUE32(c&))
        a$ = CHR$(_ALPHA32(c&))       '       PUT #1, , a$ alpha field not saved in .bmp format used  so ONLY 3 bytes RGB used per pixel

        PUT #1, , r$
        PUT #1, , g$
        PUT #1, , b$
    NEXT
NEXT


CLOSE #1



Now the externalprogram is NOT FULLSCREEN and the .bmp file is all black with my "..." at top left hand corner. Its as if I cannot access anything outside of the QB64 program window.

Any further suggestions (hoping its something I omitted)?


Offline RhoSigma

  • QB64 Developer
  • Forum Resident
  • Posts: 565
    • View Profile
Re: Program code to ScreenShot non QB64 program full screen
« Reply #4 on: November 15, 2020, 11:00:54 am »
1. Run external program (guess it will output something into its own window/console on the desktop)
2. Catch the current desktop contents using _SCREENIMAGE
3. Do whatever you want with the image handle obtained from step 2. (save it, print it or whatever)
4. Free the desktop image handle using _FREEIMAGE
My Projects:   https://qb64forum.alephc.xyz/index.php?topic=809
GuiTools - A graphic UI framework (can do multiple UI forms/windows in one program)
Libraries - ImageProcess, StringBuffers (virt. files), MD5/SHA2-Hash, LZW etc.
Bonus - Blankers, QB64/Notepad++ setup pack

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Program code to ScreenShot non QB64 program full screen
« Reply #5 on: November 15, 2020, 11:27:34 am »
Hi. Source for image miss:

desktop& = _SCREENIMAGE
MaxScreenx& = _WIDTH(desktop&)
MaxScreeny& = _HEIGHT(desktop&)

SCREEN _NEWIMAGE(MaxScreenx&, MaxScreeny&, 32) ' program window is sized to fit
_SCREENMOVE 0, 0

PRINT "..."


then had my stuff calling my externalprogram

and then used my simple .BMP format screendump


open "A:\screen32.bmp" for binary as #1

... 56 byte header
_SOURCE  desktop&
FOR y% = 1799 TO 0 STEP -1
    FOR x% = 0 TO 3199

        c& = POINT(x%, y%)

        r$ = CHR$(_RED32(c&))
        g$ = CHR$(_GREEN32(c&))
        b$ = CHR$(_BLUE32(c&))
        a$ = CHR$(_ALPHA32(c&))       '       PUT #1, , a$ alpha field not saved in .bmp format used  so ONLY 3 bytes RGB used per pixel

        PUT #1, , r$
        PUT #1, , g$
        PUT #1, , b$
    NEXT
NEXT

_FREEIMAGE desktop& ' free image after measuring it (you do not need graphical mode SCREEN for work with images)
CLOSE #1
« Last Edit: November 15, 2020, 11:29:30 am by Petr »

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Program code to ScreenShot non QB64 program full screen
« Reply #6 on: November 15, 2020, 11:41:28 am »
I'm not really certain what you're trying to do with your example, Richard, so I thought I'd just go the route of giving you a working example to start from:

Code: QB64: [Select]
  1. _SCREENHIDE 'Hide our QB64 screen, so we don't grab a capture of it
  2. DesktopImage = _SCREENIMAGE
  3. SCREEN QB64Screen 'set our screen
  4. _SCREENSHOW 'Show our QB64 screen, so we can see what we're doing
  5. _SCREENMOVE 0, 0 'move it to the top left of our desktop
  6. _PUTIMAGE (_WIDTH, _HEIGHT)-(0, 0), DesktopImage 'place the screenimage onto our QB64 screen -- upside down
  7.  
  8. SaveBMP "UpsideDown.bmp", 0, 0, 0, _WIDTH, _HEIGHT 'Save it to the drive
  9.  
  10.  
  11.  
  12. SUB SaveBMP (filename$, image&, x1%, y1%, x2%, y2%)
  13.     'Super special STEVE-Approved BMP Export routine for use with any QB64 graphic mode.
  14.     IF x2% = _WIDTH(image&) THEN x2% = x2% - 1
  15.     IF y2% = _HEIGHT(image&) THEN y2% = y2% - 1
  16.  
  17.     IF _PIXELSIZE(image&) = 0 THEN
  18.         IF SaveTextAs256Color THEN
  19.             tempimage& = TextScreenToImage256&(image&)
  20.         ELSE
  21.             tempimage& = TextScreenToImage32&(image&)
  22.         END IF
  23.         F = _FONT(image&)
  24.         FW = _FONTWIDTH(F): FH = _FONTHEIGHT(F)
  25.         SaveBMP filename$, tempimage&, x1% * FW, y1% * FH, x2% * FW, y2% * FH
  26.         _FREEIMAGE tempimage&
  27.         EXIT FUNCTION
  28.     END IF
  29.  
  30.     TYPE BMPFormat
  31.         ID AS STRING * 2
  32.         Size AS LONG
  33.         Blank AS LONG
  34.         Offset AS LONG
  35.         Hsize AS LONG
  36.         PWidth AS LONG
  37.         PDepth AS LONG
  38.         Planes AS INTEGER
  39.         BPP AS INTEGER
  40.         Compression AS LONG
  41.         ImageBytes AS LONG
  42.         Xres AS LONG
  43.         Yres AS LONG
  44.         NumColors AS LONG
  45.         SigColors AS LONG
  46.     END TYPE
  47.  
  48.  
  49.     DIM BMP AS BMPFormat
  50.     DIM x AS LONG, y AS LONG
  51.     DIM temp AS STRING, t AS STRING * 1
  52.  
  53.     DIM n AS _MEM, o AS _OFFSET, m AS _MEM
  54.     m = _MEMIMAGE(image&)
  55.  
  56.     IF x1% > x2% THEN SWAP x1%, x2%
  57.     IF y1% > y2% THEN SWAP y1%, y2%
  58.     IF x2% = _WIDTH(imagehandle%) THEN x2% = _WIDTH(imagehandle%) - 1 'troubleshoot in case user does a common mistake for 0-width instead of 0 - (width-1) for fullscreen
  59.     IF y2% = _HEIGHT(imagehandle%) THEN y2% = _HEIGHT(imagehandle%) - 1 'troubleshoot in case user does a common mistake for 0-width instead of 0 - (width-1) for fullscreen
  60.  
  61.     s& = _SOURCE
  62.     _SOURCE image&
  63.  
  64.     BMP.PWidth = (x2% - x1%) + 1
  65.     BMP.PDepth = (y2% - y1%) + 1
  66.     BMP.ID = "BM"
  67.     BMP.Blank = 0
  68.     BMP.Hsize = 40
  69.     BMP.Planes = 1
  70.     BMP.Compression = 0
  71.     BMP.Xres = 0
  72.     BMP.Yres = 0
  73.  
  74.     BMP.SigColors = 0
  75.  
  76.     SELECT CASE _PIXELSIZE(image&)
  77.         CASE 1
  78.             temp = SPACE$(x2% - x1% + 1)
  79.             OffsetBITS& = 54 + 1024 'add palette in 256 color modes
  80.             BMP.BPP = 8
  81.             IF BMP.PWidth MOD 4 THEN ZeroPAD$ = SPACE$(4 - (BMP.PWidth MOD 4))
  82.             ImageSize& = (BMP.PWidth + LEN(ZeroPAD$)) * BMP.PDepth
  83.             BMP.ImageBytes = ImageSize&
  84.             BMP.NumColors = 256
  85.             BMP.Size = ImageSize& + OffsetBITS&
  86.             BMP.Offset = OffsetBITS&
  87.         CASE 4
  88.             temp = SPACE$(3)
  89.             OffsetBITS& = 54 'no palette in 24/32 bit
  90.             BMP.BPP = 24
  91.             IF ((BMP.PWidth * 3) MOD 4) THEN ZeroPAD$ = SPACE$(4 - ((BMP.PWidth * 3) MOD 4))
  92.             ImageSize& = (BMP.PWidth + LEN(ZeroPAD$)) * BMP.PDepth
  93.             BMP.ImageBytes = ImageSize&
  94.             BMP.NumColors = 0
  95.             BMP.Size = ImageSize& * 3 + OffsetBITS&
  96.             BMP.Offset = OffsetBITS&
  97.     END SELECT
  98.  
  99.     F = FREEFILE
  100.     n = _MEMNEW(BMP.Size)
  101.     _MEMPUT n, n.OFFSET, BMP
  102.     o = n.OFFSET + 54
  103.     zp& = LEN(ZeroPAD$)
  104.  
  105.     IF BMP.BPP = 8 THEN 'Store the Palette for 256 color mode
  106.         FOR c& = 0 TO 255 ' read BGR color settings from JPG image + 1 byte spacer(CHR$(0))
  107.             cv& = _PALETTECOLOR(c&, image) ' color attribute to read.
  108.             b$ = CHR$(_BLUE32(cv&)) + CHR$(_GREEN32(cv&)) + CHR$(_RED32(cv&)) + CHR$(0) 'spacer byte
  109.             _MEMPUT n, o, b$
  110.             o = o + 4
  111.         NEXT
  112.         y = y2% + 1
  113.         w& = _WIDTH(image&)
  114.         x = x2% - x1% + 1
  115.         DO
  116.             y = y - 1
  117.             _MEMGET m, m.OFFSET + (w& * y + x1%), temp
  118.             _MEMPUT n, o, temp
  119.             o = o + x
  120.             _MEMPUT n, o, ZeroPAD$
  121.             o = o + zp&
  122.         LOOP UNTIL y = y1%
  123.     ELSE
  124.         y = y2% + 1
  125.         w& = _WIDTH(image&)
  126.         DO
  127.             y = y - 1: x = x1% - 1
  128.             DO
  129.                 x = x + 1
  130.                 _MEMGET m, m.OFFSET + (w& * y + x) * 4, temp
  131.                 _MEMPUT n, o, temp
  132.                 o = o + 3
  133.             LOOP UNTIL x = x2%
  134.             _MEMPUT n, o, ZeroPAD$
  135.             o = o + zp&
  136.         LOOP UNTIL y = y1%
  137.     END IF
  138.     _MEMFREE m
  139.     OPEN filename$ FOR BINARY AS #F
  140.     t1$ = SPACE$(BMP.Size)
  141.     _MEMGET n, n.OFFSET, t1$
  142.     PUT #F, , t1$
  143.     _MEMFREE n
  144.     CLOSE #F
  145.     _SOURCE s&
  146.  
  147.  

I hope the comments show what we're doing at each step of our code, but if you have any questions about anything, feel free to ask.  With this, you should end up with an "UpsideDown.bmp" file inside your QB64 folder, which looks like your desktop turned upside down and backwards.  :)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Richard

  • Seasoned Forum Regular
  • Posts: 364
    • View Profile
Re: Program code to ScreenShot non QB64 program full screen
« Reply #7 on: November 15, 2020, 02:04:58 pm »
@ Steve

MANY THANKS

Your program met my requirements "to capture the whole screen as I see it (eg Windows File Explorer, etc) - effectively a Windows 10 Print Screen.

In case you are interested - just to give you an example of what I wanted to achieve:-

Call an "externalprogram" (in this case MSedge.exe) and let it do its thing with a file as listed just below AND then let the QB64 program take a complete screenshot (saved as upsidedown.bmp). SO the very minor modifications to your program is the addition as below

_DELAY 5
SHELL _DONTWAIT "START /MAX msedge.exe A:\Download_NTFS_Reader_for_DOS_-_MajorGeeks.mhtml"
_DELAY 5

Note: the computer was "off-line" when running the program

The .bmp file was converted to a .png file and is below and represents exactly ALL that I see on my display.

WARNING It has been reported by some that stuff from the above website is suspicious

Now to work out how to make it right way round before saving

Thanks again Steve!

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Program code to ScreenShot non QB64 program full screen
« Reply #8 on: November 15, 2020, 02:39:13 pm »
It’s my PUTIMAGE that is reversing the image for us, by putting it from bottom right to top left.  Just reverse the order in that command to do it proper.

_PUTIMAGE (0, 0)-(_WIDTH, _HEIGHT), DesktopImage

Though, it sounds like all you need is to change the imagehandle in the SaveBMP command.

SaveBMP “MyFile.bmp”, DesktopImage, 0, 0, _WIDTH, _HEIGHT
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Richard

  • Seasoned Forum Regular
  • Posts: 364
    • View Profile
Re: Program code to ScreenShot non QB64 program full screen
« Reply #9 on: November 15, 2020, 02:47:54 pm »
@ Steve

Thanks again

I will try it out again tonite - it is sunrise now (I am going to bed)

@ Petr
@ RhoSigma

Thanks for your replies - will also check out tonite.
https://www.qb64.org/forum/index.php?topic=2276.75#lastPost
« Last Edit: December 12, 2020, 09:21:04 pm by Richard »