Any MS Paint-like programs written in AHK?

Get help with using AutoHotkey and its commands and hotkeys
Sam_
Posts: 111
Joined: 20 Mar 2014, 20:24

Any MS Paint-like programs written in AHK?

10 Jul 2019, 10:05

I am interested in any Microsoft Paint-like programs written in AHK. Has something like this ever been done? I know there are scattered functions and bits of code around the forums that do some relevant things with GDIPlus, but I don't know of anyone who has brought them together in a cohesive GUI interface, much less an approximation of MS Paint.

By far the best I have seen is Hellbent's Gdip Bitmap Maker, but it seems to have a different use-case and certainly is a different style (e.g. drawing with buttons and the keyboard instead of the mouse).

Any thoughts, suggestions, or pointers in relevant directions?

TIA,
Sam.
Hellbent
Posts: 869
Joined: 23 Sep 2017, 13:34

Re: Any MS Paint-like programs written in AHK?

07 Jan 2020, 01:28

I'm a bit late to the party but here is a little proof of concept.

While drawing DOTS or RECTANGLES you can press the ARROW keys to do fine movements.

Code: Select all

;***************************************************************************************************
;***************************************************************************************************
;***************************************************************************************************
#Include <My Altered Gdip Lib>  ;<------       Replace with your copy of GDIP
;***************************************************************************************************
;***************************************************************************************************
;***************************************************************************************************
#SingleInstance,Force
SetBatchLines,-1
CoordMode,Mouse,Client
Gdip_Startup()
global ColorList := ["000000","7F7F7F","880015","ED1C24","FF7F27","FFF200","22B14C","00A2E8","3F48CC","A349A4","FFFFFF","C3C3C3","B97A57","FFAEC9","FFC90E","EFE4B0","B5E61D","99D9EA","7092BE","C8BFE7"]
global ColorSelector := []
global Canvas:={}
global BrushType:=1
global BrushColor:=ColorList[4]
global Zone:={X:10,Y:90,W:485,H:300}
global MyBrush,MyPen
Gui,1:+AlwaysOnTop -DPIScale hwndWinHwnd

Canvas.HWND:=WinHwnd
Canvas.hdc1:=GetDC(Canvas.HWND)
Canvas.hdc2:=CreateCompatibleDC()
Canvas.hbm:=CreateDIBSection(485,300)
Canvas.obm:=SelectObject(Canvas.hdc2,Canvas.hbm)
Canvas.G:=Gdip_GraphicsFromHDC(Canvas.hdc2)
Gdip_SetSmoothingMode(Canvas.G,2)
Bitmap1:=Gdip_CreateBitmap( 485,300 ) 
G1 := Gdip_GraphicsFromImage( Bitmap1 )
Gdip_SetSmoothingMode( G1 , 2 )
Bitmap2:=Gdip_CreateBitmap( 485,300 ) 
G2 := Gdip_GraphicsFromImage( Bitmap2 )
Gdip_SetSmoothingMode( G2 , 2 )

Brush := Gdip_BrushCreateSolid( "0xFF004444" )
Gdip_FillRectangle(G1,Brush,-1,-1,487,302)

Gdip_DrawImage(Canvas.G,Bitmap1)

Gui,1:Color,222429

x:=-20,w:=20
Loop,% ColorList.Length()	{
	ColorSelector[A_Index]:=New Colors(x+=w+5,y:=10,w,h:=w,Window:="1",color:=ColorList[A_Index])
}
global HB_Button:=[]
HB_Button.Push(New Clipboard_Master_v2_Buttons(x:=20, y:=40, w:=150, h:=30, window:="1", Label:="DrawDots", Text:="Draw Dots", Font:="Segoe UI", Font_Size:="10 Bold", Font_Color_Top:="33aaff", Font_Color_Bottom:="000000", Background_Color:="222429", y_Offset,Type:="Open Folder"))
HB_Button.Push(New Clipboard_Master_v2_Buttons(x+=w+10, y:=40, w:=150, h:=30, window:="1", Label:="DrawLines", Text:="Draw Lines", Font:="Segoe UI", Font_Size:="10 Bold", Font_Color_Top:="33aaff", Font_Color_Bottom:="000000", Background_Color, y_Offset,Type:="Open Folder"))
HB_Button.Push(New Clipboard_Master_v2_Buttons(x+=w+10, y:=40, w:=150, h:=30, window:="1", Label:="DrawRectangles", Text:="Draw Rectangles", Font:="Segoe UI", Font_Size:="10 Bold", Font_Color_Top:="33aaff", Font_Color_Bottom:="000000", Background_Color, y_Offset,Type:="Open Folder"))

SetBrush()

Gui,1:Show,% "x" A_ScreenWidth-520 " y50 w505 h400" ,HB Paint
BitBlt(Canvas.hdc1,10,90,485,300,Canvas.hdc2,0,0)

SetTimer,HB_Button_Hover,50

SetTimer,Paint_It,10
return
GuiClose:
;~ GuiContextMenu:
*ESC::
	ExitApp

DrawDots:
	BrushType:=1
	return
DrawLines:
	BrushType:=2
	return
DrawRectangles:
	BrushType:=3
	return
	
Paint_It:
	if(GetKeyState("Up"))
		
		MouseMove,0,-1,0,r
	
	else if(GetKeyState("Down"))
		
		MouseMove,0,1,0,r
	
	if(GetKeyState("Left"))
		
		MouseMove,-1,0,0,r
	
	else if(GetKeyState("Right"))
		
		MouseMove,1,0,0,r
	
	MouseGetPos,tx,ty
	
	if(WinActive("ahk_id " Canvas.HWND)&&GetKeyState("LButton")){
		
		if(tx>=Zone.X&&tx<=Zone.X+Zone.W&&ty>=Zone.Y&&ty<=Zone.Y+Zone.H){
			
			if(BrushType=1){
				
				
					Gdip_FillEllipse( G1 , MyBrush , tx-15 , ty-95 , 10 , 10 )
				
			}
			
			else if(BrushType=2){
				
				MouseGetPos,sx,sy
				
				While(GetKeyState("LButton")){	
					
					MouseGetPos,cx,cy
					
					Gdip_DrawImage(G2,Bitmap1)
					Gdip_DrawLine(G2, MyPen, sx-10, sy-90, cx-10, cy-90)  
					
					Gdip_DrawImage(Canvas.G,Bitmap2)
					BitBlt(Canvas.hdc1,10,90,485,300,Canvas.hdc2,0,0)   
					
					sleep,10

				}
				
				Gdip_DrawLine(G1, MyPen, sx-10, sy-90, cx-10, cy-90)
				
			}else if(BrushType=3){
				CoordMode,Mouse,Client
				MouseGetPos,sx,sy
				Fx:=sx,Fy:=sy
				While(GetKeyState("LButton")){
					MouseGetPos,ex,ey
					(sx<ex)?(x1:=sx,x2:=ex-sx):(x1:=ex,x2:=sx-ex)
					(sy<ey)?(y1:=sy,y2:=ey-sy):(y1:=ey,y2:=sy-ey)
					
						(GetKeyState("Up"))?(Move(0,-1),(!GetKeyState("Shift"))?(sy-=1))
						(GetKeyState("Right"))?(Move(1,0),(!GetKeyState("Shift"))?(sx+=1))
						(GetKeyState("Down"))?(Move(0,1),(!GetKeyState("Shift"))?(sy+=1))
						(GetKeyState("Left"))?(Move(-1,0),(!GetKeyState("Shift"))?(sx-=1))
					if(GetKeyState("RButton")){
						Click U
						Gdip_DrawImage(Canvas.G,Bitmap1)
						BitBlt(Canvas.hdc1,10,90,485,300,Canvas.hdc2,0,0)
						return
					}
					Gdip_DrawImage(G2,Bitmap1)
					Gdip_DrawRectangle( G2 , MyPen , x1-10 , y1-90 , x2 , y2 )
					Gdip_DrawImage(Canvas.G,Bitmap2)
					BitBlt(Canvas.hdc1,10,90,485,300,Canvas.hdc2,0,0)
					sleep,10
				}
				Gdip_DrawRectangle( G1 , MyPen , x1-10 , y1-90 , x2 , y2 )
				
			}
			
			Gdip_DrawImage(Canvas.G,Bitmap1)
			BitBlt(Canvas.hdc1,10,90,485,300,Canvas.hdc2,0,0)
			
		}
		
	}
	
	return

Move(x,y){
	MouseMove,x,y,0,R
}


SetBrush(){
	Gdip_DeleteBrush( MyBrush )
	MyBrush := Gdip_BrushCreateSolid( "0xFF" BrushColor)
	Gdip_DeletePen(MyPen)

	MyPen:=Gdip_CreatePen("0xFF" BrushColor,5)

}

SetColor(hwnd){
	Loop,% ColorSelector.Length()	{
		if(Format("{1:#x}", hwnd)=ColorSelector[A_Index].hwnd){
			BrushColor:=ColorList[A_Index]
			SetBrush()
			SoundBeep,400
			return
		}
	}
}

Class Colors	{
	__New(x:="",y:="",w:="",h:="",Window:="1",color:="FF0000"){
		This.X:=x
		This.Y:=y 
		This.W:=w 
		This.H:=h 
		This.Window:=Window
		This.Color:= "0xFF" Color
		This._Trigger()
		sleep,20
		This._Draw()
	}
	_Trigger(){
		local hwnd
		Gui,% This.Window ": Add",Picture,% "x" This.X " y" This.Y " w" This.W " h" This.H " hwndhwnd 0xE gSetColor"
		This.Hwnd:=hwnd
	}
	_Draw(){
		pBitmap:=Gdip_CreateBitmap( This.W , This.H ) 
		G := Gdip_GraphicsFromImage( pBitmap )
		Gdip_SetSmoothingMode( G , 3 )
		Brush := Gdip_BrushCreateSolid( "0xFF222222" )
		Gdip_FillRectangle( G , Brush , -1 , -1 , This.W+2 , This.H+2 )
		Gdip_DeleteBrush( Brush )
		Brush := Gdip_BrushCreateSolid( This.Color )
		Gdip_FillRectangle( G , Brush , 1 , 1 , This.W-2 , This.H-2 )
		Gdip_DeleteBrush( Brush )
		Gdip_DeleteGraphics( G )
		This.BitMap := Gdip_CreateHBITMAPFromBitmap(pBitmap)
		Gdip_DisposeImage(pBitmap)
		SetImage( This.Hwnd , This.BitMap )
	}
}

HB_Button_Hover(){
	static Hover_On,Index
	MouseGetPos,,,,ctrl,2
	if(!Hover_On&&ctrl){
		Loop,% HB_Button.Length()	{
			if(ctrl=HB_Button[A_Index].Hwnd)
				HB_Button[A_Index].Draw_Hover(),Index:=A_Index,Hover_On:=1,break
		}
	}else if(Hover_On){
		if(HB_Button[Index].Hwnd!=ctrl)
			HB_Button[Index].Draw_Default(),Hover_On:=0
	}
}

class Clipboard_Master_v2_Buttons	{
	__New(x:=10, y:=10, w:=100, h:=30, window:="1", Label:="", Text:="Button", Font:="Arial", Font_Size:="10 Bold", Font_Color_Top:="FFFFFF", Font_Color_Bottom:="000000", Background_Color:="333437", y_Offset:=0, Typek:="",Name:="" ){
		This.X:=x,This.Y:=y,This.W:=w,This.H:=h,This.Window:=window,This.Label:=Label,This.Background_Color:="0xFF" Background_Color
		This.Text:=Text,This.Font:=Font,This.Font_Color_Top:="0xFF" Font_Color_Top,This.Font_Color_Bottom:="0xFF" Font_Color_Bottom
		This.Font_Size:=Font_Size,This.Y_Offset:=y_Offset,This.Type:=Typek,This.Name:=Name
		This._Create_Trigger(),This._Create_Default_Bitmap(),This._Create_Hover_Bitmap(),This._Create_Pressed_Bitmap()
		Sleep, 20
		This.Draw_Default()
		GuiControl,% This.Window ":Focus",% This.Hwnd
	}
	_Create_Trigger(){
		local hwnd,bbp
		Gui,% This.Window ":Add",Picture,% "x" This.X " y" This.Y " w" This.W " h" This.H " hwndhwnd 0xE"
		This.Hwnd:=hwnd
		bbp:=This._Draw_Pressed.Bind(This)
		GuiControl,% This.Window ":+G",% This.Hwnd,% bbp
		if(This.Label)
			(isFunc(This.Label))?(This.Function:=Func(This.Label))
	}
	_Create_Default_Bitmap(){
		;Bitmap Created Using: HB Bitmap Maker
		pBitmap:=Gdip_CreateBitmap( This.W , This.H ) 
		G := Gdip_GraphicsFromImage( pBitmap )
		Gdip_SetSmoothingMode( G , 1 )
		Brush := Gdip_BrushCreateSolid( This.Background_Color )
		Gdip_FillRectangle( G , Brush , -2 , 0 , This.W+3 , This.H+3 )
		Gdip_DeleteBrush( Brush )
		Brush := Gdip_BrushCreateSolid( "0xFF252627" )   
		Gdip_FillRectangle( G , Brush , 3 , 3 , This.W-6 , This.H-6 ) 
		Gdip_DeleteBrush( Brush )
		Brush := Gdip_CreateLineBrushFromRect( 4 , 3 , This.W-9 , This.H-7 , "0xFF363C45" , "0xFF2B2C2E" , 1 , 1 )
		Gdip_FillRectangle( G , Brush , 4 , 4 , This.W-8 , This.H-8 )
		Gdip_DeleteBrush( Brush )
		Pen := Gdip_CreatePen( "0xFF4D535B" , 1 )
		Gdip_DrawLine( G , Pen , 4 , 4 , This.W-5 , 4 )
		Gdip_DeletePen( Pen )
		Brush := Gdip_BrushCreateSolid( This.Font_Color_Bottom )
		Gdip_TextToGraphics( G , This.Text , "s" This.Font_Size " Center vCenter c" Brush " x0 y" 1+This.Y_Offset , This.Font , This.W , This.H )
		Gdip_DeleteBrush( Brush )
		Brush := Gdip_BrushCreateSolid( This.Font_Color_Top )
		Gdip_TextToGraphics( G , This.Text , "s" This.Font_Size " Center vCenter c" Brush " x1 y" 2+This.Y_Offset , This.Font , This.W , This.H )
		Gdip_DeleteBrush( Brush )
		Gdip_DeleteGraphics( G )
		This.Default_Bitmap:=Gdip_CreateHBITMAPFromBitmap(pBitmap)
		Gdip_DisposeImage(pBitmap)
	}
	_Create_Hover_Bitmap(){
		;Bitmap Created Using: HB Bitmap Maker
		pBitmap:=Gdip_CreateBitmap( This.W , This.H ) 
		G := Gdip_GraphicsFromImage( pBitmap )
		Gdip_SetSmoothingMode( G , 1 )
		Brush := Gdip_BrushCreateSolid( This.Background_Color )
		Gdip_FillRectangle( G , Brush , -2 , 0 , This.W+3 , This.H+3 )
		Gdip_DeleteBrush( Brush )
		Brush := Gdip_BrushCreateSolid( This.Font_Color_Top )  
		Gdip_FillRectangle( G , Brush , 3 , 3 , This.W-6 , This.H-6 )
		Gdip_DeleteBrush( Brush )
		Brush := Gdip_CreateLineBrushFromRect( 4 , 3 , This.W-9 , This.H-7 , "0xFF464C55" , "0xFF3B3C3E" , 1 , 1 )
		Gdip_FillRectangle( G , Brush , 4 , 4 , This.W-8 , This.H-8 )
		Gdip_DeleteBrush( Brush )
		Pen := Gdip_CreatePen( "0xFF4D535B" , 1 )
		Gdip_DrawLine( G , Pen , 4 , 4 , This.W-5 , 4 )
		Gdip_DeletePen( Pen )
		Brush := Gdip_BrushCreateSolid( This.Font_Color_Bottom )
		Gdip_TextToGraphics( G , This.Text , "s" This.Font_Size " Center vCenter c" Brush " x0 y" 1+This.Y_Offset , This.Font , This.W , This.H )
		Gdip_DeleteBrush( Brush )
		Brush := Gdip_BrushCreateSolid( This.Font_Color_Top )
		Gdip_TextToGraphics( G , This.Text , "s" This.Font_Size " Center vCenter c" Brush " x1 y" 2+This.Y_Offset , This.Font , This.W , This.H )
		Gdip_DeleteBrush( Brush )
		Gdip_DeleteGraphics( G )
		This.Hover_Bitmap:=Gdip_CreateHBITMAPFromBitmap(pBitmap)
		Gdip_DisposeImage(pBitmap)
	}
	_Create_Pressed_Bitmap(){
		;Bitmap Created Using: HB Bitmap Maker
		pBitmap:=Gdip_CreateBitmap( This.W , This.H ) 
		G := Gdip_GraphicsFromImage( pBitmap )
		Gdip_SetSmoothingMode( G , 1 )
		Brush := Gdip_BrushCreateSolid( This.Background_Color )
		Gdip_FillRectangle( G , Brush , -2 , 0 , This.W+3 , This.H+3 )
		Gdip_DeleteBrush( Brush )
		;----------------------------------------------------------------
		;credit jeeswg   -  https://www.autohotkey.com/boards/viewtopic.php?f=76&t=65764
		cc:= This.Font_Color_Top
		Match := StrSplit(RegExReplace(cc, "^0x(..)(..)(..)(..)$", "0x$1 0x$2 0x$3 0x$4"), " ")
		cc := Format("0x{:02X}{:02X}{:02X}{:02X}", Match.1, Max(Match.2-0x33,0), Max(Match.3-0x33,0), Max(Match.4-0x33,0))
		Brush := Gdip_BrushCreateSolid( cc ) 
		;----------------------------------------------------------------
		Gdip_FillRectangle( G , Brush , 3 , 3 , This.W-6 , This.H-6 )
		Gdip_DeleteBrush( Brush )
		Brush := Gdip_CreateLineBrushFromRect( 4 , 3 , This.W-9 , This.H-7 , "0xFF2B2C2E" , "0xFF363C45" , 1 , 1 )
		Gdip_FillRectangle( G , Brush , 4 , 4 , This.W-8 , This.H-8 )
		Gdip_DeleteBrush( Brush )
		Pen := Gdip_CreatePen( "0x881D232B" , 1 )
		if(HB_Button.Length()+1=884) 
		Gdip_DrawLine( G , Pen , 4 , This.H-5 , This.W-5 , This.H-5 )
		Gdip_DeletePen( Pen )
		Pen := Gdip_CreatePen( "0x881D232B" , 1 )
		Gdip_DrawLine( G , Pen , 4 , 4 , This.W-5 , 4 )
		Gdip_DeletePen( Pen )
		Pen := Gdip_CreatePen( "0x881D232B" , 1 )
		Gdip_DrawLine( G , Pen , 4 , 4 , 4 , This.H-6 )
		Gdip_DeletePen( Pen )
		Pen := Gdip_CreatePen( "0x881D232B" , 1 ) 
		Gdip_DrawLine( G , Pen , This.W-5 , 4 , This.W-5 , This.H-6 ) 
		Gdip_DeletePen( Pen )
		Brush := Gdip_BrushCreateSolid( This.Font_Color_Bottom )
		Gdip_TextToGraphics( G , This.Text , "s" This.Font_Size " Center vCenter c" Brush " x0 y" 2+This.Y_Offset , This.Font , This.W , This.H )
		Gdip_DeleteBrush( Brush )
		Brush := Gdip_BrushCreateSolid( This.Font_Color_Top )
		Gdip_TextToGraphics( G , This.Text , "s" This.Font_Size " Center vCenter c" Brush " x1 y" 3+This.Y_Offset , This.Font , This.W , This.H )
		Gdip_DeleteBrush( Brush )
		Gdip_DeleteGraphics( G )
		This.Pressed_Bitmap:=Gdip_CreateHBITMAPFromBitmap(pBitmap)
		Gdip_DisposeImage(pBitmap)
	}
	_Draw_Pressed(){
		local ctrl
		GuiControl,% This.Window ":Focus",% This.Hwnd
		SetTimer,HB_Button_Hover,Off
		SetImage(This.Hwnd,This.Pressed_Bitmap)
		While(GetKeyState("LButton"))
			Sleep,10
		SetTimer,HB_Button_Hover,On
		MouseGetPos,,,,ctrl,2
		if(ctrl=This.Hwnd){
			This.Draw_Hover()
			if(This.Function)
				This.Function.Call()
			else if(This.Label)
				gosub,% This.Label
		}else	{
			This.Draw_Default()
		}
	}
	Draw_Hover(){
		SetImage(This.Hwnd,This.Hover_Bitmap)
	}
	Draw_Default(){
		SetImage(This.Hwnd,This.Default_Bitmap)
	}
}
.


Some of the functionality (such as flood fill) might take a bit of effort, but other things (such as saving as a .png,creating layers, etc ) would be rather easy to add.

Return to “Ask For Help”

Who is online

Users browsing this forum: Bing [Bot], flyingDman, kirabc, telanx, WarriorOfSneak and 238 guests