AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

How to call the standard Choose-Font-dialog?

 
Reply to topic    AutoHotkey Community Forum Index -> Ask for Help
View previous topic :: View next topic  
Author Message
Tekl



Joined: 24 Sep 2004
Posts: 814
Location: Germany

PostPosted: Mon Aug 22, 2005 11:11 pm    Post subject: How to call the standard Choose-Font-dialog? Reply with quote

Hi,

does anyone know, how I can get the common choosefont-dialog into a ahk-script? I tried it with

Code:
DllCall("COMDLG32.DLL\ChooseFontA")


but that does not work, because there are some parameteres needed. I don't know how to translate the docs to a dllcall.

Or is there another way to let a user choose the font inside the gui? I just need fontface, style and size. Is the registry (HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts) a reliable source for the installed fonts?

Tekl
Back to top
View user's profile Send private message Visit poster's website
Chris
Site Admin


Joined: 02 Mar 2004
Posts: 10716

PostPosted: Tue Aug 23, 2005 4:03 am    Post subject: Reply with quote

I'm glad you asked because I've been meaning to try this but have been procrastinating. Below is a script that seems to work but probably needs some refinement. It displays the following dialog:


Code:
Gui, Add, Button, Default gButtonSelectFont, Press this to show font-picker dialog
Gui, Add, Text, w60 right, Font face:
Gui, Add, Edit, x+10 ReadOnly vFontFace
Gui, Add, Text, w60 right xm, Font size:
Gui, Add, Edit, x+10 ReadOnly vFontSize
Gui, Add, Text, w60 right xm, RGB Color:
Gui, Add, Edit, x+10 ReadOnly vColor

; Most of the setup for the font picker dialog needs to be done only once,
; which is why this section is here rather than in the button's subroutine.
SizeOfStructForChooseFont = 60
OffsetToFontFaceName = 28
SizeOfFontFaceName = 32
SizeOfStructForLogFont := OffsetToFontFaceName + SizeOfFontFaceName
VarSetCapacity(StructForChooseFont, SizeOfStructForChooseFont, 0)
VarSetCapacity(StructForLogFont, SizeOfStructForLogFont)  ; No need to zero it.
InsertInteger(SizeOfStructForChooseFont, StructForChooseFont, 0)  ; DWORD lStructSize
Gui, +LastFound
GuiHWND := WinExist()  ; Relies on the line above to get the unique ID of GUI window.
InsertInteger(GuiHWND, StructForChooseFont, 4)  ; HWND hwndOwner (makes dialog "modal").
InsertInteger(&StructForLogFont, StructForChooseFont, 12)  ; LPLOGFONT lpLogFont
InsertInteger(0x101, StructForChooseFont, 20)
; Above is DWORD Flags: CF_EFFECTS = 0x100, CF_SCREENFONTS = 1 (omit printer fonts)

Gui, Show
return

ButtonSelectFont:
if not DllCall("comdlg32\ChooseFontA", str, StructForChooseFont)  ; Display the dialog.
   return  ; The user canceled the dialog.
; Otherwise, the user pressed OK in the dialog, so determine what was selected.
VarSetCapacity(FontFace, SizeOfFontFaceName)
DllCall("RtlMoveMemory", str, FontFace, Uint, &StructForLogFont + OffsetToFontFaceName, Uint, SizeOfFontFaceName)
GuiControl,, FontFace, %FontFace%
GuiControl,, FontSize, % ExtractInteger(StructForChooseFont, 16) // 10
SetFormat, integer, hex  ; Show RGB color extracted below in hex format.
GuiControl,, Color, % BGRtoRGB(ExtractInteger(StructForChooseFont, 24))
SetFormat, integer, d
return

GuiClose:
ExitApp

ExtractInteger(ByRef pSource, pOffset = 0, pIsSigned = false, pSize = 4)
; See DllCall documentation for details.
{
   SourceAddress := &pSource + pOffset  ; Get address and apply the caller's offset.
   result := 0  ; Init prior to accumulation in the loop.
   Loop %pSize%  ; For each byte in the integer:
   {
      result := result | (*SourceAddress << 8 * (A_Index - 1))  ; Build the integer from its bytes.
      SourceAddress += 1  ; Move on to the next byte.
   }
   if (!pIsSigned OR pSize > 4 OR result < 0x80000000)
      return result  ; Signed vs. unsigned doesn't matter in these cases.
   ; Otherwise, convert the value (now known to be 32-bit) to its signed counterpart:
   return -(0xFFFFFFFF - result + 1)
}

InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
; To preserve any existing contents in pDest, only pSize number of bytes starting at
; pOffset are altered in it. The caller must ensure that pDest has sufficient capacity.
{
   mask := 0xFF  ; This serves to isolate each byte, one by one.
   Loop %pSize%  ; Copy each byte in the integer into the structure as raw binary data.
   {
      DllCall("RtlFillMemory", UInt, &pDest + pOffset + A_Index - 1, UInt, 1  ; Write one byte.
         , UChar, (pInteger & mask) >> 8 * (A_Index - 1))  ; This line is auto-merged with above at load-time.
      mask := mask << 8  ; Set it up for isolation of the next byte.
   }
}

BGRtoRGB(pColorBGR)
; This can also convert in the opposite direction, just give it an RGB color instead.
{
   return (pColorBGR & 0xFF) << 16 | ((pColorBGR >> 8) & 0xFF) | (pColorBGR >> 16)
}


I think the following color picker dialog could be displayed using a technique similar to above, but I haven't tried it yet:

Back to top
View user's profile Send private message Send e-mail
Tekl



Joined: 24 Sep 2004
Posts: 814
Location: Germany

PostPosted: Tue Aug 23, 2005 9:09 am    Post subject: Reply with quote

Hi Chris,

thanks, that's a good base. In the meantime I tried it with the registry-entries like this:

Code:

   Loop, HKEY_LOCAL_MACHINE, SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts, 0 ,0
   {
      StringGetPos, tempPos, A_LoopRegname, (
      If tempPos > 2
         StringLeft, LoopRegname, A_LoopRegname, % tempPos-1
      Else
         LoopRegname = %LoopRegname%
      AllFonts = %LoopRegname%|%AllFonts%
   }
...
; The GUI-Part
   Gui, Add, Text, xs+10 y+30, %lng_Font%
   Gui, Add, ComboBox, x+5 yp-3 w300 vFont gsub_ChangeFont, %AllFonts%
   Gui, Add, Text, x+10 yp+3, %lng_FontSize%
   Gui, Add, ComboBox, x+5 yp-3 w50 vFontSize gsub_ChangeFont, 8|9|10|11|12|14|16|18|20|24|36|48
   GuiControl,ChooseString, Font, %Font%
   GuiControl,ChooseString, FontSize, %FontSize%
...
;The result is used like this
   Gui, Font,s%FontSize%,%Font%

Interesting, that Names like "Arial Bold" also work directly and not only via Gui, Font, bold, Arial

For me, this way has some advantages. 1st It's less complicated, 2nd Less code and 3rd With the g-Label it's possible to change the font immediatly

Tekl
Back to top
View user's profile Send private message Visit poster's website
Chris
Site Admin


Joined: 02 Mar 2004
Posts: 10716

PostPosted: Tue Aug 23, 2005 10:59 am    Post subject: Reply with quote

Thanks for posting your registry approach. Anyone wishing a GUI way to select a font will now have two scripts from which to choose.
Back to top
View user's profile Send private message Send e-mail
toralf



Joined: 31 Jan 2005
Posts: 3910
Location: Bremen, Germany

PostPosted: Tue Nov 28, 2006 8:32 pm    Post subject: Reply with quote

Do other options besides CF_EFFECTS or CF_SCREENFONTS exist for the dialog?
_________________
Ciao
toralf
Back to top
View user's profile Send private message Send e-mail Visit poster's website
PhiLho



Joined: 27 Dec 2005
Posts: 6836
Location: France (near Paris)

PostPosted: Wed Nov 29, 2006 11:50 am    Post subject: Reply with quote

http://msdn2.microsoft.com/en-us/library/ms646914.aspx
http://msdn2.microsoft.com/en-us/library/ms646832.aspx
_________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")
Back to top
View user's profile Send private message Visit poster's website
majkinetor



Joined: 24 May 2006
Posts: 4511
Location: Belgrade

PostPosted: Wed Nov 29, 2006 12:03 pm    Post subject: Reply with quote

This should be function.

The one for the standard library.
_________________
Back to top
View user's profile Send private message
Joy2DWorld



Joined: 04 Dec 2006
Posts: 561
Location: Galil, Israel

PostPosted: Sat Apr 21, 2007 6:33 pm    Post subject: Reply with quote

Seemed to be missing return of the font type: Bold, Italics, etc..


this basically works:

Code:
FType :=  ExtractInteger(StructForChooseFont, 49,0,2) & 0x07 FontType := (Ftype = 4) ? "Norm" : (Ftype = 3) ? "bold italic" : (Ftype = 2) ? "italic" : (Ftype = 1) ? "bold" : ""




and (hopefully maybe when more time allows, will come back and update), here is the very cool Select Font as a function if might be helpful for 'beginners' to clip and use:

Code:
fontselect(Font, Options)
msgbox Font: %font%`n%Options%
exitapp

FontSelect( byref Font,byref Options, x = "", y = ""){
if (!x) and (!y)
    NOGUI
   
SizeOfStructForChooseFont = 60
OffsetToFontFaceName = 28
SizeOfFontFaceName = 32
SizeOfStructForLogFont := OffsetToFontFaceName + SizeOfFontFaceName
VarSetCapacity(StructForChooseFont, SizeOfStructForChooseFont, 0)
VarSetCapacity(StructForLogFont, SizeOfStructForLogFont)  ; No need to zero it.
InsertInteger(SizeOfStructForChooseFont, StructForChooseFont, 0)  ; DWORD lStructSize
if !NOGUI
       gui show, x%x%  y%y%
Gui, +LastFound
GuiHWND := WinExist()  ; Relies on the line above to get the unique ID of GUI window.
InsertInteger(GuiHWND, StructForChooseFont, 4)  ; HWND hwndOwner (makes dialog "modal").
InsertInteger(&StructForLogFont, StructForChooseFont, 12)  ; LPLOGFONT lpLogFont
InsertInteger(0x101, StructForChooseFont, 20)
; Above is DWORD Flags: CF_EFFECTS = 0x100, CF_SCREENFONTS = 1 (omit printer fonts)


;ButtonSelectFont:

if not DllCall("comdlg32\ChooseFontA", str, StructForChooseFont) {  ; Display the dialog.
                if !NOGUI
               gui, destroy
   return  ; The user canceled the dialog.
} ; Otherwise, the user pressed OK in the dialog, so determine what was selected.
if !NOGUI
            gui, destroy
VarSetCapacity(FontFace, SizeOfFontFaceName)
DllCall("RtlMoveMemory", str, FontFace, Uint, &StructForLogFont + OffsetToFontFaceName, Uint, SizeOfFontFaceName)
; FontFace .
fontsize :=  ExtractInteger(StructForChooseFont, 16) // 10

SetFormat, integer, hex
Fontcolor :=   BGRtoRGB(ExtractInteger(StructForChooseFont, 24))SetFormat, integer, D

FType :=  ExtractInteger(StructForChooseFont, 49,0,2) & 0x07 ; ExtractInteger(StructForChooseFont, 48,0,2) > 8 & 0x0f
FontType := (Ftype = 4) ? "Norm" : (Ftype = 3) ? "bold italic" : (Ftype = 2) ? "italic" : (Ftype = 1) ? "bold" : ""



Font := FontFace
if fontsize
   Options .= "S" . fontsize
if FontColor {
   SetFormat, integer, hex  ; Show RGB color extracted below in hex format.
   Options .= " C" . FontColor
   SetFormat, integer, d
}
if FontType
   Options .= " " . FontType

return

}

ExtractInteger(ByRef pSource, pOffset = 0, pIsSigned = false, pSize = 4)
; See DllCall documentation for details.
{
   SourceAddress := &pSource + pOffset  ; Get address and apply the caller's offset.
   result := 0  ; Init prior to accumulation in the loop.
   Loop %pSize%  ; For each byte in the integer:
   {
      result := result | (*SourceAddress << 8 * (A_Index - 1))  ; Build the integer from its bytes.
      SourceAddress += 1  ; Move on to the next byte.
   }
   if (!pIsSigned OR pSize > 4 OR result < 0x80000000)
      return result  ; Signed vs. unsigned doesn't matter in these cases.
   ; Otherwise, convert the value (now known to be 32-bit) to its signed counterpart:
   return -(0xFFFFFFFF - result + 1)
}

InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
; To preserve any existing contents in pDest, only pSize number of bytes starting at
; pOffset are altered in it. The caller must ensure that pDest has sufficient capacity.
{
   mask := 0xFF  ; This serves to isolate each byte, one by one.
   Loop %pSize%  ; Copy each byte in the integer into the structure as raw binary data.
   {
      DllCall("RtlFillMemory", UInt, &pDest + pOffset + A_Index - 1, UInt, 1  ; Write one byte.
         , UChar, (pInteger & mask) >> 8 * (A_Index - 1))  ; This line is auto-merged with above at load-time.
      mask := mask << 8  ; Set it up for isolation of the next byte.
   }
}

BGRtoRGB(oldValue)
{
  Value := (oldValue & 0x00ff00)
  Value += ((oldValue & 0xff0000) >> 16)
  Value += ((oldValue & 0x0000ff) << 16) 
  return Value
}





ok, first update.. and this is a working but still slightly incomplete function , simply have not been ably yet to come back back to polish off... It does (mostly) work... ,


Code:

FontSelect( byref Font,byref Options, byref StructForChooseFont , x = "300", y = "100") {



SizeOfStructForChooseFont = 60
OffsetToFontFaceName = 28
SizeOfFontFaceName = 32
SizeOfStructForLogFont := OffsetToFontFaceName + SizeOfFontFaceName
VarSetCapacity(StructForLogFont, SizeOfStructForLogFont)  ; No need to zero it.
if !StructForChooseFont {
   VarSetCapacity(StructForChooseFont, SizeOfStructForChooseFont, 0)
   InsertInteger(&StructForLogFont, StructForChooseFont, 12)  ; LPLOGFONT lpLogFont
   InsertInteger(SizeOfStructForChooseFont, StructForChooseFont, 0)  ; DWORD lStructSize
   InsertInteger(0x101, StructForChooseFont, 20)
; Above is DWORD Flags: CF_EFFECTS = 0x100, CF_SCREENFONTS = 1 (omit printer fonts)
}
; gui show, x%x%  y%y%
Gui, +LastFound
GuiHWND := WinExist()  ; Relies on the line above to get the unique ID of GUI window.
InsertInteger(GuiHWND, StructForChooseFont, 4)  ; HWND hwndOwner (makes dialog "modal").

;ButtonSelectFont:

if not DllCall("comdlg32\ChooseFontA", str, StructForChooseFont) {  ; Display the dialog.
;   gui, destroy
   return  ; The user canceled the dialog.
} ; Otherwise, the user pressed OK in the dialog, so determine what was selected.
;gui, destroy
VarSetCapacity(FontFace, SizeOfFontFaceName)
DllCall("RtlMoveMemory", str, FontFace, Uint, &StructForLogFont + OffsetToFontFaceName, Uint, SizeOfFontFaceName)
; FontFace .
regexmatch(Options,"( S\d++)",hasSize)
regexmatch(Options,"( C\s*0\s*[xX]\s*[0-9ABCDEFabcdef]++)",hasColor)
regexmatch(Options,"i)(Norm|bold italic|italic|bold)",hasType)
Options =

;;tooltip % ExtractInteger(StructForChooseFont, 16)  "`n" ExtractInteger(StructForChooseFont, 16) / 10
fontsize :=  ExtractInteger(StructForChooseFont, 16) // 10
SetFormat, integer, hex  ; Show RGB color extracted below in hex format.
Fontcolor :=   BGRtoRGB(ExtractInteger(StructForChooseFont, 24))
SetFormat, integer, d
;SetFormat, integer, hex
;tooltip % ExtractInteger(StructForChooseFont, 48,0,4) "`n" ExtractInteger(StructForChooseFont, 49,0,2) & 0x07 "`n" ExtractInteger(StructForChooseFont, 50,0,4) "`n"

FType :=  ExtractInteger(StructForChooseFont, 49,0,2) & 0x07 ; ExtractInteger(StructForChooseFont, 48,0,2) > 8 & 0x0f
FontType := (Ftype = 4) ? "Norm" : (Ftype = 3) ? "bold italic" : (Ftype = 2) ? "italic" : (Ftype = 1) ? "bold" : ""

;tooltip % Ftype "  " FontType

Font := FontFace
Options .= (fontsize) ? " S" . fontsize  : hasSize
if (FontColor != "") {
   SetFormat, integer, hex  ; Show RGB color extracted below in hex format.
   Options .= " C" . FontColor
   SetFormat, integer, d
} else
   Options .= hasColor
   
 
Options .= (FontType) ? " " . FontType : " " . hasType

return

}

_________________
Joyce Jamce
Back to top
View user's profile Send private message
daorc



Joined: 18 Oct 2006
Posts: 169

PostPosted: Wed Apr 13, 2011 2:33 pm    Post subject: Reply with quote

Tekl, I think your line 7 should be:

Code:
         LoopRegname = %A_LoopRegname%

Really useful - thanks!
Back to top
View user's profile Send private message
daorc



Joined: 18 Oct 2006
Posts: 169

PostPosted: Wed Apr 13, 2011 2:54 pm    Post subject: Reply with quote

p.s. I also added:
Code:
sort,allfonts,D| ;sort list alphabetically
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    AutoHotkey Community Forum Index -> Ask for Help All times are GMT
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group