Does this work?

Get help with using AutoHotkey and its commands and hotkeys
Hellbent
Posts: 572
Joined: 23 Sep 2017, 13:34

Does this work?

15 Jun 2019, 08:49

Hi.
I'm currently working on some of the components of a larger project. As far as I can tell everything is working exactly as it should, but experience tells me that different versions of windows etc can play a role in how things work out. So I'm hoping that I can get a few people that can test the current functionality on a few different systems.

The main function of the current script is to simple allow the user to select a region of any monitor while showing the area selected with some simple lines running along the x and y axis for the starting corner and ending corner.

If the user switches monitors the window containing the lines should automatically follow and resize its self to the dimensions of the new monitor.
As far as I can tell it is working the way it should, but both of my two monitors have the exact same dimensions 1366x768 so I can't definitively same that it's working as expected.

A secondary function of the current script is to take a screenshot based on the dimensions selected. Once again everything is working fine, and I don't foresee there being any problems with this, but if for some reason the first function isn't working properly, there could be a issue here.

The last function of the current script is to run a image search on the screen shot taken by the second function. This isn't really a planned part of the larger project, but when I had the other two functions added in I could see that I was only a few lines of code from adding it in. So I just decided to add it in and see if there are any issues running it on other computers.

So here is what I need from you if you are so kind to help me out.

When you run the script, you will see a simple gui with 3 buttons on it. There are also 3 hotkeys that also execute the same functions as each of the 3 buttons. These hotkeys are Numpad1 - 2 and 3 and each corresponds to each of the buttons in the same order.

Once the script is running, press the "Take Screen Shot" button (or press numpad1). Once pressed, you should see two lines centered on your cursor going all the way across the full width and full height of your screen.

While the lines are there, move your cursor to any other monitor, the lines should be drawn on any screen.
Next press the left mouse button, this will lock the position of the first lines and create another set of them as well as a rectangle that fills the space between them.

If the second set of lines is to the left and below the center of the first set you should see a green translucent rectangle filling the space, else you should see a red rectangle. If the box is red you shouldn't be able to exit it, but if the box is green, clicking will remove the graphics from your screen. Next you will here a beep and the gui should now have a copy of the image you just took. It is set to max out at 300x300 depending on the ratio of width and height of the screenshot.

Next click the "Set Search Area" button, it works exactly the same way the first time did, this time it is just setting a area for the search. So if need be, redo the first button and get a small screenshot and then with the second button just set a area that contains the first.

Lastly, press "Search", if it finds the image it will beep once and move your cursor to where it found the image +20px x and y offset.
There is no loop so don't worry about it getting stuck.

Hopefully everything works exactly as expected regardless of computer/system etc.

If you are kind enough to help.
Please give the outcome of the tests, whether or not you have at least two different monitor sizes (optionally how many monitors and or resolutions). And your OS.

I am running a two monitor setup (both 1366x768) and am running Windows 8.1 64bit.


*** while setting the positions, you can press the hotkeys to restart ***

*** You can also right click the gui or press esc to exit the script ***

***The script creates a folder in the same directory that you create this script to hold the screen shot.
Once you are done running and want to do cleanup, just delete the script and the folder called "Temp Screen Shots"***

Here is the script. It contains everything needed to run.

Code: Select all

;Written By: Hellbent aka CivReborn
;Date: June 15th 2019
#SingleInstance,Force
SetBatchLines,-1
IfNotExist,%A_ScriptDir%\Recorded Shots
	FileCreateDir, %A_ScriptDir%\Temp Screen Shots
SetWorkingDir,%A_ScriptDir%\Temp Screen Shots
Coordmode,Mouse,screen
CoordMode,Pixel,Screen
global CapActive:=0,SP,XCAP,YCAP,WCAP,HCAP,OB:=0,CAPIT:=0
global CapWin:={},Monitors := New MonitorClass()
Gdip_Startup()
global TXC,TYC,BB:=New_Brush("000000","88"),GB:=New_Brush("00ff00","55"),RB:=New_Brush("ff0000","55")


Gui,1:+AlwaysOnTop -DPIScale +HWNDGUI1HWND
Gui,1:Color,333333,444444
Gui,1:Font,cwhite s10 Bold ,Segoe UI
Gui,1:Add,Button,xm ym w300 h30 -Theme gSet_Capture_Area vSCAP,Take Screen Shot
Gui,1:Add,Button,xm w300 h30 -Theme gSet_Capture_Area vSSA,Set Search Area
Gui,1:Add,Button,xm w300 h30 -Theme gImageSearch,Search
Gui,1:Add,Picture,xm y+10 w300 h300 vPic gUpdatePic,% A_WorkingDir "\Test Screen Shot.png"
UpdatePic()
Gui,1:Show,AutoSize,HB Snap it
return
GuiClose:
GuiContextMenu:
2GuiContextMenu:
*ESC::
	ExitApp
	
UpdatePic(){
	static FakePic
	Gui,Fake:Add,Picture,vFakePic,% A_WorkingDir "\Test Screen Shot.png"
	GuiControlGet,Pos,Fake:Pos,FakePic
	Gui,Fake:Destroy
	if(PosW<=300&&PosH<=300){
		NW:=PosW,NH:=PosH
	}else if(PosW>PosH){
		ratio:=PosH/PosW,NW:=300,NH:=300*Ratio
	}else if(PosW<PosH){
		ratio:=PosW/PosH,NH:=300,NW:=300*Ratio
	}else	{
		NW:=300,NH:=300
	}
	GuiControl,1:Move,Pic,% "w" NW " h" NH
	GuiControl,1:,Pic,% A_WorkingDir "\Test Screen Shot.png"
	Gui,1:Show,AutoSize
}

Set_Capture_Area:
	if(A_GuiControl="SCAP")
		CAPIT:=1
	Create_Capture_Size_Window()
	return
	
Numpad3::	
ImageSearch:
	ImageSearch,foundx,foundy,XCAP,YCAP,XCAP+WCAP,YCAP+HCAP,%A_WorkingDir%\Test Screen Shot.png
	if(ErrorLevel=0){
		SoundBeep,500
		MouseMove,FoundX+20,FoundY+20
	}else if(ErrorLevel=1){
		Loop 3
			SoundBeep,600
	}
	return

Create_Capture_Size_Window(){
	static ft
	Gui,2:Destroy
	CapWin:=Layered_Window_SetUp(3,0,0,A_ScreenWidth,A_ScreenHeight,"2","+AlwaysOnTop -DPIScale -Caption +Owner1")
	Max:=Monitors.Get_Largest_Monitor_Size()
	CapWin.hbm:=CreateDIBSection(Max.Width,Max.Height)
	CapWin.hdc := CreateCompatibleDC()
	CapWin.obm := SelectObject(CapWin.hdc,CapWin.hbm),CapWin.G := Gdip_GraphicsFromHDC(CapWin.hdc)
	Gdip_SetSmoothingMode(CapWin.G,3)

	;~ ToolTip,% Max.Width "`n" Max.Height
	if(!ft){
		Monitors.Set_Window_Move_Timer(GUINAME:=2,GUIHWND:=CapWin.hwnd,TCount:=300,xpOff:=0,ypOff:=0,xr:=1,yr:=1,Fill_Screen:=1)
		ft:=1
	}else 	{
		Monitors.Window_Move_Obj.GUIHWND:=CapWin.hwnd
		Monitors.Turn_On_Window_Move_Timer()
	}
	CapActive:=1,SP:=0,OB:=0
	SetTimer,Set_Positions,10
}

Set_Positions(){
	Coordmode,Mouse,Window
	If(!WinActive("ahk_Id" CapWin.Hwnd)){
		WinActivate,% "ahk_Id" CapWin.Hwnd
	}
	Gdip_GraphicsClear(CapWin.g)
	MouseGetPos,tx,ty
	if(SP=0){
		Fill_Box(CapWin.G,BB,tx,0,1,Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Bottom-Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Top)
		Fill_Box(CapWin.G,BB,0,ty,Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Right-Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Left,1)
		TXC:=tx,TYC:=ty
	}else if(SP=1){
		Fill_Box(CapWin.G,BB,TXC,0,1,Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Bottom-Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Top)
		Fill_Box(CapWin.G,BB,0,TYC,Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Right-Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Left,1)
		Fill_Box(CapWin.G,BB,tx,0,1,Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Bottom-Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Top)
		Fill_Box(CapWin.G,BB,0,ty,Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Right-Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Left,1)
		if(TXC<tx&&TYC<ty){
			Fill_Box(CapWin.G,GB,TXC,TYC,tx-TXC,ty-TYC)
			WCAP:=tx-TXC,HCAP:=ty-TYC,OB:=0
			XCAP:=TXC+Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Left,YCAP:=TYC+Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Top
		}else if(TXC>tx&&TYC<ty){
			Fill_Box(CapWin.G,RB,tx,TYC,TXC-tx,ty-TYC)
			OB:=1
		}else if(TXC>tx&&TYC>ty){
			Fill_Box(CapWin.G,RB,tx,ty,TXC-tx,TYC-ty)
			OB:=1
		}else if(TXC<tx&&TYC>ty){
			Fill_Box(CapWin.G,RB,TXC,ty,tx-TXC,TYC-ty)
			OB:=1
		}
	}
	UpdateLayeredWindow(CapWin.hwnd, CapWin.hdc,Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Left,Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Top,Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Right-Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Left, Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Bottom-Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Top)
}

#IF (CapActive=1)
	LButton::
		if(SP=0)
			SP:=1
		else if(SP=1&&OB=0){
			Monitors.Turn_Off_Window_Move_Timer()
			CapActive:=0
			SelectObject(CapWin.hdc,CapWin.obm),DeleteObject(CapWin.hbm),DeleteDC(CapWin.hdc),gdip_deleteGraphics(CapWin.g)
			CapWin:="",SP:=0
			Gui,2:Destroy
			SetTimer,Set_Positions,Off
			if(CAPIT)
				gosub,Take_ScreenShot
		}
		return
#IF

Numpad1::
	SelectObject(CapWin.hdc,CapWin.obm),DeleteObject(CapWin.hbm),DeleteDC(CapWin.hdc),gdip_deleteGraphics(CapWin.g)
	CapWin:="",SP:=0,CapActive:=0,CAPIT:=1
	Create_Capture_Size_Window()
	return
	
Numpad2::
	SelectObject(CapWin.hdc,CapWin.obm),DeleteObject(CapWin.hbm),DeleteDC(CapWin.hdc),gdip_deleteGraphics(CapWin.g)
	CapWin:="",SP:=0,CapActive:=0,CAPIT:=0
	Create_Capture_Size_Window()
	return

Take_ScreenShot:
	CAPIT:=0
	TempBitmap:=Gdip_BitmapFromScreen(XCAP "|" YCAP "|" WCAP "|" HCAP)
	Gdip_SaveBitmapToFile(TempBitmap,A_WorkingDir "\Test Screen Shot.png", 100)
	Gdip_DisposeImage(TempBitmap)
	SoundBeep,400,300
	SetPicToWindow()
	return	

SetPicToWindow(){
	static FakePic
	Gui,Fake:Add,Picture,vFakePic,% A_WorkingDir "\Test Screen Shot.png"
	GuiControlGet,Pos,Fake:Pos,FakePic
	Gui,Fake:Destroy
	if(PosW<=300&&PosH<=300){
		NW:=PosW
		NH:=PosH
	}else if(PosW>PosH){
		ratio:=PosH/PosW
		NW:=300
		NH:=300*Ratio
	}else if(PosW<PosH){
		ratio:=PosW/PosH
		NH:=300
		NW:=300*Ratio
	}else	{
		NW:=300
		NH:=300
	}
	GuiControl,1:Move,Pic,% "w" NW " h" NH
	GuiControl,1:,Pic,% A_WorkingDir "\Test Screen Shot.png"
	Gui,1:Show,AutoSize
	
}


;-------------------------------------------------------------------------------------------------
;-------------------------------------------------------------------------------------------------
;-------------------------------------------------------------------------------------------------

class MonitorClass	{
	__New(){
		This._SetMonCount()
		This._SetPrimeMonitor()
		This._Set_Bounds()
	}
	_SetMonCount(){
		local MC
		SysGet, MC, MonitorCount 
		This.MonitorCount := MC
	}
	_SetPrimeMonitor(){
		local PM
		SysGet, PM, MonitorPrimary
		This.PrimeMonitor := PM
	}
	_Set_Bounds(){
		local bmon,bmonLeft,bmonRight,bmonTop,bmonBottom
		This.Monitors:=[]
		Loop,% This.MonitorCount	{
			SysGet, bmon, Monitor, % A_Index
			This.Monitor[A_Index]:=	{ Left		: 	bmonLeft
									, Top		: 	bmonTop
									, Right		: 	bmonRight
									, Bottom	: 	bmonBottom 	}
		}
	}
	Get_Current_Monitor(){
		local x,y
		CoordMode,Mouse,Screen
		MouseGetPos,x,y
		Loop,% This.MonitorCount	{
			if(x>=This.Monitor[A_Index].Left&&x<=This.Monitor[A_Index].Right&&y>=This.Monitor[A_Index].Top&&y<=This.Monitor[A_Index].Bottom){
				return A_Index
			}
		}
	}
	Get_New_Window_Position(curMon,xpOff,ypOff,xr,yr){
		local tposa:="",tposa:={}
		if(xr=1) ; 1 xr = relative to the left side ; 2 xr = relative to the right side
			tposa.x:=This.Monitor[curMon].Left+xpOff
		else 
			tposa.x:=This.Monitor[curMon].Right-xpOff
		if(yr=1) ; 1 yr = relative to the top  ; 2 yr = relative to the bottom
			tposa.y:=This.Monitor[curMon].Top+ypOff
		else 
			tposa.y:=This.Monitor[curMon].Bottom-ypOff
		return tposa
	}
	Set_Window_Move_Timer(GUINAME:=1,GUIHWND:="",TCount:=500,xpOff:=0,ypOff:=0,xr:=1,yr:=1,Fill_Screen:=0){
		
		local Window_Timer
		
		This.Window_Move_Obj:=	{ 	Interval		:	TCount
								,	GUINAME			:	GUINAME
								,	FILLSCREEN		:	Fill_Screen
								,	GUIHWND			:	GUIHWND
								,	XPOFF			:	xpOff
								,	YPOFF			:	ypOff
								,	XRelative		:	xr
								,	YRelative		:	yr	
								,	Current_Monitor	:	This.Get_Current_Monitor()
								,	Old_Monitor		:	This.Get_Current_Monitor()	
								,	NEW_GUI_POS		:	This.Get_New_Window_Position(This.Get_Current_Monitor(),xpOff,ypOff,xr,yr)	}
								
		This.Window_Timer := Window_Timer :=  ObjBindMethod(This, "_Window_Move_Timer")
		
		This._Set_TFTime()
		
		SetTimer,%Window_Timer%,%TCount%

	}
	Get_Largest_Monitor_Size(){
		local tempMSW:="",tempMSH:=""
		Loop,% This.MonitorCount	{
			if(This.Monitor[A_Index].Right-This.Monitor[A_Index].Left>=This.Monitor[A_Index+1].Right-This.Monitor[A_Index+1].Left&&This.Monitor[A_Index].Right-This.Monitor[A_Index].Left>=This.Monitor[tempMSW].Right-This.Monitor[tempMSW].Left)
				tempMSW:=A_index
			if(This.Monitor[A_Index].Bottom-This.Monitor[A_Index].Top>=This.Monitor[A_Index+1].Bottom-This.Monitor[A_Index+1].Top&&This.Monitor[A_Index].Bottom-This.Monitor[A_Index].Top>=This.Monitor[tempMSH].Bottom-This.Monitor[tempMSH].Top)
				tempMSH:=A_index
		}
		This.Max_Monitor_Dimensions := {Width: This.Monitor[tempMSW].Right-This.Monitor[tempMSW].Left, Height: This.Monitor[tempMSH].Bottom-This.Monitor[tempMSH].Top}
		return This.Max_Monitor_Dimensions
	}
	_Window_Move_Timer(){
		This.Window_Move_Obj.Current_Monitor := This.Get_Current_Monitor()
		if(This.Window_Move_Obj.Current_Monitor!=This.Window_Move_Obj.Old_Monitor&&!DllCall("IsIconic", "Ptr", This.Window_Move_Obj.GUIHWND, "UInt")){
			This.Window_Move_Obj.NEW_GUI_POS:=This.Get_New_Window_Position(This.Window_Move_Obj.Current_Monitor,This.Window_Move_Obj.XPOFF,This.Window_Move_Obj.YPOFF,This.Window_Move_Obj.XRelative,This.Window_Move_Obj.YRelative)
			This._Move_Window()
			This.Window_Move_Obj.Old_Monitor := This.Window_Move_Obj.Current_Monitor
		}
	}
	_Set_TFTime(){
		This.Window_Move_Obj.Current_Monitor := This.Get_Current_Monitor()
		This.Window_Move_Obj.NEW_GUI_POS:=This.Get_New_Window_Position(This.Window_Move_Obj.Current_Monitor,This.Window_Move_Obj.XPOFF,This.Window_Move_Obj.YPOFF,This.Window_Move_Obj.XRelative,This.Window_Move_Obj.YRelative)
		This.Window_Move_Obj.Old_Monitor := This.Window_Move_Obj.Current_Monitor
		This._Move_Window()
	}
	_Move_Window(){
		if(!This.Window_Move_Obj.FILLSCREEN)
			Gui,% This.Window_Move_Obj.GUINAME ":Show",% "x" This.Window_Move_Obj.NEW_GUI_POS.X " y" This.Window_Move_Obj.NEW_GUI_POS.Y " NA"
		else
			Gui,% This.Window_Move_Obj.GUINAME ":Show",% "x" This.Window_Move_Obj.NEW_GUI_POS.X " y" This.Window_Move_Obj.NEW_GUI_POS.Y " w" This.Monitor[This.Window_Move_Obj.Current_Monitor].Right " h" This.Monitor[This.Window_Move_Obj.Current_Monitor].Bottom " NA"
	}
	Turn_Off_Window_Move_Timer(){
		local Window_Timer
		Window_Timer := This.Window_Timer
		SetTimer,%Window_Timer%,Off
	}
	Turn_On_Window_Move_Timer(){
		local Window_Timer
		Window_Timer := This.Window_Timer
		This._Set_TFTime()
		SetTimer,%Window_Timer%,On
	}
	GetGuiPos(){
		local x,y
		WinGetPos,x,y,,,% "ahk_id " This.Window_Move_Obj.GUIHWND 
		return x
	}
}
;######################################################################################################################################
;#####################################################   					    #######################################################
;#####################################################  	  Gdip LITE		    #######################################################
;#####################################################  					    #######################################################
;######################################################################################################################################
Layered_Window_SetUp(Smoothing,Window_X,Window_Y,Window_W,Window_H,Window_Name:=1,Window_Options:=""){
	Layered:={}
	Layered.W:=Window_W,Layered.H:=Window_H,Layered.X:=Window_X,Layered.Y:=Window_Y
	Layered.Name:=Window_Name,Layered.Options:=Window_Options
	;~ Layered.Token:=Gdip_Startup()
	Create_Layered_GUI(Layered),Layered.hwnd:=winExist()
	;~ Layered.hbm := CreateDIBSection(Window_W,Window_H),Layered.hdc := CreateCompatibleDC()
	;~ Layered.obm := SelectObject(Layered.hdc,Layered.hbm),Layered.G := Gdip_GraphicsFromHDC(Layered.hdc)
	;~ Gdip_SetSmoothingMode(Layered.G,Smoothing)
	return Layered
}
Create_Layered_GUI(Layered){
	Gui,% Layered.Name ": +E0x80000 +LastFound " Layered.Options 
	Gui,% Layered.Name ":Show",% "x" Layered.X " y" Layered.Y " w" Layered.W " h" Layered.H ;" NA"
}	
Layered_Window_ShutDown(This){
	SelectObject(This.hdc,This.obm),DeleteObject(This.hbm),DeleteDC(This.hdc)
	gdip_deleteGraphics(This.g),Gdip_Shutdown(This.Token)
}
New_Brush(colour:="000000",Alpha:="FF"){
	new_colour := "0x" Alpha colour 
	return Gdip_BrushCreateSolid(new_colour)
}
New_Pen(colour:="000000",Alpha:="FF",Width:= 5){
	new_colour := "0x" Alpha colour 
	return Gdip_CreatePen(New_Colour,Width)
}	
Fill_Box(pGraphics,pBrush,x,y,w,h)	{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	return DllCall("gdiplus\GdipFillRectangle", Ptr, pGraphics, Ptr, pBrush, "float", x, "float", y, "float", w, "float", h)
}
; Gdip standard library v1.45 by tic (Tariq Porter) 07/09/11
; Modifed by Rseding91 using fincs 64 bit compatible Gdip library 5/1/2013
BitBlt(ddc, dx, dy, dw, dh, sdc, sx, sy, Raster=""){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	return DllCall("gdi32\BitBlt", Ptr, dDC, "int", dx, "int", dy, "int", dw, "int", dh, Ptr, sDC, "int", sx, "int", sy, "uint", Raster ? Raster : 0x00CC0020)
}
Gdip_SetImageAttributesColorMatrix(Matrix){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	VarSetCapacity(ColourMatrix, 100, 0)
	Matrix := RegExReplace(RegExReplace(Matrix, "^[^\d-\.]+([\d\.])", "$1", "", 1), "[^\d-\.]+", "|")
	StringSplit, Matrix, Matrix, |
	Loop, 25
	{
		Matrix := (Matrix%A_Index% != "") ? Matrix%A_Index% : Mod(A_Index-1, 6) ? 0 : 1
		NumPut(Matrix, ColourMatrix, (A_Index-1)*4, "float")
	}
	DllCall("gdiplus\GdipCreateImageAttributes", A_PtrSize ? "UPtr*" : "uint*", ImageAttr)
	DllCall("gdiplus\GdipSetImageAttributesColorMatrix", Ptr, ImageAttr, "int", 1, "int", 1, Ptr, &ColourMatrix, Ptr, 0, "int", 0)
	return ImageAttr
}
Gdip_GetImageWidth(pBitmap){
   DllCall("gdiplus\GdipGetImageWidth", A_PtrSize ? "UPtr" : "UInt", pBitmap, "uint*", Width)
   return Width
}
Gdip_GetImageHeight(pBitmap){
   DllCall("gdiplus\GdipGetImageHeight", A_PtrSize ? "UPtr" : "UInt", pBitmap, "uint*", Height)
   return Height
}
Gdip_DeletePen(pPen){
   return DllCall("gdiplus\GdipDeletePen", A_PtrSize ? "UPtr" : "UInt", pPen)
}
Gdip_DeleteBrush(pBrush){
   return DllCall("gdiplus\GdipDeleteBrush", A_PtrSize ? "UPtr" : "UInt", pBrush)
}
Gdip_DisposeImage(pBitmap){
   return DllCall("gdiplus\GdipDisposeImage", A_PtrSize ? "UPtr" : "UInt", pBitmap)
}
Gdip_DeleteGraphics(pGraphics){
   return DllCall("gdiplus\GdipDeleteGraphics", A_PtrSize ? "UPtr" : "UInt", pGraphics)
}
Gdip_DisposeImageAttributes(ImageAttr){
	return DllCall("gdiplus\GdipDisposeImageAttributes", A_PtrSize ? "UPtr" : "UInt", ImageAttr)
}
CreateCompatibleDC(hdc=0){
   return DllCall("CreateCompatibleDC", A_PtrSize ? "UPtr" : "UInt", hdc)
}
SelectObject(hdc, hgdiobj){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	return DllCall("SelectObject", Ptr, hdc, Ptr, hgdiobj)
}
DeleteObject(hObject){
   return DllCall("DeleteObject", A_PtrSize ? "UPtr" : "UInt", hObject)
}
GetDC(hwnd=0){
	return DllCall("GetDC", A_PtrSize ? "UPtr" : "UInt", hwnd)
}
GetDCEx(hwnd, flags=0, hrgnClip=0){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
    return DllCall("GetDCEx", Ptr, hwnd, Ptr, hrgnClip, "int", flags)
}
ReleaseDC(hdc, hwnd=0){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	return DllCall("ReleaseDC", Ptr, hwnd, Ptr, hdc)
}
DeleteDC(hdc){
   return DllCall("DeleteDC", A_PtrSize ? "UPtr" : "UInt", hdc)
}
Gdip_SetClipRegion(pGraphics, Region, CombineMode=0){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	return DllCall("gdiplus\GdipSetClipRegion", Ptr, pGraphics, Ptr, Region, "int", CombineMode)
}
CreateDIBSection(w, h, hdc="", bpp=32, ByRef ppvBits=0){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	hdc2 := hdc ? hdc : GetDC()
	VarSetCapacity(bi, 40, 0)
	NumPut(w, bi, 4, "uint"), NumPut(h, bi, 8, "uint"), NumPut(40, bi, 0, "uint"), NumPut(1, bi, 12, "ushort"), NumPut(0, bi, 16, "uInt"), NumPut(bpp, bi, 14, "ushort")
	hbm := DllCall("CreateDIBSection", Ptr, hdc2, Ptr, &bi, "uint", 0, A_PtrSize ? "UPtr*" : "uint*", ppvBits, Ptr, 0, "uint", 0, Ptr)
	if !hdc
		ReleaseDC(hdc2)
	return hbm
}
Gdip_GraphicsFromHDC(hdc){
    DllCall("gdiplus\GdipCreateFromHDC", A_PtrSize ? "UPtr" : "UInt", hdc, A_PtrSize ? "UPtr*" : "UInt*", pGraphics)
    return pGraphics
}
Gdip_GetDC(pGraphics){
	DllCall("gdiplus\GdipGetDC", A_PtrSize ? "UPtr" : "UInt", pGraphics, A_PtrSize ? "UPtr*" : "UInt*", hdc)
	return hdc
}
Gdip_Startup(){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	if !DllCall("GetModuleHandle", "str", "gdiplus", Ptr)
		DllCall("LoadLibrary", "str", "gdiplus")
	VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), si := Chr(1)
	DllCall("gdiplus\GdiplusStartup", A_PtrSize ? "UPtr*" : "uint*", pToken, Ptr, &si, Ptr, 0)
	return pToken
}
Gdip_CreatePen(ARGB, w){
   DllCall("gdiplus\GdipCreatePen1", "UInt", ARGB, "float", w, "int", 2, A_PtrSize ? "UPtr*" : "UInt*", pPen)
   return pPen
}
Gdip_BrushCreateSolid(ARGB=0xff000000){
	DllCall("gdiplus\GdipCreateSolidFill", "UInt", ARGB, A_PtrSize ? "UPtr*" : "UInt*", pBrush)
	return pBrush
}
Gdip_BrushCreateHatch(ARGBfront, ARGBback, HatchStyle=0){
	DllCall("gdiplus\GdipCreateHatchBrush", "int", HatchStyle, "UInt", ARGBfront, "UInt", ARGBback, A_PtrSize ? "UPtr*" : "UInt*", pBrush)
	return pBrush
}
CreateRectF(ByRef RectF, x, y, w, h){
   VarSetCapacity(RectF, 16)
   NumPut(x, RectF, 0, "float"), NumPut(y, RectF, 4, "float"), NumPut(w, RectF, 8, "float"), NumPut(h, RectF, 12, "float")
}
CreatePointF(ByRef PointF, x, y){
   VarSetCapacity(PointF, 8)
   NumPut(x, PointF, 0, "float"), NumPut(y, PointF, 4, "float")
}
Gdip_FillRectangle(pGraphics, pBrush, x, y, w, h){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	return DllCall("gdiplus\GdipFillRectangle", Ptr, pGraphics, Ptr, pBrush, "float", x, "float", y, "float", w, "float", h)
}
Gdip_SetClipRect(pGraphics, x, y, w, h, CombineMode=0){
   return DllCall("gdiplus\GdipSetClipRect",  A_PtrSize ? "UPtr" : "UInt", pGraphics, "float", x, "float", y, "float", w, "float", h, "int", CombineMode)
}
Gdip_ResetClip(pGraphics){
   return DllCall("gdiplus\GdipResetClip", A_PtrSize ? "UPtr" : "UInt", pGraphics)
}
Gdip_SetSmoothingMode(pGraphics, SmoothingMode){
   return DllCall("gdiplus\GdipSetSmoothingMode", A_PtrSize ? "UPtr" : "UInt", pGraphics, "int", SmoothingMode)
}
Gdip_GraphicsClear(pGraphics, ARGB=0x00ffffff){
    return DllCall("gdiplus\GdipGraphicsClear", A_PtrSize ? "UPtr" : "UInt", pGraphics, "int", ARGB)
}
UpdateLayeredWindow(hwnd, hdc, x="", y="", w="", h="", Alpha=255){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	if ((x != "") && (y != ""))
		VarSetCapacity(pt, 8), NumPut(x, pt, 0, "UInt"), NumPut(y, pt, 4, "UInt")
	if (w = "") ||(h = "")
		WinGetPos,,, w, h, ahk_id %hwnd%
	return DllCall("UpdateLayeredWindow", Ptr, hwnd, Ptr, 0, Ptr, ((x = "") && (y = "")) ? 0 : &pt, "int64*", w|h<<32, Ptr, hdc, "int64*", 0, "uint", 0, "UInt*", Alpha<<16|1<<24, "uint", 2)
}
Gdip_BitmapFromScreen(Screen=0, Raster=""){
	if (Screen = 0){
		Sysget, x, 76
		Sysget, y, 77	
		Sysget, w, 78
		Sysget, h, 79
	}
	else if (SubStr(Screen, 1, 5) = "hwnd:")
	{
		Screen := SubStr(Screen, 6)
		if !WinExist( "ahk_id " Screen)
			return -2
		WinGetPos,,, w, h, ahk_id %Screen%
		x := y := 0
		hhdc := GetDCEx(Screen, 3)
	}
	else if (Screen&1 != "")
	{
		Sysget, M, Monitor, %Screen%
		x := MLeft, y := MTop, w := MRight-MLeft, h := MBottom-MTop
	}
	else
	{
		StringSplit, S, Screen, |
		x := S1, y := S2, w := S3, h := S4
	}
	if (x = "") || (y = "") || (w = "") || (h = "")
		return -1
	chdc := CreateCompatibleDC(), hbm := CreateDIBSection(w, h, chdc), obm := SelectObject(chdc, hbm), hhdc := hhdc ? hhdc : GetDC()
	BitBlt(chdc, 0, 0, w, h, hhdc, x, y, Raster)
	ReleaseDC(hhdc)
	pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)
	SelectObject(chdc, obm), DeleteObject(hbm), DeleteDC(hhdc), DeleteDC(chdc)
	return pBitmap
}
Gdip_SaveBitmapToFile(pBitmap, sOutput, Quality=75){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	SplitPath, sOutput,,, Extension
	if Extension not in BMP,DIB,RLE,JPG,JPEG,JPE,JFIF,GIF,TIF,TIFF,PNG
		return -1
	Extension := "." Extension
	DllCall("gdiplus\GdipGetImageEncodersSize", "uint*", nCount, "uint*", nSize)
	VarSetCapacity(ci, nSize)
	DllCall("gdiplus\GdipGetImageEncoders", "uint", nCount, "uint", nSize, Ptr, &ci)
	if !(nCount && nSize)
		return -2
	If (A_IsUnicode){
		StrGet_Name := "StrGet"
		Loop, %nCount%
		{
			sString := %StrGet_Name%(NumGet(ci, (idx := (48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize), "UTF-16")
			if !InStr(sString, "*" Extension)
				continue
			
			pCodec := &ci+idx
			break
		}
	} else {
		Loop, %nCount%
		{
			Location := NumGet(ci, 76*(A_Index-1)+44)
			nSize := DllCall("WideCharToMultiByte", "uint", 0, "uint", 0, "uint", Location, "int", -1, "uint", 0, "int",  0, "uint", 0, "uint", 0)
			VarSetCapacity(sString, nSize)
			DllCall("WideCharToMultiByte", "uint", 0, "uint", 0, "uint", Location, "int", -1, "str", sString, "int", nSize, "uint", 0, "uint", 0)
			if !InStr(sString, "*" Extension)
				continue
			
			pCodec := &ci+76*(A_Index-1)
			break
		}
	}
	if !pCodec
		return -3
	if (Quality != 75)
	{
		Quality := (Quality < 0) ? 0 : (Quality > 100) ? 100 : Quality
		if Extension in .JPG,.JPEG,.JPE,.JFIF
		{
			DllCall("gdiplus\GdipGetEncoderParameterListSize", Ptr, pBitmap, Ptr, pCodec, "uint*", nSize)
			VarSetCapacity(EncoderParameters, nSize, 0)
			DllCall("gdiplus\GdipGetEncoderParameterList", Ptr, pBitmap, Ptr, pCodec, "uint", nSize, Ptr, &EncoderParameters)
			Loop, % NumGet(EncoderParameters, "UInt")      ;%
			{
				elem := (24+(A_PtrSize ? A_PtrSize : 4))*(A_Index-1) + 4 + (pad := A_PtrSize = 8 ? 4 : 0)
				if (NumGet(EncoderParameters, elem+16, "UInt") = 1) && (NumGet(EncoderParameters, elem+20, "UInt") = 6)
				{
					p := elem+&EncoderParameters-pad-4
					NumPut(Quality, NumGet(NumPut(4, NumPut(1, p+0)+20, "UInt")), "UInt")
					break
				}
			}      
		}
	}
	if (!A_IsUnicode)
	{
		nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sOutput, "int", -1, Ptr, 0, "int", 0)
		VarSetCapacity(wOutput, nSize*2)
		DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sOutput, "int", -1, Ptr, &wOutput, "int", nSize)
		VarSetCapacity(wOutput, -1)
		if !VarSetCapacity(wOutput)
			return -4
		E := DllCall("gdiplus\GdipSaveImageToFile", Ptr, pBitmap, Ptr, &wOutput, Ptr, pCodec, "uint", p ? p : 0)
	}
	else
		E := DllCall("gdiplus\GdipSaveImageToFile", Ptr, pBitmap, Ptr, &sOutput, Ptr, pCodec, "uint", p ? p : 0)
	return E ? -5 : 0
}
Gdip_Shutdown(pToken){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	DllCall("gdiplus\GdiplusShutdown", Ptr, pToken)
	if hModule := DllCall("GetModuleHandle", "str", "gdiplus", Ptr)
		DllCall("FreeLibrary", Ptr, hModule)
	return 0
}
Gdip_CreateBitmapFromHBITMAP(hBitmap, Palette=0){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", Ptr, hBitmap, Ptr, Palette, A_PtrSize ? "UPtr*" : "uint*", pBitmap)
	return pBitmap
}




Thank you for your time.
Last edited by Hellbent on 15 Jun 2019, 20:34, edited 6 times in total.
Hellbent
Posts: 572
Joined: 23 Sep 2017, 13:34

Re: Request for assistance.

15 Jun 2019, 09:57

As soon as I posted this requested I noticed that there could be a issue with the dib section if the users main monitor is smaller than the secondary ones.

I created what is hopefully a fix for that and will update the op in a second.

If anyone has knowledge about this sort of thing perhaps you can let me know if this will fix it.

I am now getting the max width and the max height of any of the monitors and setting that as the dib section.
Hellbent
Posts: 572
Joined: 23 Sep 2017, 13:34

Re: Request for assistance.

15 Jun 2019, 19:58

Here is a short clip of how it should work.

User avatar
Frosti
Posts: 228
Joined: 27 Oct 2017, 14:30
GitHub: Ixiko

Re: Does this work?

16 Jun 2019, 06:31

Your script works great and the search function works amazing fast and correct. The use of two crossing lines is a great idea. The drawing of this two lines is a bit slow on my system but not to slow to adjust good boundaries for the screenshot.
Testsystem is: Windows 7 Ultimate with Service Pack 1 with a two 4k-Monitor setup (Resolution: 2x3840px width and 2160px height).
swagfag
Posts: 2610
Joined: 11 Jan 2017, 17:59

Re: Does this work?

16 Jun 2019, 08:11

is it normal for the lines to jump around when trying to select the space between two monitors
Spoiler

win10x64 v1903 with 2 1080p screens
Last edited by swagfag on 16 Jun 2019, 09:42, edited 2 times in total.
Hellbent
Posts: 572
Joined: 23 Sep 2017, 13:34

Re: Does this work?

16 Jun 2019, 09:10

Frosti wrote:
16 Jun 2019, 06:31
Your script works great and the search function works amazing fast and correct. The use of two crossing lines is a great idea. The drawing of this two lines is a bit slow on my system but not to slow to adjust good boundaries for the screenshot.
Testsystem is: Windows 7 Ultimate with Service Pack 1 with a two 4k-Monitor setup (Resolution: 2x3840px width and 2160px height).
Thank you Frosti.

I'll take a look at putting the Area selection into a normal loop rather than in a timer. Thank you again for the feedback.

swagfag wrote:
16 Jun 2019, 08:11
is it normal for the lines to jump around when trying to select the space between two monitors
For now that is the intended action.
There is a number of points of info that this gives me, and with that I should be able to proceed with different
implementations confident that they will work as intended across a wide range of systems and setups.

Thank you very much for your assistance. :thumbup:

***Edit*** BTW, what OS are you running Swag?

Return to “Ask For Help”

Who is online

Users browsing this forum: cahek0404, Google [Bot], just me, Odlanir and 138 guests