How to get the current Gui font w/o creating a control?

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

How to get the current Gui font w/o creating a control?

06 Oct 2013, 04:22

If you want to create owner-drawn controls, you have to process the WM_MEASUREITEM message and set the item height.
MSDN wrote:The system sends the WM_MEASUREITEM message to the owner window of combo boxes and list boxes created with the OWNERDRAWFIXED style before sending the WM_INITDIALOG message. As a result, when the owner receives this message, the system has not yet determined the height and width of the font used in the control; function calls and calculations requiring these values should occur in the main function of the application or library.
Does anybody know a way to get the current Gui control font without creating a control, as this might interfere with relative control positioning? (I've been asking this in 2009 already, but without success).
User avatar
SKAN
Posts: 1551
Joined: 29 Sep 2013, 16:58

Re: How to get the current Gui font w/o creating a control?

06 Oct 2013, 04:54

Code: Select all

#NoEnv  
#SingleInstance, Force

GuiDefaultFont() {        ; By SKAN www.autohotkey.com/forum/viewtopic.php?p=465438#465438
 hFont := DllCall( "GetStockObject", UInt,17 ) ; DEFAULT_GUI_FONT
 VarSetCapacity( LF, szLF := 60 * ( A_IsUnicode ? 2 : 1 ) )
 DllCall( "GetObject", UInt,hFont, Int,szLF, UInt,&LF )
 hDC := DllCall( "GetDC", UInt,hwnd ),
 DPI := DllCall( "GetDeviceCaps", UInt,hDC, Int,90 )
 DllCall( "ReleaseDC", Int,0, UInt,hDC ), 
 S := Round( ( -NumGet( LF,0,"Int" )*72 ) / DPI )
Return DllCall( "MulDiv",Int,&LF+28, Int,1,Int,1, Str )
     , DllCall( "SetLastError", UInt,S )
}

A_GuiFont     := GuiDefaultFont()
A_GuiFontSize := A_LastError

MsgBox, %A_GuiFont%`t%A_GuiFontSize%
:)
My Scripts and Functions: V1  V2
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: How to get the current Gui font w/o creating a control?

06 Oct 2013, 06:00

THX SKAN, but it seems I have to be more clear:

I want to retrieve the current Gui control font as set with Gui, Font, ..., ....

BTW: Would someone please increase the font size of inline code?
User avatar
SKAN
Posts: 1551
Joined: 29 Sep 2013, 16:58

Re: How to get the current Gui font w/o creating a control?

06 Oct 2013, 10:31

just me wrote:retrieve the current Gui control font as set with Gui, Font, ..., ....
That is not easy, I guess. Here is an idea:

Fetch a list of all controls in GUI and reverse it so that latest created control is on top.
Find the font used for each control and if none is found use default Gui font.

Code: Select all

#NoEnv  
SetWorkingDir %A_ScriptDir%  
#SingleInstance, Force
#Persistent

Gui, Font, S10, Arial
Gui, Add, Text,, Line1
Gui, Font, S9, Tahoma
Gui, Add, Text,, Line2
Gui, Font, S8, Courier New
Gui, Add, Text,, Line3
Gui, Font, S7, Times New Roman
Gui, Add, Picture, wp hp, C:\NonExistentFile
Gui, Font, S6, NonExistentFont
Gui, Add, Text,, Line4

Gui, Show, w100 

Gui +LastFound
hWnd := WinExist()

WinGet, CHL, ControlListHwnd, ahk_id %hWnd% ; List of all Controls in GUI
Loop, Parse, CHL, `n                        ; Reverse the order of Controls so that
 CH := A_LoopField "`n" CH                  ; the lastest created control is on top    
StringTrimRight, CH, CH, 1


Loop, Parse, CH, `n
 {
  hFont := DllCall( "SendMessage", UInt,A_LoopField, UInt,0x31, UInt,0, UInt,0, UInt )
  If ( hFont )
     MsgBox % GetFontname( hFont ) "`t" A_LastError
 }
Return


GetFontname( hFont ) {
 VarSetCapacity( LF, szLF := 60*( A_IsUnicode ? 2:1 ) )
 DllCall( "GetObject", UInt,hFont, Int,szLF, UInt,&LF )
 hDC := DllCall( "GetDC", UInt,hwnd ), 
 DPI := DllCall( "GetDeviceCaps", UInt,hDC, Int,90 )
 DllCall( "ReleaseDC", Int,0, UInt,hDC ), 
 S := Round( ( -NumGet( LF,0,"Int" )*72 ) / DPI )
Return DllCall( "MulDiv",Int,&LF+28, Int,1,Int,1, Str )
     , DllCall( "SetLastError", UInt,S )
}
User avatar
SKAN
Posts: 1551
Joined: 29 Sep 2013, 16:58

Re: How to get the current Gui font w/o creating a control?

06 Oct 2013, 10:44

Ahh! This method would not work if Gui,Font was called but no control was created! :(
User avatar
jballi
Posts: 723
Joined: 29 Sep 2013, 17:34

Re: How to get the current Gui font w/o creating a control?

14 Oct 2013, 09:11

just me wrote:I want to retrieve the current Gui control font as set with Gui, Font, ..., ....
This information is not available. As SKAN showed, the font information can be derived if a control was created after the font was set and you know which control it was. Otherwise, there is no way to know.

This sounds like something to add to the Wish List forum. I'm thinking a request for a A_LastFont system variable that would return 0 if no fonts have been created, otherwise the handle to the last logical font that was created or referred to via the gui Font command would be returned.
HotKeyIt
Posts: 2364
Joined: 29 Sep 2013, 18:35
Contact:

Re: How to get the current Gui font w/o creating a control?

14 Oct 2013, 09:47

just me wrote:BTW: Would someone please increase the font size of inline code?
How about that?
DRocks
Posts: 565
Joined: 08 May 2018, 10:20

Re: How to get the current Gui font w/o creating a control?

13 Jan 2020, 23:19

BUMP,

@just me
Did any one find how to solve OP question?
(How to get a GuiControl current font)

Reason: make it easy to toggle from one font to another for each controls in a Gui.
Example :

Code: Select all

;--------------------------------------------------------------------------------
toggle_row_highlight(boolean) {
;--------------------------------------------------------------------------------
	Global hGuiMain, column_names
	
	row := get_row_under_mouse()
	
	;prev_font := ???
	Gui, font, % (boolean ? " Bold":prev_font)
	For column, variable_name in column_names {
		GuiControl, %hGuiMain%:Font, % variable_name . row
	}
}
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: How to get the current Gui font w/o creating a control?

14 Jan 2020, 01:25

Like this?

Code: Select all

Gui, New, +hwndhGui

Gui, Font,, Verdana
MsgBox, % GetFont(hGui)

Gui, Font,, Calibri
MsgBox, % GetFont(hGui)
ExitApp

GetFont(hWnd) {
   static WM_GETFONT := 0x31
   hFont := DllCall("SendMessage", "Ptr", hWnd, "UInt", WM_GETFONT, "Ptr", 0, "Ptr", 0, "Ptr")
   if !hFont {
      Gui, %hWnd%: Add, Text, xp yp wp hp Hidden hwndhText
      hFont := DllCall("SendMessage", "Ptr", hText, "UInt", WM_GETFONT, "Ptr", 0, "Ptr", 0, "Ptr")
   }
   size := DllCall("GetObject", "Ptr", hFont, "Int", 0, "Ptr", 0)
   VarSetCapacity(LOGFONT, size, 0)
   DllCall("GetObject", "Ptr", hFont, "Int", size, "Ptr", &LOGFONT)
   fontName := StrGet(&LOGFONT + 28)
   ( hText && DllCall("DestroyWindow", "Ptr", hText) )
   Return fontName
}
guest3456
Posts: 3454
Joined: 09 Oct 2013, 10:31

Re: How to get the current Gui font w/o creating a control?

14 Jan 2020, 01:36

teadrinker wrote:
14 Jan 2020, 01:25
Like this?
can you DestroyWindow inside the same if-block after doing WM_GETFONT? or does that destroy the font object too?

teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: How to get the current Gui font w/o creating a control?

14 Jan 2020, 01:42

You are right, it could be done like this:

Code: Select all

GetFont(hWnd) {
   static WM_GETFONT := 0x31
   hFont := DllCall("SendMessage", "Ptr", hWnd, "UInt", WM_GETFONT, "Ptr", 0, "Ptr", 0, "Ptr")
   if !hFont {
      Gui, %hWnd%: Add, Text, xp yp wp hp Hidden hwndhText
      hFont := DllCall("SendMessage", "Ptr", hText, "UInt", WM_GETFONT, "Ptr", 0, "Ptr", 0, "Ptr")
      DllCall("DestroyWindow", "Ptr", hText)
   }
   size := DllCall("GetObject", "Ptr", hFont, "Int", 0, "Ptr", 0)
   VarSetCapacity(LOGFONT, size, 0)
   DllCall("GetObject", "Ptr", hFont, "Int", size, "Ptr", &LOGFONT)
   Return StrGet(&LOGFONT + 28)
}
DRocks
Posts: 565
Joined: 08 May 2018, 10:20

Re: How to get the current Gui font w/o creating a control?

14 Jan 2020, 17:29

@teadrinker thanks,
Would this be meant to work with the hwnd of a GuiControl or is it restricted for a top level window?
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: How to get the current Gui font w/o creating a control?

14 Jan 2020, 17:50

Should work for controls too:

Code: Select all

Gui, Font, s24, Comic Sans MS
Gui, Add, Edit, hwndhEdit, Hello
MsgBox, % GetFont(hEdit)
Gui, Show

GetFont(hWnd) {
   static WM_GETFONT := 0x31
   hFont := DllCall("SendMessage", "Ptr", hWnd, "UInt", WM_GETFONT, "Ptr", 0, "Ptr", 0, "Ptr")
   if !hFont {
      Gui, %hWnd%: Add, Text, xp yp wp hp Hidden hwndhText
      hFont := DllCall("SendMessage", "Ptr", hText, "UInt", WM_GETFONT, "Ptr", 0, "Ptr", 0, "Ptr")
      DllCall("DestroyWindow", "Ptr", hText)
   }
   size := DllCall("GetObject", "Ptr", hFont, "Int", 0, "Ptr", 0)
   VarSetCapacity(LOGFONT, size, 0)
   DllCall("GetObject", "Ptr", hFont, "Int", size, "Ptr", &LOGFONT)
   Return StrGet(&LOGFONT + 28)
}
DRocks
Posts: 565
Joined: 08 May 2018, 10:20

Re: How to get the current Gui font w/o creating a control?

14 Jan 2020, 19:14

teadrinker wrote:
14 Jan 2020, 17:50
Should work for controls too:
Hey, thanks! I've tested it and read the content of the function.
It does work for what the function is called "GetFont()"
But I'm afraid I am refering to a more complex "kind of font".
I mean like everything that this GuiControl has relating to its display properties like size, quality, weight, font, etc.
The thing is that it gets messy real quick if you can't store automatically what the GuiControl's display / font properties are.

For now I am trying to store properties manually like so:

Code: Select all

static normal_header_font := "s12 q5 w400"
	, bold_header_font := "s12 q5 w700"
Then I try to toggle from the special font to the original one
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: How to get the current Gui font w/o creating a control?

14 Jan 2020, 20:28

No problem. :)

Code: Select all

Gui, New, +hwndhGui
Gui, Font, s12 italic bold q4, Comic Sans MS

res := GetFont(hGui), sResult := ""
for k, v in res
   sResult .= (A_Index = 1 ? "" : "`n") . k . ": " . v
Gui, Add, Text,, % sResult

Gui, Font, s14 norm underline q5, Calibri

Gui, Add, Edit, hwndhEdit xp y+10 wp hp r7
res := GetFont(hEdit), sResult := ""
for k, v in res
   sResult .= (A_Index = 1 ? "" : "`n") . k . ": " . v
GuiControl,, Edit1, % sResult

GuiControl, Focus, Static1
Gui, Show
Return

GuiClose:
   ExitApp

GetFont(hWnd) {
   static WM_GETFONT := 0x31
                              
   hFont := DllCall("SendMessage", "Ptr", hWnd, "UInt", WM_GETFONT, "Ptr", 0, "Ptr", 0, "Ptr")
   if !hFont {
      Gui, %hWnd%: Add, Text, xp yp wp hp Hidden hwndhText
      hFont := DllCall("SendMessage", "Ptr", hText, "UInt", WM_GETFONT, "Ptr", 0, "Ptr", 0, "Ptr")
      DllCall("DestroyWindow", "Ptr", hText)
   }
   sizeLF := DllCall("GetObject", "Ptr", hFont, "Int", 0, "Ptr", 0)
   VarSetCapacity(LOGFONT, sizeLF, 0)
   DllCall("GetObject", "Ptr", hFont, "Int", sizeLF, "Ptr", &LOGFONT)
   
   Size      :=-NumGet(LOGFONT, "Int")*72//A_ScreenDPI
   Weight    := NumGet(LOGFONT, 16, "Int")
   Italic    := NumGet(LOGFONT, 20, "Char")
   Underline := NumGet(LOGFONT, 21, "Char")
   Strike    := NumGet(LOGFONT, 22, "Char")
   Quality   := NumGet(LOGFONT, 26, "Char")
   FaceName  := StrGet(&LOGFONT + 28)
   
   res := {}
   for k, v in ["Size", "Weight", "Italic", "Underline", "Strike", "Quality", "FaceName"]
      res[v] := %v%
   Return res
}

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: OrangeCat and 163 guests