Functions > GUI >


GUIRegisterMsg

Enregistre une fonction utilisateur pour un ID de message Windows connu (WM_MSG).

GUIRegisterMsg ( msgID, "function" )

Paramètres

msgID Un ID de Messages Windows. (Voir Annexe: Codes des Messages Windows.)
function Le nom de la fonction utilisateur à appeler lorsque le message est reçu ou une chaîne vide "" pour annuler l'inscription du message.

Valeur de retour

Succès: Retourne 1.
Échec: Retourne 0.

Remarques

!!! Pour réaliser une fonction utilisateur valide, vous devez la définir avec au maximum 4 paramètres sinon la fonction ne sera pas appelée !!!
Par exemple:
Func MyUserFunction($hWndGUI, $MsgID, $WParam, $LParam)
...
EndFunc

ou

Func MyUserFunction($hWndGUI, $MsgID)
...
EndFunc

Lorsque la fonction utilisateur sera appelée, ces quatre paramètres auront les valeurs suivantes:

Position Paramètre Signification
1 hWnd Le handle de la GUI dans laquelle le message est reçu.
2 Msg L'ID du message Windows.
3 wParam Le premier paramètre du message sous forme de valeur hexadécimale.
4 lParam Le deuxième paramètre du message sous forme de valeur hexadécimale.

Jusqu'à 256 fonctions utilisateur peuvent être enregistrées pour les IDs de message.

Par défaut le gestionnaire de message interne à AutoIt (s'il y en a un pour ce message) sera actionné après que la fonction utilisateur existe. Le gestionnaire de message interne à AutoIt sera aussi actionné si le mot-clé Return est utilisé avec la constante $GUI_RUNDEFMSG (qui se trouve dans GUIConstantsEx.au3).

Cependant, si Return est utilisé avec une autre valeur (y compris aucune valeur du tout) le gestionnaire de message interne à AutoIt ne sera PAS actionné (Voir WM_COMMAND dans Exemple).

Ainsi un retour anticipé d'une fonction utilisateur nécessite Return $GUI_RUNDEFMSG si le gestionnaire interne à AutoIt de ce message doit s'exécuter (voir les autres exemples).

Attention: le blocage de l'exécution des fonctions utilisateur qui exécutent les messages de fenêtre avec des commandes comme "MsgBox()" peut conduire à un comportement inattendu, le retour au système doit être aussi rapide que possible!!!

Certains contrôles consomment en interne des IDs de message Windows spécifiques, de sorte que leur enregistrement n'aura aucun effet, par exemple: WM_CHAR, WM_KEYDOWN, WM_KEYUP sont consommés par un contrôle Edit.

En relation

GUICtrlGetHandle

Exemple

; Crée un bouton auto-dessiné et coloré

#include <ButtonConstants.au3>
#include <FrameConstants.au3>
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>

Example()

Func Example()
    Local $hGUI = GUICreate("My Ownerdrawn Created Button", 300, 200)

    Local $idButton = GUICtrlCreateButton("", 90, 50, 120, 30)
    GUICtrlSetStyle($idButton, BitOR($WS_TABSTOP, $BS_NOTIFY, $BS_OWNERDRAW)) ; Définit le flag Ownerdrawn

    Local $idButton2 = GUICtrlCreateButton("Bouton Normal", 90, 110, 120, 30)

    GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")

    ; WM_DRAWITEM est enregistré avant d'afficher la GUI sinon le dessin initial n'est pas fait
    GUIRegisterMsg($WM_DRAWITEM, "WM_DRAWITEM")

    GUISetState(@SW_SHOW)

    Local $iMsg = GUIGetMsg()
    While $iMsg <> $GUI_EVENT_CLOSE
        Switch $iMsg
            Case $idButton
                ; Normalement, ne doit pas s'exécuter à cause de notre fonction  MY_WM_COMMAND
                MsgBox($MB_SYSTEMMODAL, "Info", "Bouton pressé")

            Case $idButton2
                ; Normalement, ne doit pas s'exécuter à cause de notre fonction MY_WM_COMMAND
                MsgBox($MB_SYSTEMMODAL, "Info", "Bouton2 pressé")
        EndSwitch
        $iMsg = GUIGetMsg()
    WEnd

    GUIDelete()
EndFunc   ;==>Example

; Réagit sur un clic de bouton
Func WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)
    Local $nNotifyCode = BitShift($wParam, 16)
    Local $iID = _WinAPI_LoWord($wParam)
    Local $hCtrl = $lParam

    If $iID <> 2 And $nNotifyCode = 0 Then ; Vérifie IDCANCEL - 2
        ; Les boutons Ownerdrawn n'envoient pas quelque chose en appuyant sur ENTER
        ; Donc IDOK - 1 apparait, maintenant vérifie le contrôle qui a le focus courant
        If $iID = 1 Then
            Local $hFocus = _WinAPI_GetFocus()
            Local $idControl = _WinAPI_GetDlgCtrlId($hFocus)
            PostButtonClick($hWnd, $idControl)
        Else
            MsgBox($MB_SYSTEMMODAL, "WM_COMMAND", "GUIHWnd" & @TAB & ":" & $hWnd & @CRLF & _
                    "MsgId" & @TAB & ":" & $iMsg & @CRLF & _
                    "wParam" & @TAB & ":" & $wParam & @CRLF & _
                    "lParam" & @TAB & ":" & $lParam & @CRLF & @CRLF & _
                    "WM_COMMAND - Infos:" & @CRLF & _
                    "-----------------------------" & @CRLF & _
                    "Code" & @TAB & ":" & $nNotifyCode & @CRLF & _
                    "CtrlId" & @TAB & ":" & $iId & @CRLF & _
                    "CtrlHWnd" & @TAB & ":" & $hCtrl)
        EndIf
        Return 0 ; Only workout clicking on the button
    EndIf

    ; À la fermeture, le gestionnaire de message interne AutoIt3 par défaut s'exécutera
    ; Il sera également exécuté si "Return" renvoie $GUI_RUNDEFMSG comme ci-dessous
    ; L'utilisation de "Return" avec n'importe quelle autre valeur (ou aucune valeur) 
    ; signifie que le gestionnaire de AutoIt ne s'exécutera pas
    Return $GUI_RUNDEFMSG
EndFunc   ;==>MY_WM_COMMAND

; Republie un message WM_COMMAND à un contrôle de la fenêtre GUI
Func PostButtonClick($hWnd, $nCtrlID)
    DllCall("user32.dll", "int", "PostMessage", _
            "hwnd", $hWnd, _
            "int", $WM_COMMAND, _
            "int", _WinAPI_LoWord($idControl), _
            "hwnd", GUICtrlGetHandle($idControl))
EndFunc   ;==>PostButtonClick

; Dessine le bouton
Func WM_DRAWITEM($hWnd, $iMsg, $wParam, $lParam)
    #forceref $iMsg, $wParam, $lParam
    Local Const $tagDRAWITEMSTRUCT = "uint;uint;uint;uint;uint;hwnd;handle;long[4];ulong_ptr"
    Local $tDrawItem = DllStructCreate($tagDRAWITEMSTRUCT, $lParam)

    Local Const $ODT_BUTTON = 4

    Local $nCtlType = DllStructGetData($tDrawItem, 1)
    If $nCtlType = $ODT_BUTTON Then
        ;$Locale = nCtrlID DllStructGetData ($tDrawItem, 2)
        Local $nItemState = DllStructGetData($tDrawItem, 5)
        Local $hCtrl = DllStructGetData($tDrawItem, 6)
        Local $hDC = DllStructGetData($tDrawItem, 7)
        Local $nLeft = DllStructGetData($tDrawItem, 8, 1)
        Local $nTop = DllStructGetData($tDrawItem, 8, 2)
        Local $nRight = DllStructGetData($tDrawItem, 8, 3)
        Local $nBottom = DllStructGetData($tDrawItem, 8, 4)
        Local $sText = "Ownerdrawn Button"
        Local $nTextColor = 0x5555DD
        Local $nBackColor = 0xFFEEDD
        DrawButton($hWnd, $hCtrl, $hDC, $nLeft, $nTop, $nRight, $nBottom, $nItemState, $sText, $nTextColor, $nBackColor)
        $tDrawItem = 0
        Return 1 ; Le gestionnaire de message interne d'AutoIt ne s'exécutera pas
    EndIf

    $tDrawItem = 0
    Return $GUI_RUNDEFMSG ; Exécute le gestionnaire de message interne par défaut d'AutoIt
EndFunc   ;==>MY_WM_DRAWITEM

; Procédure principale de dessin
Func DrawButton($hWnd, $hCtrl, $hDC, $nLeft, $nTop, $nRight, $nBottom, $nItemState, $sText, $nTextColor, $nBackColor)
    #forceref $hWnd

    Local Const $ODS_SELECTED = 0x0001
    Local Const $ODS_GRAYED = 0x0002
    Local Const $ODS_DISABLED = 0x0004
    Local Const $ODS_FOCUS = 0x0010

    Local $bFocused = BitAND($nItemState, $ODS_FOCUS)
    Local $bGrayed = BitAND($nItemState, BitOR($ODS_GRAYED, $ODS_DISABLED))
    Local $bSelected = BitAND($nItemState, $ODS_SELECTED)

    Local $tRECT = DllStructCreate($tagRECT)
    DllStructSetData($tRECT, 'Left', $iLeft)
    DllStructSetData($tRECT, 'Top', $iTop)
    DllStructSetData($tRECT, 'Right', $iRight)
    DllStructSetData($tRECT, 'Bottom', $iBottom)

    Local $nClrTxt = 0
    If $bGrayed Then
        $nClrTxt = _WinAPI_SetTextColor($hDC, _WinAPI_GetSysColor($COLOR_HIGHLIGHTTEXT))
    ElseIf $nTextColor = -1 Then
        $nClrTxt = _WinAPI_SetTextColor($hDC, _WinAPI_GetSysColor($COLOR_BTNTEXT))
    Else
        $nClrTxt = _WinAPI_SetTextColor($hDC, $nTextColor)
    EndIf

    Local $hBrush, $nClrSel
    If $nBackColor = -1 Then
        $hBrush = _WinAPI_GetSysColorBrush($COLOR_BTNFACE)
        $nClrSel = _WinAPI_GetSysColor($COLOR_BTNFACE)
    Else
        $hBrush = _WinAPI_CreateSolidBrush($nBackColor)
        $nClrSel = $nBackColor;
    EndIf

    Local $nClrBk = _WinAPI_SetBkColor($hDC, $nClrSel)
    Local $hOldBrush = _WinAPI_SelectObject($hDC, $hBrush)

    Local $nTmpLeft = $iLeft
    Local $nTmpTop = $iTop
    Local $nTmpRight = $iRight
    Local $nTmpBottom = $iBottom

    If $bSelected Then
        InflateRect($nTmpLeft, $nTmpTop, $nTmpRight, $nTmpBottom, -1, -1)
        Local $hBrushSel = _WinAPI_CreateSolidBrush(_WinAPI_GetSysColor($COLOR_BTNSHADOW))
        FrameRect($hDC, $nTmpLeft, $nTmpTop, $nTmpRight, $nTmpBottom, $hBrushSel)
        _WinAPI_DeleteObject($hBrushSel)
    Else
        If $bFocused And Not $bSelected Then InflateRect($nTmpLeft, $nTmpTop, $nTmpRight, $nTmpBottom, -1, -1)
        DrawFrameControl($hDC, $nTmpLeft, $nTmpTop, $nTmpRight, $nTmpBottom, $DFC_BUTTON, $DFCS_BUTTONPUSH)
    EndIf

    $nTmpLeft = $iLeft
    $nTmpTop = $iTop
    $nTmpRight = $iRight
    $nTmpBottom = $iBottom

    If $bSelected Then
        InflateRect($nTmpLeft, $nTmpTop, $nTmpRight, $nTmpBottom, -2, -2)
    Else
        If $bFocused And Not $bSelected Then
            InflateRect($nTmpLeft, $nTmpTop, $nTmpRight, $nTmpBottom, -3, -3)
            $nTmpLeft -= 1
            $nTmpTop -= 1
        Else
            InflateRect($nTmpLeft, $nTmpTop, $nTmpRight, $nTmpBottom, -2, -2)
            $nTmpLeft -= 1
            $nTmpTop -= 1
        EndIf
    EndIf

    FillRect($hDC, $nTmpLeft, $nTmpTop, $nTmpRight, $nTmpBottom, $hBrush)

    If $bSelected Or $bGrayed Then
        $nTmpLeft = $nTmpLeft + 2
        $nTmpTop = $nTmpTop + 2
    EndIf

    Local $iFlags = BitOR($DT_NOCLIP, $DT_CENTER, $DT_VCENTER)

    If Not BitAND(_WinAPI_GetWindowLong($hCtrl, $GWL_STYLE), $BS_MULTILINE) Then $iFlags = BitOR($iFlags, $DT_SINGLELINE)

    DrawText($hDC, $sText, $nTmpLeft, $nTmpTop, $nTmpRight, $nTmpBottom, $iFlags)

    If $bGrayed Then
        $nTmpLeft = $iLeft
        $nTmpTop = $iTop
        $nTmpRight = $iRight
        $nTmpBottom = $iBottom

        $nTmpLeft -= 1

        $nClrTxt = _WinAPI_SetTextColor($hDC, _WinAPI_GetSysColor($COLOR_GRAYTEXT))
        DrawText($hDC, $sText, $nTmpLeft, $nTmpTop, $nTmpRight, $nTmpBottom, BitOR($DT_NOCLIP, $DT_CENTER, $DT_VCENTER, $DT_SINGLELINE))
    EndIf

    $nTmpLeft = $iLeft
    $nTmpTop = $iTop
    $nTmpRight = $iRight
    $nTmpBottom = $iBottom

    If $bFocused Then
        $hBrush = _WinAPI_CreateSolidBrush(0)
        FrameRect($hDC, $nTmpLeft, $nTmpTop, $nTmpRight, $nTmpBottom, $hBrush)

        $nTmpLeft = $iLeft
        $nTmpTop = $iTop
        $nTmpRight = $iRight
        $nTmpBottom = $iBottom

        InflateRect($nTmpLeft, $nTmpTop, $nTmpRight, $nTmpBottom, -4, -4)
        DrawFocusRect($hDC, $nTmpLeft, $nTmpTop, $nTmpRight, $nTmpBottom)
    EndIf

    _WinAPI_SelectObject($hDC, $hOldBrush)
    _WinAPI_DeleteObject($hBrush)
    _WinAPI_SetTextColor($hDC, $nClrTxt)
    _WinAPI_SetBkColor($hDC, $nClrBk)

    Return 1 ; The internal AutoIt message handler will not run
EndFunc   ;==>DrawButton

Func DrawFrameControl($hDC, $iLeft, $iTop, $iRight, $iBottom, $iType, $iState)
    Local $tRECT = DllStructCreate($tagRECT)

    DllStructSetData($tRECT, 'Left', $iLeft)
    DllStructSetData($tRECT, 'Top', $iTop)
    DllStructSetData($tRECT, 'Right', $iRight)
    DllStructSetData($tRECT, 'Bottom', $iBottom)

    _WinAPI_DrawFrameControl($hDC, $tRECT, $iType, $iState)
EndFunc   ;==>DrawFrameControl

Func DrawFocusRect($hDC, $iLeft, $iTop, $iRight, $iBottom)
    Local $tRECT = DllStructCreate($tagRECT)

    DllStructSetData($tRECT, 'Left', $iLeft)
    DllStructSetData($tRECT, 'Top', $iTop)
    DllStructSetData($tRECT, 'Right', $iRight)
    DllStructSetData($tRECT, 'Bottom', $iBottom)

    _WinAPI_DrawFocusRect($hDC, $tRECT)
EndFunc   ;==>DrawFocusRect

Func DrawText($hDC, $sText, $iLeft, $iTop, $iRight, $iBottom, $iFlags)
    Local $tRECT = DllStructCreate($tagRECT)

    DllStructSetData($tRECT, 'Left', $iLeft)
    DllStructSetData($tRECT, 'Top', $iTop)
    DllStructSetData($tRECT, 'Right', $iRight)
    DllStructSetData($tRECT, 'Bottom', $iBottom)

    _WinAPI_DrawText($hDC, $sText, $tRECT, $iFlags)
EndFunc   ;==>DrawText

Func FillRect($hDC, $iLeft, $iTop, $iRight, $iBottom, $hBrush)
    Local $tRECT = DllStructCreate($tagRECT)

    DllStructSetData($tRECT, 'Left', $iLeft)
    DllStructSetData($tRECT, 'Top', $iTop)
    DllStructSetData($tRECT, 'Right', $iRight)
    DllStructSetData($tRECT, 'Bottom', $iBottom)

    _WinAPI_FillRect($hDC, $tRECT, $hBrush)
EndFunc   ;==>FillRect

Func FrameRect($hDC, $iLeft, $iTop, $iRight, $iBottom, $hBrush)
    Local $tRECT = DllStructCreate($tagRECT)

    DllStructSetData($tRECT, 'Left', $iLeft)
    DllStructSetData($tRECT, 'Top', $iTop)
    DllStructSetData($tRECT, 'Right', $iRight)
    DllStructSetData($tRECT, 'Bottom', $iBottom)

    _WinAPI_FrameRect($hDC, $tRECT, $hBrush)
EndFunc   ;==>FrameRect

Func InflateRect(ByRef $iLeft, ByRef $iTop, ByRef $iRight, ByRef $iBottom, $iDX, $iDY)
    Local $tRECT = DllStructCreate($tagRECT)

    DllStructSetData($tRECT, 'Left', $iLeft)
    DllStructSetData($tRECT, 'Top', $iTop)
    DllStructSetData($tRECT, 'Right', $iRight)
    DllStructSetData($tRECT, 'Bottom', $iBottom)

    _WinAPI_InflateRect($tRECT, $iDX, $iDY)

    $iLeft = DllStructGetData($tRECT, 'Left')
    $iTop = DllStructGetData($tRECT, 'Top')
    $iRight = DllStructGetData($tRECT, 'Right')
    $iBottom = DllStructGetData($tRECT, 'Bottom')
EndFunc   ;==>InflateRect