[gelöst]Mausevent bei Ownerdraw-Commoncontrols(XP-Controls) verarbeiten



  • Hi Leute,

    Ich habe folgendes Problem und ich hoffe, dass mir hier jemand helfen kann.

    In meiner Firma haben wir von den alten Controls auf die neuen CommonControls im WinXP-Stil umgestellt. Dabei sollte die Funktionalität der alten Controls erhalten bleiben.
    Das Problem war die Schriftfarbe bei den Controls. Bei Groupbox und Button kann man die nur dann ändern, wenn man die Controls OWNERDRAW macht und selbst zeichnet. Bei der Groupbox hat auch alles wunderbar geklappt, nur beim Button habe ich ein Problem.

    Wenn die Maus den über den Button fährt, dann soll er ja anfangen so hellbläulich zu schimmern(PBS_HOT) und wenn sie ihn wieder verlässt, dann soll er ganz normal aussehen(PBS_NORMAL).

    Mit WM_MOUSEMOVE und WM_SETCURSOR bekomme ich mit, wenn die Maus den Bereich betritt, oder verlässt. Aber was muss ich tun, mein Button anschließend die Message WM_DRAWITEM, oder WM_PAINT erhält?

    Ich habe bereits UpdateWindow() und RedrawWindow() mit dem Button und mit dem ParentFenster versucht. Ich habe auch direkt mit SendMessage() WM_PAINT und WM_DRAWITEM an die Fenster geschickt, aber iwie kommen die Nachrichten nicht an.

    Vielleicht kann mir ja jemand sagen, was ich falsch mache 😞

    Die beiden Variablen sind außerhalb der Main deklariert, damit sie global gültig sind:

    bool bMouseOver=false;
    HWND btn;
    

    Der Button wurde in der Main wie folgt erstellt:

    btn = CreateWindowA("BUTTON", "Mein Button", WS_CHILD | WS_TABSTOP | WS_VISIBLE | BS_OWNERDRAW, 50, 50, 300, 30, hWnd, NULL, hInstance, NULL);
    

    Und das ist die WndProc:

    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;
    switch (message)
    { 
      case WM_PAINT:
      {
        hdc = BeginPaint(hWnd, &ps);
        if (hWnd == btn) {
          HTHEME hTheme = OpenThemeData(btn, L"Button");
          RECT rc;
          rc.left = rc.top = 0;
          rc.right = 300;
          rc.bottom = 30;
    
          bMouseOver = CursorInArea(btn);
    
          int state = bMouseOver ? PBS_HOT : PBS_NORMAL;
    
          DrawThemeBackground(hTheme, hdc, BP_PUSHBUTTON, state, &rc, 0);
          DTTOPTS opts = { 0 };
          opts.dwSize = sizeof(opts);
          opts.crText = RGB(0xff,0x10,0x10);
          opts.dwFlags |= DTT_TEXTCOLOR;
          WCHAR caption[255];
          GetWindowText(btn, caption, 255);
          size_t cch;
          StringCchLength(caption, (sizeof(caption)/sizeof(caption[0])), &cch);
          DrawThemeTextEx(hTheme, hdc, BP_PUSHBUTTON, PBS_NORMAL, caption, cch, DT_CENTER | DT_SINGLELINE | DT_VCENTER, &rc, &opts);
    
          CloseThemeData(hTheme);
          return true;
        }
       EndPaint(hWnd, &ps);
       break;
      }
      case WM_DESTROY:
        PostQuitMessage(0);
        break;
      break;
      case WM_DRAWITEM:
      {
        LPDRAWITEMSTRUCT IS = (LPDRAWITEMSTRUCT)lParam;
        if (IS->hwndItem == grp) {
          hdc = IS->hDC;
          RECT c;
          c.left = 0;
          c.top = 0;
          c.bottom = c.right = 500;
    
          WCHAR caption[255];
          GetWindowText(grp, caption, 255);
          COLORREF textColor = RGB(0,255,255);
          WCHAR Class[255] = L"EDIT";
          int Part = EP_BACKGROUND;
          int State = EBS_DISABLED;
    
          c.top += 7;
          HTHEME hTheme = OpenThemeData(grp, L"Button");
          DrawThemeBackground(hTheme, hdc, BP_GROUPBOX, GBS_NORMAL, &c, NULL);
          HTHEME textTheme = OpenThemeData(grp, Class);
          size_t cch;
          c.top -= 7;
          c.left += 10;
          RECT rcText;
          StringCchLength(caption, (sizeof(caption)/sizeof(caption[0])), &cch);
          GetThemeTextExtent(hTheme, hdc, BP_GROUPBOX, GBS_NORMAL, caption, cch, DT_LEFT | DT_SINGLELINE, &c, &rcText);
          DrawThemeBackground(textTheme, hdc, Part , State, &rcText,0);
          CloseThemeData(textTheme);
    
          DTTOPTS opts = { 0 };
          opts.dwSize = sizeof(opts);
          opts.crText = textColor;
          opts.dwFlags |= DTT_TEXTCOLOR;
    
          DrawThemeTextEx(hTheme, hdc, BP_GROUPBOX, GBS_NORMAL, caption, cch, DT_LEFT | DT_SINGLELINE, &c, &opts);
          CloseThemeData(hTheme);
          return true;    
        } else if(IS->hwndItem == btn) {
          HTHEME hTheme = OpenThemeData(btn, L"Button");
          hdc = IS->hDC;
    
          bool bIsPressed =   (IS->itemState & ODS_SELECTED);
          bool bIsFocused  = (IS->itemState & ODS_FOCUS);
    
          RECT rc;
          rc.left = rc.top = 0;
          rc.right = 300;
          rc.bottom = 30;
    
          bMouseOver = CursorInArea(btn);
    
          int state = bIsPressed ? PBS_PRESSED : (bMouseOver ? PBS_HOT : (bIsFocused ? PBS_DEFAULTED : PBS_NORMAL));
    
          DrawThemeBackground(hTheme, hdc, BP_PUSHBUTTON, state, &rc, 0);
          DTTOPTS opts = { 0 };
          opts.dwSize = sizeof(opts);
          opts.crText = RGB(0xff,0x10,0x10);
          opts.dwFlags |= DTT_TEXTCOLOR;
          WCHAR caption[255];
          GetWindowText(btn, caption, 255);
          size_t cch;
          StringCchLength(caption, (sizeof(caption)/sizeof(caption[0])), &cch);
          DrawThemeTextEx(hTheme, hdc, BP_PUSHBUTTON, PBS_NORMAL, caption, cch, DT_CENTER | DT_SINGLELINE | DT_VCENTER, &rc, &opts);
    
          CloseThemeData(hTheme);
          return true;
        }
      }
      case WM_SETCURSOR:
      case WM_MOUSEMOVE:
      {
        if ((bMouseOver && !CursorInArea(btn)) || (!bMouseOver && CursorInArea(btn))) { //Wenn die Maus den Breiech betritt, oder verlässt
          //???!!!???
        }
      }
      default:
         return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
    }
    

    Schonmal vielen Dank 😃



  • Ich hab's durch rumprobieren doch noch herausgefunden...

    Ich muss WM_KILLFOCUS senden, da es dazu führt, dass das Control neu gezeichnet wird.

    SendMessage(btn, WM_KILLFOCUS, (WPARAM)btn, NULL);
    

    Dadurch ist der Übergang zwar nicht so schön smooth, wie bei den von Windows verwalteten Controls, aber so bin ich auch schon zufrieden ^^



  • Soley schrieb:

    Ich habe bereits UpdateWindow() und RedrawWindow() mit dem Button und mit dem ParentFenster versucht. Ich habe auch direkt mit SendMessage() WM_PAINT und WM_DRAWITEM an die Fenster geschickt, aber iwie kommen die Nachrichten nicht an.

    Ich hätte es eventuell mal mit InvalidateRect() probiert. Das sagt dem System, daß der angegebenene Bereich neu gezeichnet werden soll.

    PS: Sorry, wenn das etwas verpätet kommt, aber soviel Code auf einmal kann einen schon abschrecken.



  • Kein Problem ^^

    Ich finde es auch abschreckend, sich erst in Code einzulesen, der über 100 Zeilen hat, ich hätte ihn noch etwas mehr kürzen sollen ^^"

    Trotzdem danke für die Mühe 🙂

    Edit:
    Mit

    InvalidateRect(btn,NULL,true);
    

    hat es übrigens auch funktioniert 😃


  • Mod

    1. Man sendet kein WM_KILLFOCUS! Das ist eine interne Nachricht. Das gehörtin den Bereich Unfug/Unsitte!
    2. Wenn Du möchtest, dass sich Dein Control bei verschiedenen Ereignissen neu zeichnet, dann Ruf einfach InvalidateRect auf.
    3. Wenn Du wissen willst wann die Maus Dein Fenster betritt oder verlässt, dann reagiere auf WM_MOUSEMOVE bzw. TrackMouseEvent!
    4. Ich würde Dir raten, das Ganze Ownerdraw Zeugsin einer eigenen Controlklasse zu verbergen.



  • Mit MouseTrackEvent habe ich es bereits versucht und es hat nicht geklappt.


Anmelden zum Antworten