Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   InvalidateRect und 100% CPU ? (https://www.delphipraxis.net/122921-invalidaterect-und-100-cpu.html)

EWeiss 24. Okt 2008 10:25


InvalidateRect und 100% CPU ?
 
da bei mir die Button nicht neu gezeichnet werden wenn ich mit der maus drüberfahre
habe ich mich zu InvalidateRect entschlossen.

Delphi-Quellcode:
begin
  ImgW := ImgW div cardinal(StateMax);
  if IsWindowEnabled(WinHandle) then
  begin
    UseState := 1;
    if (WinHandle = GetFocus) and (StateMax > 3) then
      UseState := 4;
    GetCursorPos(CurPos);
    ScreenToClient(WinHandle, CurPos);
    InvalidateRect(WinHandle, @rc, False);
    UpdateWindow(WinHandle);
    if PtInRect(rc, CurPos) then
      if IsLButtonDown then
      begin
        if WinHandle = GetFocus() then
          if (GetCursor = LoadCursor(0, IDC_ARROW)) and (StateMax > 1) then
            UseState := 2;
      end else
      if StateMax > 4 then UseState := 5;
  end else
  if StateMax > 2 then UseState := 3;
end;
Jetzt funktioniert alles bestens aber mit gut 80-100% CPU
wenn ich mit der Maus innerhalb des Window bin.

Das kann es doch nicht sein oder ?
Hat vielleicht jemand eine lösung dafür ?

gruss Emil

Roachford 24. Okt 2008 10:37

Re: InvalidateRect und 100% CPU ?
 
InvalidateRect() bringt dir so lange keinen Vorteil, so lange du sofort mit UpdateWindow() das Paint erzwingst. InvalidateRect() würde dir Vorteile bringen, wenn du Windows die dirty areas sammeln lässt und dann kombinierte und effektivere Paint Aufrufe machen lässt.

1. InvalidateRect() ohne das UpdateWindow() dahinter
2. Das Clipping Rectangle aus der PAINTSTRUCT von BeginPaint() beachten und entsprechend BitBlt() auf dieses Rechteck beschränken und Zeichenoperationen ausserhalb des Rechtecks komplett unterlassen im Paint.

EWeiss 24. Okt 2008 10:43

Re: InvalidateRect und 100% CPU ?
 
Zitat:

Zitat von Roachford
InvalidateRect() bringt dir so lange keinen Vorteil, so lange du sofort mit UpdateWindow() das Paint erzwingst. InvalidateRect() würde dir Vorteile bringen, wenn du Windows die dirty areas sammeln lässt und dann kombinierte und effektivere Paint Aufrufe machen lässt.

1. InvalidateRect() ohne das UpdateWindow() dahinter
2. Das Clipping Rectangle aus der PAINTSTRUCT von BeginPaint() beachten und entsprechend BitBlt() auf dieses Rechteck beschränken und Zeichenoperationen ausserhalb des Rechtecks komplett unterlassen im Paint.

Habe es jetzt so geändert ..
Delphi-Quellcode:
            begin
              ImgW := ImgW div cardinal(StateMax);
              if IsWindowEnabled(WinHandle) then
              begin
                UseState := 1;
                if (WinHandle = GetFocus) and (StateMax > 3) then
                  UseState := 4;
                GetCursorPos(CurPos);
                ScreenToClient(WinHandle, CurPos);

                GetClientRect(WinHandle, rc);
                InvalidateRect(WinHandle, @rc, False);

                if PtInRect(rc, CurPos) then
                  if IsLButtonDown then
                  begin
                    if WinHandle = GetFocus() then
                      if (GetCursor = LoadCursor(0, IDC_ARROW)) and (StateMax > 1) then
                        UseState := 2;
                  end else
                  if StateMax > 4 then UseState := 5;
              end else
              if StateMax > 2 then UseState := 3;
            end;
Das bringt einiges und es wird nur der Client bereich neu gezeichnet auf dem sich
die Maus gerade befindet.
Verstehen tu ich das ganze trotzdem nicht warum bei mir das Paintevent nicht anspringt
ohne das ich über InvalidateRect gehe.

Die Main proc macht nichts besonderes..
Delphi-Quellcode:
      WM_PAINT:
      begin
        BeginPaint(WinHandle, ps);
        PaintDoubleBuffer(WinHandle, ps.hdc);
        EndPaint(WinHandle, ps);
        Result := 0;
        exit;
      end;
gruss Emil

Luckie 24. Okt 2008 11:15

Re: InvalidateRect und 100% CPU ?
 
Wozu das Result und das Exit am Ende?

EWeiss 24. Okt 2008 11:22

Re: InvalidateRect und 100% CPU ?
 
Zitat:

Zitat von Luckie
Wozu das Result und das Exit am Ende?

Um aus der Proc zu springen.
Da sonst meine DefWindowProc aufgerufen wird welche die WM_NCHITTEST
Messagen verarbeitet.

gruss Emil

Luckie 24. Okt 2008 11:24

Re: InvalidateRect und 100% CPU ?
 
Und diese Nachricht soll nicht verarbeitet werden? Dann verarbeite sie doch und tue nichts. Dann wird deutlicher was du vorhast. So musste ioch die Frage stellen, das entfällt, wen du es so machst, wie ich es vorgeschlagen habe.

EWeiss 24. Okt 2008 11:28

Re: InvalidateRect und 100% CPU ?
 
Zitat:

Zitat von Luckie
Und diese Nachricht soll nicht verarbeitet werden? Dann verarbeite sie doch und tue nichts. Dann wird deutlicher was du vorhast. So musste ioch die Frage stellen, das entfällt, wen du es so machst, wie ich es vorgeschlagen habe.

Reden wir aneinander vorbei ?
Oder was willst mir damit sagen..

Meine APP Proc
Delphi-Quellcode:
function WndProc(WinHandle: HWND; Msg: UINT; wP: WParam; lP: LParam): longint;
  stdcall;
var
  ps:  TPaintStruct;
  rw:  PRect;
  hBut: THandle;
  imgW: cardinal;
  pMM: PMinMaxInfo;
  CaptionHeight: integer;
  p:   TPoint;

begin

  with SkinEngine do
  begin

    case Msg of
      WM_GETMINMAXINFO:
      begin
        pMM := PMinMaxInfo(lP);
        pMM^.ptMinTrackSize.x := MinTrackSizeX[0];
        pMM^.ptMinTrackSize.y := MinTrackSizeY[0];
      end;
      WM_COMMAND:
      begin
        if ButtonSysCommand(WinHandle, wP) then
        begin
          Result := 0;
          Exit;
        end;
        case LoWord(wP) of
          ID_AEROCRYSTAL:
          begin
            if GetCheckButtonStatus(GetMainItem(ID_AEROCRYSTAL)) then
            begin
              SplitColorARGB(SK_AEROCOLOR, Alpha, Red, Green, Blue);
              FConfig.AeroColor[ColorARGB(GetTrackValue(GetMainItem(
                ID_TRACK_OPACITY)), RGB(Red, Green, Blue)), SK_WRITE];
              SetCheckButtonStatus(GetMainItem(ID_AERODISABLE), False);
              SetCheckButtonStatus(GetMainItem(ID_AEROBLUR), False);
              FConfig.AeroEmulate[SK_WRITE, SK_WRITE];
              FConfig.AeroBlueLevel[SK_FALSE, SK_WRITE];
              SetTrackValue(GetMainItem(ID_TRACK_BLURLEVEL), SK_AEROBLURLEVEL);

              SetTimer(WinHandle, AERO_TIMER, SK_AEROTIMERDELAY, nil);

              FConfig.UseVistaBlur[SK_FALSE, SK_WRITE];
              FConfig.UseVistaCrystal[SK_WRITE, SK_WRITE];
              FConfig.TextRendering[TextRenderingHintAntiAlias, 1];
            end else
            begin
              FConfig.TextRendering[TextRenderingDefault, 1];
              KillTimer(WinHandle, AERO_TIMER);
              FConfig.AeroEmulate[SK_FALSE, SK_WRITE];

              SetCheckButtonStatus(GetMainItem(ID_AERODISABLE), True);

              FConfig.UseVistaBlur[SK_FALSE, SK_WRITE];
              FConfig.UseVistaCrystal[SK_FALSE, SK_WRITE];
            end;
            GetWindowRect(WinHandle, rc);
            MoveBackground(rc.Left, rc.Top);
            FUpdateWindow(WinHandle, False);
          end;
          ID_AEROBLUR:
          begin
            if GetCheckButtonStatus(GetMainItem(ID_AEROBLUR)) then
            begin
              SplitColorARGB(SK_AEROCOLOR, Alpha, Red, Green, Blue);
              FConfig.AeroColor[ColorARGB(GetTrackValue(GetMainItem(
                ID_TRACK_OPACITY)), RGB(Red, Green, Blue)), SK_WRITE];
              SetCheckButtonStatus(GetMainItem(ID_AERODISABLE), False);
              SetCheckButtonStatus(GetMainItem(ID_AEROCRYSTAL), False);
              FConfig.AeroEmulate[SK_WRITE, SK_WRITE];
              FConfig.AeroBlueLevel[6, SK_WRITE];
              SetTrackValue(GetMainItem(ID_TRACK_BLURLEVEL), SK_AEROBLURLEVEL);
              SetTimer(WinHandle, AERO_TIMER, SK_AEROTIMERDELAY, nil);

              FConfig.UseVistaCrystal[SK_FALSE, SK_WRITE];
              FConfig.UseVistaBlur[SK_WRITE, SK_WRITE];
              FConfig.TextRendering[TextRenderingHintAntiAlias, 1];
            end else
            begin
              FConfig.TextRendering[TextRenderingDefault, 1];
              KillTimer(WinHandle, AERO_TIMER);
              FConfig.AeroEmulate[SK_FALSE, SK_WRITE];

              SetCheckButtonStatus(GetMainItem(ID_AERODISABLE), True);

              FConfig.UseVistaBlur[SK_FALSE, SK_WRITE];
              FConfig.UseVistaCrystal[SK_FALSE, SK_WRITE];
            end;
            GetWindowRect(WinHandle, rc);
            MoveBackground(rc.Left, rc.Top);
            FUpdateWindow(WinHandle, False);
          end;
          ID_AERODISABLE:
          begin
            if GetCheckButtonStatus(GetMainItem(ID_AERODISABLE)) then
            begin
              SetCheckButtonStatus(GetMainItem(ID_AEROBLUR), False);
              SetCheckButtonStatus(GetMainItem(ID_AEROCRYSTAL), False);
              FConfig.AeroEmulate[SK_FALSE, SK_WRITE];
              FConfig.TextRendering[TextRenderingDefault, 1];
              KillTimer(WinHandle, AERO_TIMER);

              FConfig.UseVistaBlur[SK_FALSE, SK_WRITE];
              FConfig.UseVistaCrystal[SK_FALSE, SK_WRITE];

              GetWindowRect(WinHandle, rc);
              MoveBackground(rc.Left, rc.Top);
              FUpdateWindow(WinHandle, False);
            end else
              SetCheckButtonStatus(GetMainItem(ID_AERODISABLE), True);
          end;
          ID_TRACK_OPACITY:
          begin
            if SK_AEROEMULATE <> 0 then
            begin
              SplitColorARGB(SK_AEROCOLOR, Alpha, Red, Green, Blue);
              FConfig.AeroColor[ColorARGB(lP, RGB(Red, Green, Blue)), SK_WRITE];
              GetWindowRect(WinHandle, rc);
              MoveBackground(rc.Left, rc.Top);
              FUpdateWindow(WinHandle, False);
            end;
          end;
          ID_TRACK_BLURLEVEL:
          begin
            if lP <> SK_AEROBLURLEVEL then
            begin
              FConfig.AeroBlueLevel[lP, SK_WRITE];
              if SK_AEROEMULATE = 1 then
              begin
                GetWindowRect(WinHandle, rc);
                MoveBackground(rc.Left, rc.Top);
                FUpdateWindow(WinHandle, False);
              end;
            end;
          end else
          begin
            Result := 0;
            exit;
          end;
        end;
      end;
      WM_SIZE:
      begin
        DrawBackground;
        EnumChildWindows(WinHandle, @AnchorEnum, 0);
        FUpdateWindow(WinHandle, False);
      end;
      WM_SETTEXT:
      begin
        Result := DefWindowProc(WinHandle, Msg, wP, lP);
        // Aktualisiere das Caption
        PaintBackground;
        // Nur Caption neuzeichnen
        GetClientRect(WinHandle, rc);

        GetImageSize(GetProperty(WinHandle, FORM_TopMid),
          imgW, cardinal(rc.Bottom));
        InvalidateRect(WinHandle, @rc, False);
        UpdateWindow(WinHandle);
        exit;
      end;
      WM_NCLBUTTONDBLCLK:
      begin
        if IsIconic(WinHandle) then
        begin
          p.X := LoWord(lP);
          p.Y := HiWord(lP);
          ScreenToClient(WinHandle, p);

          GetImageSize(GetProperty(WinHandle, FORM_TopMid),
            imgW, cardinal(CaptionHeight));
          if p.Y < CaptionHeight then
          begin
            if IsZoomed(WinHandle) then
              ButtonSysCommand(WinHandle, MAKELONG(ID_RESTORE, 0))
            else
              ButtonSysCommand(WinHandle, MAKELONG(ID_MAXIMIZE, 0));

            Result := 0;
            exit;
          end;
        end;
      end;
      WM_NCACTIVATE:
      begin
        hBut := GetDlgItem(WinHandle, ID_LED);
        if hBut <> 0 then
        begin
          Result := DefWindowProc(WinHandle, Msg, wP, lP);
          if MainWindow(0) = GetForegroundWindow then
            gColorCaption := SK_ACTIVECAPTION
          else
            gColorCaption := SK_INACTIVECAPTION;

          // Aktualisiere das Caption
          PaintBackground;

          // Nur Caption neuzeichnen
          GetClientRect(WinHandle, rc);
          GetImageSize(GetProperty(WinHandle, FORM_TopMid),
            imgW, cardinal(rc.Bottom));
          InvalidateRect(WinHandle, @rc, False);
          UpdateWindow(WinHandle);
          exit;
        end;
      end;
      WM_ERASEBKGND:
      begin
        Result := 1;
        exit;
      end;
      WM_PAINT:
      begin
        BeginPaint(WinHandle, ps);
        PaintDoubleBuffer(WinHandle, ps.hdc);
        EndPaint(WinHandle, ps);
        Result := 0;
        exit;
      end;
      WM_DESTROY:
      begin
        RemoveAllImageResource;
        DestroyWindowResource(WinHandle);

        PostQuitMessage(0);
        Result := 0;
        Exit;
      end;
      WM_TIMER:
      begin
        if IsCompositionEnabled = False then
        begin
          if (SK_AEROEMULATE = 1) and IsAeroLayered then
          begin
            if IsLButtonDown = False then
              IsMoving := False;
            if (IsMoving = False) or (IsLButtonDown and (IsMoving)) then
            begin
              GetWindowRect(WinHandle, rc);
              MoveBackground(rc.Left, rc.Top);
              FUpdateWindow(WinHandle, False);
            end;
          end;
        end;
      end;
      WM_NCLBUTTONDOWN:
        IsMoving := True;
      WM_MOVING:
      begin
        if IsCompositionEnabled = False then
        begin
          if (SK_AEROEMULATE = 1) and IsAeroLayered then
          begin
            rw := PRect(lP);
            MoveBackground(rw.Left, rw.Top);
            FUpdateWindow(WinHandle, False);
            Result := 1;
            exit;
          end;
        end;
      end;
    end;

    Result := skDefWindowProc(WinHandle, Msg, wP, lP);
  end;

end;
Meine Def Proc
Delphi-Quellcode:
function skDefWindowProc(WinHandle: HWND; Msg: UInt; wP: WParam; lP: lParam): longint;
  stdcall;
var
  rc: TRect;
  p: TPoint;
  CaptionHeight: cardinal;
  xF, yF, xSide, BORDER: integer;
  HITTEST: integer;

begin

  Result := DefWindowProc(WinHandle, Msg, wP, lP);

  HITTEST := 0;

  if Msg = WM_NCHITTEST then
  begin

    SkinEngine.GetImageSize(SkinEngine.GetProperty(WinHandle, FORM_TopMid),
      imgW, CaptionHeight);

    p.X := LoWord(lP);
    p.Y := HiWord(lP);

    ScreenToClient(WinHandle, p);
    if IsZoomed(WinHandle) = False then
    begin
      if Result = HTCLIENT then
      begin
        HITTEST := HTCAPTION;
        if SkinEngine.SK_DRAG_BACKGROUND = 0 then
        begin
          if (p.Y > integer(CaptionHeight)) and (CaptionHeight > 0) then
          begin
            HITTEST := HTNOWHERE;
            if WinHandle <> GetForegroundWindow then
              SetFocus(WinHandle);
          end;
        end;
        if SkinEngine.WinResizable(WinHandle) <> 0 then
          GetClientRect(WinHandle, rc);

        xF    := rc.Right;
        yF    := rc.Bottom;
        xSide := 0;
        BORDER := GetSystemMetrics(32);
        if ((p.X >= xF - BORDER) and ((p.Y >= yF - BORDER))) then
        begin
          HITTEST := HTBOTTOMRIGHT;
        end else
        begin
          // Linke Seite
          if (p.X <= 8) then
          begin
            if (p.X <= BORDER) then
              HITTEST := HTLEFT;
            xSide := 1;
          end;
          // Rechte Seite
          if (p.X >= xF - 8) then
          begin
            if (p.X >= xF - BORDER) then
              HITTEST := HTRIGHT;
            xSide := 2;
          end;
          // Obere Seite
          if (p.Y <= BORDER) then
          begin
            HITTEST := HTTOP;
            if (xSide = 1) then
              HITTEST := HTTOPLEFT
            else if (xSide = 2) then
              HITTEST := HTTOPRIGHT;
          end;
          // Untere Seite
          if (p.Y >= yF - BORDER) then
          begin
            if (xSide = 1) then
              HITTEST := HTBOTTOMLEFT
            else
              HITTEST := HTBOTTOM;
          end;
        end;
      end;
      Result := HITTEST;
    end else
    begin
      if p.Y < integer(CaptionHeight) then
        Result := HTCAPTION;
    end;
  end;

end;
Ich springe bei WM_PAINT raus um diese danach nicht zu verarbeiten wenn das Paint Event beendet ist.
Was ist da falsch ?

gruss Emil

Luckie 24. Okt 2008 11:33

Re: InvalidateRect und 100% CPU ?
 
OK, jetzt habe ich es verstanden.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:26 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz