Einzelnen Beitrag anzeigen

Vjay

Registriert seit: 2. Dez 2003
Ort: Berlin/Eschede
481 Beiträge
 
Delphi 7 Professional
 
#3

Re: Welche Windows-Events zum Zeichnen eines Buttons

  Alt 9. Dez 2005, 11:26
InvalidateRect erzeugt doch auch nur eine WM_PAINT ( + evtl. WM_ERASEBKGND) ...

Ich vermute, dass manche (Windowsbehandlungs-)Funktionen den Button direkt über DrawFrameControl neu Zeichnen und das Windows-Messageprinzip umgehen.

Ich habe nämlich genau das gleiche Problem.
Ein Beispiel: Wenn man in einer nicht (Manifest-) XP-Anwendung die Maustaste auf dem Button gedrückt hält, so wird dieser neu gezeichnet, aber ich erhalte nie eine Message darüber.

Evtl. hilft dir ein Funktionshook weiter, ich habe an diesem Punkt keine Lust mehr gehabt weiter zu suchen.

Weiterhelfen konnte mir damals auch niemand, da dies doch wirklich tief ins Eingemachte geht.

Ich hänge hier mal meine alte WNDProc an, die größtenteils funktioniert.
Zur Erklärung: Während die Maustasten gedrückt werden, erzeuge ich ein Overlay-Fenster, welches das Neuzeichnen des Buttons durch die Original-Wndproc verdeckt.
Es gibt zwar Funktionen um das Neuzeichenen von Fenster vorübergehend zu unterdrücken, aber von diesen kann ich nur abraten, da sie negative Nebeneffekte besitzen. Besonders wenn man in Fremdanwendungen "rumwurschtelt" sollte man sich so transparent und unauffällig benehmen wie es nur möglich ist.

Delphi-Quellcode:
// result= true = originalwndproc wird direkt aufgerufen
function TPulseButton.buttonWndProc( const handle: dWord; const Msg: cardinal; const wParam, lParam: dWord; var rueckgabe: dWord): Boolean;
begin
 result:= false;
 if MovingControlWndProc( handle, Msg, wParam, lParam) then exit;

 
   case Msg of
    WM_PAINT{, WM_NCPAINT}: begin
               if wParam= 0 then Paint
               else result:= true;
              end;
    WM_TIMER: begin
               if WParam = 999 then NextPulse
               else if WParam = 996 then
               begin
                if not isAltDown then
                begin
                 killTimer(handle, 996);
                 InvalidateRect(handle, NIL, false);
                end;
               end
               else if WParam = 998 then checkMouseOver
               else if WParam = 995 then
               begin
                killTimer(handle, 995);
                InvalidateRect(handle, NIL, false);
               end
               else result:= true;

               result:= true;
              end;
   WM_SIZE, WM_WINDOWPOSCHANGED, WM_MOVE: begin
              Rueckgabe := CallWindowProc( origWndProc, handle, Msg, wParam, lParam);
              InvalidateRect(handle, NIL, false);
             end;
   WM_LBUTTONDOWN: begin
                     if not LButtonDown then
                     begin
                      LButtonDown:= true;
                      activate;
                      createOverlayWindow;
                      Rueckgabe := CallWindowProc( origWndProc, handle, Msg, wParam, lParam);
                      destroyOverlayWindow;
                      InvalidateRect(handle, NIL, false);
                     end;
                    end;
   WM_LBUTTONUP, WM_LBUTTONDBLCLK: begin
                   if LButtonDown then
                   begin
                    LButtonDown:= false;
                    createOverlayWindow;
                    Rueckgabe := CallWindowProc( origWndProc, handle, Msg, wParam, lParam);
                    destroyOverlayWindow;
                    InvalidateRect(handle, NIL, false);
                   end;
                  end;
   WM_ENABLE, WM_RBUTTONDBLCLK, WM_SHOWWINDOW, WM_NCACTIVATE, WM_CAPTURECHANGED,
   WM_KILLFOCUS, WM_SETFOCUS, BM_SETSTATE, BM_SETSTYLE, WM_SETTEXT: begin
                  createOverlayWindow;
                  Rueckgabe := CallWindowProc( origWndProc, handle, Msg, wParam, lParam);
                  destroyOverlayWindow;
                  InvalidateRect(handle, NIL, true);
                  Paint;
                  InvalidateRect(handle, NIL, false);
                 end;
    WM_NCHITTEST: begin
                   Rueckgabe := HTCLIENT;
                   InvalidateRect(handle, NIL, false);
                  end;
    WM_MOUSEMOVE: begin
                   Rueckgabe := CallWindowProc( origWndProc, handle, Msg, wParam, lParam);
                   InvalidateRect(handle, NIL, false);
                   killTimer(handle, 998);
                   setTimer(handle, 998, 100, NIL);
                  end;
    WM_ACTIVATEPULSING: Pulsing:= boolean( wParam);
    WM_NCDESTROY: begin
                 Rueckgabe := CallWindowProc( origWndProc, handle, Msg, wParam, lParam);
                 deInitControl( handle);
                end;
   else
    result:= true;
   end;
 
end;
Dazu noch der besagte Funktionshook hat mir recht passable Ergebnisse gebracht. Ist allerdings größtenteils ungetestet. Es gibt einfach zuviele Anwendungen und Fälle.
Wer später bremst ist eher tot.
  Mit Zitat antworten Zitat