Über Button ein anderer Cursor



  • wenn ich - ohne jegliche kontrollstrukturen um zu testen um welches hwnd es sich handelt - einfach nur SetCursor in WM_SETCURSOR verwende entählt das gesamte fenster diesen cursor.
    wenn ich allerdings über den button gehe sehe ich den ganz normalen pfeil 😞



  • Du sollst doch natürlich die Nachricht des Buttons und nicht des Fensters abfangen 😃



  • Ähh..
    über subclassing, oder wie jetzt?...

    PS: vielen dank für deine bisherigen bemühungen 😃



  • Santa schrieb:

    Ähh..
    über subclassing, oder wie jetzt?...

    PS: vielen dank für deine bisherigen bemühungen 😃

    Ja genau, subclassing! Und gern geschehen 🙂 Ich hatte vor ein paar Monaten auch mal lange danach gesucht, vorher kannte ich nur die Methode, eine eigene Fensterklasse zu erstellen (via RegisterClass/Ex) und da halt einen Cursor-Typ anzugeben - ist natürlich ungleich aufwändiger.

    edit:

    MSDN schrieb:

    The DefWindowProc function passes the WM_SETCURSOR message to a parent window before processing. If the parent window returns TRUE, further processing is halted. Passing the message to a window's parent window gives the parent window control over the cursor's setting in a child window.

    Vielleicht braucht man doch kein Subclassing. Kannst ja mal versuchen über den HWND-wParam die Child-ID zu holen und so halt dementsprechend den Cursor zu setzen.



  • WM_SETCURSOR:
        if(wparam == GetDlgItem(hwnd, mybutton) {
            //MessageBoxA(hwnd, "Hallo", "WM_SETCURSOR", MB_OK);
            SetCursor(mycursor);
        }
        return true;
    

    Ich habe das nun so, die nacrhicht erhalte ich, also die messagebox erscheint, aber der cursor bleibt unverändert 😕



  • Bei mir klappts :p
    http://rafb.net/p/YaOCcU24.html

    Sicher, dass dein Cursor richtig geladen wurde?



  • ich habs genau so und bei mir funktioniert es nicht 😞

    (nur mit dem unterschied das ich meinen dialog mit CreateDialog und einer resource erstelle)



  • Zeig einfach mal den wichtigsten Source, das macht die Diagnose bestimmt leicher 🙂



  • #include <windows.h>
    
    MSG msg;
    
    BOOL FensterProzedur(HWND hwnd, int Msg, DWORD wParam, DWORD lParam) {
        switch(Msg) {
        case WM_SETCURSOR:
            if(wParam == GetDlgItem(hwnd, mybutton) {
                SetCursor(LoadCursor(0, 32649));
            }
            return TRUE;
        }
        return FALSE;
    }
    
    int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd ) {
        CreateDialog(GetModuleHandle(NULL), IDD_MAIN, 0, &FensterProzedur);
        while(GetMessage(&msg, 0, 0)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        return 0;
    }
    


  • Upsi, verguckt. Aber hast du mal überprüft, ob LoadCursor ein gültiges Handle zurückgibt?



  • Ne mach ich jetzt mal.
    aber es ist ja eigentlich nur der befehl den du auch benutzt hast (LoadCursor(0,IDC_HAND), nur halt mit dem wert von IDC_HAND) deswegen wüsste ich nicht, was da schief gehen sollte, naja ich gucke mal, ob ein fehler kommt.
    Danke


  • Mod

    Wenn der Button WM_SETCURSOR selbst behandelt, dann bekommt das Elternfenster diese Nachricht nicht zu sehen.
    Nutze Spy++ um das zu prüfen.



  • <00119> 004A02F2 S WM_SETCURSOR hwnd:004A02F2 nHittest:HTCLIENT wMouseMsg:WM_MOUSEMOVE
    <00120> 004A02F2 R WM_SETCURSOR fHaltProcessing:False

    ?



  • Santa schrieb:

    <00120> 004A02F2 R WM_SETCURSOR fHaltProcessing:False

    Da ist doch der Haken -> fHaltProcessing müsste true sein. Das bedeutet, du musst zur Nachricht WM_SETCURSOR den Wert "TRUE" zurückgeben.

    =>

    MSDN schrieb:

    If the dialog box procedure processes a message that requires a specific return value, the dialog box procedure should set the desired return value by calling SetWindowLong(hwndDlg, DWL_MSGRESULT, lResult) immediately before returning TRUE. Note that you must call SetWindowLong immediately before returning TRUE; doing so earlier may result in the DWL_MSGRESULT value being overwritten by a nested dialog box message.



  • wo denn?

    hier steht doch return TRUE;

    case WM_SETCURSOR: 
            if(wParam == GetDlgItem(hwnd, mybutton) { 
                SetCursor(LoadCursor(0, 32649)); 
            } 
            return TRUE;
    

  • Mod

    Und Deine WM_SETCURSOR Routine wird aufegrufen?



  • ja, wenn ich da eine messagebox reinmache, erscheint sie



  • Santa schrieb:

    wo denn?

    hier steht doch return TRUE;

    Lies doch mal ein wenig Doku 🙄

    MSDN schrieb:

    Typically, the dialog box procedure should return TRUE if it processed the message, and FALSE if it did not. If the dialog box procedure returns FALSE, the dialog manager performs the default dialog operation in response to the message.

    Dein "return TRUE" bedeutet nur, dass die Nachricht nicht ans Standard-Nachrichten-Bearbeitungs-System weitergeleitet wird; den Rückgabewert setzt du damit allerdings nicht. Deshalb hatte ich in meinem Post (von 14:50:59) ja den MSDN-Quote dazugenommen, wo drinsteht, wie du den Rückgabewert setzen kannst.


  • Mod

    Du hast hier keine Fenster Prozedur, sondern eine DlgProc!

    Hier gibst Du TRUE und FALSE zurück und regelst ob die DefDlgProc aufegrufen wird. Um auf WM_SETCURSOR mit TRUE zu reagieren musst Du DWL_MSGRESULT verwenden und den Code wie folgt ändern:

    case WM_SETCURSOR: 
            if(wParam == GetDlgItem(hwnd, mybutton) 
            { 
                SetCursor(LoadCursor(0, 32649)); 
                SetWindowLong(hDlg,DWL_MSGRESULT,TRUE);
            } 
            return TRUE;
    

    BTW. Speicher Dir doch das Handle, permanent und verwnede doch besser die entsprechenden symbolischen IDs.



  • Vielen Dank euch beiden, hat wunderbar funktioniert 😃

    @Badestrand:
    tut mir leid, ich dachte ich hätte es schon gelesen und habe es deswegen mehr oder weniger ignoriert, obwohl darin die lösung steckte 👍


Anmelden zum Antworten