Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Screen Capture with Transparent Windows and Mouse Cursor


  • Please log in to reply
245 replies to this topic
ZeosCentric
  • Guests
  • Last active:
  • Joined: --
BUMP, ... hi does anyone know how to do this?, is there a Registry setting or some obscure dll call for temporarily turning off screen capture? Thank you for your help if this is possible.

tic
  • Members
  • 1934 posts
  • Last active: May 30 2018 08:13 PM
  • Joined: 22 Apr 2007
make printscreen a hotkey?

Sean
  • Members
  • 2462 posts
  • Last active: Feb 07 2012 04:00 AM
  • Joined: 12 Feb 2007

is there a Registry setting or some obscure dll call for temporarily turning off screen capture? Thank you for your help if this is possible.

You better ask in Ask for Help section.

ABCza
  • Members
  • 132 posts
  • Last active: Jan 04 2015 01:02 AM
  • Joined: 03 Jun 2008
Amazing. There's the possibility to change compression level for jpeg format? I don't know that libraries...
All my scripts/snippets are released under the WTFPL: http://sam.zoy.org/wtfpl/COPYING

Sean
  • Members
  • 2462 posts
  • Last active: Feb 07 2012 04:00 AM
  • Joined: 12 Feb 2007

There's the possibility to change compression level for jpeg format? I don't know that libraries...

I guess you mean the quality level of jpeg, and yes, GDI+ supports the quality level of jpeg. As it's easy to incorporate this into the current script, I'll implement it.

Sean
  • Members
  • 2462 posts
  • Last active: Feb 07 2012 04:00 AM
  • Joined: 12 Feb 2007
Uploaded new one incorporating JPEG quality level. Example is
CaptureScreen(0, 1, A_ScriptDir . "\screen.jpg", nQuality:=95)	; nQuality: 0 - 100


ABCza
  • Members
  • 132 posts
  • Last active: Jan 04 2015 01:02 AM
  • Joined: 03 Jun 2008
NICE!!! Thank you Sean, now it's perfect!
All my scripts/snippets are released under the WTFPL: http://sam.zoy.org/wtfpl/COPYING

Icarus
  • Members
  • 851 posts
  • Last active: Jan 02 2012 11:17 AM
  • Joined: 24 Nov 2005
Hey,

I needed to do a batch cropping of an image.
Always crop at the same places, but since I updated the image in some cases, I needed something that crops it automatically into separate PNG files.

So I have made this generic batch cropper, using this capture library.
To use, just edit the CropMatrix.txt file (sample below) as follows:
First line should contain the file name to crop
Each subsequent line should contain the rectangle coordinates.
Lines with a semicolon anywhere will be ignored (to allow commenting out)

The code
#SingleInstance Force
SetWorkingDir %A_ScriptDir%

Gosub Init
Gosub Main

Return
#Include ScreenCapture.ahk

Init:
  FileRead Matrix, CropMatrix.txt
  Row0 := 0
  Loop Parse, Matrix, `n,`r
  {
    If( A_LoopField <> "" ) and ( A_Index <> 1 ) and ( Not InStr( A_LoopField, ";" ) ) {
      Row0++
      Row%Row0% := A_LoopField
    }
    Else If( A_Index = 1 )
      SourceImage := A_LoopField
  }
  
  Gui Margin, 0,0
  Gui -Caption
  Gui Add, Picture,, %SourceImage%
  Gui Show, x0 y0
Return

Main:
  Loop %Row0% {
    File := A_ScriptDir . "\crop" . A_Index . ".png"  
    FileDelete %File%
    CaptureScreen( Row%A_Index%,false,File )
    ;If( FileExist( File ) )    ; Uncomment to see each capture 
    ; RunWait %File%
  }
  ExitApp
Return


The sample matrix file
screen.png
2,22,499,245
2,240,268,480
264,240,389,365
384,240,499,365
264,358,499,480


femke
  • Members
  • 16 posts
  • Last active: Nov 12 2008 02:10 PM
  • Joined: 02 Jun 2008
thanks for the very usefull script

i only noticed that the file when capturing in bmp is larger than with irfanview

230454 Kb for a 320 240 image in irfanview

307254 Kb with ahk

if i capture a single color a get a file with repeating values

for irfanview 5E 48 B0

for ahk 5E 00 48 B0

is this some coding inefficientcy?

Sean
  • Members
  • 2462 posts
  • Last active: Feb 07 2012 04:00 AM
  • Joined: 12 Feb 2007

for irfanview 5E 48 B0
for ahk 5E 00 48 B0

The used bit-depth (:bpp) is different, 24bit (:3byte) with irfanview and 32bit (:4byte) with this script. So, the script always produce 4/3 bigger bmp than irfanview. I think you may change the script to use 24bit instead in CreateDIBSection function if the size difference bothers you much.

femke
  • Members
  • 16 posts
  • Last active: Nov 12 2008 02:10 PM
  • Joined: 02 Jun 2008
thanks Sean

your script is saving me a lot of time and work javascript:emoticon(':D')

i had already inserted a line that let irfanview do a copy / paste after the script capture but i will try your suggestion to adapt the bitdepth in the script


update

changed
CreateDIBSection(hDC, nW, nH, bpp = 24, ByRef pBits = "")

and i get the smaller filesize

ABCza
  • Members
  • 132 posts
  • Last active: Jan 04 2015 01:02 AM
  • Joined: 03 Jun 2008

Calling the following function before "CaptureScreen" the script checks if a file with the same name is present in the destination directory and in that case, renames it adding a _# (where # is a progressive number).
 

CheckFile(ByRef sFile = "")
{
        If (! sFile)
            sFile = %A_ScriptDir%\AHK_Screen.bmp
        SplitPath, sFile,, sFilePath, sFileExt, sFileName
        Loop
        {
            If (FileExist(sFile))
                sFile = %sFilePath%\%sFileName%_%A_Index%.%sFileExt%
            Else Break
        }
    }
}

All my scripts/snippets are released under the WTFPL: http://sam.zoy.org/wtfpl/COPYING

ScottMattes
  • Members
  • 195 posts
  • Last active: Feb 16 2015 01:43 AM
  • Joined: 21 May 2007
Edit: nothing like posting to help you finally find an example that answers your question. Test number 4 works if I remove the " and % from around the variable.

I am trying to use ScreenCapture with Rhys gdi32 routine that lets me select a portion of the screen and I am getting nowhere real fast. Basically, I want the user to be able to select a portion of the screen and have it saved to a file, or the clipboard - neither of which works if I use variables for the

Here is Rhys' code, with a mod to save the xy's

;SetBatchLines, -1
OnExit, handle_exit
CoordMode, Mouse, Screen
line_c  = 0x008000       ; line color
frame_c = 0x0000FF      ; frame color
frame_t = 1             ; frame thickness

  ; added by Scott Mattes
  rect_mx = 0
  rect_my = 0
  rect_mx_end = 0
  rect_my_end = 0
  ; end of add by Scott Mattes
  
return
; end of autoexec

; When user clicks with Left-Mouse Button and drags, a frame is drawn on screen
+Lbutton::
  ;get starting position
  MouseGetPos, MX, MY

  ; show transparent GUI covering the whole screen
  Gui, 1:Color, Black
  Gui, 1:+Lastfound +AlwaysOnTop
  WinSet, TransColor, Black
  Gui, 1:-Caption
  Gui, Show, x0 y0 w%A_ScreenWidth% h%A_ScreenHeight%

  ; retrieve the unique ID number (HWND/handle) of that window
  WinGet, hw_frame, id

  ; The GetDC function retrieves a handle to
  ; a display device context (DC) for the client area
  ; of a specified window or for the entire screen.
  ; You can use the returned handle in subsequent GDI functions to draw in the DC.
  hdc_frame := DllCall( "GetDC"
                      , "uint", hw_frame )
                     
  ; create buffer to store old color data to remove drawn rectangles
  ; The CreateCompatibleDC function creates a memory device context (DC)
  ; compatible with the specified device.
  hdc_buffer := DllCall( "gdi32.dll\CreateCompatibleDC"
                       , "uint", hdc_frame )
 
  ; The CreateCompatibleBitmap function creates a bitmap compatible
  ; with the device that is associated with the specified device context.
  hbm_buffer := DllCall( "gdi32.dll\CreateCompatibleBitmap"
                       , "uint", hdc_frame
                       , "int", A_ScreenWidth
                       , "int", A_ScreenHeight )
 
  ; The SelectObject function selects an object into the specified
  ; device context (DC). The new object replaces the previous object of the same type.
  DllCall( "gdi32.dll\SelectObject"
         , "uint", hdc_buffer
         , "uint", hbm_buffer )

  ; create a dummy rectangular region.
  ; The CreateRectRgn function creates a rectangular region.
  h_region := DllCall( "gdi32.dll\CreateRectRgn"
                     , "int", 0
                     , "int", 0
                     , "int", 0
                     , "int", 0 )

  ; specify the color of the frame.
  ; The CreateSolidBrush function creates a logical
  ; brush that has the specified solid color.
  h_brush := DllCall( "gdi32.dll\CreateSolidBrush"
                    , "uint", frame_c )

  ;check continously if the mouse is draged while LButton is down and redraw frame.
  Loop
    {
      ;redraw frame when LButton is still down
      If GetKeyState("LButton", "P")
        {
          ;get mouse position
          MouseGetPos, MXend, MYend
         
          ;redraw only if mouse moved to a different position
          If ( MXend <> MXend_old
               AND MYend <> MYend_old)
            {
              ;compute width and height of frame
              w := abs(MX - MXend)
              h := abs(MY - MYend)
             
              ;find upper left corner
              X := Min( MX, MXend )
              Y := Min( MY, MYend )
           
              DrawFrame( X, Y, w, h, frame_t )
             
              ;memorize position
              MXend_old = %MXend%
              MYend_old = %MYend%
            }
         }       
      Else      ;LButton is released
          Break
    Sleep, 50
   }
  GoSub, CleanUp
  ToolTip, %MX% %MY%`n%MXend% %MYend%`n%w% %h%

  ; added by Scott Mattes
  rect_mx = %mx%
  rect_my = %my%
  rect_mx_end = %mxend%
  rect_my_end = %myend%
  ; end of add by Scott Mattes
Return

ESC::
handle_exit:
  GoSub, CleanUp
  ExitApp
Return

CleanUp:
  DeleteObject( h_brush )
  DeleteObject( h_region )
  DeleteObject( hbm_buffer )
   
  DeleteDC( hdc_frame )
  DeleteDC( hdc_buffer )
  Gui, 1:Destroy
Return

DrawFrame( p_x, p_y, p_w, p_h, p_t )
  {
    global   hdc_frame, hdc_buffer, h_region, h_brush
    static   buffer_state, old_x, old_y, old_w, old_h
     
    ; Copies the source rectangle directly to the destination rectangle.
    SRCCOPY   = 0x00CC0020
       
    ;remove previously drawn rectangle (restore previoulsy buffered color data)
    if ( buffer_state = "full")
       ; The BitBlt function performs a bit-block transfer of the color data
       ; corresponding to a rectangle of pixels from the specified
       ; source device context into a destination device context.
       DllCall( "gdi32.dll\BitBlt"
              , "uint", hdc_frame
              , "int", old_x
              , "int", old_y
              , "int", old_w
              , "int", old_h
              , "uint", hdc_buffer
              , "int", 0
              , "int", 0
              , "uint", SRCCOPY )
    else
       buffer_state = full
 
    ;remember new rectangle for next loop (to be removed)
    old_x := p_x
    old_y := p_y
    old_w := p_w
    old_h := p_h
 
    ; Store current color data of new ractangle in buffer
    ; The BitBlt function performs a bit-block transfer of the color data
    ; corresponding to a rectangle of pixels from the specified
    ; source device context into a destination device context.
    DllCall( "gdi32.dll\BitBlt"
           , "uint", hdc_buffer
           , "int", 0
           , "int", 0
           , "int", p_w
           , "int", p_h
           , "uint", hdc_frame
           , "int", p_x
           , "int", p_y
           , "uint", SRCCOPY )
 
    ; modify dummy rectangular region to desired reactangle
    ; The SetRectRgn function converts a region into a
    ; rectangular region with the specified coordinates.
    DllCall( "gdi32.dll\SetRectRgn"
           , "uint", h_region
           , "int", p_x
           , "int", p_y
           , "int", p_x+p_w
           , "int", p_y+p_h )
   
   
    ; draw region frame with thickness (width and hight are the same)
    ; The FrameRgn function draws a border around the
    ; specified region by using the specified brush.
    DllCall( "gdi32.dll\FrameRgn"
           , "uint", hdc_frame
           , "uint", h_region
           , "uint", h_brush
           , "int", p_t
           , "int", p_t )
   
   
/*
    PS_DASH = PS_DASH
   
    ; The CreatePen function creates a logical pen that has the
    ; specified style, width, and color. The pen can subsequently
    ; be selected into a device context and used to draw lines and curves.
    h_pen := DllCall( "gdi32.dll\CreatePen"
                     , "int", PS_DASH
                     , "int", p_t
                     , "uint", line_c)

    ; The SelectObject function selects an object into the specified
    ; device context (DC). The new object replaces the previous object of the same type.
    h_penold := DllCall( "gdi32.dll\SelectObject"
                       , "uint", hdc_frame
                       , "uint", h_pen )

    ; The MoveToEx function updates the current position to
    ; the specified point and optionally returns the previous position.
    DllCall( "gdi32.dll\MoveToEx"
           , "uint", hdc_frame
           , "int", p_x
           , "int", p_y
           , "uint", lppoint)
   
    ; The LineTo function draws a line from the current
    ; position up to, but not including, the specified point.
    DllCall( "gdi32.dll\LineTo"
           , "uint", hdc_frame
           , "int", p_x+p_w
           , "int", p_y+p_h)
   
    DllCall( "gdi32.dll\MoveToEx"
           , "uint", hdc_frame
           , "int", p_x+p_w
           , "int", p_y
           , "uint", lppoint)

    DllCall( "gdi32.dll\LineTo"
           , "uint", hdc_frame
           , "int", p_x
           , "int", p_y+p_h)
   
    ; The SelectObject function selects an object into the specified
    ; device context (DC). The new object replaces the previous object of the same type.
    DllCall( "gdi32.dll\SelectObject"
           , "uint", hdc_frame
           , "uint", h_penold )
    DeleteObject( h_pen )
*/
  }

DeleteDC( p_dc )
  {
    ; The DeleteDC function deletes the specified device context (DC).
    DllCall( "gdi32.dll\DeleteDC", "uint", p_dc )
  }

DeleteObject( p_object )
  {
    ; The DeleteObject function deletes a logical pen, brush,
    ; font, bitmap, region, or palette, freeing all system resources
    ; associated with the object. After the object is deleted,
    ; the specified handle is no longer valid.
    DllCall( "gdi32.dll\DeleteObject", "uint", p_object )
  }

Min( value1, value2 )
  {
    If ( value1 < value2 )
        return value1
    Else
        return value2
  }

here is my code to use it

clipboard = this is a test

filerecycle, c:\temp\screen.png
capturescreen( "686, 570, 832, 745", false, "c:\temp\screen.png" )
ifexist c:\temp\screen.png
  msgbox, the file was made
else
  msgbox, the file WAS NOT made

#include %A_ScriptDir%\ScreenCapture.ahk
#include %A_ScriptDir%\Rhys gdi32 drawrect.ahk  

return

; use shift left mouse to get the rectangle values


#1:: ; test 1, use points captured by rhys' code
clip_save = %clipboardall%
msgbox, "%rect_mx%, %rect_my%, %rect_mx_end%, %rect_my_end%" 
capturescreen( "rect_mx%, %rect_my%, %rect_mx_end%, %rect_my_end%", false, 0 )
msgbox, errorlevel-%errorlevel% running test 1

  run, mspaint
  WinWait, untitled - Paint,
  IfWinNotActive, untitled - Paint, , WinActivate, untitled - Paint,
  WinWaitActive, untitled - Paint,
  Send, {SHIFTDOWN}{INS}{SHIFTUP}{ENTER}
  ; result, Paint reports "Error getting the Clipboard data"
clipboard = %clip_save%
return



#2:: ; test 1, use points captured by rhys' code
clip_save = %clipboardall%
msgbox, "%rect_mx%, %rect_my%, %rect_mx_end%, %rect_my_end%" 
capturescreen( "rect_mx, rect_my, rect_mx_end, rect_my_end", false, 0 )
msgbox, errorlevel-%errorlevel% running test 2

  run, mspaint
  WinWait, untitled - Paint,
  IfWinNotActive, untitled - Paint, , WinActivate, untitled - Paint,
  WinWaitActive, untitled - Paint,
  Send, {SHIFTDOWN}{INS}{SHIFTUP}{ENTER}
  ; result, Paint reports "Error getting the Clipboard data"
clipboard = %clip_save%
return



#3::
; test 2, use points captured by rhys' code
clip_save = %clipboardall%
msgbox, use points reported by rhys' code, but typed by me
capturescreen( "686, 570, 832, 745", false, 0 )
msgbox, errorlevel-%errorlevel% running test 3

  run, mspaint
  WinWait, untitled - Paint,
  IfWinNotActive, untitled - Paint, , WinActivate, untitled - Paint,
  WinWaitActive, untitled - Paint,
  Send, {SHIFTDOWN}{INS}{SHIFTUP}{ENTER}
  ; result, Paint now contains part of the screen
  
clipboard = %clip_save%
return

  

#4:: ; test 3, use points captured by rhys' code, but put into a local variable first
clip_save = %clipboardall%
my_rect = "%rect_mx%, %rect_my%, %rect_mx_end%, %rect_my_end%" 

msgbox, %my_rect%
capturescreen( "%my_rect%", false, 0 )
msgbox, errorlevel-%errorlevel% running test 4

  run, mspaint
  WinWait, untitled - Paint,
  IfWinNotActive, untitled - Paint, , WinActivate, untitled - Paint,
  WinWaitActive, untitled - Paint,
  Send, {SHIFTDOWN}{INS}{SHIFTUP}{ENTER}
  ; result, Paint reports "Error getting the Clipboard data"
clipboard = %clip_save%
return



#5:: ; test 4, use points captured by rhys' code to save to a file
clip_save = %clipboardall%

msgbox, "%rect_mx%, %rect_my%, %rect_mx_end%, %rect_my_end%" 
capturescreen( "%rect_mx%, %rect_my%, %rect_mx_end%, %rect_my_end%", false, "c:\temp\asdf.png" )
msgbox, errorlevel-%errorlevel% running test 5

  run, mspaint
  WinWait, untitled - Paint,
  IfWinNotActive, untitled - Paint, , WinActivate, untitled - Paint,
  WinWaitActive, untitled - Paint,
  Send, ^o
  send, c:\temp
  send, {enter}
  send, asdf.png
  ; result, Paint reports "file not found"
clipboard = %clip_save%
return

test 4 now looks like this (i found that if i clicked and dragged right to left the rectangle points would be 'wrong' for ScreenCapture and paint would give the error trying to paste from the clipboard.

#4:: ; test 4, use points captured by rhys' code, but put into a local variable first
clip_save = %clipboardall%
if rect_mx < %rect_mx_end%
{
  top_x = %rect_mx%
  top_y = %rect_my%
  bot_x = %rect_mx_end%
  bot_y = %rect_my_end%
}
else
{  
  top_x = %rect_mx_end%
  top_y = %rect_my_end%
  bot_x = %rect_mx%
  bot_y = %rect_my%
}  
;my_rect = %rect_mx%, %rect_my%, %rect_mx_end%, %rect_my_end%
my_rect = %top_x%, %top_y%, %bot_x%, %bot_y%

;msgbox, %my_rect%
capturescreen( my_rect, false, 0 )
;msgbox, errorlevel-%errorlevel% running test 4

  run, mspaint
  WinWait, untitled - Paint,
  IfWinNotActive, untitled - Paint, , WinActivate, untitled - Paint,
  WinWaitActive, untitled - Paint,
  Send, {SHIFTDOWN}{INS}{SHIFTUP}{ENTER}
  ; result, Paint reports "Error getting the Clipboard data"
clipboard = %clip_save%
return


ScottMattes
  • Members
  • 195 posts
  • Last active: Feb 16 2015 01:43 AM
  • Joined: 21 May 2007
Not everyone will run into this problem, but since I was using the script from Rhys for gdi32 drawing on the desktop I did.

If the xy points are not top left to bottom right no file is made and no error seems to be raised.

; test of different xy pairs and capturescreen.ahk

#include C:\temp\ScreenCapture.ahk

testdir = c:\temp\123-testing capturescreen-456

ifexist, testdir
  FileRemoveDir, testdir, 0

  
FileCreateDir, %testdir%
if errorlevel
{
   msgbox, ERROR: Could not create output directory, test aborted.
   exitapp
}

; test with xy pairs being top left and bottom right
myrect = 0, 1, 100, 101
testfile = %testdir%\test-0-1-100-101.png
capturescreen( myrect, false, testfile )
errlvl = %errorlevel%

msgbox, capturescreen( myrect, false, testfile ), errlvl = %errorlevel%


ifexist, %testfile%
  msgbox, successful test output file %testfile% was made
else
  msgbox, unsuccessful test output file %testfile% does not exist
  
  
; test with xy pairs being bottom right and top left
myrect = 100, 101, 0, 1
testfile = %testdir%\test-100-101-0-1.png
capturescreen( myrect, false, testfile )
errlvl = %errorlevel%

msgbox, capturescreen( myrect, false, testfile ), errlvl = %errorlevel%


ifexist, %testfile%
  msgbox, successful test output file %testfile% was made
else
  msgbox, unsuccessful test output file %testfile% does not exist
  
  


BoBo²
  • Guests
  • Last active:
  • Joined: --
Is it possible with that script to have a snapshoot and rescale/downsize it to a variable/preset ratio of eg 33/100% before saving? That to create thumbnail images from screenshoots 'on-the-fly'.

Feedback much appreciated.
8)