Announcement

Collapse
No announcement yet.

Thread Teil eines Objektes?

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

  • Thread Teil eines Objektes?

    Hallo Leute!

    Ich habe folgendes Problem mit einem Thread. Ich will ihn wie<br>
    folgt aufrufen:<br><br>
    <font face="Courier New" size="2">CreateThread(Nil, 0, @derTread, Nil, 0 ,THID),</font><br><br>
    Die Aufgerufene procedure TEinObject.derthread(NotUsed : pointer);<br><br>
    ist dabei der Teil eines Objectes aus welchem der Thread aber auch aufgerufen. dies funktionier aber leider nicht. Ich danke für jede Hilfe<br> Hendrik

  • #2
    Hallo,

    wenn eine Methode (die implizit den Parameter Self verwendet) an Win32 übergeben werden soll, muss diese über <b>MakeObjectInstance</b> vorbereitet und nach dem Gebrauch über <b>FreeObjectInstance</b> wieder entsorgt werden

    Comment


    • #3
      hallo andreas.

      kannst du mir zufällig noch erklären wie ich das ganze durchführen kann? leider sagt mir die delphi hilfe weder zu MakeObjectInstance noch zu FreeObjectInstance etwas (nicht einmal die volltextsuche). also ich wäre sehr dankbar über einige genauere infos danke
      hendri

      Comment


      • #4
        Hallo,

        das folgende Beispiel für die Verwendung einer Formular-Methode als Fensterprozedur (WndProc) für Win32 stammt aus meinem Buch <i>Delphi Win32-Lösungen</i>:
        <pre>
        type
        TFormMain = class(TForm)
        StatusBar1: TStatusBar;
        StaticText1: TStaticText;
        procedure FormCreate(Sender: TObject);
        private
        { Private-Deklarationen }
        pOldWndProc : Pointer; // Zeiger auf die alte Fensterprozedur
        procedure NewWindowProcedure(var Message: TMessage);
        public
        { Public-Deklarationen }
        end;

        procedure TFormMain.FormCreate(Sender: TObject);
        begin
        pOldWndProc := Pointer(SetWindowLong(Handle, GWL_WndProc,
        LongInt(MakeObjectInstance(NewWindowProcedure))));
        end;

        procedure TFormMain.FormClose(Sender: TObject; var Action: TCloseAction);
        begin
        if Assigned(pOldWndProc) then
        FreeObjectInstance(Pointer(SetWindowLong(Handle, GWL_WndProc,
        LongInt(pOldWndProc))));
        end;
        </pre&gt

        Comment


        • #5
          Hm, Andreas

          Scheint ein bißchen umständlich und anfällig zu sein.
          Ein echtes Problem wird es geben wenn sich das Form.Handle neu erstellen muß weil z.B. BorderStyle/BorderIcons o.ä. geändert wurden. In all diesen Fällen wird intern RecreateWnd aufgerufen. Wird das aber nicht berücksichtigt geht obige Methode schief.

          Aber warum einfach wenn's umständlich geht, ab D3 gehts auch so:

          <pre>

          type
          TForm1 = class(TForm)

          private
          FOldWndProc: TWndMethod;
          procedure NewWndproc(var Message: TMessage);
          public
          end;<br>

          procedure TForm1.NewWndProc(var Message: TMessage);
          begin
          FOldWndProc(Message);
          end;

          procedure TForm1.FormCreate();
          begin
          FOldWndproc := WndProc;
          WndProc := NewWndProc;
          end;

          </pre>

          Der "Hook" muß NICHT entfernt werden, da er eigentlich nur wie ein Ereigniss funktioniert. Borland hat also diesen Weg ermöglicht um unanhängig von den Windowshandle und deren Eigenheiten zu sein.

          Gruß Hage

          Comment


          • #6
            Hallo Hagen,

            das Beispiel sollte nur den Aufruf von <b>MakeObjectInstance</b> demonstrieren (Methode als Callback-Funktion für Win32) - ein plausibleres Beispiel hatte ich aber nicht am Lager ;-

            Comment


            • #7
              Hi Andreas,

              macht ja nichts Allerdings erzeugt MakeObjectInstance() nur einen "Funktions" Rumpf der mit Fenster-Callback proceduren arbeiten kann. Für Hendriks Problem also keine Lösung.

              <pre>

              type
              TMyObject = class
              private
              FThreadID: DWord;
              procedure ThreadProc; stdcall;
              end;<br>

              var
              MyObject: TMyObject;
              begin
              MyObject := TMyObject.Create;
              CreateThread(nil, 0, @TMyObject.ThreadProc, MyObject, 0, @MyObject.FThreadID);
              end;

              </pre>

              Das dürfte aber funktionieren. Allerdings rate ich explizit zur Nutzung der Delphi TThread Objecte.

              Gruß Hage

              Comment


              • #8
                hallo hagen!

                leider bekomme ich die Fehlermeldung
                <br>
                "Die Typen der tatsächlichen und formalen var-parameter müssen übereinstimmen."

                was mache ich falsch bzw was muss ich tun?

                vielen danke hendri

                Comment


                • #9
                  CreateThread(nil, 0, @TMyObject.ThreadProc, MyObject, 0, MyObject.FThreadID);

                  Ich nehme mal an der letzte Parameter auf die ThreadID darf nicht als Zeigerreference übergeben werden. Das ist ein immer wiederkehrendes problem mit der Borland-like Importierung von funktionen. Borland nutzt für solche Parameter immer "var" Referencen, versperrt damit aber den Weg auch ohne diesen Param zu arbeiten. Normalerweise wird das API einen Zeiger auf eine Variable erwarten. Dadurch ist mit Übergabe von "nil" auch die Möglichkeit gegeben diesen Param "wegzulassen". Bei einer Importierung als "var" geht das nun NICHT mehr und der Param muß jedesmal übergeben werden, auch wenn man diesen nicht braucht

                  Gruß Hage

                  Comment


                  • #10
                    es gibt auch dafür eine Lösung.

                    <pre>
                    <p>
                    <b>var</b>
                    noDWORD: DWORD <b>absolute</b> 0; <i>// eine Variable an Adresse 0 (dadurch wird nil(0) übergeben)</i>
                    <b>begin</b>
                    ApiFuncMitOptDWordParamDerVonBorlandAlsVarDeclWurd e(noDWORD);
                    <p>
                    </pre>

                    Gruß Nico

                    &#10

                    Comment


                    • #11
                      Hi Nico

                      Ja richtig, aber es müsste nicht sein wenn Borlands Translater ihre Arbeit richtig machen würden.

                      Als zusätzliche Alternative liese sich ja die API Funktion erneut importieren, diesmal mit den richtigen Aufrufparametern.

                      Schön sind beide Lösungen nicht.

                      Gruß Hage

                      Comment


                      • #12
                        Es gibt auch noch eine bessere Lösung,<p>

                        ApiFuncMitOptDWordParamDerVonBorlandAlsVarDeclWurd e(DWORD(<b>nil</b>^));<p>
                        Aber ich gebe Dir vollkommen Recht, das die Funktionen teilweise schlecht übertragen wurden.<br>Doch bei einigen Funktionen wurden diese erst später offiziell optional.<br>Zudem sind schon viele Funktionen in Delphi 5 überladen (overload), damit geht dann sowohl der alte Quelltext, als die neue Variante, die optionale Parameter berücksichtigt.<p>

                        Gruß Nic

                        Comment

                        Working...
                        X