Label-Zugriff von Thread
-
Hallo,
nachdem ich mich einige Zeit mit Visual C++ befasst habe - und nebenbeigesagt mich beim Thema "Programmierung von Benutzerdefinierten Dialogen" grün und blau geärgert habe (man denke nur daran was man alles machen muss um die Schriftgröße oder -farbe eines Textfeldes zu ändern) - komme ich langsam auf den Genuß vom C++Builder...
Leider Stecke ich noch zu sehr in den Visual C++ Schuhen und vergleiche noch zu sehr. Es ist in Visual C++ sehr einfach von einem parallel-laufendem Thread auf ein Static-Feld (in Borland 'Label' genannt) des Hauptthread zuzugreifen und z.B. dessen Text zu ändern.
Der Code innerhalb des Thread würde in Visual C++ so aussehen:CString Str = "Hallo"; SetDlgItemText(hWnd, IDC_STATIC1, Str);
wobei 'hWnd' das Handle des Hauptthreads ist und 'IDC_STATIC1' die ID des Static-Feldes. Ich habe im C++Builder bisher keine Möglichkeit gefunden ein Label durch einen Thread direkt anzusprechen - ausser über eine Nachricht mit SendMessage.
Hat jemand eine Idee?
Trotz dieses kleinen Problems sehe ich beim C++Builder dennoch eher die Vorteile...
-
Warum benutzt du nicht ...
Label1->Caption = "Ich bin die Caption eines Labels";
Außerdem sind CString`s eher unüblich im C++ Builder .. ( empfehle da eher
std::string und wenns net anderst geht AnsiString )
-
1ntrud0r schrieb:
Warum benutzt du nicht ...
Label1->Caption = "Ich bin die Caption eines Labels";
weil mein Thread Label1 nicht kennt..
1ntrud0r schrieb:
Außerdem sind CString`s eher unüblich im C++ Builder .. ( empfehle da eher std::string und wenns net anderst geht AnsiString )
Das wäre der Code in Visual C++ gewesen.
Übrigens: Hast Du meinen Beitrag eigentlich gelesen?
-
öh eigentlich hab ich dein post schon gelesen ..blos
das :
SetDlgItemText(hWnd, IDC_STATIC1, Str);
ist Winapi und hat nix mit BCB zu tun ..
der BCB hat seine VCL und CLX welche die api's kapseln ..
Wenn du in nem TThread .. deine TForm bekannt machst kannst
du auch auf die Caption des TLabel zugreifen .. ich weiss net
was dein Problem ist !!!!!Hättest du meinen Beitrag gelesen und verstanden wär das eh schon alles gelöst
-
hallo,
ist ganz gut das du dieses frage gestellt hast, denn da gibt es etwas wichtiges zu beachten, das wenn man es nicht beachtet nicht unbedingt sofort zu einem fehler führt, früher oder später aber zu ganz bösen dingen führen kann. angenommen du hast eine form auf der dein label sitzt (es gibt im CBuilder übrigens auch einen TStaticText). in einer anderen unit ist dein TThread-Object (ich nehme hier jetzt an, das du das TThread-Object der VCL verwendest und nicht die api-funktionen). nun ist es so, das hauptformular mit den vcl-kompos läuft in einem anderen prozess wie das thread objekt. damit du aber dennoch vom thread aus auf die kompos des formulars zugreifen kannst ohne gefahr zu laufen, gibt es eine methode namens Synchronize(...), dieser Methode übergibst die routine in der der zugriff auf die form-kompos stattfindet, denn die methode die du synchronize übergibst wird im selben kontext wie der vcl hauptthread ausgeführt, ein beispiel:
void __fastcall TMyThread::Execute() { FCount = 1; do { Synchronize(GuiElements); //Aufruf von synchonize. FCount++; } while (FCount <= 200000); } void __fastcall TMyThread::GuiElements() { //läuft im kontext des vcl-hauptthreads. Form1->DisplayLabel->Caption = IntToStr(FCount); }
mfg
murph
-
q15: Ob "1ntrud0r" den Text gelesen hat spielt keine Rolle. Er hat ihn einfach nicht verstanden
1ntrud0r: Lesen lernen und üben. Sätze möglichst bis zum Ende durchlesen, usw.
-
Besten Dank an murphy, der Hinweis, dass es auch StaticText Komponenten gibt war sehr hilfreich. Hier kann ich den Handle (z.B. hWndStatic) vom StaticText an den Thread übergeben und da mit folgendem Code den StaticText beeinflussen.
AnsiString StaticText = "Irgend ein Text"; SendMessage(hWndStatic, WM_SETTEXT, 0, (LPARAM)(LPCSTR)&LabelText)
Übrigens, ich arbeite nicht mit 'TThread' sondern mit '_beginthreadNT'. Was das mit TThread auf sich hat, werde ich mir später einmal zu Gemüte ziehen.
Grüße aus Regensburg
-
q150022 schrieb:
Übrigens, ich arbeite nicht mit 'TThread' sondern mit '_beginthreadNT'. Was das mit TThread auf sich hat, werde ich mir später einmal zu Gemüte ziehen.
Abgesehen davon, dass du dieses Detail vielleicht hättst früher erwähnen sollen, würde ich dir empfehlen, die Informationen über TThread besser jetzt als später einzuziehen...
-junix
-
Ups, funktioniert doch nicht
Auch nachdem ich 'LabelText' in 'StaticText' umgetauscht habe...
AnsiString StaticText = "Irgend ein Text"; SendMessage(hWndStatic, WM_SETTEXT, 0, (LPARAM)(LPCSTR)&StaticText)
Beim Probieren wird der Text nicht "richtig" angezeigt, sondern es sind nur irgendwelche Ascii-Zeichen zu sehen...
-
Kleines Rätsel für dich:
(LPARAM)(LPCSTR)&StaticText
Was bedeutet die obige Zeile?
-
Bevor Du Dich totsuchst. AnsiString auf char*: AnsiString::c_str()
Junix hat Recht: lieber gleich TThread, sparst Dir ne Menge Stress.
Kurzeinweisung:
Datei->Neu->Weiter, dann "Thread-Objekt" auswählen. Klassenname nach Geschmack eingeben, und hallelujah!- eine neue Unit, mit einer neuen von TThread abgeleiteten Klasse, mit den wichtigsten Funktionsrümpfen schon drin.
Die wichtigsten Hinweise stehen dann schon als Kommentare im Code.
Der Thread-Code kommt in die Execute()-Methode.
Um auf der Haupt-Form an den VCL-Komponenten rumzufummeln, dazu jeweils eigene Threadklasse-Memberfunktion schreiben und aus Execute() heraus mit Synchronize() arbeiten, wie oben schon mal erwähnt.
Steht in den generierten Kommentaren aber auch schon sehr schön drin, für die meisten Zwecke alles ziemlich Idiotensicher.
-
Leser schrieb:
q15: Ob "1ntrud0r" den Text gelesen hat spielt keine Rolle. Er hat ihn einfach nicht verstanden
1ntrud0r: Lesen lernen und üben. Sätze möglichst bis zum Ende durchlesen, usw.mach jmd andren dumm von der seite an ...
Ich hab ihn nur druff hingewiesen das er die Memberfunktionen von TLabel benutzen kann und nicht die Räder neu erfinden brauch .. mehr net
-
Ach ja, und aus Deinem Hauptcode heraus (#includes nicht vergessen!) einfach eine (oder mehrere!) Instanz Deiner TThread-basierten Klasse erzeugen, etwa:
meinThread = new MeineThreadKlasse (true); // fasle, um gleich zu starten
Dann nach Belieben über meinThread->Resume() und ->Suspend() das Ding starten und anhalten.
Viel Spaß!!
-
Genau die Methode 'c_str()' von AnsiString habe ich gesucht - Danke!
Das Thema TThread scheint wirklich easy zu sein - ich weiss garnicht warum ich nicht früher mit Borland angefangen habe...
-
Leser schrieb:
Bevor Du Dich totsuchst. AnsiString auf char*: AnsiString::c_str()
Danke für diese äusserst effektive Zerstörung des Lerneffekts.
Er hätte sich nicht todgesucht, sondern hätte einfach mal antworten sollen. Ich hätte ihn dann schon in die richtige Richtung geschubst. Alleine schon die konstellation des Codes den er da geschrieben hat, verrät nämlich dass er gar nicht genau wusste, was er da eigentlich tat. Viel mehr weiss er nun auch nicht.
Wie dem auch sei, die "konvertierung" von AnsiString nach char-Pointer ist eigentlich auch schon in der FAQ vermerkt und mit einigen wichtigen Hinweisen versehen, die man unbedingt lesen sollte!
-junix