Custom Control mithilfe von _WinAPI_CreateWindowEx()

  • Servus Community! :)
    Ich hänge an einem Problem wo ich nicht mehr weiter weiß. Ich versuche ein eigenes Control zu schreiben. Ich weiß dass es die Möglichkeit gibt einfach ein vorhandenes Control (z.B. das AutoIt Graphic Control) mit _WinAPI_SetWindowLong() zu "hooken" (weiß nicht wie man es nennt). Will ich aber nicht, ziel soll es sein das Control von Anfang an mit _WinAPI_CreateWindowEx() zu erstellen.

    Die Klasse wird registriert, aber die Erstellung des Controls schlägt fehl. Leider spuckt mir _WinAPI_GetLastError() keinen Fehlercode entgegen. Aber ein Handle bekomme ich trotzdem nicht. Hier der Source:

    [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit][autoit][/autoit][autoit]

    #include "CustomControl.au3"
    #include <WinAPI.au3>

    [/autoit][autoit][/autoit][autoit]

    Global $hGUI, $hCustom

    [/autoit][autoit][/autoit][autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit][autoit][/autoit][autoit]

    $hGUI = GUICreate('MainWindow', 350, 250, -1, -1, $WS_OVERLAPPEDWINDOW)
    GUISetState()

    [/autoit][autoit][/autoit][autoit]

    $hCustom = _WinAPI_CreateWindowEx(0, $CUSTOM_WC, 0, BitOR($WS_CHILD, $WS_VISIBLE), 10, 10, 100, 100, $hGUI)
    ConsoleWrite($hCustom & @CRLF & '! ' & _WinAPI_GetLastError() & @CRLF)

    [/autoit][autoit][/autoit][autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit][autoit][/autoit][autoit]

    While GUIGetMsg() <> -3
    WEnd

    [/autoit][autoit][/autoit][autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit]

    Benötigt wird noch die CustomControl.au3. In der definiere ich mein Control:

    CustomControl.au3
    [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    #include <WinAPI.au3>
    #include <WinAPIEx.au3>
    #include <WindowsConstants.au3>

    [/autoit] [autoit][/autoit] [autoit]

    OnAutoItExitRegister(__CUSTOM_FREE__)

    [/autoit] [autoit][/autoit] [autoit]

    Global Const $WNDCLASS = 'uint Style;ptr hWndProc;int ClsExtra;int WndExtra;ptr hInstance;ptr hIcon;ptr hCursor;ptr hBackground;ptr MenuName;ptr ClassName'

    [/autoit] [autoit][/autoit] [autoit]

    Global Const $CUSTOM_WC = 'CustomControl'

    [/autoit] [autoit][/autoit] [autoit]

    Global Const $CS_GLOBALCLASS = 0x4000
    Global Const $CS_HREDRAW = 0x0002
    Global Const $CS_VREDRAW = 0x0001

    [/autoit] [autoit][/autoit] [autoit]

    Global Const $hCustomProc = DllCallbackRegister(CustomProc, 'LRESULT', 'HWND;UINT;WPARAM;LPARAM')

    [/autoit] [autoit][/autoit] [autoit]

    CustomRegister()

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    Func CustomPaint($hWnd)
    Local $tRect = _WinAPI_GetClientRect($hWnd)
    Local $tPS = DllStructCreate($tagPAINTSTRUCT)
    Local $hDC = _WinAPI_BeginPaint($hWnd, $tPS)

    [/autoit] [autoit][/autoit] [autoit]

    _WinAPI_SetTextColor($hDC, 0x000000)
    _WinAPI_SetBkMode($hDC, $TRANSPARENT)
    _WinAPI_DrawText($hDC, 'Hello World!', $tRect, BitOR($DT_SINGLELINE, $DT_CENTER, $DT_VCENTER))
    _WinAPI_EndPaint($hWnd, $tPS)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func CustomProc($hWnd, $uMsg, $wParam, $lParam)
    Switch $uMsg
    Case $WM_PAINT
    CustomPaint(hWnd)
    Return
    EndSwitch

    [/autoit] [autoit][/autoit] [autoit]

    Return _WinAPI_DefWindowProc($hWnd, $uMsg, $wParam, $lParam)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func CustomRegister()
    Local $tClassName = DllStructCreate('WCHAR str[' & StringLen($CUSTOM_WC) +1 & ']')
    Local $tWC = DllStructCreate($WNDCLASS)

    [/autoit] [autoit][/autoit] [autoit]

    $tClassName.str = $CUSTOM_WC

    [/autoit] [autoit][/autoit] [autoit]

    With $tWC
    .style = BitOR($CS_GLOBALCLASS, $CS_HREDRAW, $CS_VREDRAW)
    .WndProc = DllCallbackGetPtr($hCustomProc)
    ;~ .hCursor = _WinAPI_LoadCursor(Null, $IDC_ARROW)
    .hBackground = _WinAPI_CreateSolidBrush(0xFFFFFF)
    .ClassName = DllStructGetPtr($tClassName, 'str')
    EndWith

    [/autoit] [autoit][/autoit] [autoit]

    _WinAPI_RegisterClass($tWC)
    ConsoleWrite('! ' & _WinAPI_GetLastError() & @CRLF)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func CustomUnregister()
    _WinAPI_UnregisterClass($CUSTOM_WC, Null)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    Func __CUSTOM_FREE__()
    DllCallbackFree($hCustomProc)
    CustomUnregister()
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit]

    Weiß jemand was ich falsch mache? Ich komme zum erbrechen nicht darauf...

  • Ach peinlich,... Ich habe da 2 Rechtschreibfehler eingebaut.

    Zeile 37: CustomPaint(hWnd)
    --> Da habe ich das $ Zeichen vor der Variable $hWnd vergessen...

    Zeile 52: .WndProc = DllCallbackGetPtr($hCustomProc)
    --> Es müsste eigentlich .hWndProc heißen...


    Aber ich habe noch ein anderes anliegen. Meinem Control würde ich gerne IDs verteilen. Das geht bei der Funktion _WinAPI_CreateWindowEx() mit dem $hMenu Parameter. Kann ich irgendwie feststellen welche IDs schon vergeben sind? Wollte keine doppelten IDs vergeben und bei jedem neuen Control um eins hochzählen. Natürlich müssen auch die Controls berücksichtigt werden die vorab mit GUICtrlCreate...() erstellt worden sind. Da fehlt mir drz. ein Ansatzpunkt.


    €dit *1:
    Dazu habe ich schon ein Ansatz gefunden. Mit _WinAPI_EnumChildWindows() kann man sich alle Child Windows (also auch alle Controls) einer GUI ausgeben lassen. Jetzt muss ich nur noch irgendwie aus den Handles die IDs herausfinden, damit ich den größten vergebenen ID ermitteln kann...


    €dit *2:
    Habe jetzt auch eine Funktion gefunden die genau das macht was ich will: _WinAPI_GetDlgCtrlID()
    Naja, da ich mein Problem jetzt selber lösen konnte... [gelöst]

    3 Mal editiert, zuletzt von Yjuq (5. Januar 2015 um 04:50)