Announcement

Collapse
No announcement yet.

wie kann ich eine timer-komponente durch einen thread ersetzen????

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • wie kann ich eine timer-komponente durch einen thread ersetzen????

    tagchen,

    ich habe festgestellt, daß die timerkomponente, wenn viel quellcode drin
    steht, ziemlich resourcen frißt. jetzt wollte ich den timer durch einen
    thread ersetzen. hier mein versuch:

    type
    TLupenThread = class(TThread)
    protected
    procedure Execute; override;
    public
    constructor create;
    end;

    constructor tlupenthread.create;
    begin
    FreeOnTerminate := True;
    inherited Create(False);
    end;

    procedure tlupenthread.execute;
    var r,Rt: TRect;
    Pt, OldPt: tPoint;
    DC: HDC;
    x,y:integer;
    handle:hwnd;
    tick,punkt,akt:integer;

    begin

    while not terminated do
    begin
    {ermitteln des Desktophandles}
    DC:=GetDC(GetDesktopWindow);

    {*****************VERGRÖSSERUNGSBEREICH*********** ***********}
    if vergroeserungsbereich = 'Maus' then
    {Bereich unterhalb der maus wird vergrößert}
    begin
    GetCursorPos(Pt);
    x := 0;
    y := 0;
    {ermittelt die Eckpunkte von panel1}
    GetWindowRect(form1.Handle, Rt);
    end;

    {******************STANDORT DER LUPE**************************}
    if Mausverfolgen = 'Ja' then
    {Lupe folgt der Maus}
    begin
    {abfragen rechter rand}
    if pt.x <= screen.width - form1.width - abwx then form1.left := pt.x +abwx else
    form1.left := screen.width - form1.width;
    {abfragen unterer Rand}
    if pt.y <= screen.height - form1.height - abwx then form1.top := pt.y +abwx else
    form1.top := screen.height - form1.height-abwy;
    end;

    if Mausverfolgen = 'gehweg' then
    {Lupe geht der Maus aus dem weg}
    begin
    {wenn die maus von links kommt geht die lupe nach rechts}
    if (pt.x +10 >= form1.left-10) and (pt.x + 10 <= form1.left) and (pt.y > form1.top)
    and (pt.y < form1.top+form1.height) then
    if form1.left + form1.width + 10 <= screen.width then form1.left := form1.left + 10;

    {wenn die maus von rechts kommt geht die lupe nach links}
    if (pt.x -10 <= form1.left+form1.width+10) and (pt.x - 10 >= form1.left+form1.width) and (pt.y > form1.top)
    and (pt.y < form1.top+form1.height) then
    if form1.left - 10 >= 0 then form1.left := form1.left - 10;

    {wenn die maus von unten kommt geht die lupe nach oben}
    if (pt.y -10 <= form1.top+form1.height+10) and (pt.y - 10 >= form1.top+form1.height)
    and (pt.x > form1.left) and (pt.x < form1.left+form1.width) then
    if form1.top -10 >= 0 then form1.top := form1.top - 10;

    {wenn die maus von oben kommt geht die lupe nach unten}
    if (pt.x > form1.left) and (pt.x < form1.left+form1.width)
    and (pt.y + 10 < form1.top) and (pt.y + 10 > form1.top-10)
    and (form1.top+10+form1.height <= screen.height-10) then form1.top := form1.top + 10;

    end;

    {deskbmp ist vom typ bitmap}
    DeskBmp.Canvas.FillRect(DeskBmp.Canvas.ClipRect);

    if ((OldPt.x<>Pt.x) or (OldPt.y<>Pt.y)) or (GetTickCount - Tick >= 100) // sind 100 Millisekunden vergangen ?
    then
    begin
    Tick := GetTickCount; // sichere neue zeit

    {die Mauszeigerposition wird gespeichert}
    OldPt:=Pt;
    if vergroeserungsbereich = 'Maus' then
    begin
    form1.ScanDC(DC, DeskBmp.Canvas.handle, x, y, Rect(Pt.x-w div
    Herzliche Grüße

    Markus Lemcke
    barrierefreies Webdesign

  • #2
    Hallo Markus,

    das ist definitiv zu viel Text für eine Frage ;-) <br>
    In derartigen Fällen ist es besser, wenn <i>Pseudocode</i> verwendet wird, der beschreibt, was gemacht werden soll. Das könnte zum Beispiel so aussehen:

    <pre>
    procedure tlupenthread.execute;
    var
    ...

    begin
    while not terminated do begin
    Hole_DesktopDC;
    Ermittle_Vergrößerungsbereich;
    Ermittle_Lupenstandort;
    // Thread simuliert einen Timer;
    Sleep(100);
    end;
    end;
    </pre>

    Anstelle der ständigen, CPU-Zeit "fressenden" GetTickCount-Aufrufe ist es eleganter, den Thread über den Aufruf der Win32-API-Funktion <b>Sleep</b> für eine definerte Millisekunden-Zeit schlafen zu legen. Der Windows-Scheduler teilt dem Thread in dieser Zeit keinen Zeitschlitz mehr zu, so das der Thread für diesen Zeitraum faktisch "eingefroren" wird

    Comment


    • #3
      Hi Andreas

      Der Aufruf von Sleep(x) ist richtig, für einen Timer, Markus hat aber die Aufgabe des Threads ein bißchen ungenau beschrieben, es ist ein Überwachungsthread (in meinen Sourcen heißt er TWatchThread).
      Dieser Thread fragt permanent bestimmte Systemwerte ab (z.B. Mousepos, KeyState etc.) sollten diese sich geändert haben ODER seit der letzten Aktualisierung 100 ms vergangen sein wird die entsprechende Lupenaktion getätigt. Die Zeitüberprüfung (alle 100ms) ermöglicht es ohne System-Hooks trotzdem z.B. Mouseclicks oder Fensteränderungen anderer Anwendung im Lupenfenster darzustellen. 100ms sind dann in der Sekunde 10 Neudarstellungen der Lupe, ich glaube kaum das ein Anwender schneller ist. Es erscheint so als ob die Lupe sofort auf jede Anwenderinteraktion reagiert.

      Hi Markus

      Du solltest NUR die Überwachungsroutinen in den Thread packen. Den eigentlichen Lupencode packst Du in eine Funktion die dann durch eine Message aufgerufen wird. Hier sind wir auch bei der Message "wm_UpdatePos" angekommen, KEINER kann Deine Frage beantworten, da "wm_UpdatePos" von mir als Userdefinierte Message im Code definiert worden ist, d.h. sie erfüllt eine ganz spezielle, nur für die Lupe gültige, Aufgabe. Diese Message wird von dem TLupenThread (TWatchThread) mit PostMessage() an das Lupen fenster gesendet. Nun, man hätte auch den Methodik von Borland beschreiten können und mit TLupenThread.Synchronize() arbeiten können, aber diese methode arbeitet mit SendMessage() was im Lupen-Fall unschöne Nebeneffecte hervorruft. 1.) die Aktuallisierung wird dann bei jeder kleinen Änderung ausgeführt, 2.) die Synchronize Methodik von Borland kann zu Deadlocks führen. Ich habe ganz bewußt PostMessage(LupenForm.Handle, wm_UpdatePos, 0, 0) benutzt. Stell dir vor Dein Lupencode benötigt ca. 5 ms um das Bild zu holen,vergrößern und darzustellen. Der User schleift die Maus aber oft und schnell hinundher, so daß nun alle 1ms geupdated werden muß. Mit SendMessage() würde die "Mausbewegung" gebremst da Deine Routine ja 5ms braucht und SOFORT auf jede Bewegung mit neuzeichnen reagiert. Mit PostMessage() wird die "wm_UpdatePos" Message in den Anwendungsinternen Messagequeue gestellt. Das Lupenfenster "holt" sich dann, wenn Zeit ist, alle Messages aus diesem Queue, und bearbeitet diese. Kurz: PostMessage() stellt im Lupencode sozusagen ein "Zeit/CPU-Auslastungs Synchronizer" dar, der verhindert das die Lupen-Darstellungs-Routine das System blockiert. Auch deshalb werden nach der Lupen-Darstellung alle noch nicht bearbeiteten "wm_UpdatePos" Messages aus dem MessageQueue entfernt, mit PeekMessage().
      Nun, Deine TTimer Methode hat im Grunde das gleiche Problem wie mit SendMessage().

      Du siehst, in meinem Code ist JEDE Kleinigkeit der Programmierung wichtig, so das das Gesamtsystem der Lupe ausgewogen reagiert. Eine Lupe ist eben kein einfaches Eingabeformular sondern schon ein bißchen mehr, zumindestens sollte man das Zusammenspiel aller funktionen des Windows-Betriebssystem kennen.

      Generell kannst Du die Lupe in 2 Modulen beschreiben:

      A.) Überwachung des Systems (Mouse, Keyboard, Fensteränderungen)

      B.) Darstellung der Lupe

      Wichtig ist nun das Modul A pemanent im Hintergrund überwacht, also ein Thread, und das Modul B nicht schneller aufgerufen wird als es selber abgearbeitet ist. Dieser Fall wird mit der Synchronisierung (Modul A und B) durch PostMessage() erreicht.

      Gruß Hage

      Comment


      • #4
        Hi Markus

        Eins noch, Du selber sagst das meine Lupe sauber arbeitet, warum kopierst Du nicht den TWatchThread aus meinen Sourcen und nutzt diesen so wie er ist ? Ich verstehe das Du wissen möchtest wie was funktioniert, aber man muß das Rad doch nicht zweimal neuerfinden.

        Gruß Hage

        Comment


        • #5
          tag hagen,

          sehr erfreut was von dir zu "sehen" und dann noch soviel!!!
          meine lupe hat ja einige dinge die deine nicht hat. um einfach deinen code zu übernehmen, muß
          ich ihn zuerst mal verstehen, damit ich ihn so abändern kann, das er in meinen restlichen quellcode
          paßt!!! und die zusammenhänge waren mir bisher höchst unklar!!!!!
          ich werde das was du geschrieben hast ausdrucken und in ruhe durchlesen und dann mal schauen
          ob ich das nicht gebacken bekomme!!!!

          also, danke nochmal!!!! vielleicht kapiere ich es jetzt!!!!

          mfg

          markus

          p.s. du schreibst du hast die message wm_updatepos selbst definiert.
          kann meine message auch anders heißen????
          Herzliche Grüße

          Markus Lemcke
          barrierefreies Webdesign

          Comment

          Working...
          X