Page 1 of 1

GUIs via DllCall: MsgBox

Posted: 18 Apr 2017, 00:30
by jeeswg
This is a first example in GUIs via DllCall. I also plan to release a DllCall version of my 'control zoo' and a Notepad replacement. I might recreate some of the examples in the AHK documentation, and then more generally, when I want to create a new GUI, or improve one of my existing GUIs, do it via DllCall.

Creating GUIs from scratch is relatively simple. To create a custom class name, e.g. AutoHotkeyGUI, you use RegisterClassEx. To create windows and controls you use CreateWindowEx. To receive information from windows and controls you use a WndProc function, which is very similar to an OnMessage function.

The script is based on a script by majkinetor, which was the first time I saw a GUI made in AutoHotkey, made without the Gui commands, and made using DllCall only.

[EDIT:] Compared to that script, I have tidied up all the code and functions, and made them AHK v1.1 U64/U32 compatible, I have fixed the cursor to have the correct appearance (to not have the 'busy' cursor) when you hover over the MsgBox when it first appears, and I have made the GUI handle the Enter and Esc keys.

[tutorial] Creating windows without GUI commands - Scripts and Functions - AutoHotkey Community
https://autohotkey.com/board/topic/2112 ... -commands/

Code: Select all

;[updated: 2017-04-19]

#SingleInstance force
#KeyHistory 0
#UseHook
#NoEnv
ListLines, Off
Menu, Tray, Click, 1
AutoTrim, Off

#Persistent
DetectHiddenWindows, On
;SplitPath, A_ScriptName,,,, vScriptNameNoExt
;Menu, Tray, Tip, % vScriptNameNoExt

;AHK v1.1 script
;remake by jeeswg of:
;[tutorial] Creating windows without GUI commands - Scripts and Functions - AutoHotkey Community
;https://autohotkey.com/board/topic/21124-tutorial-creating-windows-without-gui-commands/

hFont := JEE_FontCreate("Courier New", 10)
JEE_ConstantsWinStyles()
vPIDAhk := DllCall("kernel32\GetCurrentProcessId", UInt)
return

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

q::
DetectHiddenWindows, On
if WinExist("ahk_id " hGui " ahk_pid " vPIDAhk)
	return
vText := " ;continuation section
(LTrim
	Volume in drive C has no label.
	Volume Serial Number is B857-7430

	Directory of C:\Documents and Settings\mmilic

	07.09.2007  16:18    <DIR>          .
	07.09.2007  16:18    <DIR>          ..
	07.09.2007  10:12    <DIR>          Desktop
	19.01.2007  16:01    <DIR>          Favorites
	28.08.2007  15:28    <DIR>          My Documents
	07.09.2007  16:18               532 out
	14.02.2007  16:57    <DIR>          Start Menu
	1 File(s)            532 bytes
	6 Dir(s)  180.445.904.896 bytes free
)"

;DT_EDITCONTROL := 0x2000 ;DT_NOPREFIX := 0x800
;DT_CALCRECT := 0x400 ;DT_NOCLIP := 0x100
;DT_EXPANDTABS := 0x40 ;DT_SINGLELINE := 0x20
;DT_WORDBREAK := 0x10
vLimW := 500, vLimH := 500
JEE_StrGetDim(vText, hFont, vTextW, vTextH, 0x2D50, vLimW, vLimH)

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

;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 := A_ScriptName ;window title
vWinStyle := WS_SYSMENU ;start off hidden with WS_VISIBLE off
vWinExStyle := WS_EX_DLGMODALFRAME | WS_EX_ACCEPTFILES
vPosX := 100, vPosY := 100
vPosW := vTextW+40, vPosH := vTextH+vCaptionH+80
hWndParent := 0, hMenu := 0, hInstance := 0, vParam := 0
hGui := JEE_DCCreateWindowEx(vWinExStyle, vWinClass, vWinText, vWinStyle, vPosX, vPosY, vPosW, vPosH, hWndParent, hMenu, hInstance, vParam)

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

;create Static control
;SS_EDITCONTROL := 0x2000 ;SS_NOPREFIX := 0x80

vWinClass := "Static"
vWinText := vText
vWinStyle := WS_VISIBLE | WS_CHILD | 0x2080
vWinExStyle := 0
vPosX := 0, vPosY := 0, vPosW := vTextW, vPosH := vTextH
hWndParent := hGui, hMenu := 0, hInstance := 0, vParam := 0
hStatic := JEE_DCCreateWindowEx(vWinExStyle, vWinClass, vWinText, vWinStyle, vPosX, vPosY, vPosW, vPosH, hWndParent, hMenu, hInstance, vParam)

SendMessage, 0x30, % hFont, 1,, % "ahk_id " hStatic ;WM_SETFONT := 0x30

;pStaticProc := RegisterCallback("MyStaticProc", "")
;GWL_WNDPROC := -4
;vSfx := (A_PtrSize=8) ? "Ptr" : ""
;pStaticProcOld := DllCall("SetWindowLong" vSfx, Ptr,hStatic, Int,-4, Ptr,pStaticProc, Ptr)

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

;create Button control
vWinClass := "Button"
vWinText := "OK"
vWinStyle := WS_VISIBLE | WS_CHILD
vWinExStyle := 0
vPosX := 10, vPosY := vTextH+30, vPosW := 50, vPosH := 25
hWndParent := hGui, hMenu := 0, hInstance := 0, vParam := 0
hBtn := JEE_DCCreateWindowEx(vWinExStyle, vWinClass, vWinText, vWinStyle, vPosX, vPosY, vPosW, vPosH, hWndParent, hMenu, hInstance, vParam)

pBtnProc := RegisterCallback("MyBtnProc", "")
;GWL_WNDPROC := -4
vSfx := (A_PtrSize=8) ? "Ptr" : ""
pBtnProcOld := DllCall("SetWindowLong" vSfx, Ptr,hBtn, Int,-4, Ptr,pBtnProc, Ptr)

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

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

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

MyWndProc(hWnd, uMsg, wParam, lParam)
{
	DetectHiddenWindows, On
	global hGui, hBtn

	;VK_ESCAPE := 0x1B ;VK_RETURN := 0xD
	if (uMsg = 0x102) ;WM_CHAR := 0x102
	&& ((wParam = 0x1B) || (wParam = 0xD))
	&& (hWnd = hGui)
		DllCall("DestroyWindow", Ptr,hWnd)

	;BN_CLICKED := 0
	if (uMsg = 0x111) ;WM_COMMAND := 0x111
	&& (wParam >> 16 = 0) && (lParam = hBtn)
		DllCall("DestroyWindow", Ptr,hWnd)

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

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

MyBtnProc(hWnd, uMsg, wParam, lParam)
{
	global pBtnProcOld, hGui

	;VK_ESCAPE := 0x1B ;VK_RETURN := 0xD
	if (uMsg = 0x102) ;WM_CHAR := 0x102
	&& ((wParam = 0x1B) || (wParam = 0xD))
		DllCall("DestroyWindow", Ptr,hGui)

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

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

;;;FUNCTIONS

;JEE_FontCreate
;JEE_ConstantsWinStyles
;JEE_StrGetDim
;JEE_RegisterClassExCFI
;JEE_DCCreateWindowEx

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

;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)
}

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

;e.g. hFont := JEE_FontCreate("Arial", 12, "bius")

;JEE_CreateFont
JEE_FontCreate(vName, vSize, vFontStyle="", vWeight="")
{
	vHeight := -DllCall("kernel32\MulDiv", Int,vSize, Int,A_ScreenDPI, Int,72)
	vWidth := 0
	vEscapement := 0
	vOrientation := 0
	vWeight := (InStr(vFontStyle, "b") && (vWeight="")) ? 700 : 400
	vItalic := InStr(vFontStyle, "i") ? 1 : 0
	vUnderline := InStr(vFontStyle, "u") ? 1 : 0
	vStrikeOut := InStr(vFontStyle, "s") ? 1 : 0
	vCharSet := 0
	vOutPrecision := 0
	vClipPrecision := 0
	vQuality := 0
	vPitchAndFamily := 0
	vFaceName := vName
	vOutPrecision := 3
	vClipPrecision := 2
	vQuality := 1
	vPitchAndFamily := 34
	return DllCall("CreateFont", Int,vHeight, Int,vWidth, Int,vEscapement, Int,vOrientation, Int,vWeight, UInt,vItalic, UInt,vUnderline, UInt,vStrikeOut, UInt,vCharSet, UInt,vOutPrecision, UInt,vClipPrecision, UInt,vQuality, UInt,vPitchAndFamily, Str,vFaceName, 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)
}

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

;JEE DrawText
JEE_StrGetDim(vText, hFont, ByRef vTextW, ByRef vTextH, vDTFlags:=0x400, vLimW:="", vLimH:="")
{
	;DT_EDITCONTROL := 0x2000 ;DT_NOPREFIX := 0x800
	;DT_CALCRECT := 0x400 ;DT_NOCLIP := 0x100
	;DT_EXPANDTABS := 0x40 ;DT_SINGLELINE := 0x20
	;DT_WORDBREAK := 0x10

	;HWND_DESKTOP := 0
	hDC := DllCall("user32\GetDC", Ptr,0, Ptr)
	hFontOld := DllCall("gdi32\SelectObject", Ptr,hDC, Ptr,hFont)
	VarSetCapacity(SIZE, 8, 0)
	vTabLengthText := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
	DllCall("GetTextExtentPoint32", Ptr,hDC, Str,vTabLengthText, Int,52, Ptr,&SIZE)
	vTabLength := NumGet(SIZE, 0, "Int")
	vTabLength := Floor((vTabLength/52)+0.5)
	vTabLength := Round(vTabLength*(72/A_ScreenDPI))
	vLen := StrLen(vText)

	VarSetCapacity(DRAWTEXTPARAMS, 20, 0)
	NumPut(20, DRAWTEXTPARAMS, 0, "UInt") ;cbSize
	NumPut(vTabLength, DRAWTEXTPARAMS, 4, "Int") ;iTabLength
	;NumPut(0, DRAWTEXTPARAMS, 8, "Int") ;iLeftMargin
	;NumPut(0, DRAWTEXTPARAMS, 12, "Int") ;iRightMargin
	NumPut(vLen, DRAWTEXTPARAMS, 16, "UInt") ;uiLengthDrawn

	VarSetCapacity(RECT, 16, 0)
	if !(vLimW = "")
		NumPut(vLimW, RECT, 8, "Int")
	if !(vLimH = "")
		NumPut(vLimH, RECT, 12, "Int")
	DllCall("user32\DrawTextEx", Ptr,hDC, Str,vText, Int,vLen, Ptr,&RECT, UInt,vDTFlags, Ptr,&DRAWTEXTPARAMS)
	DllCall("gdi32\SelectObject", Ptr,hDC, Ptr,hFontOld)
	DllCall("user32\ReleaseDC", Ptr,0, Ptr,hDC)

	vTextW := NumGet(RECT, 8, "Int")
	vTextH := NumGet(RECT, 12, "Int")
}

;==================================================
Two issues with this script are that:
- it doesn't properly handle more than one MsgBox being open at the same time
- the window doesn't handle the Enter or Esc keys [EDIT: fixed]

To receive keypress messages directed at the Button control, do I need to subclass the control?
[EDIT:] I have since used subclassing. The problem I had was that SetWindowLongPtr appears to work for x64 but not x32. I thought that logically it should work for both x64 and x32. So I've made it use either SetWindowLongPtr or SetWindowLong based on the script's 'bitness'.

[function] Subclass - helper function to subclass control - Scripts and Functions - AutoHotkey Community
https://autohotkey.com/board/topic/2397 ... s-control/

The issue with multiple GUIs existing at the same time is one I've asked about here also:

An attempt at a script that creates MsgBoxes/InputBoxes for other scripts - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 53#p138253

Cheers.

[EDIT:] I have noticed that if you activate another window, and then re-activate the GUI, the OK button loses the focus.

Re: GUIs via DllCall: MsgBox

Posted: 18 Apr 2017, 02:03
by just me
Well, I'm somewhat disappointed. No progress since September 2007. The only advantage over simple AHK GUIs is the missing title bar icon. This example doesn't prove that the concept is capable to be used with complex GUIs without severe issues.

Re: GUIs via DllCall: MsgBox

Posted: 18 Apr 2017, 09:19
by jeeswg
@just me
I'm quite sympathetic to your viewpoint. I would have liked that other people had worked on creating GUIs from scratch via DllCall, it's made things harder for me, because fundamental GUI issues have never been discussed on the forum.

What are the 'severe issues' that you imagine? Is there anything that the Gui commands can do that can't be done via DllCall in your view?

In the worst-case scenario, a lot of the functions that I'm working on, can be used alongside the Gui command, or can do things that existing AutoHotkey commands can't do.

I think that there were 'severe issues' with the AHK v1 Gui command, it is amazing not having to use it, especially its event handling. You can also specify custom class names, and windows with no icons, as you mentioned, which people have wanted for years.

[EDIT:] Btw this GUIs via DllCall approach could be useful for people who want to translate GUIs from or to other programming languages.

Re: GUIs via DllCall: MsgBox

Posted: 19 Apr 2017, 03:39
by just me
Hi jeeswg,

you didn't read much about Message Queues and Window Procedures as yet, did you?
In the worst-case scenario, a lot of the functions that I'm working on, can be used alongside the Gui command, or can do things that existing AutoHotkey commands can't do.
If you would search the forums you would find out that a lot of this functions already exist, of course without the JEE_ prefix.


GUI COMMANDS: COMPLETE RETHINK
(12) 'Any script that uses the GUI command anywhere is automatically persistent'
Didn't you notice that your example in this thread wouldn't work if the script wouldn't be #Persistent?
(13) some aspects of GUI commands are quirky like: Gui Submit/AltSubmit, special variables, and special letters (e.g. g-label notifications for listviews)
You should try to implement the event handlers using your non-AHK-GUI concept. Good luck!

Re: GUIs via DllCall: MsgBox

Posted: 19 Apr 2017, 11:41
by jeeswg
Message queues and window procedures are fundamental to GUIs, however they have not proved too much of an obstacle so far. I don't mind knowing more about them, but there hasn't been that much that I've needed to know so far.

I feel that I have 95% of the problems fixed, many problems are general and not specific to 'GUIs via DllCall'. Of course, one major problem, and you don't have a working script!

There are quite a lot of GUI functions available now, however, back in 2011 for example, there were far fewer. Unfortunately a lot of people writing functions combine the object and the functions together. This obscures the code, making it harder to understand, also, often I want the raw function combined with *my own* object implementation, or more specifically, I want all windows/controls to use one object implementation, not to each have their own implementation. My approach will be to create raw functions, and let other's create their own object around the functions, or use my object.

[I've added a section 'GUI - WINDOWS / CONTROLS (LIBRARIES)' to:]
best utilities + best AutoHotkey scripts (+ useful tips) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=7&t=28149

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

I made the script #Persistent, but I would like to be able to make a script temporarily #Persistent like AutoHotkey's MsgBox/InputBox commands.

This little hack for temporary persistence didn't work unfortunately, it just made the script permanently persistent:

Code: Select all

Hotkey, q, MyLabel
ToolTip, HELLO
Sleep 3000
Hotkey, q, Off ;script does not close at this point, but remains open
MyLabel:
#Persistent
https://autohotkey.com/docs/commands/_Persistent.htm
hotkeys, hotstrings, or any use of OnMessage() or Gui
The idea for the 'temporary persistence' hack, which didn't work, was that the presence of a hotkey in the script, makes a script Persistent, so perhaps 1 hotkey (or more) = persistent, turn hotkeys off and 0 hotkeys = not persistent.

My 0-hotkey script started off non-persistent, I defined 1 hotkey, which made the script persistent, even after I turned off the hotkey.

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

I don't personally want a direct equivalent to AutoHotkey's Submit/AltSubmit and special variable-associated-with-a-control approach, or 'A_' variables, I would just specify the hWnds and grab the text. I plan to handle events on a case-by-case basis using WndProcs for the controls.

Now that I've fixed the subclassing issue, I'm feeling fairly optimistic about 'GUIs via DllCall'. It appears that it's all doable, although some of it may be fiddly, but then, it's fiddly even if you do it via the Gui commands. Overall though, I feel it's much easier to use one approach: DllCall, rather than two approaches at the same time: the Gui command and extras via DllCall.

Thanks for your response.

Re: GUIs via DllCall: MsgBox

Posted: 19 Apr 2017, 11:53
by Helgef
Interesting code, it also gives a hint about the amount of time ahk saves us with its gui features. Regarding temporary persistence, although its a funny expression, I get what you mean, I think :wave: . How about a winwaitclose wait for the msgbox?
Cheers.

Re: GUIs via DllCall: MsgBox

Posted: 19 Apr 2017, 12:32
by jeeswg
I'm close to finishing a DllCall version of my 'control zoo'. Creating an equivalent has made it clear to me how the Gui command is good at making the right assumptions about how you want a control to appear (style, extended style, size, position), thus reducing say 10 lines of code to 1.

My JEE_RegisterClassExCFI command works on a similar basis to this, making certain assumptions for you. I had thought that I could make an alternative to JEE_DCCreateWindowEx, based on 'Gui, Add', that makes more assumptions, but that allows customisation in the same way that 'Gui, Add' does.

Anyhow, hopefully it appears fairly easy to create windows/controls in my script, and I much prefer handling events etc via WndProcs than the Gui command way.

That said, AutoHotkey v1 and its Gui commands, might be one of the best attempts ever at a program that makes it easy to create GUIs. I would be interested to hear of any other examples.

Ideally I would like something like 'Persistent, On', 'Persistent, Off'. Thanks for reminding me, I had used WinWaitClose in the past. I would be interested generally in any ideas for achieving 'temporary persistence'.

[Btw @Helgef, 1357 posts, nice number.]

Re: GUIs via DllCall: MsgBox

Posted: 20 Apr 2017, 02:53
by just me
jeeswg, it's easy to create and show windows via DllCall(). But you might find out that it isn't that easy to provide the flexibility of the Gui command options and - more important - to implement event handling (message processing) which comes near to the implementation for built-in AHK Guis.

Re: GUIs via DllCall: MsgBox

Posted: 20 Apr 2017, 05:12
by Drugwash
@ jeeswg: The concept is interesting, at some point I had thought of using it in SmartGUIXP Creator Mod - or rather a complete rewrite of it - thus eliminating the limit on GUI number creation (max 99) but never got around to working on that and seeing the interest in that old script is next to zero it probably won't see any (major) updates anymore.

I've had an attempt at creating dialog windows from binary templates in myCompiler which was intended to be a crossbreed between a resource editor and the AHK compiler. Only managed to display resources so far, it's still buggy and most of all it only works (almost) correctly with ANSI binaries/resources because I haven't gotten to converting it to use ANSI/Unicode AHK. Pure AHK 1.0 code, because main target is Win98SE, as always. You may check it out at my repository if you think it may be of any help.

Re: GUIs via DllCall: MsgBox

Posted: 04 Aug 2017, 13:52
by jeeswg
While checking the help file for all references to #Persistent/persistent/persistence, I found what may be a way to achieve 'temporary persistence':

Code: Select all

BlockInput, MouseMove ;this line begins 'temporary persistence'
BlockInput, MouseMoveOff
ToolTip hello
Sleep 3000
Suspend ;this line ends 'temporary persistence'
Suspend, Off
And one method that in theory would work, but appeared not to:
(although it does seem to introduce 'permanent persistence', where a script was previously not persistent)

Code: Select all

;doesn't work:
Input, vDummy, T0.001 ;this line begins 'temporary persistence'
ToolTip hello
Sleep 3000
Suspend ;this line ends 'temporary persistence'
Suspend, Off

Re: GUIs via DllCall: MsgBox

Posted: 04 Aug 2017, 15:41
by gwarble
Thanks for sharing...

I have a need to create windows of different class names for EitherMouse... basically I want to add the system window shadow attribute to my normal gui windows (done successfully with ShadowEnabled := DllCall("SetClassLong", "uint", WinExist(), "int", -26, "int", DllCall("GetClassLong", "uint", WinExist(), "int", -26) | 0x20000 | 0x0800)) but then I want to create other windows (temporary cursors) without that shadow, so I think they need to be created with a different class than AutoHotkeyGUI which can't be done with gui commands. Is this the proper solution for this?

Re: GUIs via DllCall: MsgBox

Posted: 05 Aug 2017, 02:29
by jeeswg
It seems that you're trying to change the default window style (GCL_STYLE := -26) for a class.

Did you try changing the default window style for the AutoHotkeyGUI class, as appropriate, each time (just before) you created a window (with the Gui command)? Does WinSetStyle work to change the style after the window has been created?

If you can use more than one script, then you can edit the class name 'AutoHotkeyGUI' in the exe file, and have two classes that way. That would change the GUI class name.

If you only want a finite number of windows, it may be possible to create some windows using the 'AutoHotkeyGUI' class, and then change the class name in the address space, and create more windows using a different class name. (In my tests I was able to change the class once but only once, it may be simpler or more complicated than this.)

But in general, to create a GUI with any class name, this is the basis of the approach, to create the GUI via DllCall using CreateWindowEx and RegisterClassEx. There are some other examples in the forums e.g. for ToolTips using DllCall, just search for CreateWindow or CreateWindowEx.

If this information doesn't solve your problem, then you should consider starting a new thread in Ask For Help. Best of luck.

Re: GUIs via DllCall: MsgBox

Posted: 12 Nov 2018, 15:37
by burque505
(Bump)
I think line 236 of the script (function JEE_FontCreate()) should be

Code: Select all

vHeight := DllCall("kernel32\MulDiv", Int,vSize, Int,A_ScreenDPI, Int,72)
instead of

Code: Select all

vHeight := -DllCall("kernel32\MulDiv", Int,vSize, Int,A_ScreenDPI, Int,72)
Nice job, by the way :clap:
Regards,
burque505

Re: GUIs via DllCall: MsgBox

Posted: 14 Nov 2018, 14:13
by jeeswg
- @burque505: Thanks.
- Here are some links about fonts and negative heights (specifically the lfHeight item):
tagLOGFONTA | Microsoft Docs
https://docs.microsoft.com/en-us/window ... aglogfonta
Negative Font height/size in IDE or at runtime - Delphi Pages Forums
http://www.delphipages.com/forum/showth ... p?t=120942
font.height - how get the positive value (actual textheight)? - delphi
http://www.delphigroups.info/2/4d/103197.html
- Just for anyone unfamiliar with heights v. size, the size value, e.g. that you specify in Notepad, is different from the height value.
- This script shows that when I retrieve the details of a font used in an Edit control, e.g. in Notepad, it shows a negative height:

Code: Select all

q:: ;Edit control - get font size
ControlGet, hCtl, Hwnd,, Edit1, A
SendMessage, 0x31, 0, 0,, % "ahk_id " hCtl ;WM_GETFONT := 0x31
hFont := ErrorLevel
VarSetCapacity(LOGFONT, 92, 0)
vSize := DllCall("gdi32\GetObject", Ptr,hFont, Int,0, Ptr,0)
DllCall("gdi32\GetObject", Ptr,hFont, Int,vSize, Ptr,&LOGFONT)
vHeight := NumGet(&LOGFONT, 0, "Int") ;lfHeight
vWidth := NumGet(&LOGFONT, 4, "Int") ;lfWidth
vSize := DllCall("kernel32\MulDiv", Int,-vHeight, Int,72, Int,A_ScreenDPI)
MsgBox, % vHeight " " vWidth " " vSize
return
- Perhaps you had a specific reason in mind for suggesting a positive font height, which I would be happy to hear. Thanks.

Re: GUIs via DllCall: MsgBox

Posted: 14 Nov 2018, 14:46
by burque505
Actually I thought it was just a typo. :)
Thanks for the clarification. Negative value looks better.
GIF with positive value (17 on my system):
positive.GIF
positive.GIF (53.21 KiB) Viewed 5340 times
GIF with negative value (-17 on my system):
negative.GIF
negative.GIF (70.44 KiB) Viewed 5340 times