Jump to content

Hack of _ChooseFont()possible?


ahha
 Share

Go to solution Solved by Nine,

Recommended Posts

I like using _ChooseFont(), however I'd prefer not to let a user link to the Internet (Show more fonts) and would like to get rid of Script: as circled in the screen shot below.
I've looked into Misc.au3 where _ChooseFont() is located and I can't find "Show more fonts" or "Script:".  It looks like Gary Frost (gafrost) wrote it.  I am not at all familiar with Dll structures and was hoping to just comment out the code that dealt with "Show more fonts" and "Script:".  My search on the forum came up empty on how to do this. Even WeMartiansAreFriendly's code seems to show the unwanted elements (https://www.autoitscript.com/forum/topic/80288-_fontselect/?tab=comments#comment-577724). I feel like a babe in the woods, so my first question is can this be done without me creating my own version of ChooseFont?  If so, can someone point the way? 

 

Screen Shot 02-25-23 at 05.01 PM.JPG

Edited by ahha
Link to comment
Share on other sites

  • Solution

Try this :

#include <WinAPISys.au3>
#include <WinAPIProc.au3>
#include <WinAPIConstants.au3>
#include <Misc.au3>
#include <Array.au3>

Global $hHook

Example()

Func Example()
  Local $hProc = DllCallbackRegister(CbtHookProc, "int", "int;int;int")
  $hHook = _WinAPI_SetWindowsHookEx($WH_CBT, DllCallbackGetPtr($hProc), 0, _WinAPI_GetCurrentThreadId())
  Local $aFont = _ChooseFont("Arial", 8)
  _ArrayDisplay($aFont)

  _WinAPI_UnhookWindowsHookEx($hHook)
  DllCallbackFree($hProc)
EndFunc   ;==>Example2

Func CbtHookProc($nCode, $wParam, $lParam)
  Local $hWnd = HWnd($wParam)
  If $hWnd = WinGetHandle("Police") And $nCode = 5 Then ; "Police" = french title for ChooseFont // 5=HCBT_ACTIVATE
    ControlHide($hWnd, "", "SysLink1")
    ControlHide($hWnd, "", "Static7")
    ControlHide($hWnd, "", "ComboBox5")
  EndIf
  Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam)
EndFunc   ;==>CbtHookProc

 

Link to comment
Share on other sites

$nCode = 5 is sufficient, I don't see a need to match the title in my testing.
 

Spoiler
#include <WinAPISys.au3>
#include <WinAPIProc.au3>
#include <WinAPIConstants.au3>
#include <Misc.au3>
#include <Array.au3>

Global $hHook

Example()
Example()

Func Example()
  Local $hProc = DllCallbackRegister(CbtHookProc, "int", "int;int;int")
  $hHook = _WinAPI_SetWindowsHookEx($WH_CBT, DllCallbackGetPtr($hProc), 0, _WinAPI_GetCurrentThreadId())
  Local $aFont = _ChooseFont("Arial", 8)
  _WinAPI_UnhookWindowsHookEx($hHook)
  DllCallbackFree($hProc)
  _ArrayDisplay($aFont)
EndFunc   ;==>Example2

Func CbtHookProc($nCode, $wParam, $lParam)
    If $nCode = 5 Then ;  5 = HCBT_ACTIVATE
        Local $hWnd = HWnd($wParam)
        If Not @error Then
            ControlHide($hWnd, "", "SysLink1") ; <A>Show more fonts</A>
            ControlHide($hWnd, "", "Static7") ; Script:
            ControlHide($hWnd, "", "ComboBox5") ; Script comboBox
            ControlHide($hWnd, "", "Static4") ; Color:
            ControlHide($hWnd, "", "ComboBox4") ; Color comboBox
        EndIf
    EndIf
    Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam)
EndFunc   ;==>CbtHookProc

 

 

Edited by argumentum
added the code

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

@argumentum @ahha The reason I have added the title of the _ChooseFont window is that it is highly possible that, for a given script, many popups like this could be shown.  You do not want to hide by error controls in other windows and create a bug not easily solvable. 

Link to comment
Share on other sites

... I went at it again

Spoiler
#include <WinAPISys.au3>
#include <WinAPIProc.au3>
#include <WinAPIConstants.au3>
#include <Misc.au3>
#include <Array.au3>

Global $hHook

Example()


Func Example()
  Local $hProc = DllCallbackRegister(CbtHookProc, "int", "int;int;int")
  $hHook = _WinAPI_SetWindowsHookEx($WH_CBT, DllCallbackGetPtr($hProc), 0, _WinAPI_GetCurrentThreadId())
  Local $aFont = _ChooseFont("Arial", 8)
  _WinAPI_UnhookWindowsHookEx($hHook)
  DllCallbackFree($hProc)
  _ArrayDisplay($aFont)
EndFunc   ;==>Example2

Func CbtHookProc($nCode, $wParam, $lParam) ; https://learn.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms644977(v=vs.85)
    
    If $nCode = 5 Then ;  5 = HCBT_ACTIVATE = "The system is about to activate a window."
        Local $hWnd = HWnd($wParam)
        If Not @error Then ;  "StringLen(WinGetTitle($hWnd))" to know is a window, maybe ?
            
            ; For debug:
            ConsoleWrite('- CbtHookProc(' & $nCode & ', ' & $wParam & ', ' & $lParam & ') ' & $hWnd & ' >' & WinGetTitle($hWnd) & '<' & ' >' & ControlGetText($hWnd, "", $lParam) & '<' &  @CRLF)
            
            ControlHide($hWnd, "", "SysLink1") ; <A>Show more fonts</A>
            
            ControlHide($hWnd, "", "Static7") ; Script:
            ControlHide($hWnd, "", "ComboBox5") ; Script comboBox
            
            ControlHide($hWnd, "", "Static4") ; Color:
            ControlHide($hWnd, "", "ComboBox4") ; Color comboBox
            
            ; For debug:
            If Not StringInStr(WinGetTitle($hWnd), "(PID:") Then WinSetTitle($hWnd, "", WinGetTitle($hWnd) & "  (PID:" & @AutoItPID & ")")
            
        EndIf
    EndIf
    Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam)
EndFunc   ;==>CbtHookProc

 

 and truly found no side effects or bug inducing logic. I don't read or understand much as far as code but, I can abuse the heck out of it and in my abuse-based testing found no need for the added safety, as this added safety is a problem when the user has a language different than the developer did, creating a bug. 

Even tested on WinXP to see if blindly hiding controls would behave adversely in older Win32controls and all looked fine.

If you envision a bug in the making do tell why and how as the good of an open forum, talking about code enlightens everyone involved :gathering:

Edited by argumentum
better code

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

Hi everybody :)

9 hours ago, argumentum said:

$nCode = 5 is sufficient, I don't see a need to match the title in my testing.

Just tested : matching the title is necessary in case you got several windows in the same thread, and 2 controls got the same class+instance, each one placed in a different window. Example based on Nine's script :

#include <WinAPISys.au3>
#include <WinAPIProc.au3>
#include <WinAPIConstants.au3>
#include <Misc.au3>
#include <Array.au3>

Global $hHook

Example()

Func Example()
    Local $hProc = DllCallbackRegister(CbtHookProc, "int", "int;int;int")
    $hHook = _WinAPI_SetWindowsHookEx($WH_CBT, DllCallbackGetPtr($hProc), 0, _WinAPI_GetCurrentThreadId())
    ConsoleWrite("_WinAPI_GetCurrentThreadId() = 0x" & Hex(_WinAPI_GetCurrentThreadId(), 4) & @crlf)

    GuiCreate("Test GUI")
    For $i = 1 To 7
        GUICtrlCreateLabel("label " & $i, 10, $i*25)
    Next
    GUISetState()

    Local $aFont = _ChooseFont("Arial", 8)
    _ArrayDisplay($aFont)

    _WinAPI_UnhookWindowsHookEx($hHook)
    DllCallbackFree($hProc)
EndFunc   ;==>Example2

Func CbtHookProc($nCode, $wParam, $lParam)
    Local $hWnd = HWnd($wParam)
    ; If $hWnd = WinGetHandle("Police") And $nCode = 5 Then ; "Police" = french title for ChooseFont // 5=HCBT_ACTIVATE
    If $nCode = 5 Then ; 5=HCBT_ACTIVATE
        ControlHide($hWnd, "", "SysLink1")
        ControlHide($hWnd, "", "Static7")
        ControlHide($hWnd, "", "ComboBox5")
    EndIf
    Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam)
EndFunc   ;==>CbtHookProc

1744783069_label7missing.png.1aea9116b0db7d5b89c2705c625fd066.png

Why isn't the label 7 displayed in the GUI ?
Because we didn't test the window title and there is a "Static7" control in both windows.

No matter you create the hook before or after creating the GUI, the result will be same :
* Label 7 not displayed in GUI if you don't check the window title in the hook function.
* Label 7 displayed in GUI if you check the window title in the hook function.

Link to comment
Share on other sites

25 minutes ago, pixelsearch said:

Just tested : matching the title is necessary

is not

#include <WinAPISys.au3>
#include <WinAPIProc.au3>
#include <WinAPIConstants.au3>
#include <Misc.au3>
#include <Array.au3>

Global $hHook, $hHook_hWnd = 0

Example()

Func Example()

    Local $hParent = GuiCreate("Test GUI")
    For $i = 1 To 7
        GUICtrlCreateLabel("label " & $i, 10, $i*25)
    Next
    GUISetState()

    Sleep(1000)

    Local $hProc = DllCallbackRegister(CbtHookProc, "int", "int;int;int")
    $hHook = _WinAPI_SetWindowsHookEx($WH_CBT, DllCallbackGetPtr($hProc), 0, _WinAPI_GetCurrentThreadId())
    ConsoleWrite("_WinAPI_GetCurrentThreadId() = 0x" & Hex(_WinAPI_GetCurrentThreadId(), 4) & @crlf)

    ;   Unrelated to the topic but, if part of a parent GUI, the $hParent should be declared. Behaves better
    Local $aFont = _ChooseFont("Arial", 8) ; , Default, Default, Default, Default, Default, $hParent)

    _WinAPI_UnhookWindowsHookEx($hHook)
    DllCallbackFree($hProc)
    $hHook_hWnd = 0

    _ArrayDisplay($aFont)

EndFunc   ;==>Example2

Func CbtHookProc($nCode, $wParam, $lParam)
    Local $hWnd = HWnd($wParam)
    ; If $hWnd = WinGetHandle("Police") And $nCode = 5 Then ; "Police" = french title for ChooseFont // 5=HCBT_ACTIVATE
    If $nCode = 5 And $hHook_hWnd = 0 Then ; 5=HCBT_ACTIVATE
        $hHook_hWnd = $hWnd ; <-------------------------------- this is all it'd need
        ControlHide($hWnd, "", "SysLink1")
        ControlHide($hWnd, "", "Static7")
        ControlHide($hWnd, "", "ComboBox5")
    EndIf
    Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam)
EndFunc   ;==>CbtHookProc

as HCBT_ACTIVATE = "The system is about to activate a window." so, catching that is all that's need.

If you find a flaw in my presentation, show me. I really love to discern code and always welcome anyone to prove me wrong.
Again, thanks for posting :gathering:

PS: I hope not to come across as aggressive as is not my intention. Reading this I feel like "fight me" but I'm chicken shiet and don't like fighting as I don't like loosing but do like understanding and in coding the best way I know is: "ok, show me", but it may come across as "fight me" and all I want to do is to make sure that I'm not misleading anyone and the idea is good :)  

Edited by argumentum
insecurities

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

I won't enter that game of "who's wright, who's wrong" because that's not me.

Of course you can do it your way, now that you just added global new variables ($hHook_hWnd) and moved the hook creation after the GUI creation.

My point was simple (and I think Nine's point too) . It's safer to check what is gonna be hidden by adding a test (based on windows title, or handle, or active window... whatever)

No matter the answers to come, this will be my last input in this thread.
Good luck and stay safe :)

Link to comment
Share on other sites

Yep, @pixelsearch is right.  It is exactly what I am talking about.  But I understand you @argumentum.  It is not mandatory if you only have a single that popup in your script (like in my example and yours).  But you need to specify which window you want to hide controls from if you have multiple windows.  Just to make sure you do not create a false hide.

Anyway, my intention was to provide robust code to @ahha.  After that he can do what he wants. ;)

Link to comment
Share on other sites

The title is a bug inducing method. Finding a non bug inducing method is important. I could not put any of this together all by my self. The OP would trust the code as is, because he too could not put it together all by his self.
All I can do is push for a copy'n'paste solution that I can trust, as again, I do not trust my self to understand this in the future as I might as well be in a trance when I play with things I don't quite know.
Being a bit obsessive ( and mindlessly more than mindful ), I believe this next code posting would be a nice "copy and paste" chunk of code for future seekers of the "copy and paste into a something that runs" methodology. 😛

#include <WinAPISys.au3>
#include <WinAPIProc.au3>
#include <WinAPIConstants.au3>
#include <Misc.au3>
#include <Array.au3>
#include <WinAPISysWin.au3> ; _WinAPI_GetSysColor ( $iIndex )
#include <WindowsConstants.au3> ; _WinAPI_GetSysColor ( $iIndex )

Example()

Func Example()
    Local $hParent = GUICreate("Test GUI")
    For $i = 1 To 7
        GUICtrlCreateLabel("label " & $i, 10, $i * 25)
    Next
    GUISetState()
    Sleep(1000)
    Local $aFont = _ChooseFont_Mod("Segoe UI", 8, Default, Default, Default, Default, Default, $hParent, 7, "Please choose a font:")
    _ArrayDisplay($aFont)
    Sleep(1000)
EndFunc   ;==>Example


; $sNewWinTitle = "" to keep as is or change it
; $iHideThese = 7 (default) hide all
;       1: hide SysLink
;       2: hide Script
;       4: hide Color
; the other values just like in _ChooseFont()
Func _ChooseFont_Mod($sFontName = "Courier New", $iPointSize = 10, $iFontColorRef = Default, $iFontWeight = 0, _
        $bItalic = False, $bUnderline = False, $bStrikethru = False, $hWndOwner = 0, $iHideThese = 7, $sNewWinTitle = "")
    Local $aRet, $iErr, $iExt ; $iHideThese = 1:hide SysLink, 2:hide Script, 4:hide Color
    If $iFontColorRef = Default Then $iFontColorRef = _WinAPI_GetSysColor($COLOR_BTNTEXT) ; I use a dark theme, so 0x000000 is not my default.
    __ChooseFont_Mod_Hook("StartIt", $iHideThese, $sNewWinTitle) ; logic moved to this func to keep hook variables as local
    $aRet = _ChooseFont($sFontName, $iPointSize, $iFontColorRef, $iFontWeight, $bItalic, $bUnderline, $bStrikethru, $hWndOwner)
    $iErr = @error
    $iExt = @extended
    __ChooseFont_Mod_Hook("EndIt", "", "")
    Return SetError($iErr, $iExt, $aRet)
EndFunc   ;==>_ChooseFont_Mod

; internal ; For _ChooseFont_Mod()
Func __ChooseFont_Mod_Hook($nCode, $wParam, $lParam) ; Tested in XP, 10 and 11
    Local Static $hProc = 0, $hHook = 0, $iHideThese = 7, $sNewWinTitle = "", $wParamKept = 0 ; <---- if this always behave like this, it's good
    Switch $nCode
        Case "StartIt"
            $sNewWinTitle = $lParam
            If $wParam < 0 Or $wParam > 7 Or $wParam = Default Then
                $iHideThese = 7
            Else
                $iHideThese = Int($wParam)
            EndIf
            $hProc = DllCallbackRegister(__ChooseFont_Mod_Hook, "int", "int;int;int")
            $hHook = _WinAPI_SetWindowsHookEx($WH_CBT, DllCallbackGetPtr($hProc), 0, _WinAPI_GetCurrentThreadId())
            Return
        Case "EndIt"
            _WinAPI_UnhookWindowsHookEx($hHook)
            DllCallbackFree($hProc)
            $hHook = 0
            $hProc = 0
            Return
    EndSwitch
    If $nCode = 3 And $wParamKept = 0 Then $wParamKept = $wParam
    If $nCode = 9 And $wParamKept = 1 Then $wParamKept = 0
    If $nCode = 5 And $wParamKept = $wParam Then
        $wParamKept = 1
        Local $hWnd = HWnd($wParam)
        If BitAND($iHideThese, 1) Then ControlHide($hWnd, "", "SysLink1")     ; <A>Show more fonts</A>
        If BitAND($iHideThese, 2) Then
            ControlHide($hWnd, "", "Static7")     ; Script:
            ControlHide($hWnd, "", "ComboBox5")     ; Script comboBox
        EndIf
        If BitAND($iHideThese, 4) Then
            ControlHide($hWnd, "", "Static4")     ; Color:
            ControlHide($hWnd, "", "ComboBox4")     ; Color comboBox
        EndIf
        If $sNewWinTitle <> "" Then WinSetTitle($hWnd, "", $sNewWinTitle)
        $sNewWinTitle = ""
    EndIf
    Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam)
EndFunc   ;==>__ChooseFont_Mod_Hook

called the function _ChooseFontVme() as it needs a name and is fun for me as a pun.

Version 2.1:
Used better naming to reflect it's use.
Added bitwise selection of what to hide.
Added ButtonText color as Default.  Zero is not my default color ( using a Dark mode theme from elsewhere )
Added to optionally change the WinTitle 

Thank you all for your patience with me and do please tell me if I made an "oops" :)
It would not be the first time that a big oops goes unnoticed by me for years 

Edit: ended up rearranging all this into a UDF in examples

Edited by argumentum
made an UDF

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...