After reading this topic https://www.autohotkey.com/boards/viewtopic.php?t=60827
I was curious to find a way to draw several shapes and lines with the mouse and display them at the same time on the screen.
I don't know if it's the right method, but the BitBlt() function seems to do the trick.
Here's the script of course it can still be improved with a lot of options and other shapes but as I'm not sure if it's the right way to do it I prefer to keep it basic.
shortcuts:
Shift + lmouse = draw lines
Alt + lmouse = draw filled rectangles
Ctrl + lmouse = draw rectangles
Win + lmouse = draw ellipses
Ctrl + Z = undo last drawing
F9 = clear the screen
F1 = Toggle Gui
Ctrl+F1 = toggle help
Code: Select all
;================================================================================================================================
; Subject: Gdip Draw shapes and lines with the mouse
; Description: Proof of concept for drawing shapes and lines with the mouse using BitBlt()
; Topic: https://www.autohotkey.com/boards/viewtopic.php?f=6&t=74009
; Sript version: 1.5
; AHK Version: 1.1.24.03 (U32)
; Tested on: Win 7 (x64)
; Authors: SpeedMaster, Hellbent
; Credits : Special thanks to Linear Spoon (how to draw a filled rectangle)
; https://autohotkey.com/board/topic/92184-deleting-a-rectangle-or-range-created-with-gdi/
;
; Shortcuts: Shift + left mouse = draw lines
; Alt + left mouse = draw filled rectangles
; Ctrl + left mouse = draw rectangles
; Win + left mouse = draw ellipses
; Ctrl + Z = undo last drawing
; F1 = Toggle Gui
; Ctrl + F1 = Display Help
; F9 = clear the screen
;
;
; other related topic: https://www.autohotkey.com/boards/viewtopic.php?f=76&t=60827&hilit=draw+on+screen
#SingleInstance force
;;#Include <My Altered Gdip Lib> ;<------ Replace with your copy of GDIP
;******* HB Alteration ******
global ColorList := ["000000","7F7F7F","880015","ED1C24","FF7F27","FFF200","22B14C","00A2E8","3F48CC","A349A4","FFFFFF","C3C3C3","B97A57","FFAEC9","FFC90E","EFE4B0","B5E61D","99D9EA","7092BE","C8BFE7"]
global Handles := [],Handles2:=[],ALED,Thickness,LH,LA:="FF",LT:=5
;*********************************
SetBatchLines -1
SetMouseDelay -1
coordmode, mouse, screen
Gui, 1: -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs
Gui, 1: Show, NA
hwnd7 := WinExist() ; hwnd7 to avoid conflict ("hwnd1" name is too much used in other scripts)
steps:=[]
pens:=[]
gosub f1
for k, v in handles {
if (v=1) {
LH:=k
}
}
Onexit, exit
;---------------------------------------------------- Gdip stuff ----------------------------------------------
Width := A_ScreenWidth, Height := A_ScreenHeight
If !pToken := Gdip_Startup()
{
MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
ExitApp
}
hbm := CreateDIBSection(Width, Height) ;screen
hdc := CreateCompatibleDC() ;screen
obm := SelectObject(hdc, hbm) ;screen
hbm2 := CreateDIBSection(Width, Height) ;buffer
hdc2 := CreateCompatibleDC() ;buffer
obm2 := SelectObject(hdc2, hbm2) ;buffer
hbm3 := CreateDIBSection(Width, Height) ;saving buffer
hdc3 := CreateCompatibleDC() ;saving buffer
obm3 := SelectObject(hdc3, hbm3) ;saving buffer
G := Gdip_GraphicsFromHDC(hdc)
G2 := Gdip_GraphicsFromHDC(hdc2)
Gdip_SetSmoothingMode(G, 4)
Gdip_SetSmoothingMode(G2, 4)
;------------------------------------------------ create some brushes and pencils ------------------------------------
global pPen := Gdip_CreatePen("0xFF" ColorList[1] , 5)
, pBrush := Gdip_BrushCreateSolid("0xFF" ColorList[1])
;------------------------------------------------ Undo/Redo stuff ----------------------------------------------------
;clear the screen
f9::
Gdip_GraphicsClear(G) ;This sets the entire area of the graphics to 'transparent'
BitBlt(hdc2, 0, 0, Width, Height, hdc, 0, 0)
BitBlt(hdc3, 0, 0, Width, Height, hdc, 0, 0)
UpdateLayeredWindow(hwnd7, hdc, 0, 0, Width, Height) ;This is what actually changes the display
steps:=[]
return
; undo last drawing
^Z::
steps.pop() ; erase last step
Gdip_GraphicsClear(G) ;This sets the entire area of the graphics to 'transparent'
;UpdateLayeredWindow(hwnd7, hdc, 0, 0, Width, Height) ;This is what actually changes the display
for k, v in steps {
refresh(v)
if (k=steps.maxindex()-1)
BitBlt(hdc3, 0, 0, Width, Height, hdc, 0, 0) ; save previous hdc
}
UpdateLayeredWindow(hwnd7, hdc, 0, 0, Width, Height)
BitBlt(hdc2, 0, 0, Width, Height, hdc, 0, 0) ; refresh buffer
refresh(v) {
global
Gdip_DeleteBrush( pBrush )
Gdip_DeletePen( pPen )
pPen := Gdip_CreatePen(v.1,v.2)
pBrush := Gdip_BrushCreateSolid(v.1)
LA:=substr(v.1,3,2) ; transparency
currentcontrol:="2_" _HasVal(colorlist, substr(v.1,5))
loop, % colorlist.length()
GuiControl,% "99:+Background" "555555", % "2_" A_Index
GuiControl,% "99:+Background" "00FFFF", % currentcontrol ;select
LH:=_HasVal(handles, _HasVal(colorlist, substr(v.1,5)))
if (v.2!="br") {
LT:=v.2 ;Thickness
v[3](G, pPen, v.4, v.5, v.6, v.7) ;draw the shape
}
else
v[3](G, pBrush, v.4, v.5, v.6, v.7) ;draw the shape
GuiControl,, % Thickness, % LT ;thickness
GuiControl,, % ALED, % LA ;transparency
}
return
;------------------------------------------------ Help -------------------------------------------------
^F1::
help:=!help
if help {
helptext:="Shift + lmouse = draw lines`n"
helptext.="Shift + lmouse = draw lines`n"
helptext.="Alt + lmouse = draw filled rectangles`n"
helptext.="Ctrl + lmouse = draw rectangles`n"
helptext.="Win + lmouse = draw ellipses`n"
helptext.="Ctrl + Z = undo last drawing`n"
helptext.="F9 = clear the screen`n"
helptext.="F1 = toggle help"
tooltip, % helptext
}
else
tooltip
return
;------------------------------------------------ Draw rectangles ----------------------------------------------------
;Draw rectangles
^LButton::
CoordMode, Mouse, Screen
MouseGetPos, x1, y1
BitBlt(hdc3, 0, 0, Width, Height, hdc, 0, 0) ; save previous hdc first
while getKeyState("LButton", "P") ; draw in buffer
{
MouseGetPos, x2, y2
Gdip_GraphicsClear(G2)
BitBlt(hdc2, 0, 0, Width, Height, hdc, 0, 0) ; BitBlt first before drawing
Gdip_DrawRectangle(G2, pPen, min(x1,x2), min(y1,y2), abs(x2-x1), abs(y2-y1))
UpdateLayeredWindow(hwnd7, hdc2, 0, 0, Width, Height)
}
step:=["0x" LA ColorList[Handles[LH]],LT,"Gdip_DrawRectangle",min(x1,x2),min(y1,y2),abs(x2-x1),abs(y2-y1)]
steps.push(step)
BitBlt(hdc, 0, 0, Width, Height, hdc2, 0, 0) ;copy buffer to screen
UpdateLayeredWindow(hwnd7, hdc, 0, 0, Width, Height) ; now draw on screen
return
;---------------------------------------------- Draw a filled rectangles --------------------------------------------
;Draw a filled rectangles
!LButton::
CoordMode, Mouse, Screen
MouseGetPos, x1, y1
BitBlt(hdc3, 0, 0, Width, Height, hdc, 0, 0) ; save previous hdc first
while getKeyState("LButton", "P") ; draw in buffer
{
MouseGetPos, x2, y2
Gdip_GraphicsClear(G2)
BitBlt(hdc2, 0, 0, Width, Height, hdc, 0, 0) ; BitBlt first before drawing
;FillRect seems to expect the (x,y) coordinates passed to always be the upper left corner and width,height to be positive
Gdip_FillRectangle(G2, pBrush, min(x1,x2), min(y1,y2), abs(x2-x1), abs(y2-y1))
UpdateLayeredWindow(hwnd7, hdc2, 0, 0, Width, Height)
}
step:=["0x" LA ColorList[Handles[LH]],"Br","Gdip_FillRectangle",min(x1,x2),min(y1,y2),abs(x2-x1),abs(y2-y1)]
steps.push(step)
BitBlt(hdc, 0, 0, Width, Height, hdc2, 0, 0) ;copy buffer to screen
UpdateLayeredWindow(hwnd7, hdc, 0, 0, Width, Height) ; now draw on screen
min(a,b)
{
return a < b ? a : b
}
return
f2::reload
f5::
GuiControl,, % Thickness, 11
return
;---------------------------------------------------- draw lines -----------------------------------------------------
;draw lines
+lbutton::
CoordMode, Mouse, Screen
MouseGetPos, x1, y1
BitBlt(hdc3, 0, 0, Width, Height, hdc, 0, 0) ; save previous hdc first
while getKeyState("LButton", "P")
{
MouseGetPos, x2, y2
Gdip_GraphicsClear(G2)
BitBlt(hdc2, 0, 0, Width, Height, hdc, 0, 0)
Gdip_DrawLine(G2, pPen, x1, y1, x2, y2)
UpdateLayeredWindow(hwnd7, hdc2, 0, 0, Width, Height)
}
step:=["0x" LA ColorList[Handles[LH]],LT,"Gdip_DrawLine",x1,y1,x2,y2]
steps.push(step)
BitBlt(hdc, 0, 0, Width, Height, hdc2, 0, 0) ;copy buffer to screen
UpdateLayeredWindow(hwnd7, hdc, 0, 0, Width, Height) ; now draw on screen
return
;---------------------------------------------------- Draw ellipse -------------------------------------------------
;Draw ellipse
#LButton::
CoordMode, Mouse, Screen
MouseGetPos, x1, y1
BitBlt(hdc3, 0, 0, Width, Height, hdc, 0, 0) ; save previous hdc first
while getKeyState("LButton", "P") ; draw in buffer
{
MouseGetPos, x2, y2
Gdip_GraphicsClear(G2)
BitBlt(hdc2, 0, 0, Width, Height, hdc, 0, 0) ; BitBlt first before drawing
;seems to expect the (x,y) coordinates passed to always be the upper left corner and width,height to be positive
Gdip_DrawEllipse(G2, pPen, min(x1,x2), min(y1,y2), abs(x2-x1), abs(y2-y1))
UpdateLayeredWindow(hwnd7, hdc2, 0, 0, Width, Height)
}
step:=["0x" LA ColorList[Handles[LH]],LT,"Gdip_DrawEllipse",min(x1,x2),min(y1,y2),abs(x2-x1),abs(y2-y1)]
steps.push(step)
BitBlt(hdc, 0, 0, Width, Height, hdc2, 0, 0) ;copy buffer to screen
UpdateLayeredWindow(hwnd7, hdc, 0, 0, Width, Height) ; now draw on screen
return
exit:
SelectObject(hdc, obm)
DeleteObject(hbm)
DeleteDC(hdc)
Gdip_DeleteGraphics(G)
SelectObject(hdc2, obm2)
DeleteObject(hbm2)
DeleteDC(hdc2)
Gdip_DeleteGraphics(G2)
SelectObject(hdc3, obm3)
DeleteObject(hbm3)
Gdip_Shutdown(pToken)
exitapp
return
esc::exitapp
;******* HB Alteration ******
;********************************************************************************************************************************************
;********************************************************************************************************************************************
;********************************************************************************************************************************************
F1::
99GuiClose:
if(showgui:=!showgui){
if(!ft){
ft:=1
Gui,99:+AlwaysOnTop +ToolWindow
Gui,99:Color,% ColorList[1], 333333
Gui,99:Font,cWhite s8 ,Segoe UI
y:=0,x:=m:=20,w:=m,C:="00ffff"
Gui,99:Margin,20,20
Loop,% ColorList.Length() {
if(A_Index=11)
x:=m+w,y:=0
y+=m
Gui,99:Add,Text,% "x" x " y" y " w" m " h" m " hwndhwnd gChangeColor" " v1_" a_index, x
Handles[hwnd] := A_Index
Gui,99:Add,Progress,% "x" x " y" y " w" m " h" m " c" ColorList[A_Index] " Background" C " hwndhwnd" " v2_" a_index ,100
Handles2[A_Index]:= hwnd, C:="555555"
}
Gui,99:Add,Edit,xm y+1 w40 r1 Limit2 Center hwndALED gChangeBrush,FF
Gui,99:Add,Edit,xm y+1 w40 r1 Limit2 Center hwndThickness gChangeBrush,5
Gui,99:Add,button,xm y+2 w40 gapply, APPLY
GuiControl,% "99:Focus", % hwnd
}
Gui,99:Show,% "x" A_ScreenWidth-250 " y150",Color
}
else{
Gui,99:Hide
}
return
ChangeColor(hwnd){
;global LH
static LC := 1, C :="00FFFF"
loop, % colorlist.length()
GuiControl,% "99:+Background" "555555", % "2_" A_Index
LH:=hwnd
GuiControl,% "99:Focus", % Handles2[Handles[hwnd]]
GuiControl,% "99:+Background555555", % "2_" LC
GuiControl,% "99:+Background" C, % Handles2[Handles[hwnd]]
Gui,99:Color,% ColorList[Handles[hwnd]]
LC := Handles[hwnd]
ChangeBrush()
}
ChangeBrush(){
;global LA, LT
GuiControlGet,LA,99:,% ALED
GuiControlGet,LT,99:,% Thickness
Gdip_DeleteBrush( pBrush )
Gdip_DeletePen( pPen )
pPen := Gdip_CreatePen("0x" LA ColorList[Handles[LH]] , LT)
pBrush := Gdip_BrushCreateSolid("0x" LA ColorList[Handles[LH]])
}
apply:
if (!steps.Maxindex())
return
BitBlt(hdc, 0, 0, Width, Height, hdc3, 0, 0)
steps[steps.maxindex()][1]:="0x" LA ColorList[Handles[LH]] ;apply new selected color to the last shape
(steps[steps.maxindex()][2]!="br") && steps[steps.maxindex()][2]:=LT ; apply transparency and thickness to the last shape
refresh(steps[steps.maxindex()])
UpdateLayeredWindow(hwnd7, hdc,0,0, Width, Height)
return
_HasVal(haystack, needle) {
for index, value in haystack
if (value = needle)
return index
if !(IsObject(haystack))
throw Exception("Bad haystack!", -1, haystack)
return 0
}
Cheers