GUI COMMANDS: COMPLETE RETHINK

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

GUI COMMANDS: COMPLETE RETHINK

20 Dec 2016, 10:39

GUI COMMANDS: COMPLETE RETHINK

tl;dr do everything GUI via custom functions

(1) I've already created about 100 functions
(2) issues with MsgBox / InputBox / ToolTip (e.g. font size, background colour, countdown, beep, word wrap, ampersands, text dimension calculations via DrawTextEx)
(3) AutoHotkey v2 phase out of Progress / SplashImage / SplashTextOn/Off
(4) more support needed for external listviews / treeviews / save as prompts / status bars etc
(5) doubling up of commands for internal/external windows
(6) the regular need for functions as hacks to GUI commands (e.g. image lists)
(7) can't create a window with no icon without dodgy workarounds (e.g. in Windows XP)
(8) all GUI windows must have the same class name (which must be pre-edited in the AutoHotkey.exe binary)
(9) AutoHotkey depends on other programs having unique class names (especially before the 'ahk_exe' option was added), so alas there is hypocrisy there
(10) various issues I had even trying to make a Notepad clone (e.g. save as prompt with additional 'Encoding:' drop-down menu, and 'about' window with no icon)
(11) if I want to replace MsgBox, with a custom MsgBox() in all my scripts, will GUI 99 already be in use in some of them? (CRUCIAL ISSUE)
(12) 'Any script that uses the GUI command anywhere is automatically persistent' and single-instance, so potentially fairly-involved alterations to all scripts will be necessary (CRUCIAL ISSUE)
(13) some aspects of GUI commands are quirky like: Gui Submit/AltSubmit, special variables, and special letters (e.g. g-label notifications for listviews)
(14) Forms 0.8 has useful initial code (e.g. Dlg.ahk, RichEdit.ahk, Toolbar.ahk)
(15) GUI via functions will make it easier for programming newbies
(16) GUI via functions will make it easier for programming experts new to AutoHotkey (the functions and message queues are more like how they would program in say C++)
(17) programmers of other languages can learn more easily from AutoHotkey code, leading to cross-fertilisation
(18) uniformity is achieved between how all control types in GUIs are treated

- Although various exe updates and custom functions have resolved most of my AutoHotkey problems, I don't think this problem is going to be solved without a major rethink.
- If we don't do something about this, I'm planning on a breakaway fork called AutoGUI. (jk)

- I was a newbie when I began using AutoHotkey, and things like there being no functions for modifying external listviews/treeviews were a real headache, and almost immediately I was working with things like VirtualAllocEx, because the functions weren't there.
- And a lot of the quirks of the GUI commands, confused me and caused problems, but when I actually started to take a look under the bonnet (hood), it all made a lot more sense and became easier.

- The dilemma for me, whenever I want to do anything GUI, is, which route, GUI commands or custom functions?
- Invariably I need custom GUI functions anyway, but dealing with GUI commands can often get clunky, and I double up the work.
- If I take the custom-functions-only route, that's fine, but for some reason, up till now, it seems nobody else has shared any serious 'GUI from scratch via DllCall' examples. Every time I hit a slight obstacle trying to recreate some of the GUI commands, no-one's there to help, because the GUI commands already perform that function.
- Surely I can't have been the only one having these thoughts.
- Anyway, I feel that I've done 95% of the work, and with a few pointers my GUI command replacement scheme can be completed (e.g. full Basic/32/64-bit support).

- I did find majkinetor's custom MsgBox, the one time I got lucky in this quest, and for anyone who doesn't know how GUI works behind the scenes, it's basically: RegisterClass and CreateWindowEx. Then you handle messages in a message queue and make use of WndProcs.

- AutoHotkey as a community should consider GUI via custom-made functions, rather than the AutoHotkey GUI commands, as a standard way of producing GUI, even the preferred way, in a similar way to Gdip.ahk and Acc.ahk being key parts of AutoHotkey.
- Welcome to the new golden age of AutoHotkey.
Last edited by jeeswg on 12 Oct 2017, 12:21, edited 10 times in total.
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: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: GUI COMMANDS: COMPLETE RETHINK

20 Dec 2016, 10:52

And the question is? Many of the problems seem to be related to AHK 1.0 (Basic).
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: GUI COMMANDS: COMPLETE RETHINK

20 Dec 2016, 11:28

- thank you very much guest3456, I didn't know about these,
I will see if there is some useful code there
(i.e. rewrites of the AHK GUI source code in function form)
- I do not use objects in any of my GUI functions, I want them to be as short and low-level as possible
- I favour the 'small government' approach

==================================================

[EDIT:]
functions v. objects:
- fundamentally the idea is not to treat each GUI control as an object
- objects will be allowable within functions but not as input/output parameters
- it may be for some newer GUI controls that I might even allow objects as input/output parameters
- if something can be done both via dll calls and via objects, it is possible that 2 versions of the function will be created in order to have greater backwards compatibility options

advantages, standard commands v. new GUI functions:
- it will be easier to program GUIs
- it will make it easier to learn making GUIs in C++ and in other programming languages:
e.g. anything someone is struggling with on C++, they'll be able to test it first on AutoHotkey
- it will help people from other programming languages appreciate
and learn AutoHotkey faster
- there'll be more talk on the forums about the difficulties
that were overcome when making the original AutoHotkey GUI command source code,
which is very valuable GUI knowledge to have
- controls will be maximally customisable
- you don't have the double babysitting of custom functions *and* standard commands at the same time,
just custom functions

initial list extended:
(19) StatusBarGetText could only get text from the first status bar in a window
(20) the weirdness of GUI controls having an 'associated variable'
(21) confusingness of the GuiControlGet parameters
(22) confusing distinctions: 'Picture'/'Text' controls are both Static controls
(23) confusing distinctions: 'Button'/'Radio'/'Checkbox'/'GroupBox' controls are all Button controls
(24) confusing distinctions: 'DropDownList' controls are ComboBox controls (with Edit controls)
Last edited by jeeswg on 29 Dec 2016, 18:04, edited 4 times in total.
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: GUI COMMANDS: COMPLETE RETHINK

20 Dec 2016, 11:53

@just me
- it is true that many of the problems relate to AutoHotkey Basic,
however I think the rationale was right,
quick and easy commands for most everyday purposes and beginners
- the key problem is the lack of a critical mass of people taking
the flexible custom-function approach over the awkward standard-command approach
- the functions are in the final review phase, there will be more questions in due course
- one thing the current GUI commands could benefit from,
is the ability to specify 'no icon' and the ability to specify a window's class name,
or more generally the ability to create a window based on a WNDCLASS struct,
which allows both these things, can AutoHotkey already be hacked to achieve this?
- although doing away with AutoHotkey hacks is one of the reasons for my functions
- another thing is, one could feasibly replace 'AutoHotkeyGUI' in the address space
each time one makes a window, to choose one's own class name,
however, I believe that that particular region of the address space
is always locked, can it be unlocked?
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: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: GUI COMMANDS: COMPLETE RETHINK

20 Dec 2016, 16:20

It simply makes no sense to discuss about your concept before you show us as a working implementation.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: GUI COMMANDS: COMPLETE RETHINK

28 Dec 2016, 14:29

@just me, yes that's a fair point, I really had no idea what people would say, so I thought I'd mention the idea and see what came out of it. guest3456's links, were very interesting as they do refer to the idea of a bold overhaul, and about concerns with what we have currently. It's only 8 days later, and I'm surprised I've already got some material, if I can get these 6 functions *right*, I can really crack on and finish the lot.
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: GUI COMMANDS: COMPLETE RETHINK

28 Dec 2016, 14:53

==================================================

FIRST SNEAK PEAK

SAVE AS PROMPT (OLD STYLE)

first sneak peek at my GUI function library

JEE_SaveAsPromptGetDir(hWnd)
JEE_SaveAsPromptSetDir(hWnd, vDir)
JEE_SaveAsPromptGetPath(hWnd)
JEE_SaveAsPromptSetPath(hWnd, vPath, vIncludeExt=1)
JEE_FileDisplayNameGetPath(vDir, vDName, vSep="|")
JEE_FileGetDisplayName(vPath)

JEE_SaveAsPromptGetPath is the interesting one, if gets the dir,
and the focused Edit control or listview item, and checks
for possible paths, retrieving 0/1/multiple matches.
E.g. ambiguity, extensions hidden: a (folder), a.txt, a.lnk
all have the same display name 'a'.

functions relating to files and whether extensions are shown/hidden:
MsgBox % JEE_FileDisplayNameGetPath("C:\Windows", "notepad")
MsgBox % JEE_FileDisplayNameGetPath("C:\Windows", "notepad.exe")
MsgBox % JEE_FileGetDisplayName("C:\Windows\notepad.exe")

these functions work on the old style open/save as prompts, which are present in:
Notepad (Windows XP) (copied to Windows 7 64-bit)
WordPad (Windows XP) (copied to Windows 7 64-bit)
Notepad++ 7.2.2.0

I use AutoHotkey 32-bit v1.1.16.5 on Windows 7 64-bit.

==================================================

SAVE AS PROMPT (NEW STYLE)

By the way, I noticed this function for the newer save as prompts,
which looks great.

SelectFolderEx() - new dialog on Win Vista+ - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?t=18939

Do we have any functions like the four above, but for the new dialog types.
I don't have any expertise in the methods for creating such functions myself.

==================================================

FUNCTION ISSUES

(1) variable names
I tend to do variables like this: vVariable, oObject.
Of these two, I think I'll go with the first: 'CDM_GETFOLDERPATH' or 'vCDM_GETFOLDERPATH'.
It pains me, but I think I'll go with the first on this too, 'FILETIME' or 'vFILETIME'.
So capital letter constants/structs I'll keep as they are.
I always go with hWnd, hIcon, hFont, hMenu, hCtl, hProc, not something like 'vHWnd'.
I tend to keep Gdip-related variables as they are, I might reconsider.
There are a few situations where I haven't decided yet, so we'll see on those.

a tricky choise is:
DllCall("FuncName", a,b, c,d)
or
DllCall("FuncName", a, b, c, d)
I think I'll go with the former.

Tricky name choices which are not set in stone: 'vDoCheckOne',
which is should it only: do the action of checking one name,
or should it: do the action of checking two names.
If I have a variable that determines whether something will or won't happen lower down,
I'm tempted to prefix it with 'Do'.

I sometimes see:
static EM_SETSEL := 0xB1
PostMessage, EM_SETSEL, 0, -1, Edit1, ahk_id %hWnd%

rather than:
PostMessage, 0xB1, 0, -1, Edit1, ahk_id %hWnd% ;EM_SETSEL := 0xB1

is not the latter preferable to creating unnecessary variables
and the tiny performance loss that brings?

(2) my notation
I tend to keep alternative function names above function names as comments,
which is useful for searching when you can't quite remember which way round it was:
;JEE_OpenPromptGetDir
JEE_SaveAsPromptGetDir(hWnd)

;JEE_StrContainsIllegalFilenameChars
;JEE_StrContainsInvalidFilenameChars
JEE_StrFilePathIsInvalid

I put '[CHECK]', any time there's something I want to correct in future.

(3) 32-bit/64-bit compatibility, ANSI/Unicode compatibility, tidy up dll calls
These are the tricky bits for me, I try my best, but not having
that much in the way of additional knowledge means more of a stumble in the dark.
I really want to tidy up the VirtualAllocEx etc dll calls, and have all the parameter values exact.
Perhaps if I can get this one right (JEE_SaveAsPromptGetDir), it will help me correct all the other ones.
And I hope to choose how the variables will be named for these types of dll calls.

(4) general criticisms
I enjoy the criticisms, absolutely rip these functions to shreds,
no criticism is too ridiculous.

[EDIT:]
(5) pointers
which is preferable:
oElt := oWB.document.activeElement
or
pElt := pWB.document.activeElement
are these pointers or objects, does pointer mean something that only points to data, is true to say that they *are* pointers, but that it is better to call them objects

==================================================

CODE

Code: Select all

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

;works on:
;Notepad (Windows XP) (copied to Windows 7 64-bit)
;WordPad (Windows XP) (copied to Windows 7 64-bit)
;Notepad++ 7.2.2.0

;doesn't work on:
;Notepad (Windows 7)
;MS Paint (Windows XP) (copied to Windows 7 64-bit)

;JEE_OpenPromptGetDir(hWnd)
JEE_SaveAsPromptGetDir(hWnd)
{
WinGet, vPID, PID, ahk_id %hWnd%
;CDM_GETFOLDERPATH := 0x466
vSize := 256

hProc := DllCall("OpenProcess", "uint", 0x38, "int", 0, "uint", vPID)
if (hProc = 0)
Return

pBuf := DllCall("VirtualAllocEx", "uint", hProc, "uint", 0, "uint", vSize, "uint", 0x3000, "uint", 0x4)
if (pBuf = "")
Return

SendMessage, 0x466, 256, pBuf,, ahk_id %hWnd% ;CDM_GETFOLDERPATH
textSize := ErrorLevel
if (textSize <= 0)
Return

VarSetCapacity(buf, 256, 0)
result := DllCall("ReadProcessMemory", "uint", hProc, "uint", pBuf, "Str", buf, "uint", vSize, "uint", 0)

result2 := DllCall("VirtualFreeEx", "uint", hProc, "uint", pBuf, "uint", 0, "uint", 0x8000)
DllCall("CloseHandle", "uint", hProc)

Return buf
}

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

;JEE_OpenPromptSetDir
JEE_SaveAsPromptSetDir(hWnd, vDir)
{
ControlGet, hCtl, Hwnd, , Edit1, ahk_id %hWnd%
if !InStr(FileExist(vDir), "D")
Return
vDir2 := JEE_SaveAsPromptGetDir(hWnd)
if (vDir = vDir2)
Return

ControlGetText, vName, Edit1, ahk_id %hWnd%
ControlSetText, Edit1, %vDir%, ahk_id %hWnd%
ControlSend, Edit1, {Enter}, ahk_id %hWnd%

Sleep 1000 ;[CHECK][delay length]
ControlGetText, vText2, Edit1, ahk_id %hWnd%
if (vText = vText2)
ControlSetText, Edit1, %vName%, ahk_id %hWnd%
PostMessage, 0xB1, 0, -1, Edit1, ahk_id %hWnd% ;EM_SETSEL
Return
}

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

;JEE_OpenPromptGetPath(hWnd)
JEE_SaveAsPromptGetPath(hWnd)
{
vDir := JEE_SaveAsPromptGetDir(hWnd)
ControlGetFocus, vCtlClassNN, ahk_id %hWnd%

if (vCtlClassNN = "Edit1")
ControlGetText, vDName, Edit1, ahk_id %hWnd%
else if (vCtlClassNN = "SysListView321")
ControlGet, vDName, List, Focused Col1, SysListView321, ahk_id %hWnd%
else
Return

;this could return 0/1/multiple paths, pipe-separated by default
vPath := JEE_FileDisplayNameGetPath(vDir, vDName)
Return vPath
}

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

;JEE_OpenPromptSetPath
JEE_SaveAsPromptSetPath(hWnd, vPath, vIncludeExt=1)
{
ControlGet, hCtl, Hwnd, , Edit1, ahk_id %hWnd%
SplitPath, vPath, vName, vDir, vExt, vNameNoExt, vDrive
if !InStr(FileExist(vDir), "D")
Return

ControlSetText, Edit1, %vDir%, ahk_id %hWnd%
ControlSend, Edit1, {Enter}, ahk_id %hWnd%

if !vIncludeExt
vName := vNameNoExt

Sleep 1000 ;[CHECK][delay length]
ControlSetText, Edit1, %vName%, ahk_id %hWnd%
PostMessage, 0xB1, 0, -1, Edit1, ahk_id %hWnd% ;EM_SETSEL
Return
}

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

JEE_FileDisplayNameGetPath(vDir, vDName, vSep="|")
{
vDir1 := vDir
SplitPath, vDName, , , , vDNameNoExt

if (vDName = vDNameNoExt) ;SplitPath will make them identical if vDName contains no dots
vDoCheckOne := 1

Loop, %vDir1%\*.*, 1, 0 ;(0/1/2=files/both/folders, 0/1=recurse no/yes)
{
vPath := A_LoopFileFullPath
SplitPath, vPath, vName, vDir, vExt, vNameNoExt, vDrive

vRet := 0
if (vDName = vNameNoExt) OR (vDName = vName)
vRet := 1
else if vDoCheckOne
continue

if !vRet AND !(vDNameNoExt = vNameNoExt) AND !(vDNameNoExt = vName)
continue

vDName2 := JEE_FileGetDisplayName(vPath)
if (vDName = vDName2)
vOutput .= vDir "\" vName vSep
}

if ("" SubStr(vOutput, 1-StrLen(vSep)) = "" vSep)
StringTrimRight, vOutput, vOutput, % StrLen(vSep)
Return vOutput
}

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

;JEE_FileGetFriendlyName
;JEE_PathGetDisplayName
JEE_FileGetDisplayName(vPath)
{
;SHGFI_TYPENAME := 0x400
;SHGFI_DISPLAYNAME := 0x200
;SHGFI_ICON := 0x100
;SHGFI_ATTRIBUTES := 0x800

VarSetCapacity(SHFILE, 692, 0)
DllCall("Shell32.dll\SHGetFileInfo" . (A_IsUnicode ? "W":"A"),"str", vPath,"UInt",0,"Uint",&SHFILE,"Uint",692,"Uint",0xF00)

VarSetCapacity(vDName, 262, 0)
DllCall("msvcrt\memcpy", "uint", &vDName, "uint", &SHFILE+12, "uint", 260)
VarSetCapacity(vDName, -1)
Return vDName
}

;==================================================
==================================================
Last edited by jeeswg on 29 Dec 2016, 15:52, edited 2 times in total.
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: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: GUI COMMANDS: COMPLETE RETHINK

29 Dec 2016, 10:46

Some thoughts about JEE_SaveAsPromptGetDir(hWnd).
  • All DllCalls seem to be designed for 32-bit ANSI.
  • vSize used in VirtualAllocEx() defines a size in bytes (256). So the reserved memory is sufficient only for a maximum of 128 Unicode characters.
  • 256 used in SendMessage defines a size in characters. 256 Unicode characters would need a buffer of 512 bytes.
  • I don't know whether the system will perform an internal conversion when the dialog of an ANSI application is called from AHK Unicode and vice versa. If not, using "Str" as the type of buf in ReadProcessMemory() might get some 'strange' results.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: GUI COMMANDS: COMPLETE RETHINK

29 Dec 2016, 11:33

- That's really excellent thank you, I will come back to DllCall when I have the slightly more complex example of roughly the same thing. I don't think I have any structs here yet either, which can be an issue. Any issues raised in the comment above or other issues are most welcome.
- The next thing I'll post is rough MsgBox/InputBox scripts with the core GUI creation functions.
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: GUI COMMANDS: COMPLETE RETHINK

31 Dec 2016, 15:18

first go at a general function using Acc on most control types: JEE_AccCtlGetText(hWnd)
[previous version of this post lacked the handling for context menus]
[also added function for selecting items on right-click context menus, similar to WinMenuSelectItem]

Code: Select all

;===============
;q::
MouseGetPos,,, hWnd, hCtl, 2
if !hCtl
	hCtl := hWnd
WinGetClass, vWinClass, % "ahk_id " hCtl
vText := JEE_AccCtlGetText(hCtl, "`r`n")
MsgBox, % "[" vWinClass "]`r`n" vText
return
;===============

;notes:
;problem - AutoHotkey Help - treeview
;problem - Explorer folders (Windows 7) - DirectUIHWND (how to invoke invert selection?)
;problem - Tools, Folder Options, View tab - treeview
;problem+ - MSTaskListWClass (taskbar), one item has error
;problem+ - WordPad (Windows XP) - toolbar (can get text from toolbar button as long as mouse over it, so move mouse as you retrieve text)
;possible to get all listview columns?
;any other roles to accept for 'if vRole in ...'? some more general criteria than a list of roles?
;possibly add option to retrieve ticked status of buttons/menu items
;add support for title bars? NCHITTEST?
;TrayTip is tooltips_class32?
;control types not considered: RICHEDIT,RichEdit20A,RichEdit20W,ComboBoxEx,DragList,ScrollBar,ReBarWindow32,msctls_trackbar32,msctls_updown32,msctls_progress32,SysAnimate32,SysMonthCal32,SysPager

;accepts hWnd/hCtl
;JEE_AccGetControlText
;JEE_AccGetCtlText
;JEE_AccControlGetText
JEE_AccCtlGetText(hWnd, vSep:="`n")
{
	WinGetClass, vWinClass, % "ahk_id " hWnd
	if vWinClass in SysTreeView32,SysListView32,SysHeader32,ListBox,ComboLBox,Static,msctls_statusbar32,ComboBox,hh_kwd_vlist,MSTaskListWClass,ToolbarWindow32,SysLink,SysTabControl32
	{
		oAcc := Acc_Get("Object", "4", 0, "ahk_id " hWnd)
		Loop, % oAcc.accChildCount
		{
			vRole := Acc_Role(oAcc, A_Index)
			if vRole in list item,outline item,text,push button,link,column header,page tab
				vOutput .= oAcc.accName(A_Index) vSep
		}
		vOutput := SubStr(vOutput, 1, -StrLen(vSep))
		vRet := 1
	}
	if vWinClass in #32768
	{
		oAcc := Acc_Get("Object", "1", 0, "ahk_id " hWnd)
		Loop, % oAcc.accChildCount
			if (Acc_Role(oAcc, A_Index) = "menu item")
				vOutput .= oAcc.accName(A_Index) vSep
		vOutput := SubStr(vOutput, 1, -StrLen(vSep))
		vRet := 1
	}
	if vWinClass in Edit,SysDateTimePick32,#32769,RICHEDIT50W
	{
		oAcc := Acc_Get("Object", "4", 0, "ahk_id " hWnd)
		vOutput := oAcc.accValue, vRet := 1
	}
	if vWinClass in Button,Static,tooltips_class32
	{
		oAcc := Acc_Get("Object", "4", 0, "ahk_id " hWnd)
		vOutput := oAcc.accName, vRet := 1
	}
	if !vRet
		oAcc := Acc_ObjectFromWindow(hWnd), vOutput := oAcc.accName
	oAcc := ""
	return vOutput
}

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

;e.g. Media Player Classic, open right-click menu, click item
;q::
;vList := "View,On Top,Default"
;JEE_MenuRCSelectItem(vList)
;return

;improve Acc error handling
;JEE_MenuRightClickSelectItem
JEE_MenuRCSelectItem(vList, vDelim:=",", vPosX:="", vPosY:="", vDelay:=0)
{
	DetectHiddenWindows, Off
	CoordMode, Mouse, Screen
	MouseGetPos, vPosX2, vPosY2
	(vPosX = "") ? (vPosX := vPosX2) : 0
	(vPosY = "") ? (vPosY := vPosY2) : 0

	if !(vPosX = vPosX2) || !(vPosY = vPosY2)
		MouseMove, % vPosX, % vPosY
	Click, right

	Loop, Parse, vList, % vDelim
	{
		vTemp := A_LoopField
		WinGet, hWnd, ID, ahk_class #32768
		if !hWnd
		{
			MsgBox, error
			return
		}
		oAcc := Acc_Get("Object", "1", 0, "ahk_id " hWnd)
		Loop, % oAcc.accChildCount
			if (Acc_Role(oAcc, A_Index) = "menu item")
			&& (oAcc.accName(A_Index) = vTemp)
			{
				oRect := Acc_Location(oAcc, A_Index), vIndex := A_Index
				break
			}
		vPosX := Round(oRect.x + oRect.w/2)
		vPosY := Round(oRect.y + oRect.h/2)
		MouseMove, % vPosX, % vPosY
		Sleep, % vDelay ;optional delay
		oAcc.accDoDefaultAction(vIndex)
		WinWaitNotActive, % "ahk_id " hWnd,, 6
		if ErrorLevel
		{
			MsgBox, error
			return
		}
	}
	MouseMove, % vPosX2, % vPosY2
}

;==================================================
Last edited by jeeswg on 04 Oct 2018, 16:30, edited 1 time in total.
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: GUI COMMANDS: COMPLETE RETHINK (latest: general control get text via acc, 'context menu select item')

03 Jan 2017, 19:30

Some ListBox selection examples. Btw is there anywhere in Explorer settings or on some very small utility where there is a multiselect ListBox for test purposes?

These were not the most complicated to program, but there where some quite interesting questions regarding presentation and organisation, naming things, and also the issue of how simple should each function be, how much should it do.

E.g. should the set selection function be able to see the goal, and think 'select all, deselect 3' is better than 'deselect all, select 9'. I decided that the complication should lie outside the function, with the invert selection function an example of a more 'intelligent' function. With the get and set selection functions just carrying out very basic tasks.

Code: Select all

^q::
ControlGet, hCtl, Hwnd, , ListBox1, A
vList = 1,3,7
JEE_ListBoxSetSel(hCtl, vList, "ds")
Sleep 2000

MsgBox % JEE_ListBoxGetSel(hCtl)
Sleep 2000

JEE_ListBoxInvSel(hCtl)
Sleep 2000
JEE_ListBoxInvSel(hCtl)
Sleep 2000
JEE_ListBoxInvSel(hCtl)
Sleep 2000
MsgBox done
Return

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

;selected GUI functions by jeeswg

;JEE_ListBoxInvertSelection
;JEE_ListBoxSetSelInv
JEE_ListBoxInvSel(hCtl)
{
SendMessage, 0x18B, , , , ahk_id %hCtl% ;LB_GETCOUNT
vCount := ErrorLevel
SendMessage, 0x190, , , , ahk_id %hCtl% ;LB_GETSELCOUNT
vCountSel := ErrorLevel

if (vCount-vCountSel > vCountSel)
vList := JEE_ListBoxGetSel(hCtl, 1), JEE_ListBoxSetSel(hCtl, vList, "sd")
else
vList := JEE_ListBoxGetSel(hCtl, 0), JEE_ListBoxSetSel(hCtl, vList, "ds")
Return
}

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

;returns 1-based index of focused item
JEE_ListBoxGetFocus(hCtl)
{
;LB_GETCARETINDEX := 0x19F
SendMessage, 0x19F, , , , ahk_id %hCtl% ;LB_GETCARETINDEX
Return ErrorLevel+1
}

;sets 1-based index of focused item
JEE_ListBoxSetFocus(hCtl, vNum, vOpt=0)
{
;LB_SETCARETINDEX := 0x19E
SendMessage, 0x19E, vNum-1, 0, , ahk_id %hCtl% ;LB_SETCARETINDEX
Return
}

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

;returns a comma-separated list of 1-based indexes for selected items
;JEE_ListBoxGetSelectedItems
JEE_ListBoxGetSel(hCtl, vOpt=1)
{
;LB_GETCOUNT := 0x18B
;LB_GETSELCOUNT := 0x190
;LB_GETSELITEMS := 0x191

SendMessage, 0x190, , , , ahk_id %hCtl% ;LB_GETSELCOUNT
vCountSel := ErrorLevel
VarSetCapacity(vBuf, 32*vCountSel)
SendMessage, 0x191, vCountSel, &vBuf, , ahk_id %hCtl% ;LB_GETSELITEMS
vRet := ErrorLevel

Loop, %vRet%
vOutput .= (NumGet(vBuf, A_Index*4-4, "UInt")+1) ","
vOutput := SubStr(vOutput, 1, -1) ;trim right

if (vOpt = 0)
{
SendMessage, 0x18B, , , , ahk_id %hCtl% ;LB_GETCOUNT
vCount := ErrorLevel
Loop, %vCount%
if A_Index not in %vOutput%
vOutput2 .= A_Index ","
vOutput2 := SubStr(vOutput2, 1, -1) ;trim right
Return vOutput2
}

Return vOutput
}

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

;description:
;hCtl: handle to ListBox control

;vList: comma-separated list of items (1-based index)
;e.g. '1,3,5' (select the 1st,3rd,5th items)
;e.g. '3' (select the 3rd item)

;vOpt: s/d/sd/ds/sa/da
;s select items in list
;d deselect items in list
;sd select all items and deselect items in list
;ds deselect all items and select items in list
;sa select all items
;da deselect all items

;JEE_ListBoxSelectItems
JEE_ListBoxSetSel(hCtl, vList, vOpt="s")
{
;LB_SETSEL := 0x185

if vOpt in sa,sd
SendMessage, 0x185, 1, -1, , ahk_id %hCtl% ;LB_SETSEL
if vOpt in da,ds
SendMessage, 0x185, 0, -1, , ahk_id %hCtl% ;LB_SETSEL
if vOpt in sa,da
Return

if vOpt in s,ds
vState := 1
if vOpt in d,sd
vState := 0

Loop, Parse, vList, `,
SendMessage, 0x185, vState, A_LoopField-1, , ahk_id %hCtl% ;LB_SETSEL
Return
}

;==================================================
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: GUI COMMANDS: COMPLETE RETHINK (latest: acc get text, menu select item, listbox select)

05 Jan 2017, 18:41

Check if menu bar/sysmenu bar active, check if context menu exists.
Useful for adding hotkeys such as arrows/enter, to preserve the keys' normal behaviour when navigating menus.

Code: Select all

;e.g.
^q::
WinGet, hWnd, ID, A
MsgBox % JEE_MenuIsActive(hWnd, "m") " " JEE_MenuIsActive(hWnd, "s") " " JEE_MenuIsActive(hWnd, "c")
Return

JEE_MenuIsActive(hWnd, vOpt="msc")
{

if InStr(vOpt, "m")
{
OBJID_MENU := 0xFFFFFFFD
vSize := (A_PtrSize=8 ? 48 : 32)
vOffset := (A_PtrSize=8 ? 40 : 28)
VarSetCapacity(MENUBARINFO, vSize, 0)
NumPut(vSize, MENUBARINFO, 0, "Ptr")
DllCall("user32\GetMenuBarInfo", Ptr,hWnd, Int,OBJID_MENU, Int,0, Ptr,&MENUBARINFO)
if (NumGet(MENUBARINFO, vOffset, "UChar") & 2)
Return 1
}

if InStr(vOpt, "s")
{
OBJID_SYSMENU := 0xFFFFFFFF
vSize := (A_PtrSize=8 ? 48 : 32)
vOffset := (A_PtrSize=8 ? 40 : 28)
VarSetCapacity(MENUBARINFO, vSize, 0)
NumPut(vSize, MENUBARINFO, 0, "Ptr")
DllCall("user32\GetMenuBarInfo", Ptr,hWnd, Int,OBJID_SYSMENU, Int,0, Ptr,&MENUBARINFO)
if (NumGet(MENUBARINFO, vOffset, "UChar") & 2)
Return 1
}

if InStr(vOpt, "c")
{
DetectHiddenWindows, Off
IfWinExist, ahk_class #32768
Return 1
}

Return 0
}
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: GUI COMMANDS: COMPLETE RETHINK (latest: acc get text, menu select item, listbox select, is menu active)

12 Jan 2017, 21:04

Progress report: finishing treeview/listview functions,
then a review of all functions will take place,
then some sample scripts will emerge e.g. MsgBox/InputBox,
and maybe a 'control zoo' with various control types.

With initial basic scripts subsequently perfected,
by resolving issues such as receiving key presses and drag-and-drop,
that should then lead to all GUIs being doable via DllCall alone,
and no GUI commands. (Nothing against GUI commands,
but when you're already doing half AHK commands / half custom functions,
it's easier to do it all functions!)

HELP: Currently, the only major control type I don't have support for is
the Common Item Dialog. The new style open/save as prompt,
present since Windows Vista.
If anybody could help me by writing, for external processes:
CommonItemDialogGetDir
CommonItemDialogSetDir
CommonItemDialogGetPath
CommonItemDialogSetPath
that would be greatly appreciated, thank you!

I have found the following links so far:

SelectFolderEx() - new dialog on Win Vista+ - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?t=18939

CommonItemDialog.ahk · GitHub
https://gist.github.com/BiggerDigger/69 ... 4d2263867e

Cheers!
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: GUI COMMANDS: COMPLETE RETHINK (latest: treeview item get text)

20 Jan 2017, 01:28

I have now managed to make JEE_TreeviewItemGetText AHK 32/64 to external 32/64 compatible, i.e. 4-way compatible. In the next few days I should be adding treeview get text (i.e. hierarchy) / expand all / contract all, and listview get text. After that, treeview/listview set item text. And then other minor functions after that. But crucially I finally have a 4-way function.

Be aware that functions such as these could potentially crash your program, and if anyone wants to check over the code, that would be greatly appreciated, my main concern is the size for the text buffer.

Code: Select all

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

;e.g.
;q::
;WinGet, hWnd, ID, A
;ControlGetFocus, vCtlClassNN, ahk_id %hWnd%
;ControlGet, hCtl, Hwnd, , %vCtlClassNN%, ahk_id %hWnd%
;WinGetClass, vWinClass, ahk_id %hCtl%
;if !(vWinClass = "SysTreeView32")
;MsgBox % "error: class is not SysTreeView32"
;else
;MsgBox % JEE_TreeviewItemGetText(hCtl)
;Return

JEE_TreeviewItemGetText(hCtl, vItemID="")
{
DetectHiddenWindows, On

vPIDAhk := DllCall("kernel32\GetCurrentProcessId")
vPBitsAhk := JEE_ProcessGetBits(vPIDAhk)
WinGet, vPID, PID, ahk_id %hCtl%
vPBits := JEE_ProcessGetBits(vPID)

vPtrSize := (vPBits = 64) ? 8 : 4
vPtrType := (vPBits = 64) ? "Int64" : "Int"

;TVGN_CARET := 0x9
vSize1 := 24+4*vPtrSize ;56:40
vSize2 := 260*(A_IsUnicode+1)

if (vItemID = "")
{
SendMessage, 0x110A, 0x9, 0, , ahk_id %hCtl% ;TVM_GETNEXTITEM
vItemID := ErrorLevel
}

hProc := JEE_DCOpenProcess(0x38, 0, vPID)
vBA1 := JEE_DCVirtualAllocEx(hProc, 0, vSize1, 0x3000, 0x4)
vBA2 := JEE_DCVirtualAllocEx(hProc, 0, vSize2, 0x3000, 0x4)

VarSetCapacity(TVITEM, vSize1, 0)
NumPut(0x11, TVITEM, 0, "UInt")
NumPut(vItemID, TVITEM, vPtrSize, vPtrType)
NumPut(vBA2, TVITEM, 8+2*vPtrSize, vPtrType)
NumPut(vSize2, TVITEM, 8+3*vPtrSize, "UInt")

VarSetCapacity(vText, vSize2, 0)
JEE_DCWriteProcessMemory(hProc, vBA1, &TVITEM, vSize1, 0)

if A_IsUnicode
SendMessage, 0x113E, 0, vBA1, , ahk_id %hCtl% ;TVM_GETITEMW
else
SendMessage, 0x110C, 0, vBA1, , ahk_id %hCtl% ;TVM_GETITEMA

JEE_DCReadProcessMemory(hProc, vBA2, &vText, vSize2, 0)
JEE_DCVirtualFreeEx(hProc, vBA2, 0, 0x8000)
JEE_DCVirtualFreeEx(hProc, vBA1, 0, 0x8000)
JEE_DCCloseHandle(hProc)

VarSetCapacity(vText, -1)
Return vText
}

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

JEE_ProcessGetBits(vPID)
{
if !A_Is64bitOS
Return 86

hProc := DllCall("kernel32\OpenProcess", UInt,0x400, Int,0, UInt,vPID, Ptr)
DllCall("kernel32\IsWow64Process", Ptr,hProc, IntP,vIsWow64Process)
DllCall("kernel32\CloseHandle", Ptr,hProc)

if vIsWow64Process
Return 86

Return 64
}

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

JEE_DCOpenProcess(vAccess, hInherit, vPID)
{
Return DllCall("kernel32\OpenProcess", UInt,vAccess, Int,hInherit, UInt,vPID, Ptr)
}
JEE_DCVirtualAllocEx(hProc, vAddress, vSize, vAllocType, vProtect)
{
Return DllCall("kernel32\VirtualAllocEx", Ptr,hProc, Ptr,vAddress, UPtr,vSize, UInt,vAllocType, UInt,vProtect, Ptr)
}
JEE_DCWriteProcessMemory(hProc, vBAddress, pBuf, vSize, vWritten)
{
Return DllCall("kernel32\WriteProcessMemory", Ptr,hProc, Ptr,vBAddress, Ptr,pBuf, UPtr,vSize, UPtr,vWritten)
}
JEE_DCReadProcessMemory(hProc, vBAddress, pBuf, vSize, vRead)
{
Return DllCall("kernel32\ReadProcessMemory", Ptr,hProc, Ptr,vBAddress, Ptr,pBuf, UPtr,vSize, UPtr,vRead)
}
JEE_DCVirtualFreeEx(hProc, vAddress, vSize, vFreeType)
{
Return DllCall("kernel32\VirtualFreeEx", Ptr,hProc, Ptr,vAddress, UPtr,vSize, UInt,vFreeType)
}
JEE_DCCloseHandle(hObject) ;e.g. hProc
{
Return DllCall("kernel32\CloseHandle", Ptr,hObject)
}

;==================================================
Last edited by jeeswg on 17 Feb 2019, 17:43, edited 2 times in total.
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: GUI COMMANDS: COMPLETE RETHINK (latest: treeview item get text)

09 Feb 2017, 17:31

Code: Select all

;JEE_SystemGetFont and JEE_SystemSetFont based on:
;[Function] MsgBox Font Information - AutoHotkey Community
;https://autohotkey.com/boards/viewtopic.php?t=9122
;by iPhilip

;e.g.
;JEE_SystemGetFont("Message", vName, vSize, vWeight, vIsItalic)
;MsgBox % vName " " vSize " " vWeight " " vIsItalic

;vType can be one of: Icon,Caption,SmCaption,Menu,Status,Message
;JEE_GetSystemFont
;JEE_SystemFontGet
JEE_SystemGetFont(vType:="", ByRef vName:="", ByRef vSize:=0, ByRef vWeight:=0, ByRef vIsItalic:=0)
{
;SPI_GETICONTITLELOGFONT := 0x1F
;SPI_GETNONCLIENTMETRICS := 0x29

static vSizeLF := A_IsUnicode ? 92 : 60
static vSizeNCM := 40 + 5*vSizeLF

if (vType = "Icon")
{
	VarSetCapacity(LOGFONT, vSizeLF, 0)
	if !DllCall("SystemParametersInfo", UInt,0x1F, UInt,vSizeLF, Ptr,&LOGFONT, UInt,0)
	Return 0
	vAddress := &LOGFONT
}
else
{
	vOffset := ""
	(vType = "Caption") ? (vOffset := 24) : ""
	(vType = "SmCaption") ? (vOffset := 32 + vSizeLF) : ""
	(vType = "Menu") ? (vOffset := 40 + 2*vSizeLF) : ""
	(vType = "Status") ? (vOffset := 40 + 3*vSizeLF) : ""
	(vType = "Message") ? (vOffset := 40 + 4*vSizeLF) : ""
	if (vOffset = "")
	Return

	VarSetCapacity(NONCLIENTMETRICS, vSizeNCM, 0)
	NumPut(vSizeNCM, &NONCLIENTMETRICS, 0, "UInt")
	if !DllCall("SystemParametersInfo", UInt,0x29, UInt,vSizeNCM, Ptr,&NONCLIENTMETRICS, UInt,0)
	Return 0
	vAddress := &NONCLIENTMETRICS + vOffset
}

vName := StrGet(vAddress+28, 32)
vHeight := NumGet(vAddress+0, "Int")
vSize := DllCall("MulDiv", Int,-vHeight, Int,72, Int,A_ScreenDPI)
vWeight := NumGet(vAddress+16, "Int")
vIsItalic := NumGet(vAddress+20, "UChar")
Return 1
}

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

;e.g.
;JEE_SystemSetFont("Message", "Arial", 18, 700)

;JEE_SetSystemFont
;JEE_SystemFontSet
JEE_SystemSetFont(vType:="", vName:="", vSize:=0, vWeight:=0, vIsItalic:=-1)
{
;SPI_GETICONTITLELOGFONT := 0x1F
;SPI_SETICONTITLELOGFONT := 0x22
;SPI_GETNONCLIENTMETRICS := 0x29
;SPI_SETNONCLIENTMETRICS := 0x2A
;SPIF_UPDATEINIFILE := 0x1
;SPIF_SENDCHANGE := 0x2

static vSizeLF := A_IsUnicode ? 92 : 60
static vSizeNCM := 40 + 5*vSizeLF

if (vType = "Icon")
{
	VarSetCapacity(LOGFONT, vSizeLF, 0)
	if !DllCall("SystemParametersInfo", UInt,0x1F, UInt,vSizeLF, Ptr,&LOGFONT, UInt,0)
	Return 0
	vAddress := &LOGFONT
	vMode := "Icon"
}
else
{
	vOffset := ""
	(vType = "Caption") ? (vOffset := 24) : ""
	(vType = "SmCaption") ? (vOffset := 32 + vSizeLF) : ""
	(vType = "Menu") ? (vOffset := 40 + 2*vSizeLF) : ""
	(vType = "Status") ? (vOffset := 40 + 3*vSizeLF) : ""
	(vType = "Message") ? (vOffset := 40 + 4*vSizeLF) : ""
	if (vOffset = "")
	Return

	VarSetCapacity(NONCLIENTMETRICS, vSizeNCM, 0)
	NumPut(vSizeNCM, &NONCLIENTMETRICS, 0, "UInt")
	if !DllCall("SystemParametersInfo", UInt,0x29, UInt,vSizeNCM, Ptr,&NONCLIENTMETRICS, UInt,0)
	Return 0
	vAddress := &NONCLIENTMETRICS + vOffset
}

if vName
StrPut(vName, vAddress+28, 32)
if vSize
{
vHeight := -DllCall("MulDiv", Int,vSize, Int,A_ScreenDPI, Int,72)
NumPut(vHeight, vAddress+0, "Int")
}
if Weight
NumPut(vWeight, vAddress+16, "Int")
if (vIsItalic = 1) || (vIsItalic = 0)
NumPut(vIsItalic, &vAddress+20, "UChar")

if (vMode = "Icon")
vRet := DllCall("SystemParametersInfo", UInt,0x22, UInt,vSizeLF, Ptr,&LOGFONT, UInt,0x3)
else
vRet := DllCall("SystemParametersInfo", UInt,0x2A, UInt,vSizeNCM, Ptr,&NONCLIENTMETRICS, UInt,0x3)

if vRet
Return 1
else
Return 0
}
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: GUI COMMANDS: COMPLETE RETHINK (latest: get/set system fonts)

16 Feb 2017, 19:34

I recall having issues with 'Control, Choose' and 'Control, ChooseString' on Windows 7, have these issues been resolved yet?
It appears that Choose/ChooseString selects but doesn't notify, I have been using code such as that below to resolve this issue:

Code: Select all

q:: ;example of Choose/ChooseString on Notepad Save As prompt (Windows 7)
;note: it appears Choose/ChooseString selects but doesn't notify
;try this on a new Notepad window with a Unicode character in the text of the Edit control
;and when the Save As prompt starts off suggesting ANSI

;based on code by c00000fd:
;windows - How to simulate selection change in the "file type" ComboBox in GetSaveFileName dialog from a separate process? - Stack Overflow
;http://stackoverflow.com/questions/28952380/how-to-simulate-selection-change-in-the-file-type-combobox-in-getsavefilename

;Control, Choose, 4, ComboBox3, A
Control, ChooseString, UTF-8, ComboBox3, A

;GWL_ID := -12 ;CBN_SELENDOK := 9
ControlGet, hCtl, Hwnd,, ComboBox3, A
vSfx := (A_PtrSize=8) ? "Ptr" : ""
vCtlID := DllCall("user32\GetWindowLong" vSfx, Ptr,hCtl, Int,-12, Ptr)
PostMessage, 0x111, % vCtlID|0x90000, % hCtl,, A
return
==================================================

JEE_ComboBoxNotify(hCtl) function: [old version]

Code: Select all

;e.g.
;Control, ChooseString, UTF-8, ComboBox3, A
;ControlGet, hCtl, Hwnd,, ComboBox3, A
;JEE_ComboBoxNotify(hCtl)

JEE_ComboBoxNotify(hCtl)
{
	static vSfx := (A_PtrSize=8) ? "Ptr" : ""
	;GWL_ID := -12 ;CBN_SELENDOK := 9
	vCtlID := DllCall("user32\GetWindowLong" vSfx, Ptr,hCtl, Int,-12, Ptr)
	hWndParent := DllCall("user32\GetParent", Ptr,hCtl, Ptr)
	SendMessage, 0x111, % vCtlID|(9 << 16), % hCtl,, % "ahk_id " hWndParent ;WM_COMMAND := 0x111
}
==================================================

JEE_ComboBoxNotify(hCtl) function: [improved][thank you just me]

Code: Select all

;e.g.
;Control, ChooseString, UTF-8, ComboBox3, A
;ControlGet, hCtl, Hwnd,, ComboBox3, A
;JEE_ComboBoxNotify(hCtl)

JEE_ComboBoxNotify(hCtl)
{
	;CBN_SELENDOK := 9
	vCtlID := DllCall("user32\GetDlgCtrlID", Ptr,hCtl)
	hWndParent := DllCall("user32\GetParent", Ptr,hCtl, Ptr)
	SendMessage, 0x111, % vCtlID|(9 << 16), % hCtl,, % "ahk_id " hWndParent ;WM_COMMAND := 0x111
}
[EDIT:] Updated version of the function:

Code: Select all

JEE_CBNotify(hCtl)
{
	;CBN_SELENDOK := 9
	vCtlID := DllCall("user32\GetDlgCtrlID", Ptr,hCtl)
	hWndParent := DllCall("user32\GetParent", Ptr,hCtl, Ptr)
	SendMessage, 0x111, % vCtlID|(9 << 16), % hCtl,, % "ahk_id " hWndParent ;WM_COMMAND := 0x111
}
Last edited by jeeswg on 05 Jan 2018, 15:20, edited 4 times in total.
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: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: GUI COMMANDS: COMPLETE RETHINK (latest: get/set system fonts, ComboBox choose string notify)

17 Feb 2017, 02:08

GetWindowLong() only works with AKK 32-bit. You might want to look for GetDlgCtrlID().
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: GUI COMMANDS: COMPLETE RETHINK (latest: get/set system fonts, ComboBox choose string notify)

20 Mar 2017, 09:24

JEE_EditGetRange and JEE_EditSetRange. [EDIT: And, JEE_EditGetRangeAnchorActive.] Get start and end of selection in an Edit control. Btw, be aware of anchor/active position v. start/end (left/right) position.
[EDIT: Renamed to JEE_EditGetSel, JEE_EditSetSel, JEE_EditGetSelAA.]

Anchor v. active:
In a text selection, if you hold shift and press right a number of times, the active position is where the caret is, and the anchor position is your original starting point. If while still holding shift, you then press left enough times, the caret (active position) goes past the anchor, and you can see more clearly how the 'anchor' position stays still, like an anchor.

Normally, the start position is the left boundary, and the end position is the right boundary. Regardless of the where the selection initially 'started', i.e. at the moment you first held down shift.

- EM_GETSEL retrieves left/right positions.
- EM_SETSEL sets anchor/active positions.

To retrieve anchor/active positions:
- use EM_GETSEL to retrieve the left/right positions
- use EM_SETSEL to temporarily set the selection to 0 characters, leaving the caret at the active position
- use EM_GETSEL to retrieve the active position
- use EM_SETSEL to restore the original selection

Code: Select all

JEE_EditGetSel(hCtl, ByRef vPos1, ByRef vPos2)
{
	VarSetCapacity(vPos1, 4), VarSetCapacity(vPos2, 4)
	SendMessage, 0xB0, % &vPos1, % &vPos2,, % "ahk_id " hCtl ;EM_GETSEL := 0xB0 ;(left, right)
	vPos1 := NumGet(&vPos1, 0, "UInt"), vPos2 := NumGet(&vPos2, 0, "UInt")
}

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

JEE_EditSetSel(hCtl, vPos1, vPos2, vDoScroll:=0)
{
	SendMessage, 0xB1, % vPos1, % vPos2,, % "ahk_id " hCtl ;EM_SETSEL := 0xB1 ;(anchor, active)
	if vDoScroll
		SendMessage, 0xB7, 0, 0,, % "ahk_id " hCtl ;EM_SCROLLCARET := 0xB7
}

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

;note: although this involves deselecting and selecting it seems to happen invisibly
JEE_EditGetSelAA(hCtl, ByRef vPos1, ByRef vPos2)
{
	;get selection
	VarSetCapacity(vPos1, 4), VarSetCapacity(vPos2, 4)
	SendMessage, 0xB0, % &vPos1, % &vPos2,, % "ahk_id " hCtl ;EM_GETSEL := 0xB0
	vPos1 := NumGet(&vPos1, 0, "UInt"), vPos2 := NumGet(&vPos2, 0, "UInt")
	if (vPos1 = vPos2)
		return
	vPos1X := vPos1, vPos2X := vPos2

	;set selection to 0 characters and get active position
	SendMessage, 0xB1, -1, 0,, % "ahk_id " hCtl ;EM_SETSEL := 0xB1
	VarSetCapacity(vPos2, 4)
	SendMessage, 0xB0, % &vPos2, 0,, % "ahk_id " hCtl ;EM_GETSEL := 0xB0
	vPos2 := NumGet(&vPos2, 0, "UInt")

	;restore selection
	vPos1 := (vPos2 = vPos2X) ? vPos1X : vPos2X
	SendMessage, 0xB1, % vPos1, % vPos2,, % "ahk_id " hCtl ;EM_SETSEL := 0xB1 ;(anchor, active)
}
==================================================

@just me. Thanks re. GetDlgCtrlID, very helpful, I didn't previously know about that.

Also, this, by you, came in handy the other day, re. handling a drag-and-drop message.
[SOLVED] Binding area of GuiDropFiles - Ask for Help - AutoHotkey Community
https://autohotkey.com/board/topic/8073 ... ntry513389
Last edited by jeeswg on 06 Nov 2017, 13:28, edited 8 times in total.
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: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: GUI COMMANDS: COMPLETE RETHINK (latest: get/set system fonts, ComboBox choose string notify)

20 Mar 2017, 10:04

Code: Select all

VarSetCapacity(vPos1, 4), VarSetCapacity(vPos2, 4)
SendMessage, 0xB0, &vPos1, &vPos2, , ahk_id %hCtl% ;EM_GETSEL
vPos1 := NumGet(vPos1), vPos2 := NumGet(vPos2)
A bit incorrect on 64-bit (!again!). vPos1 and vPos2 are of type DWORD/UInt (4 bytes) whereas the default type for NumGet() is UPtr (8 bytes on x64).

BTW: The Edit messages have been used and even wrapped many times in the forums. Why should we need additional functions with a JEE_ prefix`?

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: yabab33299 and 119 guests