GUIs via DllCall: control zoo

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

GUIs via DllCall: control zoo

21 May 2017, 18:41

This is the second example in GUIs via DllCall.

GUIs via DllCall: MsgBox - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=30688

And is a DllCall version of:

control zoo (AHK v1.1) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=30652

It tries to create a GUI window with every major control type, and implement a bit of functionality for each one. I made a version of this using AHK v1.1's Gui command, this version uses DllCall instead.

In general each control class had exactly one major sticking point, which slowed down releasing this script, which I will write more about below.

Code: Select all

;AHK v1.1 script
;'GUIs via DllCall control zoo.ahk' by jeeswg

;note: SciLexer.dll should be in the same directory for Scintilla to show
;Download Scintilla
;http://www.scintilla.org/ScintillaDownload.html

#SingleInstance force
#Persistent

;vInput := 101
InputBox, vInput,, show built-in controls 1/show built-in controls 2/show custom controls,,,,,,,, 101
vShowBuiltIn1 := SubStr(vInput, 1, 1)
vShowBuiltIn2 := SubStr(vInput, 2, 1)
vShowCustom := SubStr(vInput, 3, 1)

;==================================================

;GUI Control Types
;https://autohotkey.com/docs/commands/GuiControls.htm

;•Text, Edit, UpDown, Picture
;•Button, Checkbox, Radio
;•DropDownList, ComboBox
;•ListBox, ListView, TreeView
;•Link, Hotkey, DateTime, MonthCal
;•Slider, Progress
;•GroupBox, Tab, StatusBar
;•ActiveX (e.g. Internet Explorer Control)
;•Custom

;tabbed = in vShowBuiltIn1 (11 control types + DDL = 12)
	;Text [Static]
	;Edit [Edit]
;UpDown [msctls_updown32]
;Picture [Static]
	;Button [Button]
;Checkbox [Button]
;Radio [Button]
	;DropDownList [ComboBox]
	;ComboBox [ComboBox + Edit]
	;ListBox [ListBox]
	;ListView [SysListView32 + SysHeader32]
	;TreeView [SysTreeView32]
	;Link [SysLink]
;Hotkey [msctls_hotkey32]
	;DateTime [SysDateTimePick32]
;MonthCal [SysMonthCal32]
;Slider [msctls_trackbar32]
;Progress [msctls_progress32]
;GroupBox [Button]
;Tab [SysTabControl32]
	;StatusBar [msctls_statusbar32]
	;ActiveX (e.g. Internet Explorer Control) [AtlAxWin + Shell Embedding + Shell DocObject View + Internet Explorer_Server]
;Custom []

;[RICHEDIT50W]
;[Scintilla]
;[ToolbarWindow32]

;==================================================

hFont := JEE_FontGetDefaultGuiFont() ;MS Shell Dlg, s8
JEE_ConstantsWinStyles()

;==================================================

;create window class e.g. AutoHotkeyGUI
hIcon := LoadPicture(A_AhkPath, "", vType) ;AHK icon
hIconSm := LoadPicture(A_AhkPath, "w16 h16", vType) ;AHK icon
;hIcon := LoadPicture(A_AhkPath, "Icon-160", vType) ;AHK file icon
;hIconSm := LoadPicture(A_AhkPath, "w16 h16 Icon-160", vType) ;AHK file icon
;hIcon := hIconSm := 0
JEE_RegisterClassExCFI("JEEClass", "MyWndProc", hIcon, hIconSm)

;==================================================

;create window
;SplitPath, A_ScriptName,,,, vScriptNameNoExt
SysGet, vCaptionH, 31 ;SM_CYSIZE

vWinClass := "JEEClass"
vWinText := "control zoo" ;window title
vWinStyle := WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX ;start with WS_VISIBLE off
vWinExStyle := WS_EX_DLGMODALFRAME | WS_EX_ACCEPTFILES
vPosX := 100, vPosY := 30
vPosW := 300, vPosH := vCaptionH
vPosH += (vShowBuiltIn1|vShowBuiltIn2)*600
if vShowCustom
	if !(vShowBuiltIn1|vShowBuiltIn2)
		vPosH += 145
	else
		vPosH += 60

hWndParent := 0, hMenu := 0, hInstance := 0, vParam := 0
hGui := JEE_DCCreateWindowEx(vWinExStyle, vWinClass, vWinText, vWinStyle, vPosX, vPosY, vPosW, vPosH, hWndParent, hMenu, hInstance, vParam)

;==================================================

;menu
if vShowBuiltIn1
{
	hMenu := DllCall("CreateMenu")
	hSubMenu1 := DllCall("CreateMenu")
	hSubMenu2 := DllCall("CreateMenu")
	hSubMenu3 := DllCall("CreateMenu")

	DllCall("SetMenu", Ptr,hGui, Ptr,hMenu)
	DllCall("AppendMenu", Ptr,hMenu, UInt,0x10, UPtr,hSubMenu1, Str,"MENU 1") ;popup
	DllCall("AppendMenu", Ptr,hMenu, UInt,0x10, UPtr,hSubMenu2, Str,"MENU 2") ;popup
	DllCall("AppendMenu", Ptr,hMenu, UInt,0x10, UPtr,hSubMenu3, Str,"MENU 3") ;popup
	DllCall("AppendMenu", Ptr,hSubMenu1, UInt,0, UPtr,0, Str,"MENU 1.1")
	DllCall("AppendMenu", Ptr,hSubMenu1, UInt,0, UPtr,0, Str,"MENU 1.2")
	DllCall("AppendMenu", Ptr,hSubMenu1, UInt,0, UPtr,0, Str,"MENU 1.3")
	DllCall("AppendMenu", Ptr,hSubMenu2, UInt,0, UPtr,0, Str,"MENU 2.1")
	DllCall("AppendMenu", Ptr,hSubMenu2, UInt,0, UPtr,0, Str,"MENU 2.2")
	DllCall("AppendMenu", Ptr,hSubMenu2, UInt,0, UPtr,0, Str,"MENU 2.3")
	DllCall("AppendMenu", Ptr,hSubMenu3, UInt,0, UPtr,0, Str,"MENU 3.1")
	DllCall("AppendMenu", Ptr,hSubMenu3, UInt,0, UPtr,0, Str,"MENU 3.2")
	DllCall("AppendMenu", Ptr,hSubMenu3, UInt,0, UPtr,0, Str,"MENU 3.3")
}

;==================================================

;built-in control types
if vShowBuiltIn1
{
	vList = ;continuation section
	(LTrim
	Static|STATIC 1
	Edit|EDIT 1
	Button|BTN 1
	DROPDOWNLIST|CBX 'DDL' 1
	ComboBox|CBX 1
	ListBox|LBX 1
	SysListView32|LV 1
	SysTreeView32|TV 1
	SysLink|<a href="https://autohotkey.com/">https://autohotkey.com/</a>
	SysDateTimePick32|20060504030201
	msctls_statusbar32|SB 1
	Internet Explorer_Server|IE 1
	)

	vPosX := 5, vPosY := 0
	if vShowCustom
		vPosY := 28
	Loop, Parse, vList, `n
	{
		hWndParent := hGui, hMenu := 0, hInstance := 0, vParam := 0
		if (A_LoopField = "")
			continue
		oTemp := StrSplit(A_LoopField, "|")
		vWinClass := oTemp.1, vWinText := oTemp.2, oTemp := ""
		oTemp := ""
		vWinClass2 := JEE_CtlGetTemplate(vWinClass, vPosW, vPosH, vWinStyle, vWinExStyle)
		vWinClass := vWinClass2
		vWinStyle |= WS_VISIBLE | WS_CHILD | WS_TABSTOP

		if (vWinClass = "Internet Explorer_Server")
		{
			vAtl := "atl"
			DllCall("kernel32\LoadLibrary", Str,vAtl, Ptr)
			DllCall(vAtl "\AtlAxWinInit")
			vWinClass := "AtlAxWin"
			vWinText := "Shell.Explorer"
			vWinStyle := 0x54000000
		}

		if (vWinText = "EDIT 1") || (vWinText = "BTN 1")
			vPosW := 43
		if (vWinText = "TV 1")
			vPosH := 84
		if (vWinText = "IE 1")
			vPosH := 270

		hCtl := JEE_DCCreateWindowEx(vWinExStyle, vWinClass, vWinText, vWinStyle, vPosX, vPosY, vPosW, vPosH, hWndParent, hMenu, hInstance, vParam)
		SendMessage, 0x30, % hFont, 0,, % "ahk_id " hCtl ;WM_SETFONT := 0x30

		if (vWinText = "CBX 'DDL' 1")
		{
			Loop, 3
			{
				vText := "CBX 'DDL' " A_Index
				SendMessage, 0x143, 0, % &vText,, % "ahk_id " hCtl ;CB_ADDSTRING := 0x143
			}
			SendMessage, 0x14E, 0, 0,, % "ahk_id " hCtl ;CB_SETCURSEL := 0x14E
		}
		if (vWinText = "CBX 1")
		{
			Loop, 3
			{
				vText := "CBX " A_Index
				SendMessage, 0x143, 0, % &vText,, % "ahk_id " hCtl ;CB_ADDSTRING := 0x143
			}
			SendMessage, 0x14E, 0, 0,, % "ahk_id " hCtl ;CB_SETCURSEL := 0x14E
		}
		if (vWinClass = "ListBox")
		{
			Loop, 3
			{
				vText := "LBX " A_Index
				SendMessage, 0x180, 0, % &vText,, % "ahk_id " hCtl ;LB_ADDSTRING := 0x180
			}
			SendMessage, 0x185, 1, 0,, % "ahk_id " hCtl ;LB_SETSEL := 0x185
		}
		;===============
		;LISTVIEW - START
		if (vWinClass = "SysListView32")
		{
			;insert columns
			Loop, 3
			{
				;EACH NEW COLUMN BECOMES 'COLUMN 1' RATHER THAN COLUMN N
				;vText := "LVH " A_Index
				vText := "LVH " (4-A_Index)
				;LVCF_ORDER := 0x20 ;LVCF_TEXT := 0x4 ;LVCF_WIDTH := 0x2
				VarSetCapacity(LVCOLUMN, A_PtrSize=8?56:44, 0)
				NumPut(0x26, LVCOLUMN, 0, "UInt") ;mask
				if (A_Index = 1)
					NumPut(166, LVCOLUMN, 8, "Int") ;cx
				else
					NumPut(50, LVCOLUMN, 8, "Int") ;cx
				NumPut(&vText, LVCOLUMN, A_PtrSize=8?16:12, "Ptr") ;pszText
				NumPut(StrLen(vText+1), LVCOLUMN, A_PtrSize=8?24:16, "Int") ;cchTextMax
				;EACH NEW COLUMN BECOMES 'COLUMN 1' RATHER THAN COLUMN N
				;NumPut(A_Index-1, LVCOLUMN, A_PtrSize=8?36:28, "Int") ;iOrder
				NumPut(0, LVCOLUMN, A_PtrSize=8?36:28, "Int") ;iOrder
				SendMessage, 0x1061, 0, % &LVCOLUMN, SysListView321, % "ahk_id " hGui ;LVM_INSERTCOLUMNW := 0x1061 ;LVM_INSERTCOLUMNA := 0x101B
			}

			;insert items
			Loop, 3
			{
				vText := vIndex "LV " A_Index
				VarSetCapacity(LVITEM, A_PtrSize=8?88:60, 0)
				NumPut(0x1, LVITEM, 0, "UInt") ;mask ;LVIF_TEXT := 0x1
				NumPut(A_Index-1, LVITEM, 4, "Int") ;iItem
				NumPut(0, LVITEM, 8, "Int") ;iSubItem
				NumPut(&vText, LVITEM, A_PtrSize=8?24:20, vPtrType) ;pszText
				NumPut(vMaxChars, LVITEM, A_PtrSize=8?32:24, "Int") ;cchTextMax
				SendMessage, % A_IsUnicode?0x104D:0x1007, 0, % &LVITEM, SysListView321, % "ahk_id " hGui ;LVM_INSERTITEMW := 0x104D ;LVM_INSERTITEMA := 0x1007
			}
			Loop, 3
			{
				vRow := A_Index
				Loop, 3
				{
					vCol := A_Index, vColLet := Chr(64+vCol)
					vText := vIndex "LV " vColLet vRow
					VarSetCapacity(LVITEM, A_PtrSize=8?88:60, 0)
					NumPut(0x1, LVITEM, 0, "UInt") ;mask ;LVIF_TEXT := 0x1
					NumPut(vRow-1, LVITEM, 4, "Int") ;iItem
					NumPut(vCol-1, LVITEM, 8, "Int") ;iSubItem
					NumPut(&vText, LVITEM, A_PtrSize=8?24:20, "Ptr") ;pszText
					NumPut(vMaxChars, LVITEM, A_PtrSize=8?32:24, "Int") ;cchTextMax
					SendMessage, % A_IsUnicode?0x104C:0x1006, 0, % &LVITEM, SysListView321, % "ahk_id " hGui ;LVM_SETITEMW := 0x104C ;LVM_SETITEMA := 0x1006
				}
			}

			;select item
			;LVIF_STATE := 0x8
			;LVIS_SELECTED := 0x2 ;LVIS_FOCUSED := 0x1
			VarSetCapacity(LVITEM, A_PtrSize=8?88:60, 0)
			NumPut(0x8, LVITEM, 0, "UInt") ;mask
			NumPut(0, LVITEM, 4, "Int") ;iItem
			NumPut(0x3, LVITEM, 12, "UInt") ;state
			NumPut(0x3, LVITEM, 16, "UInt") ;stateMask
			SendMessage, % A_IsUnicode?0x104C:0x1006, 0, % &LVITEM, SysListView321, % "ahk_id " hGui ;LVM_SETITEMW := 0x104C ;LVM_SETITEMA := 0x1006
			;LVS_EX_GRIDLINES := 0x1
			;SendMessage, 0x1036, 0x1, 0x1, SysListView321, % "ahk_id " hGui ;LVM_SETEXTENDEDLISTVIEWSTYLE := 0x1036
			;LVS_EX_FULLROWSELECT := 0x20
			SendMessage, 0x1036, 0x20, 0x20, SysListView321, % "ahk_id " hGui ;LVM_SETEXTENDEDLISTVIEWSTYLE := 0x1036
		}
		;LISTVIEW - END
		;===============
		if (vWinClass = "SysTreeView32")
		{
			vTV1 := JEE_TVAdd(hCtl, "TV 1", "")
			vTV2 := JEE_TVAdd(hCtl, "TV 2", vTV1)
			vTV3 := JEE_TVAdd(hCtl, "TV 3", vTV2)
			vTV4 := JEE_TVAdd(hCtl, "TV 4", vTV1)
			vTV5 := JEE_TVAdd(hCtl, "TV 5", "")
			JEE_TVItemSelect(hCtl, vTV1)
		}
		if (vWinClass = "SysDateTimePick32")
		{
			vFormat := "HH:mm:ss dd/MM/yyyy"
			SendMessage, % A_IsUnicode?0x1032:0x1005, 0, % &vFormat,, % "ahk_id " hCtl ;DTM_SETFORMATW := 0x1032 ;DTM_SETFORMATA := 0x1005
			vDate := vWinText
			vPfx := RegExMatch(10,1,0,-1) ? "O)" : "" ;v1/v2 compatibility
			RegExMatch(vDate, vPfx "(\d\d\d\d)(\d\d)()(\d\d)(\d\d)(\d\d)(\d\d)", o)
			VarSetCapacity(ArraySYSTEMTIME, 2*16, 0)
			Loop, 7
				NumPut(o[A_Index], ArraySYSTEMTIME, (A_Index*2-2), "UShort")
			;GDT_VALID := 0
			SendMessage, 0x1002, 0, % &ArraySYSTEMTIME,, % "ahk_id " hCtl ;DTM_SETSYSTEMTIME := 0x1002
		}
		if (vWinClass = "msctls_statusbar32")
		{
			VarSetCapacity(vArray, 3*4, 0)
			NumPut(50, vArray, 0, "Int")
			NumPut(100, vArray, 4, "Int")
			NumPut(150, vArray, 8, "Int")
			SendMessage, 0x404, 3, % &vArray,, % "ahk_id " hCtl ;SB_SETPARTS := 0x404
			vText2 := "SB 2"
			vText3 := "SB 3"
			SendMessage, % A_IsUnicode?0x40B:0x401, 1, % &vText2,, % "ahk_id " hCtl ;SB_SETTEXTW := 0x40B ;SB_SETTEXTA := 0x401
			SendMessage, % A_IsUnicode?0x40B:0x401, 2, % &vText3,, % "ahk_id " hCtl ;SB_SETTEXTW := 0x40B ;SB_SETTEXTA := 0x401
		}
		if (vWinClass2 = "Internet Explorer_Server")
		{
			DllCall(vAtl "\AtlAxGetControl", Ptr,hCtl, UIntP,pUnk)
			IID_IDispatch := "{00020400-0000-0000-C000-000000000046}"
			vPtr := ComObjQuery(pUnk, IID_IDispatch)
			oWB := ComObject(9, vPtr, 1), ObjAddRef(vPtr)
			oWB.Navigate("https://www.google.com/")
			while oWB.busy || !(oWB.ReadyState = 4)
				Sleep 100
			;OLECMDID_OPTICAL_ZOOM := 63 ;OLECMDEXECOPT_DONTPROMPTUSER := 2
			oWB.ExecWB(63, 2, 30, 0) ;zoom 30%
			;oWB.document.parentWindow.scrollBy(120, 35)
			oWB.document.parentWindow.scrollBy(80, 29)
		}

		if !(vWinClass = "msctls_statusbar32")
		&& !(vWinClass = "ToolbarWindow32")
			vPosY += vPosH+5
	}
}

;==================================================

;built-in control types
if vShowBuiltIn2
{
	vList = ;continuation section
	(LTrim
	msctls_updown32|100
	ICON|STATIC 2
	CHECKBOX|BTN 2
	RADIO|BTN 3
	RADIO|BTN 4
	RADIO|BTN 5
	RADIO|BTN 6
	msctls_hotkey32|CTRL+Q
	SysMonthCal32|20060504030201
	msctls_trackbar32|100
	msctls_progress32|100
	msctls_progress32|50
	msctls_progress32|100
	GROUPBOX|BTN 7
	SysTabControl32|TAB 1
	)

	if !vShowBuiltIn1 && !vShowCustom
		vPosX := 5, vPosY := 5
	if !vShowBuiltIn1 && vShowCustom
		vPosX := 5, vPosY := 30
	Loop, Parse, vList, `n
	{
		hWndParent := hGui, hMenu := 0, hInstance := 0, vParam := 0
		if (A_LoopField = "")
			continue
		oTemp := StrSplit(A_LoopField, "|")
		vWinClass := oTemp.1, vWinText := oTemp.2
		oTemp := ""
		vWinClass2 := JEE_CtlGetTemplate(vWinClass, vPosW, vPosH, vWinStyle, vWinExStyle)
		vWinClass := vWinClass2
		vWinStyle |= WS_VISIBLE | WS_CHILD | WS_TABSTOP

		if (vWinText = "BTN 3") || (vWinText = "BTN 5")
			vWinStyle |= WS_GROUP
		if (vWinText = "STATIC 2")
			vPosH := 32

		;WS_CHILD := 0x40000000 ;WS_VISIBLE := 0x10000000 ;WS_EX_CLIENTEDGE := 0x200
		(vWinClass = "msctls_updown32") ? (vIsUpDown := 1, vWinClass := "Edit", vPosW := 104, vWinStyle := 0x50000000, vWinExStyle := 0x200) : (vIsUpDown := 0)
		hCtl := JEE_DCCreateWindowEx(vWinExStyle, vWinClass, vWinText, vWinStyle, vPosX, vPosY, vPosW, vPosH, hWndParent, hMenu, hInstance, vParam)
		SendMessage, 0x30, % hFont, 0,, % "ahk_id " hCtl ;WM_SETFONT := 0x30

		if vIsUpDown
		{
			vWinClass := "msctls_updown32"
			;UDS_ARROWKEYS := 0x20 ;UDS_ALIGNRIGHT := 4 ;UDS_SETBUDDYINT := 2
			vWinStyle := 0x50000026
			hUD := JEE_DCCreateWindowEx(vWinExStyle, vWinClass, vWinText, vWinStyle, vPosX, vPosY, vPosW, vPosH, hWndParent, hMenu, hInstance, vParam)
			SendMessage, 0x469, % hCtl, 0,, % "ahk_id " hUD ;UDM_SETBUDDY := 0x469
			SendMessage, 0x466, 0, 0,, % "ahk_id " hUD ;UDM_GETRANGE := 0x466
			ControlSetText,, % vWinText, % "ahk_id " hCtl
		}
		if (vWinText = "STATIC 2")
		{
			hIcon := LoadPicture(A_AhkPath, "", vType)
			SendMessage, 0x170, % hIcon, 0,, % "ahk_id " hCtl ;STM_SETICON := 0x170
		}
		if RegExMatch(vWinText, "^(BTN 2|BTN 3|BTN 5)$")
			SendMessage, 0xF1, 1, 0,, % "ahk_id " hCtl ;BM_SETCHECK := 0xF1
		if (vWinClass = "msctls_hotkey32")
		{
			;HOTKEYF_CONTROL := 0x2 ;Q is Chr(0x51)
			SendMessage, 0x401, 0x251, 0,, % "ahk_id " hCtl ;HKM_SETHOTKEY := 0x401
		}
		if (vWinClass = "SysMonthCal32")
		{
			vDate := vWinText
			vPfx := RegExMatch(10,1,0,-1) ? "O)" : "" ;v1/v2 compatibility
			RegExMatch(vDate, vPfx "(\d\d\d\d)(\d\d)()(\d\d)(\d\d)(\d\d)(\d\d)", o)
			VarSetCapacity(ArraySYSTEMTIME, 2*16, 0)
			Loop, 7
			{
				NumPut(o[A_Index], ArraySYSTEMTIME, (A_Index*2)-2, "UShort")
				NumPut(o[A_Index], ArraySYSTEMTIME, 16+(A_Index*2)-2, "UShort")
			}
			SendMessage, 0x1006, 0, % &ArraySYSTEMTIME,, % "ahk_id " hCtl ;MCM_SETSELRANGE := 0x1006
		}
		if (vWinClass = "msctls_trackbar32")
		{
			SendMessage, 0x405, 1, 100,, % "ahk_id " hCtl ;TBM_SETPOS := 0x405
		}
		if (vWinClass = "msctls_progress32")
			SendMessage, 0x402, % vWinText, 0,, % "ahk_id " hCtl ;PBM_SETPOS := 0x402
		;GROUPBOX|BTN 4
		if (vWinClass = "SysTabControl32")
		{
			Loop, 3
			{
				vText := "TAB " A_Index
				;TCIF_TEXT := 0x1
				VarSetCapacity(TCITEM, A_PtrSize=8?40:28, 0)
				NumPut(0x1, TCITEM, 0, "UInt") ;mask
				NumPut(&vText, TCITEM, A_PtrSize=8?16:12, "Ptr") ;pszText
				SendMessage, % A_IsUnicode?0x133E:0x1307, % A_Index-1, % &TCITEM,, % "ahk_id " hCtl ;TCM_INSERTITEMW := 0x133E ;TCM_INSERTITEMA := 0x1307
			}
		}
		vPosY += vPosH+5
	}
}

;==================================================

;custom control types
if vShowCustom
{
	;for RichEdit controls:
	hModuleRE := DllCall("LoadLibrary", Str,"msftedit.dll", Ptr)

	;for Scintilla controls:
	if FileExist(vPathSciLexer := A_ScriptDir "\SciLexer.dll")
		hModuleSL := DllCall("kernel32.dll\LoadLibrary", Str,vPathSciLexer, Ptr)
	else if FileExist(vPathSciLexer := A_AhkPath "\SciLexer.dll")
		hModuleSL := DllCall("kernel32.dll\LoadLibrary", Str,vPathSciLexer, Ptr)
	else
		vPathSciLexer := ""

	vList = ;continuation section
	(LTrim
	RICHEDIT50W|RICH 1
	Scintilla|SCIN 1
	ToolbarWindow32|TB 1
	)

	if !vShowBuiltIn1 && !vShowBuiltIn2
		vPosX := 5, vPosY := 30
	Loop, Parse, vList, `n
	{
		hWndParent := hGui, hMenu := 0, hInstance := 0, vParam := 0
		if (A_LoopField = "")
			continue
		oTemp := StrSplit(A_LoopField, "|")
		vWinClass := oTemp.1, vWinText := oTemp.2, oTemp := ""
		oTemp := ""
		vWinClass2 := JEE_CtlGetTemplate(vWinClass, vPosW, vPosH, vWinStyle, vWinExStyle)
		vWinClass := vWinClass2
		vWinStyle |= WS_VISIBLE | WS_CHILD | WS_TABSTOP

		if (vWinClass = "Scintilla") && !vPathSciLexer
			continue

		hCtl := JEE_DCCreateWindowEx(vWinExStyle, vWinClass, vWinText, vWinStyle, vPosX, vPosY, vPosW, vPosH, hWndParent, hMenu, hInstance, vParam)
		SendMessage, 0x30, % hFont, 0,, % "ahk_id " hCtl ;WM_SETFONT := 0x30

		if (vWinClass = "Scintilla")
		{
			;ControlSetText, Scintilla1, SCIN 1, % "ahk_id " hGui ;only shows 'S'
			;ControlSend, Scintilla1, SCIN 1, % "ahk_id " hGui
			;SC_CP_UTF8 := 65001
			SendMessage, 2037, 65001,, Scintilla1, % "ahk_id " hGui ;SCI_SETCODEPAGE := 2037
			vText := vWinText, vOutput := ""
			VarSetCapacity(vOutput, StrLen(vText)*4)
			StrPut(vText, &vOutput, StrLen(vText), "UTF-8")
			SendMessage, 2181,, % &vOutput, Scintilla1, % "ahk_id " hGui ;SCI_SETTEXT := 2181
		}
		if (vWinClass = "ToolbarWindow32")
		{
			hTB := hCtl
			Control, Style, +0x100,, % "ahk_id " hTB  ;TBSTYLE_TOOLTIPS := 0x100
			SendMessage, 0x43C, 0, 0,, % "ahk_id " hTB ;TB_SETMAXTEXTROWS := 0x43C ;text omitted from buttons
			;note: if more than one button has the same idCommand, then only the last button with that idCommand will have a ToolTip
			vCount := 5, vSize := A_PtrSize=8?32:20
			VarSetCapacity(TBBUTTON, vCount*vSize, 0)
			Loop, % vCount
			{
				vText%A_Index% := "TB " A_Index
				vOffset := (A_Index-1)*vSize
				;TBSTATE_ENABLED := 4
				NumPut(A_Index-1, TBBUTTON, vOffset, "Int") ;iBitmap
				NumPut(A_Index-1, TBBUTTON, vOffset+4, "Int") ;idCommand
				NumPut(0x4, TBBUTTON, vOffset+8, "UChar") ;fsState
				NumPut(&vText%A_Index%, TBBUTTON, vOffset+(A_PtrSize=8?24:16), "Ptr") ;iString
			}
			hIL := IL_Create(5, 2, 0)
			IL_Add(hIL, A_AhkPath, -159) ;green H
			IL_Add(hIL, A_AhkPath, -206) ;green S
			IL_Add(hIL, A_AhkPath, -207) ;red H
			IL_Add(hIL, A_AhkPath, -208) ;red S
			IL_Add(hIL, A_AhkPath, -160) ;file icon
			SendMessage, 0x430, 0, % hIL,, % "ahk_id " hTB ;TB_SETIMAGELIST := 0x430
			SendMessage, % A_IsUnicode?0x444:0x414, % vCount, % &TBBUTTON,, % "ahk_id " hTB ;TB_ADDBUTTONSW := 0x444 ;TB_ADDBUTTONSA := 0x414
		}
		vPosY += vPosH+5
	}
}

;==================================================

ControlMove, msctls_statusbar321, 0,0,0,0, % "ahk_id " hGui
ControlMove, ToolbarWindow321, 0,0,0,0, % "ahk_id " hGui
ControlGet, hCtl, Hwnd,, msctls_progress321, % "ahk_id " hGui
DllCall("uxtheme\SetWindowTheme", Ptr,hCtl, Str,"", Str,"")

WinShow, % "ahk_id " hGui
WinActivate, % "ahk_id " hGui
return

;==================================================

MyWndProc(hWnd, uMsg, wParam, lParam)
{
	DetectHiddenWindows, On

	if (uMsg = 0x111) ;WM_COMMAND := 0x111
		if (wParam >= 0) && (wParam <= 4)
		{
			ToolTip, % wParam
			Sleep 1500
			ToolTip
		}

	if (uMsg = 0x4E) ;WM_NOTIFY := 0x4E
	{
		;NMLINK structure (starts with an NMHDR structure)
		hCtl := NumGet(lParam+0, 0, "Ptr") ;hwndFrom
		vCode := NumGet(lParam+0, A_PtrSize=8?16:8, "UInt") ;code
		DetectHiddenWindows, On
		WinGetClass, vWinClass, % "ahk_id " hCtl

		;NM_CLICK := -2 ;0xFFFFFFFE
		;NM_RETURN := -4 ;0xFFFFFFFC
		if (vWinClass = "SysLink")
		&& ((vCode = 0xFFFFFFFE) || (vCode = 0xFFFFFFFC))
		{
			ControlGetText, vText,, % "ahk_id " hCtl
			RegExMatch(vText, "href=""\K(.*?)(?="")", vUrl)
			Run, % vUrl
		}
	}

	return DllCall("DefWindowProc", Ptr,hWnd, UInt,uMsg, UPtr,wParam, Ptr,lParam, Ptr)
}

;==================================================

;;;FUNCTIONS
;JEE_ConstantsWinStyles
;JEE_CtlGetTemplate
;JEE_DCCreateWindowEx
;JEE_FontGetDefaultGuiFont
;JEE_RegisterClassExCFI
;JEE_TVAdd
;JEE_TVItemSelect

;==================================================

;JEE_WinStylesInit
JEE_ConstantsWinStyles()
{
	global
	WS_OVERLAPPED := 0x0
	WS_TABSTOP := 0x10000
	WS_MAXIMIZEBOX := 0x10000
	WS_MINIMIZEBOX := 0x20000
	WS_GROUP := 0x20000
	WS_THICKFRAME := 0x40000
	WS_SYSMENU := 0x80000
	WS_HSCROLL := 0x100000
	WS_VSCROLL := 0x200000
	WS_DLGFRAME := 0x400000
	WS_BORDER := 0x800000
	WS_CAPTION := 0xC00000
	WS_OVERLAPPEDWINDOW := 0xCF0000
	WS_MAXIMIZE := 0x1000000
	WS_CLIPCHILDREN := 0x2000000
	WS_CLIPSIBLINGS := 0x4000000
	WS_DISABLED := 0x8000000
	WS_VISIBLE := 0x10000000
	WS_MINIMIZE := 0x20000000
	WS_CHILD := 0x40000000
	WS_POPUP := 0x80000000
	WS_POPUPWINDOW := 0x80880000

	WS_EX_LEFT := 0x0
	WS_EX_LTRREADING := 0x0
	WS_EX_RIGHTSCROLLBAR := 0x0
	WS_EX_DLGMODALFRAME := 0x1
	WS_EX_NOPARENTNOTIFY := 0x4
	WS_EX_TOPMOST := 0x8
	WS_EX_ACCEPTFILES := 0x10
	WS_EX_TRANSPARENT := 0x20
	WS_EX_MDICHILD := 0x40
	WS_EX_TOOLWINDOW := 0x80
	WS_EX_WINDOWEDGE := 0x100
	WS_EX_CLIENTEDGE := 0x200
	WS_EX_CONTEXTHELP := 0x400
	WS_EX_RIGHT := 0x1000
	WS_EX_RTLREADING := 0x2000
	WS_EX_LEFTSCROLLBAR := 0x4000
	WS_EX_CONTROLPARENT := 0x10000
	WS_EX_STATICEDGE := 0x20000
	WS_EX_APPWINDOW := 0x40000
	WS_EX_OVERLAPPEDWINDOW := 0x300
	WS_EX_PALETTEWINDOW := 0x188
}

;==================================================

;for a control class or 'name', get default sizes and styles
JEE_CtlGetTemplate(vClass, ByRef vPosW, ByRef vPosH, ByRef vWinStyle, ByRef vWinExStyle)
{
	static vIsReady, vList
	vPosW := 120, vPosH := 21, vWinStyle := 0, vWinExStyle := 0

	;normal
	(vClass = "DateTime") ? (vClass := "SysDateTimePick32") : ""
	(vClass = "DropDown") ? (vClass := "ComboBox") : ""
	(vClass = "Link") ? (vClass := "SysLink") : ""
	(vClass = "ListView") ? (vClass := "SysListView32") : ""
	(vClass = "StatusBar") ? (vClass := "msctls_statusbar32") : ""
	(vClass = "Text") ? (vClass := "Static") : ""
	(vClass = "TreeView") ? (vClass := "SysTreeView32") : ""
	;special
	(vClass = "Picture") ? (vClass := "BITMAP") : ""
	(vClass = "Checkbox") ? (vClass := "AUTOCHECKBOX") : ""
	(vClass = "Radio") ? (vClass := "AUTORADIOBUTTON") : ""

	if !vIsReady
	{
		;normal
		vList .= "|Button,,,0x0,0x0"
		vList .= "|ComboBox,,,0x2,0x0" ;CBS_DROPDOWN := 0x2
		vList .= "|Edit,,,0x0,0x200" ;WS_EX_CLIENTEDGE := 0x200
		vList .= "|Internet Explorer_Server,270,100,0x0,0x0"
		vList .= "|ListBox,120,53,0x808,0x200" ;LBS_EXTENDEDSEL := 0x800 ;LBS_MULTIPLESEL := 0x8 ;WS_EX_CLIENTEDGE := 0x200
		vList .= "|msctls_hotkey32,,,0x0,0x0"
		vList .= "|msctls_progress32,120,16,0x0,0x0"
		vList .= "|msctls_statusbar32,0,0,0x0,0x0"
		vList .= "|msctls_trackbar32,120,33,0x0,0x0"
		vList .= "|msctls_updown32,,,0x36,0x0" ;UDS_ARROWKEYS := 0x20 ;UDS_AUTOBUDDY := 0x10 ;UDS_ALIGNRIGHT := 0x4 ;UDS_SETBUDDYINT := 0x2
		vList .= "|RICHEDIT50W,270,21,0x0,0x0"
		vList .= "|Scintilla,270,34,0x0,0x0"
		vList .= "|Static,,,0x0,0x0"
		vList .= "|SysDateTimePick32,270,21,0x0,0x0"
		vList .= "|SysLink,,,0x0,0x0"
		vList .= "|SysListView32,270,80,0x9,0x220" ;WS_EX_CLIENTEDGE := 0x200 ;LVS_EX_FULLROWSELECT := 0x20 ;LVS_REPORT := 0x1 ;LVS_SHOWSELALWAYS := 0x8
		vList .= "|SysMonthCal32,225,160,0x2,0x0"  ;MCS_MULTISELECT := 0x2
		vList .= "|SysTabControl32,270,40,0x0,0x0"
		vList .= "|SysTreeView32,270,80,0x27,0x200" ;TVS_SHOWSELALWAYS := 0x20 ;TVS_LINESATROOT := 0x4 ;TVS_HASLINES := 0x2 ;TVS_HASBUTTONS := 0x1 ;WS_EX_CLIENTEDGE := 0x200
		vList .= "|ToolbarWindow32,0,0,0x0,0x0"
		;special
		vList .= "|DROPDOWNLIST,,,0x3,0x0" ;ComboBox ;CBS_DROPDOWNLIST := 0x3
		vList .= "|AUTOCHECKBOX,,,0x3,0x0" ;Button ;BS_AUTOCHECKBOX := 0x3
		vList .= "|AUTORADIOBUTTON,,,0x9,0x0" ;Button ;BS_AUTORADIOBUTTON := 0x9
		vList .= "|GROUPBOX,140,57,0x7,0x0" ;Button ;BS_GROUPBOX := 0x7
		vList .= "|BITMAP,,,0xE,0x0" ;Static ;SS_BITMAP := 0xE
		vList .= "|ICON,,,0x3,0x0" ;Static ;SS_ICON := 0x3
		vIsReady := 1
	}

	vClass2 := vClass
	(vClass = "DROPDOWNLIST") ? (vClass2 := "ComboBox") : ""
	(vClass ~= "^(AUTOCHECKBOX|AUTORADIOBUTTON|GROUPBOX)$") ? (vClass2 := "Button") : ""
	(vClass ~= "^(BITMAP|ICON)$") ? (vClass2 := "Static") : ""

	Loop, Parse, vList, |
	{
		oTemp := StrSplit(A_LoopField, ",")
		if (vClass = oTemp.1)
		{
			vPosW := oTemp.2 ? oTemp.2 : vPosW, vPosH := oTemp.3 ? oTemp.3 : vPosH, vWinStyle := oTemp.4, vWinExStyle := oTemp.5
			break
		}
	}
	oTemp := ""
	return vClass2
}

;==================================================

JEE_DCCreateWindowEx(vWinExStyle, vWinClass, vWinText, vWinStyle, vPosX, vPosY, vPosW, vPosH, hWndParent, hMenu, hInstance, vParam)
{
	return DllCall("CreateWindowEx", UInt,vWinExStyle, Str,vWinClass, Str,vWinText, UInt,vWinStyle, Int,vPosX, Int,vPosY, Int,vPosW, Int,vPosH, Ptr,hWndParent, Ptr,hMenu, Ptr,hInstance, Ptr,vParam, Ptr)
}

;==================================================

;e.g. hFont := JEE_FontGetDefaultGuiFont()

;JEE_FontGetDefaultGuiHFont
JEE_FontGetDefaultGuiFont()
{
	;DEFAULT_GUI_FONT := 17
	vSize := A_IsUnicode?92:60
	VarSetCapacity(LOGFONT, vSize, 0)
	hFont := DllCall("Gdi32\GetStockObject", Int,17, Ptr)
	if !DllCall("Gdi32\GetObject", Ptr,hFont, Int,vSize, Ptr,&LOGFONT)
		return 0
	return DllCall("CreateFontIndirect", Ptr,&LOGFONT, Ptr)
}

;==================================================

JEE_RegisterClassExCFI(vWinClass, vFunc, hIcon=0, hIconSm="")
{
	pWndProc := RegisterCallback(vFunc, "F")
	hCursor := DllCall("LoadCursor", Ptr,0, Ptr,32512, Ptr) ;IDC_ARROW := 32512
	if (hIconSm = "")
		hIconSm := hIcon

	vPIs64 := (A_PtrSize=8)
	vSize := vPIs64?80:48
	VarSetCapacity(WNDCLASSEX, vSize, 0)
	NumPut(vSize, WNDCLASSEX, 0, "UInt") ;cbSize
	NumPut(3, WNDCLASSEX, 4, "UInt") ;style
	NumPut(pWndProc, WNDCLASSEX, 8, "Ptr") ;lpfnWndProc
	NumPut(0, WNDCLASSEX, vPIs64?16:12, "Int") ;cbClsExtra
	NumPut(0, WNDCLASSEX, vPIs64?20:16, "Int") ;cbWndExtra
	NumPut(0, WNDCLASSEX, vPIs64?24:20, "Ptr") ;hInstance
	NumPut(hIcon, WNDCLASSEX, vPIs64?32:24, "Ptr") ;hIcon
	NumPut(hCursor, WNDCLASSEX, vPIs64?40:28, "Ptr") ;hCursor
	NumPut(16, WNDCLASSEX, vPIs64?48:32, "Ptr") ;hbrBackground
	NumPut(0, WNDCLASSEX, vPIs64?56:36, "Ptr") ;lpszMenuName
	NumPut(&vWinClass, WNDCLASSEX, vPIs64?64:40, "Ptr") ;lpszClassName
	NumPut(hIconSm, WNDCLASSEX, vPIs64?72:44, "Ptr") ;hIconSm
	return DllCall("RegisterClassEx", Ptr,&WNDCLASSEX, UShort)
}

;==================================================

;e.g. hTreeItem := JEE_TVAdd(hCtl, "MyLabel", 0)

JEE_TVAdd(hCtl, vText, vParentItemID)
{
	;TVIF_TEXT := 0x1
	VarSetCapacity(TVINSERTSTRUCT, A_PtrSize=8?96:68, 0)
	NumPut(vParentItemID, TVINSERTSTRUCT, 0, "Ptr") ;hParent
	NumPut(0, TVINSERTSTRUCT, A_PtrSize=8?8:4, "Ptr") ;hInsertAfter
	NumPut(0x1, TVINSERTSTRUCT, A_PtrSize=8?16:8, "UInt") ;mask
	NumPut(0, TVINSERTSTRUCT, A_PtrSize=8?24:12, "Ptr") ;hItem
	NumPut(&vText, TVINSERTSTRUCT, A_PtrSize=8?40:24, "Ptr") ;pszText
	NumPut(StrLen(vText)+1, TVINSERTSTRUCT, A_PtrSize=8?48:28, "Int") ;cchTextMax

	SendMessage, % A_IsUnicode?0x1132:0x1100, 0, % &TVINSERTSTRUCT,, % "ahk_id " hCtl ;TVM_INSERTITEMW := 0x1132 ;TVM_INSERTITEMA := 0x1100
	return ErrorLevel
}

;==================================================

JEE_TVItemSelect(hCtl, vItemID)
{
	;TVIF_STATE := 0x8 ;TVIS_SELECTED := 0x2
	VarSetCapacity(TVITEM, A_PtrSize=8?56:40, 0)
	NumPut(0x8, TVITEM, 0, "UInt") ;mask
	NumPut(vItemID, TVITEM, A_PtrSize=8?8:4, "Ptr") ;hItem
	NumPut(0x2, TVITEM, A_PtrSize=8?16:8, "UInt") ;state
	NumPut(0x2, TVITEM, A_PtrSize=8?20:12, "UInt") ;stateMask

	SendMessage, % A_IsUnicode?0x113F:0x110D, 0, % &TVITEM,, % "ahk_id " hCtl ;TVM_SETITEMW := 0x113F ;TVM_SETITEMA := 0x110D
}

;==================================================
[THOUS&TH POST]
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: GUIs via DllCall: control zoo

22 May 2017, 15:25

Notes:

General problems:
- awkwardness regarding window styles for controls, also it appears a control may be instructed to have a style, and then when you receive that style, it appears to be off

Control-specific problems:
;Text [Static]
;Edit [Edit]
;UpDown [msctls_updown32]
- UDM_SETBUDDY := 0x469 is used to join a msctls_updown32 control to an Edit control
;Picture [Static]
;Button [Button]
;Checkbox [Button]
- consider BS_CHECKBOX := 0x2 v. BS_AUTOCHECKBOX := 0x3, BS_AUTOCHECKBOX updates the control's state automatically
;Radio [Button]
- consider BS_RADIOBUTTON := 0x4 v. BS_AUTORADIOBUTTON := 0x9, BS_AUTORADIOBUTTON updates control states automatically
- use WS_GROUP := 0x20000 to specify a new group of radio buttons
;DropDownList [ComboBox]
;ComboBox [ComboBox + Edit]
;ListBox [ListBox]
;ListView [SysListView32 + SysHeader32]
- particularly complicated, if anyone has any comments on this (including if there is an alternative to: each new column becomes leftmost column rather than rightmost column, so I had to add them in reverse order)
- LVM_SETEXTENDEDLISTVIEWSTYLE is needed to make extended styles show
- consider if rightmost column fills the remaining space
;TreeView [SysTreeView32]
;Link [SysLink]
- NM_CLICK := -2 (0xFFFFFFFE), signed numbers needed to be handled
- NM_RETURN := -4 (0xFFFFFFFC), signed numbers needed to be handled
;Hotkey [msctls_hotkey32]
;DateTime [SysDateTimePick32]
;MonthCal [SysMonthCal32]
- to set the date required MCM_SETSELRANGE to specify the same date twice
;Slider [msctls_trackbar32]
;Progress [msctls_progress32]
- the SetWindowTheme dll function is required to create a basic one-colour progress bar
;GroupBox [Button]
;Tab [SysTabControl32]
- what is the difference between AHK's 3 different SysTabControl32 implementations
;StatusBar [msctls_statusbar32]
- consider if rightmost column fills the remaining space
;ActiveX (e.g. Internet Explorer Control) [AtlAxWin + Shell Embedding + Shell DocObject View + Internet Explorer_Server]
- Internet Explorer Control: I had to convert it to not use COM.ahk, based on:
IE_Add() or COM_AtlAxCreateContainer() or AtlAxWin() - Ask for Help - AutoHotkey Community
https://autohotkey.com/board/topic/3213 ... -atlaxwin/

;[RICHEDIT50W]
;[Scintilla]
- SciLexer.dll must be downloaded
- Scintilla controls use UTF-8 not UTF-16
;[ToolbarWindow32]
- if more than one button has the same idCommand, then only the last button with that idCommand will have a ToolTip
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
just me
Posts: 9458
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: GUIs via DllCall: control zoo

05 Jun 2017, 09:44

Hi jeeswg,

I still cannot see real progress. It has been clear that you can show a window containing controls using DllCalls only. AHK does the nothing else. The real challenge is the event/message handling not done automatically by the built-in default window\control procedures.
;ListView [SysListView32 + SysHeader32]
- particularly complicated, if anyone has any comments on this (including if there is an alternative to: each new column becomes leftmost column rather than rightmost column, so I had to add them in reverse order)
LVM_INSERTCOLUMN wrote:wParam
Index of the new column.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: GUIs via DllCall: control zoo

06 Jun 2017, 21:38

Many thanks for that tip just me.

A separate slightly reworked script to create listviews via DllCall:

Code: Select all

;create listview via DllCall
;note: w hotkey for: listview - get column indexes

#SingleInstance force
#Persistent

JEE_ConstantsWinStyles()

JEE_RegisterClassExCFI("JEEClass", "MyWndProc", hIcon, hIconSm)

vWinClass := "JEEClass"
vWinText := "control zoo" ;window title
vWinStyle := WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX ;start with WS_VISIBLE off
vWinExStyle := WS_EX_DLGMODALFRAME | WS_EX_ACCEPTFILES
vPosX := 100, vPosY := 30
vPosW := 300, vPosH := 300
hWndParent := 0, hMenu := 0, hInstance := 0, vParam := 0
hGui := JEE_DCCreateWindowEx(vWinExStyle, vWinClass, vWinText, vWinStyle, vPosX, vPosY, vPosW, vPosH, hWndParent, hMenu, hInstance, vParam)

hWndParent := hGui, hMenu := 0, hInstance := 0, vParam := 0
vWinClass := "SysListView32"
vWinText := ""
;LVS_SHOWSELALWAYS := 0x8 ;LVS_REPORT := 0x1
vWinStyle |= WS_VISIBLE | WS_CHILD | WS_TABSTOP | 0x9
;WS_EX_CLIENTEDGE := 0x200
vWinExStyle := 0x200
vPosX := 0, vPosY := 0
vPosW := 270, vPosH := 90
hCtl := JEE_DCCreateWindowEx(vWinExStyle, vWinClass, vWinText, vWinStyle, vPosX, vPosY, vPosW, vPosH, hWndParent, hMenu, hInstance, vParam)

		;===============
		;LISTVIEW - START
		if (vWinClass = "SysListView32")
		{
			;insert columns
			Loop, 3
			{
				vText := "LVH " A_Index
				;LVCF_ORDER := 0x20 ;LVCF_TEXT := 0x4 ;LVCF_WIDTH := 0x2
				VarSetCapacity(LVCOLUMN, A_PtrSize=8?56:44, 0)
				NumPut(0x26, LVCOLUMN, 0, "UInt") ;mask
				if (A_Index = 3)
					NumPut(166, LVCOLUMN, 8, "Int") ;cx
				else
					NumPut(50, LVCOLUMN, 8, "Int") ;cx
				NumPut(&vText, LVCOLUMN, A_PtrSize=8?16:12, "Ptr") ;pszText
				NumPut(StrLen(vText+1), LVCOLUMN, A_PtrSize=8?24:16, "Int") ;cchTextMax
				NumPut(A_Index-1, LVCOLUMN, A_PtrSize=8?36:28, "Int") ;iOrder
				SendMessage, 0x1061, % A_Index, % &LVCOLUMN, SysListView321, % "ahk_id " hGui ;LVM_INSERTCOLUMNW := 0x1061 ;LVM_INSERTCOLUMNA := 0x101B
			}

			;insert items
			Loop, 3
			{
				vText := vIndex "LV " A_Index
				VarSetCapacity(LVITEM, A_PtrSize=8?88:60, 0)
				NumPut(0x1, LVITEM, 0, "UInt") ;mask ;LVIF_TEXT := 0x1
				NumPut(A_Index-1, LVITEM, 4, "Int") ;iItem
				NumPut(0, LVITEM, 8, "Int") ;iSubItem
				NumPut(&vText, LVITEM, A_PtrSize=8?24:20, vPtrType) ;pszText
				NumPut(vMaxChars, LVITEM, A_PtrSize=8?32:24, "Int") ;cchTextMax
				SendMessage, % A_IsUnicode?0x104D:0x1007, 0, % &LVITEM, SysListView321, % "ahk_id " hGui ;LVM_INSERTITEMW := 0x104D ;LVM_INSERTITEMA := 0x1007
			}
			Loop, 3
			{
				vRow := A_Index
				Loop, 3
				{
					vCol := A_Index, vColLet := Chr(64+vCol)
					vText := vIndex "LV " vColLet vRow
					VarSetCapacity(LVITEM, A_PtrSize=8?88:60, 0)
					NumPut(0x1, LVITEM, 0, "UInt") ;mask ;LVIF_TEXT := 0x1
					NumPut(vRow-1, LVITEM, 4, "Int") ;iItem
					NumPut(vCol-1, LVITEM, 8, "Int") ;iSubItem
					NumPut(&vText, LVITEM, A_PtrSize=8?24:20, "Ptr") ;pszText
					NumPut(vMaxChars, LVITEM, A_PtrSize=8?32:24, "Int") ;cchTextMax
					SendMessage, % A_IsUnicode?0x104C:0x1006, 0, % &LVITEM, SysListView321, % "ahk_id " hGui ;LVM_SETITEMW := 0x104C ;LVM_SETITEMA := 0x1006
				}
			}

			;select item
			;LVIF_STATE := 0x8
			;LVIS_SELECTED := 0x2 ;LVIS_FOCUSED := 0x1
			VarSetCapacity(LVITEM, A_PtrSize=8?88:60, 0)
			NumPut(0x8, LVITEM, 0, "UInt") ;mask
			NumPut(0, LVITEM, 4, "Int") ;iItem
			NumPut(0x3, LVITEM, 12, "UInt") ;state
			NumPut(0x3, LVITEM, 16, "UInt") ;stateMask
			SendMessage, % A_IsUnicode?0x104C:0x1006, 0, % &LVITEM, SysListView321, % "ahk_id " hGui ;LVM_SETITEMW := 0x104C ;LVM_SETITEMA := 0x1006
			;LVS_EX_GRIDLINES := 0x1
			;SendMessage, 0x1036, 0x1, 0x1, SysListView321, % "ahk_id " hGui ;LVM_SETEXTENDEDLISTVIEWSTYLE := 0x1036
			;LVS_EX_FULLROWSELECT := 0x20
			;SendMessage, 0x1036, 0x20, 0x20, SysListView321, % "ahk_id " hGui ;LVM_SETEXTENDEDLISTVIEWSTYLE := 0x1036
		}
		;LISTVIEW - END
		;===============

WinShow, % "ahk_id " hGui
WinActivate, % "ahk_id " hGui
return

;==================================================

w:: ;listview - get column indexes
ControlGet, hCtl, Hwnd,, SysListView321, A
SendMessage, 0x101F,,,, % "ahk_id " hCtl ;LVM_GETHEADER := 0x101F
hCtl2 := ErrorLevel
SendMessage, 0x1200,,,, % "ahk_id " hCtl2 ;HDM_GETITEMCOUNT := 0x1200
vCount := ErrorLevel
vArray := ""
VarSetCapacity(vArray, vCount*4)
SendMessage, 0x103B, % vCount, % &vArray,, % "ahk_id " hCtl ;LVM_GETCOLUMNORDERARRAY := 0x103B
vOutput := ""
Loop, % vCount
	vOutput .= NumGet(vArray, A_Index*4-4, "Int")+1 ","
vOutput := SubStr(vOutput, 1, -1)
MsgBox, % vOutput
return

;==================================================

MyWndProc(hWnd, uMsg, wParam, lParam)
{
	DetectHiddenWindows, On

	if (uMsg = 0x111) ;WM_COMMAND := 0x111
		if (wParam >= 0) && (wParam <= 4)
		{
			ToolTip, % wParam
			Sleep 1500
			ToolTip
		}

	if (uMsg = 0x4E) ;WM_NOTIFY := 0x4E
	{
		;NMLINK structure (starts with an NMHDR structure)
		hCtl := NumGet(lParam+0, 0, "Ptr") ;hwndFrom
		vCode := NumGet(lParam+0, A_PtrSize=8?16:8, "UInt") ;code
		DetectHiddenWindows, On
		WinGetClass, vWinClass, % "ahk_id " hCtl

		;NM_CLICK := -2 ;0xFFFFFFFE
		;NM_RETURN := -4 ;0xFFFFFFFC
		if (vWinClass = "SysLink")
		&& ((vCode = 0xFFFFFFFE) || (vCode = 0xFFFFFFFC))
		{
			ControlGetText, vText,, % "ahk_id " hCtl
			RegExMatch(vText, "href=""\K(.*?)(?="")", vUrl)
			Run, % vUrl
		}
	}

	return DllCall("DefWindowProc", Ptr,hWnd, UInt,uMsg, UPtr,wParam, Ptr,lParam, Ptr)
}

;==================================================

;JEE_WinStylesInit
JEE_ConstantsWinStyles()
{
	global
	WS_OVERLAPPED := 0x0
	WS_TABSTOP := 0x10000
	WS_MAXIMIZEBOX := 0x10000
	WS_MINIMIZEBOX := 0x20000
	WS_GROUP := 0x20000
	WS_THICKFRAME := 0x40000
	WS_SYSMENU := 0x80000
	WS_HSCROLL := 0x100000
	WS_VSCROLL := 0x200000
	WS_DLGFRAME := 0x400000
	WS_BORDER := 0x800000
	WS_CAPTION := 0xC00000
	WS_OVERLAPPEDWINDOW := 0xCF0000
	WS_MAXIMIZE := 0x1000000
	WS_CLIPCHILDREN := 0x2000000
	WS_CLIPSIBLINGS := 0x4000000
	WS_DISABLED := 0x8000000
	WS_VISIBLE := 0x10000000
	WS_MINIMIZE := 0x20000000
	WS_CHILD := 0x40000000
	WS_POPUP := 0x80000000
	WS_POPUPWINDOW := 0x80880000

	WS_EX_LEFT := 0x0
	WS_EX_LTRREADING := 0x0
	WS_EX_RIGHTSCROLLBAR := 0x0
	WS_EX_DLGMODALFRAME := 0x1
	WS_EX_NOPARENTNOTIFY := 0x4
	WS_EX_TOPMOST := 0x8
	WS_EX_ACCEPTFILES := 0x10
	WS_EX_TRANSPARENT := 0x20
	WS_EX_MDICHILD := 0x40
	WS_EX_TOOLWINDOW := 0x80
	WS_EX_WINDOWEDGE := 0x100
	WS_EX_CLIENTEDGE := 0x200
	WS_EX_CONTEXTHELP := 0x400
	WS_EX_RIGHT := 0x1000
	WS_EX_RTLREADING := 0x2000
	WS_EX_LEFTSCROLLBAR := 0x4000
	WS_EX_CONTROLPARENT := 0x10000
	WS_EX_STATICEDGE := 0x20000
	WS_EX_APPWINDOW := 0x40000
	WS_EX_OVERLAPPEDWINDOW := 0x300
	WS_EX_PALETTEWINDOW := 0x188
}

;==================================================

JEE_DCCreateWindowEx(vWinExStyle, vWinClass, vWinText, vWinStyle, vPosX, vPosY, vPosW, vPosH, hWndParent, hMenu, hInstance, vParam)
{
	return DllCall("CreateWindowEx", UInt,vWinExStyle, Str,vWinClass, Str,vWinText, UInt,vWinStyle, Int,vPosX, Int,vPosY, Int,vPosW, Int,vPosH, Ptr,hWndParent, Ptr,hMenu, Ptr,hInstance, Ptr,vParam, Ptr)
}

;==================================================

JEE_RegisterClassExCFI(vWinClass, vFunc, hIcon=0, hIconSm="")
{
	pWndProc := RegisterCallback(vFunc, "F")
	hCursor := DllCall("LoadCursor", Ptr,0, Ptr,32512, Ptr) ;IDC_ARROW := 32512
	if (hIconSm = "")
		hIconSm := hIcon

	vPIs64 := (A_PtrSize=8)
	vSize := vPIs64?80:48
	VarSetCapacity(WNDCLASSEX, vSize, 0)
	NumPut(vSize, WNDCLASSEX, 0, "UInt") ;cbSize
	NumPut(3, WNDCLASSEX, 4, "UInt") ;style
	NumPut(pWndProc, WNDCLASSEX, 8, "Ptr") ;lpfnWndProc
	NumPut(0, WNDCLASSEX, vPIs64?16:12, "Int") ;cbClsExtra
	NumPut(0, WNDCLASSEX, vPIs64?20:16, "Int") ;cbWndExtra
	NumPut(0, WNDCLASSEX, vPIs64?24:20, "Ptr") ;hInstance
	NumPut(hIcon, WNDCLASSEX, vPIs64?32:24, "Ptr") ;hIcon
	NumPut(hCursor, WNDCLASSEX, vPIs64?40:28, "Ptr") ;hCursor
	NumPut(16, WNDCLASSEX, vPIs64?48:32, "Ptr") ;hbrBackground
	NumPut(0, WNDCLASSEX, vPIs64?56:36, "Ptr") ;lpszMenuName
	NumPut(&vWinClass, WNDCLASSEX, vPIs64?64:40, "Ptr") ;lpszClassName
	NumPut(hIconSm, WNDCLASSEX, vPIs64?72:44, "Ptr") ;hIconSm
	return DllCall("RegisterClassEx", Ptr,&WNDCLASSEX, UShort)
}

;==================================================
Some code for getting/setting the order of listview columns:

Code: Select all

q:: ;listview - add + rearrange columns
Gui, Add, ListView, r3 -LV0x20, LVH 1|LVH 2|LVH 3
Loop, 3
	if (A_Index = 1)
		LV_Add("Select", "LV A" A_Index, "LV B" A_Index, "LV C" A_Index)
	else
		LV_Add("", "LV A" A_Index, "LV B" A_Index, "LV C" A_Index)
Gui, Show
Sleep 1000
LV_InsertCol(2, "", "NEW 1")
Sleep 1000
LV_InsertCol(1, "", "NEW 2")
Sleep 1000
vCount := 5
vList := "5,4,3,2,1"
vArray := ""
VarSetCapacity(vArray, vCount*4)
Loop, Parse, vList, % ","
	NumPut(A_LoopField-1, vArray, A_Index*4-4, "Int")
ControlGet, hCtl, Hwnd,, SysListView321, A
SendMessage, 0x103A, % vCount, % &vArray,, % "ahk_id " hCtl ;LVM_SETCOLUMNORDERARRAY := 0x103A
return

w:: ;listview - get column indexes
ControlGet, hCtl, Hwnd,, SysListView321, A
SendMessage, 0x101F,,,, % "ahk_id " hCtl ;LVM_GETHEADER := 0x101F
hCtl2 := ErrorLevel
SendMessage, 0x1200,,,, % "ahk_id " hCtl2 ;HDM_GETITEMCOUNT := 0x1200
vCount := ErrorLevel
vArray := ""
VarSetCapacity(vArray, vCount*4)
SendMessage, 0x103B, % vCount, % &vArray,, % "ahk_id " hCtl ;LVM_GETCOLUMNORDERARRAY := 0x103B
vOutput := ""
Loop, % vCount
	vOutput .= NumGet(vArray, A_Index*4-4, "Int")+1 ","
vOutput := SubStr(vOutput, 1, -1)
MsgBox, % vOutput
return
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
arcticir
Posts: 694
Joined: 17 Nov 2013, 11:32

Re: GUIs via DllCall: control zoo

11 Jun 2017, 03:05

Could you add a sample so that the window is completely transparent and its controls are opaque?
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: GUIs via DllCall: control zoo

12 Jun 2017, 01:01

Do you particularly want to use the GUI via DllCall approach, or would you like it with standard AHK GUIs? I've provided some code for the former and a link for the latter.

What particularly do you have in mind? Do you want a floating controls effect? Cheers.

It's been interesting to look up about setting the GUI background colour.

[an example on standard AHK GUIs]
[SOLVED] Gui opacity - Ask for Help - AutoHotkey Community
https://autohotkey.com/board/topic/8072 ... ntry513190

c++ - How to set background color of window after I have registered it? - Stack Overflow
https://stackoverflow.com/questions/346 ... istered-it

Edit Control Background Color - Ask for Help - AutoHotkey Community
https://autohotkey.com/board/topic/3236 ... und-color/

Code: Select all

;pick a colour e.g. 0x0x000111 (RGB), which is 0x110100 (BGR)

;replace:
	NumPut(16, WNDCLASSEX, vPIs64?48:32, "Ptr") ;hbrBackground
;with:
	hBrush := DllCall("CreateSolidBrush", UInt,0x110100, Ptr) ;BGR
	NumPut(hBrush, WNDCLASSEX, vPIs64?48:32, "Ptr") ;hbrBackground

;do this if desired:
;WinSet, Style, -0xC00000, A ;WS_CAPTION := 0xC00000
;and perhaps this:
;WinSet, ExStyle, +0x80, A ;WS_EX_TOOLWINDOW := 0x80

;and also do this:
;WinSet, TransColor, 000111, A ;RGB
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
arcticir
Posts: 694
Joined: 17 Nov 2013, 11:32

Re: GUIs via DllCall: control zoo

12 Jun 2017, 02:37

thank you very much.
Sorry, I did not make it clear.
I would like to use DllCall WINAPI to wrap a complete GUI library
Then i found your script

On the "WinSet, TransColor", there is a problem, if the control uses the same color, the control will become transparent. How to avoid this situation?
Is there any other transparent solution?
e.g. use "SetLayeredWindowAttributes"?
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: GUIs via DllCall: control zoo

12 Jun 2017, 08:51

I don't have any other specific knowledge on this problem, you could try starting a new question on Ask For Help and/or search/ask on another website like Stack Overflow.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
arcticir
Posts: 694
Joined: 17 Nov 2013, 11:32

Re: GUIs via DllCall: control zoo

13 Jun 2017, 03:14

OK, Thank you. :)
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: GUIs via DllCall: control zoo

13 Jun 2017, 09:04

Cool jeeswg.
My eyes happened to fall on, pWndProc := RegisterCallback(vFunc, "F"), you might want to be careful with that F ;)
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: GUIs via DllCall: control zoo

13 Jun 2017, 10:05

Cheers Helgef.
But what could go wrong? Is the problem if I create two window classes with the same vFunc?
RegisterCallback
https://autohotkey.com/docs/commands/Re ... llback.htm
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: GUIs via DllCall: control zoo

13 Jun 2017, 10:18

Not really. I'm gonna be rude and not give you more hints :lol: (because I'm on the phone, hence typing is awkward)
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: GUIs via DllCall: control zoo

16 Jun 2017, 09:59

Hello Helgef, you were saying ...?

I did notice 'fast mode' was mentioned in the AHK documentation, and read that bit multiple times, but was still unsure as to what it actually did. Thanks.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: GUIs via DllCall: control zoo

16 Jun 2017, 10:35

Did you read: threads and RegisterCallback? I will give you a simple example later if you want, please remind me if I forget.

Cheers.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: GUIs via DllCall: control zoo

16 Jun 2017, 19:59

Thanks for the 2 links, I did read everything again, it's not immediately clear what the problems could be. So a simple example would be most appreciated. Cheers.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: GUIs via DllCall: control zoo

17 Jun 2017, 03:48

Hi jeeswg.
Consider the following (also follow the comments in the code), let's say we set the SendMode setting to Input in the auto-execute section. (the default if SendEvent)
This means that every newly launched thread will have this setting, for example,

Code: Select all

SendMode, Input ; Will apply to every new thread.
q::
	; This is a new thread.
	Msgbox, % A_SendMode ; Input
return
Now, let's say one of our threads, eg a hotkey routine, is interrupted by another thread, eg by a timer routine,

Code: Select all

SendMode, Input ; Will apply to every new thread.
SetTimer, timerLabel, 10
q::
	Msgbox, % A_SendMode ; Input
	; It takes so much time to disregard the msgbox, this thread will certainly be interupted by the timer, you will notice that the ToolTip follows your mouse, each new tooltip is an interuption of this thread (as long as any of the messageboxes shows).
	Msgbox, % A_SendMode ; Input
return

timerLabel:
	; This is a new thread when "called" via SetTimer
	SendMode, Play	; Here we want to use the Play sendmode instead, so we need to change it from the scripts default, Input.
	ToolTip, % A_SendMode  ; Play
return
Here you will notice that the SendMode in the hotkey routine is not affected by the SendMode set in the timer routine, that is in most cases the desired behaviour. Now, how does this relate to RegisterCallback, and the Fast option? Let's try the following, here we simulate our hotkey routine being interrupted by a callback, it will happen between the two messageboxes.

Code: Select all

SendMode, Input ; Will apply to every new thread.
q::
	Msgbox, % A_SendMode ; Input
	dllcall(registercallback("f"))	; Hotkey routine "interrupted" by a callback. Fast option omitted.
	Msgbox, % A_SendMode ; Input
return
f(){
	; This is called via DllCall(registercallback("f")) where the Fast option was omitted, hence THIS IS A NEW THREAD 	<--
	SendMode, Play
}
No problems, right? It behaves just as the timer routine interruption, now change the RegisterCallback to dllcall(registercallback("f","f")), you should be able to guess what's going to happen :o
So when is this a problem? Let's say you are using the zoo gui in an application, and you have a timed subroutine running, like this,

Code: Select all

WinActivate, % "ahk_id " hGui  ; Bottom of your auto execute in the zoo example.

SetTimer, someLabel, 500

return

someLabel:
	DetectHiddenWindows, off
	ToolTip, % "DetectHiddenWindows: " A_DetectHiddenWindows ; Relying in this important setting
	Sleep,300	; Doing stuff that takes some time.
	ToolTip, % "DetectHiddenWindows: " A_DetectHiddenWindows ; Relying in this important setting
return
Observe the inconsistency of the DetectHiddenWindows setting as this timer runs, compare what happens when you do and do not interact with your zoo. This type of inconsistency could cause debugging from hell issues. :angel:

There is one more type of inconsitency that can occur, lets say you make a setting in the auto execute section and then assume that this will apply to your MyWndProc function, so you do not set it there. The thing is then, that every time MyWndProc is called, that setting will be whatever the setting was in the thread which MyWndProc interrupted, because you set have the Fast option for the callback, you may have all kinds of zoo-like behaviour in your script. ;)

Cheers.
arcticir
Posts: 694
Joined: 17 Nov 2013, 11:32

Re: GUIs via DllCall: control zoo

07 Jul 2017, 17:46

Can you add an example of a scroll bar? :)
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: GUIs via DllCall: control zoo

07 Jul 2017, 20:13

Here's some code for scrollbars, put it just before the 'WinShow' line:

Btw I haven't really done anything with scrollbars, most controls come with their own scrollbars if needed. What controls are you going to use a scrollbar with? Cheers.

Code: Select all

;vertical scrollbar
vWinExStyle := 0
vWinClass := "ScrollBar"
vWinText := ""
;SBS_VERT := 0x1 ;SBS_RIGHTALIGN := 0x4
vWinStyle := WS_CHILD | WS_VISIBLE | 0x5
vPosX := 0, vPosY := 0, vPosW := 20, vPosH := 300
hWndParent := hGui, hMenu := 0, hInstance := 0, vParam := 0
hCtl := JEE_DCCreateWindowEx(vWinExStyle, vWinClass, vWinText, vWinStyle, vPosX, vPosY, vPosW, vPosH, hWndParent, hMenu, hInstance, vParam)

;horizontal scrollbar
vWinExStyle := 0
vWinClass := "ScrollBar"
vWinText := ""
;SBS_HORZ := 0x0 ;SBS_BOTTOMALIGN := 0x4
vWinStyle := WS_CHILD | WS_VISIBLE | 0x4
vPosX := 0, vPosY := 300, vPosW := 300, vPosH := 20
hWndParent := hGui, hMenu := 0, hInstance := 0, vParam := 0
hCtl := JEE_DCCreateWindowEx(vWinExStyle, vWinClass, vWinText, vWinStyle, vPosX, vPosY, vPosW, vPosH, hWndParent, hMenu, hInstance, vParam)
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
arcticir
Posts: 694
Joined: 17 Nov 2013, 11:32

Re: GUIs via DllCall: control zoo

07 Jul 2017, 22:55

Thanks.
I need it to scroll through the main window.
I reduced the height of the main window and increased the height of the scroll bar.
But this does not work, I can not scroll the main window, because of what?
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: GUIs via DllCall: control zoo

07 Jul 2017, 23:38

Ah, so you want a scrollbar to scroll the entire window. I haven't done anything like that before. Do you have any links where that is done with AutoHotkey? Do you have a working example of that with the AHK v1 Gui command? Thanks.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 152 guests