Multiple Screen Captures

Post your working scripts, libraries and tools for AHK v1.1 and older
colmik
Posts: 83
Joined: 11 Mar 2014, 18:21

Multiple Screen Captures

21 Mar 2019, 22:04

I believe this function is native to Windows-8, but I have Windows-7, so I wrote a script to do it.
When viewing certain YouTube videos which present a series of pictures with captions, I find that there is too little time to a) read the caption and b) appreciate the picture. If I stop the video, it puts the time line over the caption, which can make it difficult to read.

The script takes a screen capture and writes it to

My Pictures\date\SCnnn.PNG

The SC is for Screen Capture, the date is in yyyyMMdd format (eg 20190325), and the nnn in the file name increments for each new capture.

Note: I run an AHK script all the time, which corrects various spellings, expands abbreviations like "w/e" to "weekend",
capitalises "i" to I, and fires up other scripts I have written.
Into that script, I have written ...

Code: Select all

#insert::
Run C:\Users\USR\Documents\AutoHotKey\PrtScrn.ahk  ; I know it's not a document, but that's where I keep it
Return
When I press Win-Insert (PrintScreen and Insert are on the same key), it fires up the following script, which is in Documents\AutoHotKey\PrtScrn.ahk
(I know it's not a document as such, but don't look for logic in the layout of my PC)

Code: Select all

;  Explanation of script ...
; The folder used for saving screen captures is, typically, C:\Users\USR\Pictures\Screenshots\20190322
; The directory name, "20190322" is the date in yyyyMMdd format
; Don't forget to change USR to your User in the script. 
; Each time the script runs, it scans the directory looking for filenames with the format SCnnn.PNG   
;           SC = Screen Capture, and nnn is a zero-padded number from 000-999
; The script scans the files and finds the highest number (nnn) and increments it to form a filename for the new capture
; It then scans the screen and saves the screen capture into the folder using the filename developed.

#singleinstance force

FormatTime, dt_string,, yyyyMMdd
datei = C:\Users\USR\Pictures\Screenshots\%dt_string%
  ifNotExist, %datei%
    FileCreateDir, %datei%
    
; Read last filename.png - this will be the last one apha-numerically
MaxNum := "000"
Loop, %datei%\*.*
{ if(substr(A_LoopFileName,1,2) = "SC")  ; SC = Screen Capture
    if(substr(A_LoopFileName,3,3) > MaxNum)
      MaxNum := substr(A_LoopFileName,3,3)
}
MaxNum := printf("%03d",MaxNum + 1)
FileNam := "SC" . MaxNum . ".PNG"  ; create new filename
datei .= "\" 
datei .= FileNam

; I don't know who wrote the lines below, but it wasn't me.  Thanks to the author.
pToken := Gdip_Startup() ; Start Gdip
WinGetPos, x, y, w, h, A ; Determine dimension and position of the current window
pBitmap := Gdip_BitmapFromScreen(x "|" y "|" w "|" h) ; Take a screenshot based on the calculated values
Gdip_SaveBitmapToFile(pBitmap, datei) ; Create an image from the liner in the specified directory
Gdip_DisposeImage(pBitmap) ; Remove graphics from memory
Gdip_Shutdown(pToken) ; Close Gdip instance
return
I have been playing with it since I finished it, and it seems to work pretty well.
Hope you like it.
colmik
Posts: 83
Joined: 11 Mar 2014, 18:21

Re: Multiple Screen Captures

22 Mar 2019, 09:36

Sorry Folks, there's a couple of dependencies that I forgot to mention.

1. Gdip standard library v1.45 by tic (Tariq Porter) 07/09/11
Gdip is in C:\Users\USR\Documents\AutoHotKey\gdip

2. The script uses printf() in C:\Users\USR\Documents\AutoHotKey\Lib
I dare say other people have made better versions of printf() than mine, but mine definitely works with the Screen Capture script.

Code: Select all

; ==================================================================
; The next few lines demonstrate how to use printf()
; ==================================================================
;
;  msgbox % printf("%-4s %10s %10s |%-7.1f|  %8d`n", 23, "Thomas", "Sterling", 12.42931, 54)
;  msgbox % printf("|%04d|   |%-04d|`n", 444,5)
;  msgbox % printf("%-4s %10s %10s %7f %4s`n", 23, "Alan", "Lilly", 3.999, "A")
;  msgbox % printf("|%-7.3f|`n", 3.999)
; 
; ; Example formatting numbers:
; 
; zero_padded_number := printf(%04d, 34)  ; produces "0034"
; msgstring .= printf("%07.1f", 145.09)   ; round 1 decimal place and zerofill 7 digits
; msgbox %msgstring%
; 
; pause

; outputdebug DBGVIEWCLEAR   ; view output in dbgview utility from microsoft at www.sysinternals.com

; printf(" ID  FirstName  LastName   Number  Code`n---- ---------- ---------- ------- ----")
; printf("%-4s %10s %10s |%7f| %4s", 23, "Alan", "Lilly", 3.999, "A")
; printf("%-4s %10s %10s |%-7.3f| %4s this is amazing", 23, "Joe", "Apples", 3.999, "B")
; printf("%-4s %10s %10s |%07.0f| %4s", 23, "Thomas", "Sterling", 3.999, "C")

; Example formatting numbers:
; Borrower_num := 1572
; Calculated_bid := 126.0826541
; Total_bid := 120
; Desired_bid := 180
; Proposed_bid_percentage := 9.4

; |
; |Borrower    Desired bid    Current      Proportioned Bid    Final
; |  1572        126.08         120           180 @ 9.4       300 
; |

; Percentage := 54.35156
; outputdebug % printf("%f`%`n",percentage) ; %
; outputdebug % Printf("%6d %13.2f %11d %13d @ %4.1f`% %8d `n", Borrower_num, Calculated_bid, Total_bid, Desired_bid, Proposed_bid_percentage, Desired_bid+Total_bid)

; exitapp 

printf(string, prms*)    ; uses variadics to handle variable number of inputs
{ listlines, off
  padchar := " "
  
  for each, prm in prms
  { RegExMatch(string,"`%(.*?)([s|f|d])",m) ; regular expression search
    format := m1
	stringleft, Pad, format, 1
	if(Pad = "0")
	  padchar := "0"
    type := m2
    if (type = "f")  ; format float using setformat command
    { originalformat := A_FormatFloat
      SetFormat, Float, %format%
      prm += 0.0
      SetFormat, Float, %originalformat%
    } 
    else if (type = "s")    ; format string (pad string if necessary, negative number indicates right justify)
    { if (format < 0)
        loop % -format-StrLen(prm)
          prm := padchar prm
      else
        loop % format-StrLen(prm)
          prm := prm padchar
    } 
    else if(type = "d")
    { originalformat := A_FormatInteger
      SetFormat, Integer, %format%
      Str =
      loop % abs(format)-StrLen(prm) ; %
        str .= padchar
      if(format < 0)
        prm .= str
      else
        prm := str prm
      SetFormat, Integer, %originalformat%
    } 
    else 
      msgbox, unknown type = %type% specified in call to printf
    StringReplace, string, string, % "`" m, % prm     ; "%" symbol must be escaped with backtick
  }
  listlines, on
  return string
}
nou
Posts: 26
Joined: 24 Feb 2019, 21:21

Re: Multiple Screen Captures

23 Mar 2019, 12:53

Neat! However, instead of running the whole script by itself, why not make it into a function?

We'll call the first part "CreateFile()" because, well, we're creating a file:

Code: Select all

createFile()
{
	FormatTime, dt_string,, yyyyMMdd
	datei = C:\Users\USR\Pictures\Screenshots\%dt_string%
	  ifNotExist, %datei%
	    FileCreateDir, %datei%
	    
	; Read last filename.png - this will be the last one apha-numerically
	MaxNum := "000"
	Loop, %datei%\*.*
	{ if(substr(A_LoopFileName,1,2) = "SC")  ; SC = Screen Capture
	    if(substr(A_LoopFileName,3,3) > MaxNum)
	      MaxNum := substr(A_LoopFileName,3,3)
	}
	MaxNum := printf("%03d",MaxNum + 1)
	FileNam := "SC" . MaxNum . ".PNG"  ; create new filename
	datei .= "\" 
	datei .= FileNam
	
	; and we'll return the filename. that way, if we do (outside of this function)
	; MsgBox % createFile()
	; our result would be:
	; %datei%
	
	return  datei
}
Then, you can call the second part, idk, SC()?

Code: Select all

SC()
{
	; I don't know who wrote the lines below, but it wasn't me.  Thanks to the author.
	pToken := Gdip_Startup() ; Start Gdip
	WinGetPos, x, y, w, h, A ; Determine dimension and position of the current window
	pBitmap := Gdip_BitmapFromScreen(x "|" y "|" w "|" h) ; Take a screenshot based on the calculated values

; *****notice, we're using the "CreateFile()" function here*****
	Gdip_SaveBitmapToFile(pBitmap, createFile()) ; Create an image from the liner in the specified directory
	
	Gdip_DisposeImage(pBitmap) ; Remove graphics from memory
	Gdip_Shutdown(pToken) ; Close Gdip instance
	return
}
and then, save this file as your `PrtScrn.ahk`. near the very top of your main script, just do:

Code: Select all

#include C:\Users\USR\Documents\AutoHotKey\PrtScrn.ahk
and then, to the hotkey you want, just use

Code: Select all

#insert::SC()
----------------------

Now, onto a couple of other things:
The username of the currently logged in user is saved under a builtin variable, A_UserName. So for your code:

Code: Select all

datei = C:\Users\USR\Pictures\Screenshots\%dt_string%
You can, instead, do this:

Code: Select all

datei = C:\Users\%A_UserName%\Pictures\Screenshots\%dt_string%
That'll give it more flexibilty.

Also, your "printF()" command seems to function similar to the "Format" command? Here, take a look at my example code for the "format" command:

Code: Select all

one   := Format("{1:010}", 1)	; pad 0s left 
two   := Format("{1:-010}", 2)	; pad 0s, right 
three := Format("{1:10}", 3) ; pad spaces, left 
four  := Format("{1:-10}", 4) ; pad spaces, right

five  := Format("{1:010}", "Hello") ; same as above. With quotes this time. 
six   := Format("{1:10}", "there")	; pad left with space
seven := Format("{1:-10}", "folks!") ; pad right with space

eight := Format("{:0.2f}", 1234.5678) ; sets the format to two decimals
nine  := Format("{:0.0f}", 1234.5678) ; sets the format to no decimals 

ten   := Format("{:#.4g}", 1030.215) ; use 4 significant figures only
eleven:= Format("{:#.4g}", 001.0302) ; use 4 significant figures only 

combinations:
twelve:= Format("|{:0-10}|`n|{:-10}|", "this is", "12") ; combination 
thirteen:= Format("|{2:010}|`n|{1:10}|", "here is", "13") ; combination, with indexs. 

ToolTip, % "Here it is, with pipes (|) to show borders `n" 
		. "1) |" one "|`n"
		. "2) |" two "|`n"
		. "3) |" three "|`n"
		. "4) |" four "|`n"
		. "`n"
		. "5) |" five "|`n"
		. "6) |" six "|`n"
		. "7) |" seven "|`n"
		. "`n"
		. "Using ""1234.5678""`n"
		. "8) two decimals: " eight "`n"
		. "9) no decimals: " nine "`n"
		. "`n"
		. "4 significant figures (sigfigs): `n"
		. "10) 1030.215:	" ten "`n"
		. "11) 001.0302:	" eleven "`n"
		. "`n"
		. "12) Combo1:`n"
		.  Twelve "`n"
		. "`n"
		. "13) Combo2`n"
		.  Thirteen "`n"
Lastly, what'll happen if someone takes more than 999 screenshots in one day? That'll break this part of the script, right?

Code: Select all

Loop, %datei%\*.*
{ 
    if(substr(A_LoopFileName,1,2) = "SC")  ; SC = Screen Capture
        if(substr(A_LoopFileName,3,3) > MaxNum)
          MaxNum := substr(A_LoopFileName,3,3)
}
Why not use a RegEx?

Code: Select all

; note: I don't remember if A_LoopFileName contains the file extension or not.
if(A_LoopFileName ~= "^SC") 
   && (substr(A_LoopFileName,3,(A_LoopFileName ~= "\d+")) > MaxNum)
   MaxNum := MaxNum := substr(A_LoopFileName,3,(A_LoopFileName ~= "\d+"))
I think I did that right (without testing). The regex should give you the "string length" of your numbers. And we can use that as the "string length" for our substr() command.

Code: Select all

(A_LoopFileName ~= "\d+")
colmik
Posts: 83
Joined: 11 Mar 2014, 18:21

Re: Multiple Screen Captures

27 Mar 2019, 14:57

Thanks Folks, for the improvements. In my defense, I'd say that although all my programming these days is in AHK, (it used to be C), I do precious little programming at all since I retired. Now, it's just for odd little things that I want - like this Screen Capture program. Consequently, my AHK is a bit rusty, but still works as long as I'm happy with a program whose wheels squeak. As long as it's just for me, I am.
I agree that it's not as efficient as It might be. The way it works, each time I press Win-Insert, my always-resident script fires up the ScreenCapture script, which does everything every time -it makes a new folder if necessary, searches it to see which is the file name with the biggest number in it, develops the next logical file name, then does the save. The points you mentioned all occurred to me while I was writing it...
1) I could simply store the last filename number and increment it each time, but that would mean keeping the script in memory, and I opted to simply fire it up each time I needed it.
2) Pressing keys is a manual operation, and the script runs adequately fast enough, so the extra overhead of doing the filename search and calculation is not a problem.
3) I had an idea that the zero-padding could have been accomplished with Format, but I wasn't sure how, where I knew how to use my printf() - so using it was less think-intensive.
4) It also occurred to me that 999 might not be big enough for a public script, but I wrote it for myself, and I'll sure as Hell never exceed 999 screen captures in a day. I'll never even approach 99.

The script is offered as public property. Modify it as you will for your own purposes. Have fun. There are a lot of people in this forum that could have made a much better job of it than I did - but for me, it works. Mission accomplished!

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 148 guests