Jump to content

Recommended Posts

Posted

I'm trying to create a dark mode ChooseFont dialog. The initial hook proc with fnHook / CF_ENABLEHOOK has been successful. However, attempting to load ChooseFont dialog with a custom Font.DLG file has not been successful at all.

I have tried a few variations with $CF_ENABLETEMPLATE which failed and a few variations with $CF_ENABLETEMPLATEHANDLE that also failed.

If anyone is able to help with this, that would be fantastic. I searched back in the forum and could not find any usage of lpTemplateName with the ChooseFont dialog.

In the _ChooseFontHooked() function, I left a comment "Hook and template testing" on line 66 which is the start of the area testing hook and template stuff.

Thank you for your time. :)

Font.DLG

DARKFONTDLG DIALOG 13, 54, 243, 234
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU |
      DS_3DLOOK
CAPTION "Font"
FONT 9, "Segoe UI"
BEGIN
    LTEXT           "&Font:", stc1, 7, 7, 98, 9
    COMBOBOX        cmb1, 7, 16, 98, 76,
                    CBS_SIMPLE | CBS_AUTOHSCROLL | CBS_DISABLENOSCROLL |
                    CBS_SORT | WS_VSCROLL | WS_TABSTOP | CBS_HASSTRINGS |
                    CBS_OWNERDRAWFIXED

    LTEXT           "Font st&yle:", stc2, 114, 7, 74, 9
    COMBOBOX        cmb2, 114, 16, 74, 76,
                    CBS_SIMPLE | CBS_AUTOHSCROLL | CBS_DISABLENOSCROLL |
                    WS_VSCROLL | WS_TABSTOP | CBS_HASSTRINGS |
                    CBS_OWNERDRAWFIXED

    LTEXT           "&Size:", stc3, 198, 7, 36, 9
    COMBOBOX        cmb3, 198, 16, 36, 76,
                    CBS_SIMPLE | CBS_AUTOHSCROLL | CBS_DISABLENOSCROLL |
                    CBS_SORT | WS_VSCROLL | WS_TABSTOP | CBS_HASSTRINGS

    GROUPBOX        "Effects", grp1, 7, 97, 98, 76, WS_GROUP
    AUTOCHECKBOX    "Stri&keout", chx1, 13, 111, 90, 10, WS_TABSTOP
    AUTOCHECKBOX    "&Underline", chx2, 13, 127, 90, 10

    LTEXT           "&Color:", stc4, 13, 144, 89, 9
    COMBOBOX        cmb4, 13, 155, 85, 100,
                    CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL |
                    CBS_HASSTRINGS | WS_BORDER | WS_VSCROLL | WS_TABSTOP

    GROUPBOX        "Sample", grp2, 114, 97, 120, 43, WS_GROUP
    CTEXT           "AaBbYyZz", stc5, 116, 106, 117, 33,
                    SS_NOPREFIX | NOT WS_VISIBLE
    LTEXT           "", stc6, 7, 178, 227, 20, SS_NOPREFIX | NOT WS_GROUP

    LTEXT           "Sc&ript:", stc7, 114, 145, 118, 9
    COMBOBOX        cmb5, 114, 155, 120, 30, CBS_DROPDOWNLIST |
                    CBS_AUTOHSCROLL | CBS_HASSTRINGS |
                    WS_BORDER | WS_VSCROLL | WS_TABSTOP

    CONTROL         "<A>Show more fonts</A>", IDC_MANAGE_LINK, "SysLink",
                    WS_TABSTOP, 7, 199, 227, 9

    DEFPUSHBUTTON   "OK", IDOK, 141, 215, 45, 14, WS_GROUP
    PUSHBUTTON      "Cancel", IDCANCEL, 190, 215, 45, 14, WS_GROUP
    PUSHBUTTON      "&Apply", psh3, 92, 215, 45, 14, WS_GROUP
    PUSHBUTTON      "&Help", pshHelp, 43, 215, 45, 14, WS_GROUP
END

 

Testing script:

#include <WinAPIProc.au3>
#include <FontConstants.au3>
#include <StructureConstants.au3>
#include <GUIConstantsEx.au3>
#include <APIGdiConstants.au3>
#include <SendMessage.au3>
#include <WinAPISysWin.au3>
#include <WinAPITheme.au3>
#include <WindowsStylesConstants.au3>
#include <WinAPIGdiInternals.au3>
#include <WinAPIGdiDC.au3>
#include <AutoItConstants.au3>
#include <WindowsNotifsConstants.au3>
#include <WinAPIGdi.au3>
#include <Misc.au3>

; Initialize System DPI awareness
DllCall("user32.dll", "bool", "SetProcessDpiAwarenessContext", @AutoItX64 ? "int64" : "int", -2)

Global Const $CF_ENABLEHOOK = 8
Global Const $CF_ENABLETEMPLATE = 16
Global Const $CF_ENABLETEMPLATEHANDLE = 32

Global Const $sTemplate = @ScriptDir & "\font.dlg"
Global Const $sTemplateName = "DARKFONTDLG"
Global $hTemplate = FileOpen($sTemplate)

Global $g_hDialogProc = 0

_ChooseFontHooked()

FileClose($hTemplate)

Func _ChooseFontHooked($sFontName = "Courier New", $iPointSize = 10, $iFontColorRef = Default, $iFontWeight = 0, $bItalic = False, $bUnderline = False, $bStrikethru = False, $hWndOwner = 0)
    Local $iItalic = 0, $iUnderline = 0, $iStrikeout = 0, $iRetExtended = 0
    If $sFontName = Default Then $sFontName = "Courier New"
    If $iPointSize = Default Then $iPointSize = 10
    If $iFontColorRef = Default Then
        $iFontColorRef = 0
        Local $aRet = DllCall("user32.dll", "int", "GetSysColor", "int", 18) ; $COLOR_BTNTEXT
        If @error Then
            $iRetExtended = @error
        Else
            $iFontColorRef = $aRet[0]
        EndIf
    EndIf
    If $iFontWeight = Default Then $iFontWeight = 0
    If $bItalic = Default Then $bItalic = False
    If $bUnderline = Default Then $bUnderline = False
    If $bStrikethru = Default Then $bStrikethru = False
    If $hWndOwner = Default Then $hWndOwner = 0
    $iFontColorRef = BitOR(BitShift(BitAND($iFontColorRef, 0x000000FF), -16), BitAND($iFontColorRef, 0x0000FF00), BitShift(BitAND($iFontColorRef, 0x00FF0000), 16))

    Local $hDC = __MISC_GetDC(0)
    Local $iHeight = Round(($iPointSize * __MISC_GetDeviceCaps($hDC, $LOGPIXELSX)) / 72, 0)
    __MISC_ReleaseDC(0, $hDC)

    Local $tChooseFont = DllStructCreate($tagCHOOSEFONT)
    Local $tLogFont = DllStructCreate($tagLOGFONT)

    DllStructSetData($tChooseFont, "Size", DllStructGetSize($tChooseFont))
    DllStructSetData($tChooseFont, "hWndOwner", $hWndOwner)
    DllStructSetData($tChooseFont, "LogFont", DllStructGetPtr($tLogFont))
    DllStructSetData($tChooseFont, "PointSize", $iPointSize)

    ; Hook and template testing
    $g_hDialogProc = DllCallbackRegister(_DialogProc, "int", "hwnd;uint;wparam;lparam")
    DllStructSetData($tChooseFont, 'fnHook', DllCallbackGetPtr($g_hDialogProc))
    ;DllStructSetData($tChooseFont, "Flags", BitOR($CF_SCREENFONTS, $CF_PRINTERFONTS, $CF_EFFECTS, $CF_INITTOLOGFONTSTRUCT, $CF_NOSCRIPTSEL, $CF_ENABLEHOOK)) ; <<< this works with hook but no custom template
    DllStructSetData($tChooseFont, "Flags", BitOR($CF_SCREENFONTS, $CF_PRINTERFONTS, $CF_EFFECTS, $CF_INITTOLOGFONTSTRUCT, $CF_NOSCRIPTSEL, $CF_ENABLEHOOK, $CF_ENABLETEMPLATE))
    ;DllStructSetData($tChooseFont, "Flags", BitOR($CF_SCREENFONTS, $CF_PRINTERFONTS, $CF_EFFECTS, $CF_INITTOLOGFONTSTRUCT, $CF_NOSCRIPTSEL, $CF_ENABLEHOOK, $CF_ENABLETEMPLATEHANDLE))
    ;DllStructSetData($tChooseFont, 'hInstance', $hTemplate)
    DllStructSetData($tChooseFont, 'hInstance', Null)
    Local $tagBuffer = "char[4096]", $iBufferSize = 4095
    ;If $fUnicode Then $tagBuffer = "w" & $tagBuffer
    Local $tTemplateName = DllStructCreate($tagBuffer);'char[256]')
    DllStructSetData($tTemplateName, 1, $sTemplateName)
    DllStructSetData($tChooseFont, 'lpTemplateName', DllStructGetPtr($tTemplateName))

    DllStructSetData($tChooseFont, "rgbColors", $iFontColorRef)
    DllStructSetData($tChooseFont, "FontType", 0)

    DllStructSetData($tLogFont, "Height", $iHeight)
    DllStructSetData($tLogFont, "Weight", $iFontWeight)
    DllStructSetData($tLogFont, "Italic", $bItalic)
    DllStructSetData($tLogFont, "Underline", $bUnderline)
    DllStructSetData($tLogFont, "Strikeout", $bStrikethru)
    DllStructSetData($tLogFont, "FaceName", $sFontName)

    Local $aCall = DllCall("comdlg32.dll", "bool", "ChooseFontW", "struct*", $tChooseFont)
    If @error Then Return SetError(@error, @extended, -2) ; ..to differentiate from the error below
    If $aCall[0] = 0 Then Return SetError(-3, $iRetExtended, -1) ; user selected cancel or struct settings incorrect

    Local $sFaceName = DllStructGetData($tLogFont, "FaceName")
    If StringLen($sFaceName) = 0 And StringLen($sFontName) > 0 Then $sFaceName = $sFontName

    If DllStructGetData($tLogFont, "Italic") Then $iItalic = 2
    If DllStructGetData($tLogFont, "Underline") Then $iUnderline = 4
    If DllStructGetData($tLogFont, "Strikeout") Then $iStrikeout = 8

    Local $iAttributes = BitOR($iItalic, $iUnderline, $iStrikeout)
    Local $iSize = DllStructGetData($tChooseFont, "PointSize") / 10
    Local $iColorRef = DllStructGetData($tChooseFont, "rgbColors")
    Local $iWeight = DllStructGetData($tLogFont, "Weight")

    Local $sColor_picked = Hex(String($iColorRef), 6)

    Return SetError(0, $iRetExtended, StringSplit($iAttributes & "," & $sFaceName & "," & $iSize & "," & $iWeight & "," & $iColorRef & "," & _
            '0x' & $sColor_picked & "," & '0x' & StringMid($sColor_picked, 5, 2) & StringMid($sColor_picked, 3, 2) & StringMid($sColor_picked, 1, 2), ","))
EndFunc   ;==>_ChooseFontHooked

Func _DialogProc($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam, $lParam
    Local Static $hBrush

    Switch $iMsg

        Case $WM_INITDIALOG
            _WinAPI_DwmSetWindowAttribute($hWnd, $DWMWA_USE_IMMERSIVE_DARK_MODE, True)
            $hBrush = _WinAPI_CreateSolidBrush(0x202020)

            Local $aCtrlsEx = _WinAPI_EnumProcessWindows(0, False) ; allows getting handles for tooltips_class32, ComboLBox, etc.
            If @error = 0 Then
                For $i = 1 To $aCtrlsEx[0][0]
                    ;If $aCtrlsEx[$i][1] = 'tooltips_class32' Then _GUIDarkTheme_GUICtrlSetDarkTheme($hGui, $aCtrlsEx[$i][0], $bEnableDarkTheme)
                    If $aCtrlsEx[$i][1] = 'ComboLBox' Then
                        _WinAPI_SetWindowTheme($aCtrlsEx[$i][0], "DarkMode_Explorer")
                        _SendMessage($aCtrlsEx[$i][0], $WM_THEMECHANGED, 0, 0)
                    EndIf
                Next
            EndIf

            ; Find all controls to apply dark theme
            Local $aCtrls = _WinAPI_EnumChildWindows($hWnd, False)
            If @error = 0 Then
                For $i = 1 To $aCtrls[0][0]
                    ;ConsoleWrite("class: " & $aCtrls[$i][1] & " hwnd: " & $aCtrls[$i][0] & @CRLF)
                    If $aCtrls[$i][1] = "Button" Then
                        _WinAPI_SetWindowTheme($aCtrls[$i][0], "DarkMode_Explorer")
                        ;_WinAPI_SetWindowTheme($aCtrls[$i][0], "DarkMode_DarkTheme") ; DarkMode_DarkTheme needed for group box
                        _SendMessage($aCtrls[$i][0], $WM_THEMECHANGED, 0, 0)
                    EndIf
                    If $aCtrls[$i][1] = "ComboBox" Then
                        _WinAPI_SetWindowTheme($aCtrls[$i][0], "DarkMode_CFD")
                        _SendMessage($aCtrls[$i][0], $WM_THEMECHANGED, 0, 0)
                    EndIf
                    If $aCtrls[$i][1] = "ComboLBox" Then
                        _WinAPI_SetWindowTheme($aCtrls[$i][0], "DarkMode_Explorer")
                        _SendMessage($aCtrls[$i][0], $WM_THEMECHANGED, 0, 0)
                    EndIf
                    If $aCtrls[$i][1] = "Edit" Then
                        _WinAPI_SetWindowTheme($aCtrls[$i][0], "DarkMode_Explorer")
                        _SendMessage($aCtrls[$i][0], $WM_THEMECHANGED, 0, 0)
                        _WinAPI_SetWindowLong($aCtrls[$i][0], $GWL_EXSTYLE, BitAND(_WinAPI_GetWindowLong($aCtrls[$i][0], $GWL_EXSTYLE), BitNOT($WS_EX_CLIENTEDGE)))
                        _WinAPI_SetWindowLong($aCtrls[$i][0], $GWL_EXSTYLE, BitOR(_WinAPI_GetWindowLong($aCtrls[$i][0], $GWL_EXSTYLE), $WS_EX_STATICEDGE))
                        _WinAPI_SetWindowPos($aCtrls[$i][0], 0, 0, 0, 0, 0, BitOR($SWP_NOMOVE, $SWP_NOSIZE, $SWP_NOZORDER, $SWP_FRAMECHANGED))
                    EndIf
                Next
            EndIf

        Case $WM_SHOWWINDOW
            ; center dialog on desktop
            Local $aChildPos = WinGetPos($hWnd)
            WinMove($hWnd, "", (@DesktopWidth / 2 - ($aChildPos[2] / 2)), (@DesktopHeight / 2 - ($aChildPos[3] / 2)))

        Case $WM_CTLCOLORSTATIC,  $WM_CTLCOLORDLG
            _WinAPI_SetBkMode($wParam, $TRANSPARENT)
            _WinAPI_SetTextColor($wParam, 0xFFFFFF)
            Return $hBrush

        Case $WM_CTLCOLOREDIT, $WM_CTLCOLORLISTBOX
            _WinAPI_SetBkMode($wParam, $TRANSPARENT)
            _WinAPI_SetTextColor($wParam, 0xFFFFFF)
            Return $hBrush

        Case $WM_CTLCOLORBTN
            _WinAPI_SetBkColor($wParam, 0x000000) ; needed for focus rectangle
            Return $hBrush

        Case $WM_DESTROY
            _WinAPI_DeleteObject($hBrush)

    EndSwitch
EndFunc

 

Posted (edited)

I suppose that you need to save font.dlg to the resource of the exe file. There is ResHacker project that might assit you into adding that template into exe file.

Edited by ahmet
Edit: For hInstance maybe this will be necessary: _WinAPI_GetModuleHandle(Null)

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...