Skip to content

Instantly share code, notes, and snippets.

@alenbasic
Forked from wizcas/winterm-callout.ahk
Last active April 15, 2020 02:51
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alenbasic/004c5abeb4cc0e0b31b7681371d48898 to your computer and use it in GitHub Desktop.
Save alenbasic/004c5abeb4cc0e0b31b7681371d48898 to your computer and use it in GitHub Desktop.
AHK Script for calling out Windows Terminal in a drop down fashion
/**
* Lib: JSON.ahk
* JSON lib for AutoHotkey.
* Version:
* v2.1.3 [updated 04/18/2016 (MM/DD/YYYY)]
* License:
* WTFPL [http://wtfpl.net/]
* Requirements:
* Latest version of AutoHotkey (v1.1+ or v2.0-a+)
* Installation:
* Use #Include JSON.ahk or copy into a function library folder and then
* use #Include <JSON>
* Links:
* GitHub: - https://github.com/cocobelgica/AutoHotkey-JSON
* Forum Topic - http://goo.gl/r0zI8t
* Email: - cocobelgica <at> gmail <dot> com
*/
/**
* Class: JSON
* The JSON object contains methods for parsing JSON and converting values
* to JSON. Callable - NO; Instantiable - YES; Subclassable - YES;
* Nestable(via #Include) - NO.
* Methods:
* Load() - see relevant documentation before method definition header
* Dump() - see relevant documentation before method definition header
*/
class JSON
{
/**
* Method: Load
* Parses a JSON string into an AHK value
* Syntax:
* value := JSON.Load( text [, reviver ] )
* Parameter(s):
* value [retval] - parsed value
* text [in, ByRef] - JSON formatted string
* reviver [in, opt] - function object, similar to JavaScript's
* JSON.parse() 'reviver' parameter
*/
class Load extends JSON.Functor
{
Call(self, ByRef text, reviver:="")
{
this.rev := IsObject(reviver) ? reviver : false
; Object keys(and array indices) are temporarily stored in arrays so that
; we can enumerate them in the order they appear in the document/text instead
; of alphabetically. Skip if no reviver function is specified.
this.keys := this.rev ? {} : false
static quot := Chr(34), bashq := "\" . quot
, json_value := quot . "{[01234567890-tfn"
, json_value_or_array_closing := quot . "{[]01234567890-tfn"
, object_key_or_object_closing := quot . "}"
key := ""
is_key := false
root := {}
stack := [root]
next := json_value
pos := 0
while ((ch := SubStr(text, ++pos, 1)) != "") {
if InStr(" `t`r`n", ch)
continue
if !InStr(next, ch, 1)
this.ParseError(next, text, pos)
holder := stack[1]
is_array := holder.IsArray
if InStr(",:", ch) {
next := (is_key := !is_array && ch == ",") ? quot : json_value
} else if InStr("}]", ch) {
ObjRemoveAt(stack, 1)
next := stack[1]==root ? "" : stack[1].IsArray ? ",]" : ",}"
} else {
if InStr("{[", ch) {
; Check if Array() is overridden and if its return value has
; the 'IsArray' property. If so, Array() will be called normally,
; otherwise, use a custom base object for arrays
static json_array := Func("Array").IsBuiltIn || ![].IsArray ? {IsArray: true} : 0
; sacrifice readability for minor(actually negligible) performance gain
(ch == "{")
? ( is_key := true
, value := {}
, next := object_key_or_object_closing )
; ch == "["
: ( value := json_array ? new json_array : []
, next := json_value_or_array_closing )
ObjInsertAt(stack, 1, value)
if (this.keys)
this.keys[value] := []
} else {
if (ch == quot) {
i := pos
while (i := InStr(text, quot,, i+1)) {
value := StrReplace(SubStr(text, pos+1, i-pos-1), "\\", "\u005c")
static tail := A_AhkVersion<"2" ? 0 : -1
if (SubStr(value, tail) != "\")
break
}
if (!i)
this.ParseError("'", text, pos)
value := StrReplace(value, "\/", "/")
, value := StrReplace(value, bashq, quot)
, value := StrReplace(value, "\b", "`b")
, value := StrReplace(value, "\f", "`f")
, value := StrReplace(value, "\n", "`n")
, value := StrReplace(value, "\r", "`r")
, value := StrReplace(value, "\t", "`t")
pos := i ; update pos
i := 0
while (i := InStr(value, "\",, i+1)) {
if !(SubStr(value, i+1, 1) == "u")
this.ParseError("\", text, pos - StrLen(SubStr(value, i+1)))
uffff := Abs("0x" . SubStr(value, i+2, 4))
if (A_IsUnicode || uffff < 0x100)
value := SubStr(value, 1, i-1) . Chr(uffff) . SubStr(value, i+6)
}
if (is_key) {
key := value, next := ":"
continue
}
} else {
value := SubStr(text, pos, i := RegExMatch(text, "[\]\},\s]|$",, pos)-pos)
static number := "number", integer :="integer"
if value is %number%
{
if value is %integer%
value += 0
}
else if (value == "true")
value := "true"
else if (value == "false")
value := "false"
else if (value == "null")
value := ""
else
; we can do more here to pinpoint the actual culprit
; but that's just too much extra work.
this.ParseError(next, text, pos, i)
pos += i-1
}
next := holder==root ? "" : is_array ? ",]" : ",}"
} ; If InStr("{[", ch) { ... } else
is_array? key := ObjPush(holder, value) : holder[key] := value
if (this.keys && this.keys.HasKey(holder))
this.keys[holder].Push(key)
}
} ; while ( ... )
return this.rev ? this.Walk(root, "") : root[""]
}
ParseError(expect, ByRef text, pos, len:=1)
{
static quot := Chr(34), qurly := quot . "}"
line := StrSplit(SubStr(text, 1, pos), "`n", "`r").Length()
col := pos - InStr(text, "`n",, -(StrLen(text)-pos+1))
msg := Format("{1}`n`nLine:`t{2}`nCol:`t{3}`nChar:`t{4}"
, (expect == "") ? "Extra data"
: (expect == "'") ? "Unterminated string starting at"
: (expect == "\") ? "Invalid \escape"
: (expect == ":") ? "Expecting ':' delimiter"
: (expect == quot) ? "Expecting object key enclosed in double quotes"
: (expect == qurly) ? "Expecting object key enclosed in double quotes or object closing '}'"
: (expect == ",}") ? "Expecting ',' delimiter or object closing '}'"
: (expect == ",]") ? "Expecting ',' delimiter or array closing ']'"
: InStr(expect, "]") ? "Expecting JSON value or array closing ']'"
: "Expecting JSON value(string, number, true, false, null, object or array)"
, line, col, pos)
static offset := A_AhkVersion<"2" ? -3 : -4
throw Exception(msg, offset, SubStr(text, pos, len))
}
Walk(holder, key)
{
value := holder[key]
if IsObject(value) {
for i, k in this.keys[value] {
; check if ObjHasKey(value, k) ??
v := this.Walk(value, k)
if (v != JSON.Undefined)
value[k] := v
else
ObjDelete(value, k)
}
}
return this.rev.Call(holder, key, value)
}
}
/**
* Method: Dump
* Converts an AHK value into a JSON string
* Syntax:
* str := JSON.Dump( value [, replacer, space ] )
* Parameter(s):
* str [retval] - JSON representation of an AHK value
* value [in] - any value(object, string, number)
* replacer [in, opt] - function object, similar to JavaScript's
* JSON.stringify() 'replacer' parameter
* space [in, opt] - similar to JavaScript's JSON.stringify()
* 'space' parameter
*/
class Dump extends JSON.Functor
{
Call(self, value, replacer:="", space:="")
{
this.rep := IsObject(replacer) ? replacer : ""
this.gap := ""
if (space) {
static integer := "integer"
if space is %integer%
Loop, % ((n := Abs(space))>10 ? 10 : n)
this.gap .= " "
else
this.gap := SubStr(space, 1, 10)
this.indent := "`n"
}
return this.Str({"": value}, "")
}
Str(holder, key)
{
value := holder[key]
if (this.rep)
value := this.rep.Call(holder, key, ObjHasKey(holder, key) ? value : JSON.Undefined)
if IsObject(value) {
; Check object type, skip serialization for other object types such as
; ComObject, Func, BoundFunc, FileObject, RegExMatchObject, Property, etc.
static type := A_AhkVersion<"2" ? "" : Func("Type")
if (type ? type.Call(value) == "Object" : ObjGetCapacity(value) != "") {
if (this.gap) {
stepback := this.indent
this.indent .= this.gap
}
is_array := value.IsArray
; Array() is not overridden, rollback to old method of
; identifying array-like objects. Due to the use of a for-loop
; sparse arrays such as '[1,,3]' are detected as objects({}).
if (!is_array) {
for i in value
is_array := i == A_Index
until !is_array
}
str := ""
if (is_array) {
Loop, % value.Length() {
if (this.gap)
str .= this.indent
v := this.Str(value, A_Index)
str .= (v != "") ? v . "," : "null,"
}
} else {
colon := this.gap ? ": " : ":"
for k in value {
v := this.Str(value, k)
if (v != "") {
if (this.gap)
str .= this.indent
str .= this.Quote(k) . colon . v . ","
}
}
}
if (str != "") {
str := RTrim(str, ",")
if (this.gap)
str .= stepback
}
if (this.gap)
this.indent := stepback
return is_array ? "[" . str . "]" : "{" . str . "}"
}
} else ; is_number ? value : "value"
if value is float
return value
else
return (ObjGetCapacity([value], 1) == "") ? value : this.QuoteValue(value)
}
Quote(string)
{
static quot := Chr(34), bashq := "\" . quot
if (string != "") {
string := StrReplace(string, "\", "\\")
; , string := StrReplace(string, "/", "\/") ; optional in ECMAScript
, string := StrReplace(string, quot, bashq)
, string := StrReplace(string, "`b", "\b")
, string := StrReplace(string, "`f", "\f")
, string := StrReplace(string, "`n", "\n")
, string := StrReplace(string, "`r", "\r")
, string := StrReplace(string, "`t", "\t")
static rx_escapable := A_AhkVersion<"2" ? "O)[^\x20-\x7e]" : "[^\x20-\x7e]"
while RegExMatch(string, rx_escapable, m)
string := StrReplace(string, m.Value, Format("\u{1:04x}", Ord(m.Value)))
}
return quot . string . quot
}
QuoteValue(string)
{
static quot := Chr(34), bashq := "\" . quot
if (string != "") {
string := StrReplace(string, "\", "\\")
; , string := StrReplace(string, "/", "\/") ; optional in ECMAScript
, string := StrReplace(string, quot, bashq)
, string := StrReplace(string, "`b", "\b")
, string := StrReplace(string, "`f", "\f")
, string := StrReplace(string, "`n", "\n")
, string := StrReplace(string, "`r", "\r")
, string := StrReplace(string, "`t", "\t")
static rx_escapable := A_AhkVersion<"2" ? "O)[^\x20-\x7e]" : "[^\x20-\x7e]"
while RegExMatch(string, rx_escapable, m)
string := StrReplace(string, m.Value, Format("\u{1:04x}", Ord(m.Value)))
}
if (string == "true" || string == "false" )
return string
else
return quot . string . quot
}
}
/**
* Property: Undefined
* Proxy for 'undefined' type
* Syntax:
* undefined := JSON.Undefined
* Remarks:
* For use with reviver and replacer functions since AutoHotkey does not
* have an 'undefined' type. Returning blank("") or 0 won't work since these
* can't be distnguished from actual JSON values. This leaves us with objects.
* Replacer() - the caller may return a non-serializable AHK objects such as
* ComObject, Func, BoundFunc, FileObject, RegExMatchObject, and Property to
* mimic the behavior of returning 'undefined' in JavaScript but for the sake
* of code readability and convenience, it's better to do 'return JSON.Undefined'.
* Internally, the property returns a ComObject with the variant type of VT_EMPTY.
*/
Undefined[]
{
get {
static empty := {}, vt_empty := ComObject(0, &empty, 1)
return vt_empty
}
}
class Functor
{
__Call(method, ByRef arg, args*)
{
; When casting to Call(), use a new instance of the "function object"
; so as to avoid directly storing the properties(used across sub-methods)
; into the "function object" itself.
if IsObject(method)
return (new this).Call(method, arg, args*)
else if (method == "")
return (new this).Call(arg, args*)
}
}
}
#Include JSON.ahk
#SingleInstance,Force
Menu, Tray, NoStandard
Menu, Tray, Tip, Windows Terminal
Menu, Tray, Add, Settings, wtSettings
Menu, Tray, Add, Exit, wtExit
Menu, Tray, Default, Exit
; ############ THE PATH TO THE WINDOWS TERMINAL EXE FILE ############
wtPath = "%LOCALAPPDATA%\Microsoft\WindowsApps\wt.exe"
; ############ PROFILE AND SETTINGS ############
base_path := getBasePath() . "\LocalState\"
wtSettings = %base_path%settings.ini
wtProfile = %base_path%profiles.json
; ############ FONT STUFF ############
fontName :="Cascadia Code"
fontSize := 12
fontStyle :={size: fontSize,color:0x000000,strikeout:0,underline:0,italic:0,bold:0}
; ############ READ FILES ############
Vratio := getVratio(wtSettings)
wtProfileJSON := getProfile(wtProfile)
profile_index := getDefaultProfile(wtProfileJSON)
; ############ SC29 - CHANGE THIS PART IF YOU WANNA CHANGE THE SHORTCUT USED TO BRING UP THE DROPDOWN TERMINAL ############
SC29::ToggleTerminal()
; ############ THE FOLDER THE PROFILE IS IN DOESN'T HAVE A STANDARD NAMING CONVENTION SO WE JUST SEARCH FOR IT HERE TO USE LATER ON ############
getBasePath() {
base_path = C:\Users\%A_UserName%\AppData\Local\Packages\
Loop Files, %base_path%*WindowsTerminal*, D
{
return %A_LoopFileFullPath%
}
}
; ############ GETS THE TERMINAL VERTICAL SIZE OR SETS A DEFAULT ############
getVratio(wtSettings) {
if !FileExist(wtSettings) {
FileAppend, [Settings]`nWindowHeight=0.35, %wtSettings%
return 0.35
} else {
IniRead, VRatio, %wtSettings%, Settings, WindowHeight
return Vratio
}
}
; ############ LOADS THE PROFILE.JSON FILE AND GETS WHICH PROFILE IS SET AS THE DEFAULT ############
getProfile(wtProfile) {
FileRead, wtProfileFile, %wtProfile%
return JSON.Load(wtProfileFile)
}
getDefaultProfile(wtProfileJSON) {
for index, profile in wtProfileJSON.profiles {
if profile.guid = wtProfileJSON.defaultProfile {
return index
}
}
return 1
}
; ############ THE LOGIC TO POSITION, SIZE AND DISPLAY THE TERMINAL ############
ShowAndPositionTerminal() {
ScreenX := GetScreenLeft()
ScreenY := GetScreenTop()
ScreenWidth := GetScreenWidth()
ScreenHeight := GetScreenHeight()
global VRatio
WinShow ahk_class CASCADIA_HOSTING_WINDOW_CLASS
WinActivate ahk_class CASCADIA_HOSTING_WINDOW_CLASS
WinMove, ahk_class CASCADIA_HOSTING_WINDOW_CLASS,, ScreenX-5, ScreenY-10, ScreenWidth+10, ScreenHeight * VRatio,
}
ToggleTerminal() {
WinMatcher := "ahk_class CASCADIA_HOSTING_WINDOW_CLASS"
DetectHiddenWindows, On
if WinExist(WinMatcher)
; Window Exists
{
DetectHiddenWindows, Off
; Check if its hidden
if !WinExist(WinMatcher) || !WinActive(WinMatcher)
{
ShowAndPositionTerminal()
}
else if WinExist(WinMatcher)
{
; Script sees it without detecting hidden windows, so..
WinHide ahk_class CASCADIA_HOSTING_WINDOW_CLASS
Send !{Esc}
}
}
else
{
global wtPath
Run %wtPath%
Sleep, 1000
ShowAndPositionTerminal()
}
}
; Gets the edge that the taskbar is docked to. Returns:
; "top"
; "right"
; "bottom"
; "left"
GetTaskbarEdge() {
WinGetPos,TX,TY,TW,TH,ahk_class Shell_TrayWnd,,,
if (TW = A_ScreenWidth) { ; Vertical Taskbar
if (TY = 0) {
return "top"
} else {
return "bottom"
}
} else { ; Horizontal Taskbar
if (TX = 0) {
return "left"
} else {
return "right"
}
}
}
GetScreenTop() {
WinGetPos,TX,TY,TW,TH,ahk_class Shell_TrayWnd,,,
TaskbarEdge := GetTaskbarEdge()
if (TaskbarEdge = "top") {
return TH
} else {
return 0
}
}
GetScreenLeft() {
WinGetPos,TX,TY,TW,TH,ahk_class Shell_TrayWnd,,,
TaskbarEdge := GetTaskbarEdge()
if (TaskbarEdge = "left") {
return TW
} else {
return 0
}
}
GetScreenWidth() {
WinGetPos,TX,TY,TW,TH,ahk_class Shell_TrayWnd,,,
TaskbarEdge := GetTaskbarEdge()
if (TaskbarEdge = "top" or TaskbarEdge = "bottom") {
return A_ScreenWidth
} else {
return A_ScreenWidth - TW
}
}
GetScreenHeight() {
WinGetPos,TX,TY,TW,TH,ahk_class Shell_TrayWnd,,,
TaskbarEdge := GetTaskbarEdge()
if (TaskbarEdge = "top" or TaskbarEdge = "bottom") {
return A_ScreenHeight - TH
} else {
return A_ScreenHeight
}
}
; ############ SETS DEFAULT VALUES IF NEEDED FOR SETTINGS THAT MIGHTN'T BE IN THE PROFILE.JSON FILE ALREADY ############
setDefaults() {
global wtProfileJSON
global profile_index
global fontStyle
wtProfileJSON.profiles[profile_index].fontFace := (wtProfileJSON.profiles[profile_index].fontFace = "" ) ? ("Cascadia Code") : (wtProfileJSON.profiles[profile_index].fontFace)
wtProfileJSON.profiles[profile_index].fontSize := (wtProfileJSON.profiles[profile_index].fontSize = "" ) ? (12) : (wtProfileJSON.profiles[profile_index].fontSize)
wtProfileJSON.profiles[profile_index].acrylicOpacity := (wtProfileJSON.profiles[profile_index].acrylicOpacity = "" ) ? (1) : (wtProfileJSON.profiles[profile_index].acrylicOpacity)
wtProfileJSON.profiles[profile_index].useAcrylic := "true"
fontStyle["size"] := wtProfileJSON.profiles[profile_index].fontSize
}
; ############ THE CODE TO SHOW AND DISPLAY THE SETTINGS MENU ############
wtSettings:
defaultHeight := 21
defaultWidth := 120
global wtProfileJSON
global VRatio
global profile_index
setDefaults()
Gui, Destroy
Gui, Margin, 5,5
; ############ LEFT HAND COLUMN ############
Gui, Add, Text, h%defaultHeight% , Default Terminal:
Gui, Add, Text, h%defaultHeight% , Color Scheme:
Gui, Add, Text, h%defaultHeight% xp y+m, Terminal Font:
Gui, Add, Text, h%defaultHeight% xp y+m, Font Size
Gui, Add, Text, h%defaultHeight% xp y+m,
Gui, Add, Text, h%defaultHeight% xp y+m, Terminal Opacity:
Gui, Add, Text, h%defaultHeight% xp y+m, Terminal Height:
Gui, Add, Button, h%defaultHeight% w%defaultWidth% default xp y+m gButtonApply, Apply
; ############ RIGHT HAND COLUMN ############
Gui, Add, DropDownList, vchooseTheme gchangedTheme hwndchangedThemehcbx altsubmit ym
PostMessage, 0x153, -1, 26,, ahk_id %changedThemehcbx% ; SET HEIGHT OF SELECTION FIELD.
for index, profile in wtProfileJSON.profiles {
GuiControl,, chooseTheme, % profile.name
}
GuiControl,Choose, chooseTheme, %profile_index%
Gui, Add, DropDownList, vchooseScheme gchangedScheme hwndhcbx xp y+11
PostMessage, 0x153, -1, 26,, ahk_id %hcbx%
for index, scheme in wtProfileJSON.schemes {
GuiControl,, chooseScheme, % scheme.name
}
GuiControl,Choose, chooseScheme, % wtProfileJSON.profiles[profile_index].colorScheme
Gui, Add, Text, h%defaultHeight% w%defaultWidth% xp y+11 vFontDetails, % wtProfileJSON.profiles[profile_index].fontFace
Gui, Add, Text, h%defaultHeight% w%defaultWidth% xp vFontSize y+m, % wtProfileJSON.profiles[profile_index].fontSize
Gui, Add, Button, h%defaultHeight% w%defaultWidth% xp y+m vchooseFont gChooseFont ,Change Font
Gui, Add, Edit, h%defaultHeight% w%defaultWidth% xp y+m vopacity, % Round(wtProfileJSON.profiles[profile_index].acrylicOpacity * 100)
Gui, Add, Edit, h%defaultHeight% w%defaultWidth% xp y+m vheight, % Round(VRatio * 100)
Gui, Add, Button, h%defaultHeight% w%defaultWidth% default xp y+6, OK ; THE LABEL BUTTONOK (IF IT EXISTS) WILL BE RUN WHEN THE BUTTON IS PRESSED.
Gui, Show,, Settings
return
; ############ WE'VE CHANGED THE DEFAULT TERMINAL OR COLOR SCHEME; LET'S UPDATE THE SETTINGS MENU ############
changedTheme:
global profile_index
global FontDetails
global FontSize
global opacity
global chooseScheme
Gui, Submit, NoHide
profile_index := chooseTheme
changedTheme := true
setDefaults()
GuiControl, Text, FontDetails, % wtProfileJSON.profiles[profile_index].fontFace
GuiControl, Text, FontSize, % wtProfileJSON.profiles[profile_index].fontSize
GuiControl,Choose, chooseScheme, % wtProfileJSON.profiles[profile_index].colorScheme
GuiControl, Text, opacity, % Round(wtProfileJSON.profiles[profile_index].acrylicOpacity * 100)
return
changedScheme:
global profile_index
Gui, Submit, NoHide
changedScheme := true
wtProfileJSON.profiles[profile_index].colorScheme := chooseScheme
return
; ############ APPLYING THE CHANGES WE'VE MADE INTO THE PROFILE.JSON FILE ############
ButtonApply:
applyChanges(false)
return
ButtonOK:
applyChanges(true)
return
applyChanges(saveAndExit) {
global VRatio
global wtProfile
global FontDetails
global chooseTheme
global changedTheme
global changedScheme
global profile_index
global fontSize
global height
global wtSettings
if (saveAndExit) {
Gui, Submit
} else {
Gui, Submit, NoHide
}
changed := False
if (changedScheme) {
changed := True
}
if (changedTheme) {
wtProfileJSON.defaultProfile := wtProfileJSON.profiles[chooseTheme].guid
changed := True
}
if !(height / 100 = Vratio) {
VRatio := height / 100
IniWrite, %VRatio%, %wtSettings%, Settings, WindowHeight ; HOW MUCH HEIGHT OF SCREEN SIZE THE TERMINAL WINDOW TAKES.
changed := True
}
if !(fontName = wtProfileJSON.profiles[profile_index].fontFace) {
wtProfileJSON.profiles[profile_index].fontFace := fontName
wtProfileJSON.profiles[profile_index].fontSize := fontSize
changed := True
}
if !(fontSize = wtProfileJSON.profiles[profile_index].fontSize) {
wtProfileJSON.profiles[profile_index].fontSize := fontSize
changed := True
}
if !(opacity = wtProfileJSON.profiles[profile_index].acrylicOpacity * 100) {
wtProfileJSON.profiles[profile_index].acrylicOpacity := Round(opacity / 100,2)
changed := True
}
if (changed) {
FileDelete, %wtProfile%
data := JSON.Dump(wtProfileJSON,,4)
FileAppend, %data%, %wtProfile%
ShowAndPositionTerminal()
wtProfileJSON := getProfile(wtProfile)
profile_index := getDefaultProfile(wtProfileJSON)
}
}
; ############ LOGIC FOR OPENING THE FONT DIALOG BOX AND UPDATING THE SETTINGS MENU WITH WHAT WAS CHOSEN ############
ChooseFont:
global fontName
global fontStyle
global fontSize
SetFont(fontName,fontStyle)
if (fontStyle["size"] == 0) {
fontStyle["size"] := fontSize
} else {
fontSize := fontStyle.size
}
GuiControl, Text, FontDetails, % fontName
GuiControl, Text, FontSize, % fontSize
return
SetFont(ByRef Name,ByRef Style){
VarSetCapacity(logfont,60,0)
LogPixels:=DllCall("GetDeviceCaps","uint",DllCall("GetDC","uint",0),"uint",90)
style.size?NumPut(Floor(style.size*logpixels/72),logfont,0):NumPut(16,LOGFONT,0)
effects:=0x141
cap:=VarSetCapacity(choosefont,103,0)
for a,b in font:={16:"bold",20:"italic",21:"underline",22:"strikeout"}
if style[b]
NumPut(b="bold"?700:1,logfont,a)
StrPut(name,&logfont+28)
for index,value in [[cap,0,"Uint"],[&logfont,24,"Uptr"],[effects,36,"Uint"],[style.color,40,"Uint"]]
NumPut(value.1,choosefont,value.2,value.3)
r:=DllCall("comdlg32\ChooseFont","uint",&CHOOSEFONT,"cdecl")
; -128 - 127 with char...
temp := NumGet(CHOOSEFONT,32,"char")
mod := Mod(Abs(temp) , 128)
Color:=NumGet(CHOOSEFONT,5*A_PtrSize)
style:={size:NumGet(CHOOSEFONT,32,"Uchar")//10,name:name:=StrGet(&logfont+28),color:color,bold:bold}
for a,b in font
style[b]:=NumGet(LOGFONT,a,"UChar")?1:0
style.bold:=NumGet(LOGFONT,16)&0xffff>=700?1:0
return r
}
wtExit:
ExitApp
Return
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment