![]() |
Gemeinsame OnClick - Behandlung
Hi there,
Also, ich habe da min. zwei Gruppen von sagen wir mal, TButtons . BtnFirst1, BtnPrior1,BtnNext1... und BtnFirst2... Schön, natürlich könnte ich jetzt für jeden Button eine eigene OnClick-Routine schreiben, aber das artet ja aus, zumal BtnFirst1, BtnFirst2 etc. ja eigenlich das selbe tun. OK, ich kann über:
Delphi-Quellcode:
aber zB.
procedur NavBtnClick(Sender : TObject);
var name : String; id : Integer; begin name := (Sender AS TButton).name; id := name(length(name)); ...
Delphi-Quellcode:
erzeugt bei meinem Compiler höchstens ein hönisches Grinsen. :angle:
BtnFirst[id].enabled := True;
Ist das so überhaupt irgendwie machbar ? Thanks a lot Doc F Zitat:
|
Re: Gemeinsame OnClick - Behandlung
Ein Hallöle von
![]() also, es gibt verschiedene Möglichkeiten. Abfragen ob Sender ein bestimmtes Objekt ist:
Delphi-Quellcode:
Den Namen des Senders abfragen:
If Sender is Button1 Then ...
Delphi-Quellcode:
Der Eigenschaft TAG der verschiedenen Objekte verschiedene Werte zuweisen und diese abfragen:
If TButton(Sender).Name = 'Button1' Then ...
Delphi-Quellcode:
Direkt Sender was zuweisen:
Case TButton(Sender).Tag of
1: ... 2: ... ... End;
Delphi-Quellcode:
...
TButton(Sender).Enabled := True;
( "TButton(Sender)" und "(Sender as TButton)" kommt auf's Selbe raus ) http://www.delphipraxis.net/images/common/divider.jpg ![]() ![]() ![]() |
Re: Gemeinsame OnClick - Behandlung
Hallo,
wie Du schon an der Syntaxhervorhebung erkennen kannst, solltest Du lokale Variablen nie "name" nennen, das führt nur zu Verwechslungen mit TComponent.Name und dessen Nachfahren. Wenn Du allen Buttons den selben Eventhandler zuweist, kannst Du sie über die Eigenschaft "Tag" auseinanderhalten. Einfach für jeden Button einen anderen Tag einstellen.
Delphi-Quellcode:
mr2
procedure ButtonClick(Sender : TObject);
begin if (Sender is TButton) then begin case TButton(Sender).Tag of 1: ShowMessage('Erster Button!'); 2: ShowMessage('Zweiter Button!'); 3: ShowMessage('Dritter Button!'); 4: ShowMessage('Vierter Button!'); else ShowMessage('Anderer Button!'); end; end else ShowMessage('Kein Button!'); end; [edit]Da war mal wieder jemand schneller :lol: [/edit] |
Re: Gemeinsame OnClick - Behandlung
Wow, seid ihr aber schnell.
War nur gerade kurz was anderes am suchen, und schon... Ok, name war kein gutes Beispiel, zugegeben, aber 's ging ja eher ums Prinzip. Super, was die Buttons angeht, war ich ja doch ein wenig begriffsstutzig.
Delphi-Quellcode:
trifft's genau, autsch.
TButton(Sender).Enabled := True;
So weit, so gut. Wie aber nun, wenn nicht nur Buttons angesprochen werden müssen. Bin ich fies, wenn ich da auch noch zB. TTable reinmenge ? Ansonsten schon mal dankeschön, habt mir schon geholfen. Doc F Zitat:
|
Re: Gemeinsame OnClick - Behandlung
:oops: Ausverseh'n 'Edit' an statt 'Zitat'
(weiß aber nicht mehr genau was hier stand, dashalb nicht wundern) Vorher halt den Typ abfragen:
Delphi-Quellcode:
http://www.delphipraxis.net/images/common/divider.jpg
If Sender.ClassType = TButton Then Begin
TButton(Sender).Enabled := True; End Else If Sender.ClassType = TBitBtn Then Begin TBitBtn(Sender).Enabled := True; End Else If Sender.ClassType = TEdit Then Begin TEdit(Sender).Enabled := True; End Else If Sender.ClassType = TMemo Then Begin TMemo(Sender).Enabled := True; End; ![]() ![]() ![]() |
Re: Gemeinsame OnClick - Behandlung
Danke für die Hilfe,
Himitsu hat mich zum Schluss war falsch verstanden : Sender ist immer TButton, der diverse andere Sachen steuern soll. Trotzdem war die Lösung in euren Antworten enthalten. :love: Doc F |
Re: Gemeinsame OnClick - Behandlung
Moin,Moin
Zitat:
und führt im günstigesten Fall zu Schutzverletzungen, wenn die Annahme nicht stimmt. Hier ist alles erlaubt was dieselbe Grösse hat. d.h.
Delphi-Quellcode:
wird anstandlos kompiliert !
TButton(4).Caption := 'Bumm';
(Sender as TButton) ist dagegen ein sicherer Typecast und erzeugt eine Exception EInvalidCast, wenn die Annahme mal falsch war, weil man das Ereignis mal woanders angeklemmt hat. Ergo TButton(Sender) nur verwenden, wenn zumindest vorher mit is geprüft wurde (BTW is ist besser als xxx.ClassType= yyy, auch wenn es minimal anders arbeitet). Die Spagetti-if-else Geschichte :
Delphi-Quellcode:
kann man deutlich kürzen, wenn man sich auf den kleinsten gemeinsamen
If Sender.ClassType = TButton Then Begin
TButton(Sender).Enabled := True; End Else If Sender.ClassType = TBitBtn Then Begin TBitBtn(Sender).Enabled := True; End Else If Sender.ClassType = TEdit Then Begin TEdit(Sender).Enabled := True; End Else If Sender.ClassType = TMemo Then Begin TMemo(Sender).Enabled := True; End; Nenner der Klassen/Eigenschaften besinnt ( in diesem Fall TControl) und mit is statt ClassType arbeitet.
Delphi-Quellcode:
if Sender is TControl then
TControl(Sender).Enabled := false; else ... SCNR , Bernd |
Re: Gemeinsame OnClick - Behandlung
Das mit dem BOOM: Dafür ist natürlich der Programierer verantwortlich. (Wenn es knallt, ist er/sie halt selber Schuld)
OK, für Enabled ist das schon etwas übertrieben, aber bei Komponententypischen Eigenschaften (z.B.
Delphi-Quellcode:
) ist mit TControl(Sender).Caption nichts mehr los.
If Sender.ClassType = TButton Then Begin
TButton(Sender).Caption := 'Text'; ... http://www.delphipraxis.net/images/common/divider.jpg ![]() ![]() ![]() |
Re: Gemeinsame OnClick - Behandlung
Zitat:
bei selbstgeschriebenen Klassen mit Interfaces, für die "dreckige Lösung" mit RTTI und für den OO-Entwickler mit einem Visitor, lässt sich das Problem ohne n Fallunterscheidungen (die mit der Wahrscheinlichkeit p immer 0<m<=n Fehlerhaben, bei denen die Übersicht gegen 1/n^2 strebt und die Wartbeikeit bei n! liegt ;)) lösen. |
Re: Gemeinsame OnClick - Behandlung
2 mal Einspruch
Zitat:
Da ist für mich der Unterschied zwischen "rumcoden" und programmieren Zitat:
Mit dem man (TControl/TwinControl) im übrigen schon ne ganze Menge reissen kann. Mit Caption get es übrigens auch - zumindest wenn man zugegebenermassen etwas unsauber in den protected Bereich einbricht
Delphi-Quellcode:
type
TControlCracker = class(TControl); procedure TForm1.Button1Click(Sender: TObject); begin if Sender is TControl then TControlCracker(Sender).Caption := 'Geht nich - gibbs nich' else ShowMessage(sender.Classname); end; Bernd |
Re: Gemeinsame OnClick - Behandlung
Ohne Pointer zu programmieren ist also wie Safersex, Bernd, und was sind dann CrackerClasses, Pfui ;)
@Doc F: Weder CrackerClasses noch Konstruckte der Form
Delphi-Quellcode:
sind Lösungen, die "sicher" funktionieren (obgleich Crackerclasses bedingt auch in D8 funktioneren sollen... *grummel*)
asm
mov [Sender+$42], eax end; Ich habe schon Komponenten gesehen, die zwar von TControl erben, die Getter und Setter der Eigenschaft Caption jedoch nicht über TControl.GetText sondern über aggregierte Objekte implementiert worden sind. Nicht zuletzt in diesen Fällen würden die Zugriffe über Pointer oder CrackerClasses (die im Wesentlichen nichts anderes tun, weil sie von einem statischen Offset der Exemplarvariablen, der VMT oder einer "unbekannten" festen Methodenadresse mit einer "hingemauschelten Referenz" als impliziten Parameter ausgehen) nicht funktionieren... Abgesehen davon widerspricht dieser Ansatz dem Geheimnisprinzip der OOP! |
Re: Gemeinsame OnClick - Behandlung
Zitat:
Zitat:
Zitat:
Aber du hast ja recht - safer programming ist ne Crakcer Class nicht - können wir uns dann auf diese Variante einigen
Delphi-Quellcode:
( sag jetzt nicht nein - sonst komme ich mit TWinControl und WM_SetText , oder noch besser EnumWindows ...<g>)
procedure TForm1.Button2Click(Sender: TObject);
begin if Sender is TControl then TControl(Sender).SetTextBuf('Geht nich - gibbs nich'); end; Bernd |
Re: Gemeinsame OnClick - Behandlung
Zitat:
Zitat:
Für "die schnelle Nummer zwischendruch" ist die RTTI bei Published Properties aber durchaus eine gute Wahl, zb so (nur mit D7 getestet, ggf gibt es die easy accessors in anderen Versionen nicht in dieser Form)
Delphi-Quellcode:
uses
TypInfo; //... procedure SetStrPropIfPossible(const AnInstance: TObject; const APropName, AValue: string); begin Assert( Assigned(AnInstance) ); if IsPublishedProp(AnInstance, APropName) and (PropType(AnInstance, APropName) in [tkWChar, tkLString, tkWString]) then SetStrProp(AnInstance, APropName, AValue); end; procedure TForm1.Button1Click(Sender: TObject); begin SetStrPropIfPossible(Sender, 'Caption', 'What about RTTI?'); end; |
Re: Gemeinsame OnClick - Behandlung
Hi choose,
bei nicht Standardeigenschaften kann ich Dir bzgl RTTI nur zustimmen. Die easy Accessors sind schon einige Versionen dabei (mind D5) - aber wesentlich umständlicher wars in D1 auch nicht Grüsse Bernd |
Re: Gemeinsame OnClick - Behandlung
Der arme Doc weiß jetzt eventuell nicht mehr was hier abgeht.
Und ich bleibe dann wohl doch beim alten (kommt ja bei mir selten genug vor), da weiß/sehe ich wenigstens noch besser was dort passieren soll. :nerd: Zitat:
![]() ![]() ![]() |
Re: Gemeinsame OnClick - Behandlung
Zitat:
Wie kann man auf was klicken was enabled := false hat?
Delphi-Quellcode:
Wenn da Enabled auf True gesetzt wird, geh ich davon aus das es vorher auf false stand. Wie kann man also darauf klicken?
procedure TForm1.Button1Click(Sender:TObject);
begin If Sender.ClassType = TButton Then Begin TButton(Sender).Enabled := True; end; |
Re: Gemeinsame OnClick - Behandlung
Hi
Zitat:
Zitat:
Aber mal inm Ernst - war ja nur irgendein theorisches Beispiel. Abgesehen davon So ein Ergeinishandler kann ja auch am OnChange oder sonstwo hängen. Der Name ist ja schall und Rauch. Oder Du rufst den Ereignishandler "zu Fuss" auf
Delphi-Quellcode:
Bernd
...
Button1Click(ListBox1); ... |
Re: Gemeinsame OnClick - Behandlung
Zitat:
ich habe meine ad hoc-Lösung ein bisschen überarbeitet
Delphi-Quellcode:
so dass man die Lösung relativ simpel anwenden kann (vielleicht will sich jmd mal die Mühe machen, das ganze zu erweitern und in die Code-Library zu stellen?)
type
TTypeKinds = set of TTypeKind; procedure SetPropIfPossible(const AnInstance: TObject; const APropName: string; const ANeededTypes: TTypeKinds; const AValue: Variant); overload; begin Assert( Assigned(AnInstance) ); if IsPublishedProp(AnInstance, APropName) and (PropType(AnInstance, APropName) in ANeededTypes) then SetPropValue(AnInstance, APropName, AValue); end; procedure SetPropIfPossible(const AnInstance: TObject; const APropName, AValue: string); overload; begin SetPropIfPossible(AnInstance, APropName, [tkWChar, tkLString, tkWString], AValue); end; procedure SetPropIfPossible(const AnInstance: TObject; const APropName: string; const AValue: Boolean); overload; begin SetPropIfPossible(AnInstance, APropName, [tkEnumeration], AValue); end; procedure SetPropIfPossible(const AnInstance: TObject; const APropName: string; const AValue: Integer); overload; begin SetPropIfPossible(AnInstance, APropName, [tkInteger], AValue); end;
Delphi-Quellcode:
Ich muss sagen, dass ich die Lösung deutlich Übersichtlicher finde, als zB diese:
procedure TForm1.Button1Click(Sender: TObject);
begin SetPropIfPossible(Sender, 'Width', 200); SetPropIfPossible(Sender, 'Enabled', False); SetPropIfPossible(Sender, 'Caption', 'What about RTTI?'); end;
Delphi-Quellcode:
Darüber hinaus funktioniert sie mit jeder Delphi-Komponente, die im OI die entsprechenden Eigenschaften besitzt...
If Sender.ClassType = TButton Then Begin
TButton(Sender).Enabled := True; TButton(Sender.Width:= 200; Tbutton(Sender).Caption:= 'What about RTTI?'; End Else If Sender.ClassType = TBitBtn Then Begin TBitBtn(Sender).Enabled := True; TBitBtn(Sender.Width:= 200; TBitBtn(Sender).Caption:= 'What about RTTI?'; End Else If Sender.ClassType = TEdit Then Begin TEdit(Sender).Enabled := True; TEdit(Sender).Width:= 200; End Else If Sender.ClassType = TMemo Then Begin TMemo(Sender).Enabled := True; TMemo(Sender).Width:= 200; End; |
Re: Gemeinsame OnClick - Behandlung
@General2003: Ich hatte damit nur das Beispiel vom Anfang fortgesetzt und wie Bernd schon sagte war es halt nur eine theorisches Beispiel.
Zitat:
Werd' mir das wohl mal für gleiche Teile merken, allerdings habe ich da auch meistens noch Code, der nicht bei allen Typen vorhanden ist, und das läßt sich ja leider nicht auf so eine Weise einbinden. Da bleibt also nur meine alte Variante. http://www.delphipraxis.net/images/common/divider.jpg ![]() ![]() ![]() |
Re: Gemeinsame OnClick - Behandlung
Zitat:
Delphi-Quellcode:
bzw
SetPropIfPossibleAndIsInstanceOf(Sender, [TButton, TPanel], 'Width', 200);
Delphi-Quellcode:
Vielleicht sollte man das wirklich einmal in einer Unit zusammenfassen :gruebel:
SetPropIfPossibleAndIsNotInstanceOf(Sender, [TEdit, TMemo], 'Visible', True);
|
Re: Gemeinsame OnClick - Behandlung
@choose,
das hört sich ja langsam nach einem Beitag für die CodeLib an. Zitat:
z.B. wird mal eine Prozedur oder andere Codezeilen nur abgearbeitet, wenn das Ereignis von einem Button ausgelöst wird, aber nicht, wenn es von einer CheckBox kommt ... http://www.delphipraxis.net/images/common/divider.jpg ![]() ![]() ![]() |
Re: Gemeinsame OnClick - Behandlung
Hi, Leute,
hier fühl ich mich wohl, ihr seid lustig ! Sorry, das ich mich jetzt erst wieder melde, hab flach gelegen. Hier stehen ja wirklich viel tolle Sachen die einem Anregungen liefern, aber im Prinzip trifft alles nicht das, was ich eigentlich wollte, nämlich mit einem Button-Click div. andere Buttons steuern. Nehmen wir als Beispiel mal den DBNavigator, den ich nicht mag. Oder zwei identische Buttonleisten, die zwei verschieden Audioquellen steuern sollen. Ich hab mich gerade ein wenig in Datenbanken eingearbeitet, und brauchte zwei DBNavigatoren. Wie gestagt, die sind blöd, denn ich bin Designfreak und wollte es mir vorbehalten, wohin ich welchen Button setzte. Schön und gut, ist ja kein Problem und am Anfang hab ich auch erst mal schön für jeden Button seine eigen OnClick-Routine geschrieben und Ruck-Zuck ein ellenlangen QuälText :shock: gehabt, der meinen Augen fürchterlich missfiel und ausserdem schrecklich unübersichtlich war, deswegen meine Frage mit der einen (Na ja, bei mir sind schlussendlich dann vier geworden, der Übersichtlickkeit halber) Event-Routine. Hier nun meine Lösung zur Diskussion (wie schon vorher geschrieben, waren gleich am Anfang von diesem Forumsbeitrag ein paar gutte Tips dabei):
Delphi-Quellcode:
Ich hoffe, dieser lange Schrieb sprengt jetzt nicht das Forum.
const
// NavButton enabled Status nbNextLast = 3; // binär 1100 nbNewDel = 6; // " 0110 nbStoreCancel = 9; // " 1001 nbFirstPrior = 12; // " 0011 nbNoBtn = 15; // " 1111 NavBtnNames : Array[1..8] of ShortString = ('BtnFirst', 'BtnPrior', 'BtnNext', 'BtnLast', 'BtnNew', 'BtnStore', 'BtnCancel', 'BtnDel'); procedure TForm2.NavBtnClick(Sender: TObject); var BtnAction, BtnID : String; BtnNr, NavGroup : Integer; begin BtnAction := TSpeedButton(Sender).Hint; BtnID := IntToStr(TSpeedButton(Sender).Tag); NavGroup := StrToInt(BtnID[1]); BtnNr := StrToInt(BtnID[2]); case BtnNr of 1 : SetNavBtn(NavGroup, nbFirstPrior, BtnNr); 2..3 : SetNavBtn(NavGroup, nbNoBtn, BtnNr); 4 : SetNavBtn(NavGroup, nbNextLast, BtnNr); 5 : SetNavBtn(NavGroup, nbNewDel, BtnNr); 6..8 : SetNavBtn(NavGroup, nbStoreCancel, BtnNr); end; DoBtnAction(NavGroup, BtnNr); end; function TForm2.GetComponentID(CoName : String) : Integer; // <-- Worum's mir eigentlich ging var comp : TComponent; begin comp := TComponent(FindComponent(CoName)); result := comp.ComponentIndex; end; procedure TForm2.SetNavBtn(NavGroup, BtnState, BtnNr : Integer); var comp : TComponent; compId, mask, i : Integer; begin case BtnNr of 1..4 : begin for i := 0 To 3 do begin compID := GetComponentID(NavBtnNames[i+1] + IntToStr(NavGroup)); mask := 1 shl i; TSpeedButton(Components[compID]).enabled := (BtnState AND mask) = mask; end; end; 5..6 : begin for i := 0 To 3 do begin compID := GetComponentID(NavBtnNames[i+5] + IntToStr(NavGroup)); mask := 1 shl i; TSpeedButton(Components[compID]).enabled := (BtnState AND mask) = mask; end; end; end; if NavGroup = 1 then SetNavBtn(2, nbFirstPrior, 1); end; procedure TForm2.DoBtnAction(NavGroup, BtnNr : Integer); begin case NavGroup of 1 : .. // Anweisungsblock end; end; Danke an alle für die Hilfe. Doc F [edit=Christian Seehase]Delphi-Tags korrigiert. Mfg, Christian Seehase[/edit] |
Re: Gemeinsame OnClick - Behandlung
Ups, sorry, meine Formatierungen sin im Nirwana verschwunden. Keine Absicht.
Doc F |
Re: Gemeinsame OnClick - Behandlung
Hallo,
ich glaube für Dein Problem sind Actions am besten geeignet. Einfach eine ActionList auf das Formular ziehen. Dann per Doppelclick auf die ActionList den ListEditor öffnen und über den kleinen schwarzen Pfeil links oben eine neue Standardaktion einfügen. Jetz nach unten scrollen und unter der Rubrik DataSet TDataSetFirst, TDataSetNext etc. auswählen. In der Action kannst Du dann einstellen für welche DataSource die Action zuständig ist. Anschließend einfach dem oder den entsprechenden Button(s) die Action als Action zuweisen. Und schon hast Du erreicht was Du wolltest und das ohne eine Zeile Code zu schreiben. mr2 |
Re: Gemeinsame OnClick - Behandlung
Hallo mr2,
Prima, danke für den Tipp, funzt ja prima. Na ja, wenigstens hab ich bei meinem Versuchen einiges gelernt. Jetzt nur noch eine Frage (hoffe ich): Da gibt es zwar Aktion DatSetInsert, aber nix für append. (Hät ich aber gerne ... :wall: ) Und ausserdem funzt des zwar für für Datenbanke, aber nicht zB. für meinen momentan auf Eis gelegt Audio-Player. Kann ich da irgendwie Standarteinträge selbst erzeugen ? Hab mich schon drin versucht, mir ist aber noch nicht so ganz klar, was ich dazu alles brauch. (Nebenbei bemerkt, Objektvererbung is schon toll, sonst müsste man das ja kpl. neu schreiben). Vielleicht hat da jemand für eine vom
Delphi-Quellcode:
noch ne verständliche Antwort parat.
Type
TProgramiere = MöchtegernHobbyProgrammierer(Class) Danke Doc F |
Re: Gemeinsame OnClick - Behandlung
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,
Zitat:
Delphi-Quellcode:
bedeuten :lol:
type
TProgramierer = class(TMoechtegernHobbyProgrammierer) Aber nun zu Deinem eigentlichen Problem. Insert und Append sind prinzipiell identisch und führen nur bei Paradox oder ähnlich veralteten Datenbanken zu unterschiedlichen Ergebnissen. Du kannst natürlich trotzdem Deine eigene ActionKlasse schreiben:
Delphi-Quellcode:
Ich weiß nicht welche Erfahrungen Du bisher mit selbstgeschriebenen Komponenten hast.
type
TDataSetAppend = class(TDataSetInsert) public procedure ExecuteTarget(Target: TObject); override; end; implementation procedure TDataSetAppend.ExecuteTarget(Target: TObject); begin GetDataSet(Target).Append; end; Jedenfalls muss die Action in Delphi registriert werden. Im Anhang siehst Du wie das am besten gemacht wird (Datei U_MyActionsReg.pas). Das Beispiel ist für Delphi 6 und muss für Versionen darunter vermutlich angepass werden. Einfach die Datei MyActions.dpk in Delphi öffnen und die Schaltfläche "Installieren" betätigen. Weitere Hilfe findest Du auch in der Delphi-Hilfe unter "Komponentenentwicklung". Viel Erfolg. mr2 |
Re: Gemeinsame OnClick - Behandlung
Hallo mr2,
Super, jetzt wird programmiert, bis die (System-)Fetzen fliegen. :party: Übrigens hattest du recht mit Paradox, aber irgendwo muß man ja anfangen. Und da ich keine Client-Server-Datenbanken zu schreiben gedenke, sondern einfach nur 'just for fun' oder zum eigenen Bedarf Programme schreibe, reicht das ja (für den Anfang). Welche Datenbank würdet ihr den für den Hausgebrauch empfehlen ? Danke Doc F PS. Hab meinem PC mal ne neue Tastatur gegönnt, die vielen fehlenden Buchstaben sind ja schon peinlich. Merke: Tastatur + Cola = Autsch!!! |
Re: Gemeinsame OnClick - Behandlung
Hallo,
also was die Datenbank angeht, habe ich mit Access (per ADO) angefangen, um später auf Interbase, Oracle & MS SQL-Server zu wechseln. Interbase & die MSDE (das ist die Light-Version des SQL-Servers) kann man problemlos auf dem eigenen Rechner installieren - bei Oracle ist das etwas komplizierter :) Aber such' doch mal im Forum nach ![]() CU mr2 |
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:10 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz