onmouseover bei einem static



  • Ok, Du hast recht. Bei mir ist das zwar anders, aber was soll's. Mein Windows scheint kaputt zu sein ...

    <edit> .. und das auf drei verschiedenen Rechnern. </edit>

    [ Dieser Beitrag wurde am 29.08.2002 um 15:39 Uhr von -King- editiert. ]



  • Bei mir ist es auch so:

    Gesubclasstes Static-Control ohne SS_NOTIFY -> erhält keine WM_MOUSEMOVE Nachrichten

    Gesubclasstes Static-Control mit SS_NOTIFY -> erhält WM_MOUSEMOVE Nachrichten

    Werde es später aber nochmals testen.



  • [ Dieser Beitrag wurde am 29.08.2002 um 15:46 Uhr von -King- editiert. ]



  • @-King-
    Gut..., dann gebe ich dir jetzt mal einen kompletten Code, damit du dich nicht bemühen musst einen neuen zu schreiben. 😉 Und ich wette, der funktioniert bei dir genauso gut wie bei mir. Du kannst also ganz beruhigt sein. Dein Windows ist nicht im Eimer.

    #include <windows.h>
    //---------------------------------------------------------------------------
    #define ID_STAT 1
    //---------------------------------------------------------------------------
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR, int)
    {
         char        szAppName[] = "Name" ;
         MSG         msg;
         WNDCLASSEX  wndclass;
    
         wndclass.cbSize        = sizeof(wndclass);
         wndclass.style         = CS_HREDRAW | CS_VREDRAW;
         wndclass.lpfnWndProc   = WndProc;
         wndclass.cbClsExtra    = 0;
         wndclass.cbWndExtra    = 0;
         wndclass.hInstance     = hInstance;
         wndclass.hIcon         = LoadIcon(NULL, IDI_ASTERISK);
         wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW);
         wndclass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
         wndclass.lpszMenuName  = NULL;
         wndclass.lpszClassName = szAppName;
         wndclass.hIconSm       = LoadIcon(NULL, IDI_ASTERISK);
    
         RegisterClassEx(&wndclass);
    
         LONG style = WS_OVERLAPPEDWINDOW|WS_SIZEBOX|WS_CAPTION|WS_SYSMENU|WS_VISIBLE;
         CreateWindow(szAppName, "Ich bin ein Fenster", style, CW_USEDEFAULT, CW_USEDEFAULT,
                      250, 200, NULL, NULL, hInstance, NULL) ;
    
         while(GetMessage(&msg, NULL, 0, 0))
         {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
         }
         return msg.wParam ;
    }
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
    {
      HINSTANCE        hInstance;
      static HWND      hStat;
      static BOOL      bHot = FALSE;
      static RECT      rect;
      static POINT     pt;
    
      switch(iMsg)
      {
         case WM_CREATE:
            hInstance = ((CREATESTRUCT*)lParam)->hInstance;
            hStat = CreateWindow("Static", "HALLO_OUT", WS_CHILD | WS_VISIBLE | WS_BORDER,
                                 0, 0, 100, 25, hwnd, (HMENU)ID_STAT, hInstance, NULL);
            SendMessage(hStat, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), 0);
            break;
    
         case WM_MOUSEMOVE:
            pt.x = LOWORD(lParam);
            pt.y = HIWORD(lParam);
            ::GetClientRect(hStat, &rect);
            if(PtInRect(&rect, pt))
            {
               if(bHot==FALSE)
               {
                  bHot = TRUE;
                  SetWindowText(hStat, "HALLO_OVER");
               }
            }
            else
               if(bHot)
               {
                  bHot = FALSE;
                  SetWindowText(hStat, "HALLO_OUT");
               }
            break;
    
         case WM_DESTROY:
            PostQuitMessage(0);
            break;
      }
      return DefWindowProc(hwnd, iMsg, wParam, lParam);
    }
    


  • Hallöchen!

    Wenn ich in meiner

    BOOL CALLBACK StaticWndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
    

    Funktion als return Wert folgendes liefere, dann erhalte ich auch ein WM_MOUSEMOVE...

    return DefWindowProc (hwnd, msg, wp, lp) ;
    

    liefere ich hingegen

    return (CallWindowProc(g_wndprocOld, hwnd, msg, wp, lp));
    

    erhalte ich keines!

    CQ.



  • Ich habe so das ungute Gefühl, wir befinden und in einem Mysterium. 😉



  • Ja, das habe ich auch. Aber irgendwie muß es doch funktionieren! Andere können das ja auch ;-).



  • Was denn? Du hast doch jetzt sogar 2 Möglichkeiten. Entweder du nimmst meine Methode oder die Subclassing-Methode mit DefWindowProc() als Rückgabewert.



  • ... das teste ich nochmal!

    [ Dieser Beitrag wurde am 29.08.2002 um 16:19 Uhr von CQ editiert. ]



  • ... oki, das funktioniert erstmal. Ein kleines Problem bleibt aber noch. Dieses

    ::GetClientRect(GetDlgItem(hw, IDC_STATIC_VERGESSEN), &rect);
    

    liefert ja leider nicht die richtigen Koordinaten vom Static-Element. Top und Left sind immer 0! Somit stimmt also die Positionsbestimmung nicht und ich erhalte halt das Event zur falschen Zeit bzw. Mausbewegung.



  • Mit der SetWindowLongPtr-Variante kann man allerdings WM_NCHITTEST abfangen 😉



  • @geeky
    Jaja, hast ja Recht. 😉

    @CQ
    Das einfachste ist IMHO, die RECT-Struktur direkt nach CreateWindow() des Statics zu füllen.



  • Was hatte -King- denn im Beitrag nach mir geschrieben? Hab's nicht schnell genug mitbekommen :p



  • Hmm, ich habe das jetzt auch mal getestet und die Lösung mittels Sub-Classing
    scheint mir eindeutig besser und eleganter zu sein.
    Wenn ich mir anschaue wieviele WM_MOUSEMOVE gesendet werden, dann wird
    mir schon fast anders beim Gedanken wie oft dort unnötig auf das RECT vom static geprüft wird...
    Da ist die Lösung mittels Sub-Classing deutlich besser für die Performance.



  • Also ich habe nun nur einmal die Prüfung des RECTs vom Static drin... und zwar bei WM_INITDIALOG!



  • Original erstellt von TKool:
    Hmm, ich habe das jetzt auch mal getestet und die Lösung mittels Sub-Classing
    scheint mir eindeutig besser und eleganter zu sein.
    Wenn ich mir anschaue wieviele WM_MOUSEMOVE gesendet werden, dann wird
    mir schon fast anders beim Gedanken wie oft dort unnötig auf das RECT vom static geprüft wird...
    Da ist die Lösung mittels Sub-Classing deutlich besser für die Performance.

    Nochmal für die Langsamen (;)): man braucht das Rect nicht immer im WM_MOUSEMOVE zu füllen. Das geht auch in WM_CREATE direkt nach CreateWindow(). Insofern ist das "Performance-Problem" gelöst.



  • Original erstellt von CQ:
    Also ich habe nun nur einmal die Prüfung des RECTs vom Static drin... und zwar bei WM_INITDIALOG!

    Äh ja, oder so. 😉



  • Nochmal für die Langsamen (): man braucht das Rect nicht immer im WM_MOUSEMOVE zu füllen. Das geht auch in WM_CREATE direkt nach CreateWindow(). Insofern ist das "Performance-Problem" gelöst.

    Danke für die Blumen, aber du verstehst nicht ganz.
    Das man das RECT nur einmal füllen muss ist klar nur ist deine Lösung nicht sonderlich geschickt.
    Natürlich geht es so, aber es ist nicht optimal gelöst, nur bequem.
    Dein Zweig im WM_MOUSEMOVE wird zig mal umsonst abgearbeitet.
    Das halte ich nicht für optimal und schon gar nicht im Sinne des Windows-Konzeptes der Nachrichten.
    Naja, wenn man sich vor dem SubClassing herumdrücken will,
    dann muss man es wohl so machen..

    Wenn du den Mausklick auf einem Button überprüfst, machst du das dann auch so?



  • Du meinst, es wird andauernd überprüft, ob der Cursor im Rect ist? Ja, da hast du recht. Das ist sicher etwas langsamer als das Subgeclasse. Jedoch muss Windows das beim SubClassing ja auch immer wieder überprüfen - ich meine, über welchem Fenster nun das WM_MOUSEMOVE stattfindet. Da das aber low level ist, ist es sicherlich auch schneller. Insofern nehme ich die Blumen gerne zurück. Dann kann ich sie an die Frau meines Herzens weiterreichen. 😉



  • Original erstellt von TKool:
    Wenn du den Mausklick auf einem Button überprüfst, machst du das dann auch so?

    Na, wozu gibt es denn WM_COMMAND?! 😉


Anmelden zum Antworten