![]() |
Events zur Designtime
Moinmoin!
Gibt es eine Möglichkeit die IDE dazu zu überreden, dass Events wie MouseMove oder MouseDown zur Designtime an eine von TCustomControl abgeleitete Komponente zu übergeben? Es dürfen auch gerne schmutzige Tricks sein, aber ich würde es schon recht dringend brauchen (nicht im Sinne von "sofort jetzt" sondern von "ich brauchs echt"). Es geht um Delphi 7 Ent. Besten Dank schonmal, Das Medium |
Re: Events zur Designtime
Warum brauchst du das zur Entwurfszeit?
|
Re: Events zur Designtime
Ich erstelle eine ganze Reihe von Prozessabbildern, und in diesen sind eine Fülle sehr unterschiedlich gestalteter Elemente. Für all diese jeweils eine völlig eigene Komponente zu entwickeln, bzw. immer diese zu erweitern wäre nah an Folter. Was all die Elemente gemein haben ist, dass sie sich wunderbar über einen Polygonzug realisieren ließen, und dessen Ecken will ich zur Entwurfszeit umherschubsen können. Weil wenn ich die Koordinaten im Code erst setzte, könnte ich gleich die Kompos bauen. Zudem wäre es dann mehr als schwierig zu bearbeiten.
|
Re: Events zur Designtime
Hallo Medium,
ich weiß nicht, ob ich Dich richtig verstehe... Du könntest die entsprechende Behandlung direkt in der Klasse definieren, dann funktioniert das grundsätzlich auch zur Designtime
Delphi-Quellcode:
Jetzt sollte die Kompo auch in der IDE klingeln, wenn Du sie anklickst.
protected
procedure MouseDown(Button:TMouseButton;Shift:TShiftState;X,Y:Integer); override; ... procedure TXyz.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin inherited; SysUtils.Beep; end; Die Komponenten reagieren allerdings in der IDE anders als zur Laufzeit. Schau Dir dazu mal ComponentState und evtl. ComponentStyle an... stahli |
Re: Events zur Designtime
Funktioniert leider nur zur Laufzeit. Was mich überhaupt dazu gebracht hat, dass das irgendwie gehen muss ist: Ich hab in den bereits bestehenden Komponenten einen TTimer, der das Element auf Wunsch blinken lässt. Und es blinkt auch zur Entwurfszeit, wenn ich es nicht selbst mit Hilfe von ComponentState unterbinde. Da TTimer prinzipiell über eine Fenstermsg arbeitet, sollte das an und für sich nun kein Problem sein, aber ich hab es bisher nicht geschafft Maus-Events zu erhalten.
|
Re: Events zur Designtime
Ich hab glaub ich einen Weg gefunden, und ja, er ist ausgesprochen schmutzig :twisted:
Ich erzeuge nun in meiner Komponente ein neues TForm. Dieses erhält auch im Designer alle Messages, und ich kann damit tun was ich mag. Zur Runtime kann es dann ja weg bleiben. |
Re: Events zur Designtime
Und genauso wie du das mit einem TForm amchst, kannst du das auch mit einem TcustomControl machen.
|
Re: Events zur Designtime
Zitat:
Ich kann mir nicht so recht vorstellen, was Du da machst. Wozu brauchst Du ein DummyForm? Mal ein stückl Code...? Meinen Vorschlag von oben kann ich heute Abend mal testen. Hätte gedacht, dass das funktioniert. stahli |
Re: Events zur Designtime
Wahrscheinlich, ja. Der Kniff dabei ist nur, dass ich keine Messages für die Komponente an und für sich empfange. Bette ich darin aber ein weiteres Control ein, entzieht sich dieses der Sonderbehandlung durch die IDE, und man kann alles damit machen wie zur Laufzeit. Einfaches Überschreiben der Eventhandler der Komponente selbst ging leider nicht.
|
Re: Events zur Designtime
Hallo roter Kasen!
@stahli: Naja, stolz nur, weil ich endlich einen Weg gefunden habe. Stück Code:
Delphi-Quellcode:
Was noch fehlt sind ein paar Methoden, damit die Komponente im Designer wieder anwählbar ist und dergleichen.
type
TPoly = class(TCustomControl) private FForm: TForm; protected procedure Paint; override; procedure _MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); public constructor Create(AOwner: TComponent); override; destructor Destroy; override; published end; implementation constructor TPoly.Create(AOwner: TComponent); begin inherited; FForm := TForm.CreateParented(TForm(AOwner).Handle); // Der Cast ist Murks, einer auf TWinControl dürft auch gehen FForm.BorderStyle := bsNone; FForm.Width := Width; FForm.Height := Height; FForm.Color := clRed; // nur damit man es gut sieht zum Test FForm.OnMouseMove := _MouseMove; FForm.Top := Top; FForm.Left := Left; FForm.Visible := true; FForm.BringToFront; end; destructor TPoly.Destroy; begin FForm.Free; inherited; end; procedure TPoly._MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin inherited; self.Color := clFuchsia; // Um zu sehen, ob das Event ankommt. Es wird normal noch etwas gezeichnet, das hab ich hier rausgenommen end; procedure TPoly.Paint; begin inherited; // Um das Form immer brav mitzuziehen FForm.Left := Left; FForm.Top := Top; FForm.Width := Width; FForm.Height := Height; FForm.BringToFront; end; |
Re: Events zur Designtime
Und warum nicht einfach so ohne TForm?
Delphi-Quellcode:
type
TPoly = class(TCustomControl) procedure _MouseMove(var Msg:TWMMouseMove);message WM_MouseMove; end; |
Re: Events zur Designtime
Weil es nicht geht. Ich habs sogar ausprobiert ;)
|
Re: Events zur Designtime
Ah, es sieht so aus als ob die WindowProc von tWinControl alle MouseMsg (unter einer bestimmten Bedingung) abfängt. Hast du mal versucht die WndProc zu überschreiben?
|
Re: Events zur Designtime
Das wäre auch noch eine Idee. Könnte klappen, wenn nicht die IDE selbst schon an den Messages herumfummelt. Ich kann es heute allerdings leider nicht mehr testen, aber das wird definitiv Teil des Wochenendes. Weil das wäre doch noch ein paar Ecken elegater. Würde ja auch gerne testweise csDesigning mal nullen zum Test, aber auch das muss leider warten.
|
Re: Events zur Designtime
Hallo Medium,
Du hast recht, mein Vorschlag funktioniert nicht. Ich würde aber auch nicht unbedingt das IDE-Verhalten umbiegen. Du willst ja Deine Komponenten auch korrekt platzieren, in der Größe ändern, verschieben etc. Was willst Du denn eigentlich genau machen? Auf dem Canvas direkt zeichnen? Wie willst Du denn dann die "Eingaben" mit dem Formular speichern? Die sollen ja dann mit dem Programmstart wieder zur Verfügung stehen... Ich hab´s noch nicht ganz verstanden. stahli |
Re: Events zur Designtime
Es soll eine Art eingebetteter Editor für einfache Polygonformen werden, die zudem gruppiert werden können, unterschiedlich gefüllt, etc. pp.
Die Polygone sollen darin zur Designtime an ihren Eckpunkten bearbeitet werden können, sprich Punkte anklicken, halten und ziehen. Die Speicherung würde entweder in einem Stringformat in einer Strings-Property gemacht, oder, was je nach aufkommender Datenmenge besser ist, in einer separaten Datei. Die Gedanken rotieren noch. |
Re: Events zur Designtime
Dann würde ich so herangehen:
Die Punkte selbst werden in einer Eigenschaft "PolygonStrings: TStrings" gespeichert, so kannst Du sie leicht mit dem Formular mit speichern und jederzeit im Editor ändern. Für das direkte Bearbeiten der Polygone solltest Du einen Propertyeditor schreiben (habe ich allerdings noch keine Erfahrungen). Dann kannst Du (wenn ich das richtig verstanden habe) in der IDE Duch Doppelklick auf Deine Property Polygon einen speziellen Editor dafür starten. Das entsprechende Formular würde dann m.E. Deine TPoly wie zur Laufzeit behandeln, so dass Du darauf zeichnen kannst. Dann kannst Du in der IDE Deine Kompos anordnen und über den Eigenschaftseditor zeichnen... Ich denke, das wäre der richtige Weg. stahli |
Re: Events zur Designtime
Hallo Medium,
in ![]() Gruß Hawkeye |
Re: Events zur Designtime
@stahli:
Ein separater Editor kommt leider nicht in Frage, da diese Komponenten pixelgenau mit anderen platziert werden müssen. Z.B. muss es möglich sein ein Button darüber zu legen, oder die Ausrichtung an anderen Teilen zu orientieren. Wenn man dazu erst Teile aus ihrem Kontext nimmt um sie zu editieren, wird es in ein Edit->schließen->gucken->passt nicht->Edit->gucken->schließen... ausarten, und genau das zu verhindern ist ja das Ziel. Daher hab ich einen Propertyeditor erst garnicht ins Spiel gebracht. Was die Speicherung angeht: Gibt es irgendwelche technischen oder praktikablen Grenzen für die Größe von .dfm Files? Die o.g. Komponente werde ich mir jetzt zu Gemüte führen. Danke dir für den Tipp! |
Re: Events zur Designtime
Entweder steh ich gerade sehr auf dem Schlauch, oder aber jans Komponenten bieten zwar eine editierbarkeit zur Runtime, aber im Delphi-Designer kann ich auch nicht mehr tun, als die Komponente aufs Formular werfen und in Größe und Position ändern. Ich brauche es ja genau umgekehrt!
|
Re: Events zur Designtime
Ich finde es etwas ungewöhnlich, dass Du so flexible und dynamische Änderungen in der IDE realisieren willst. Dann musst Du ja Dein Projekt bei Änderungen jedesmal neu kompilieren.
Warum erstellst Du nicht einfach einen kleinen "Designer" und eine kleine "Palette". Zur Laufzeit kann man dann Poly´s aus der Palette auf den Designer ziehen und bearbeiten. Das ganze wird dann in einen Stream gespeichert und beim nächsten Start geladen... Deine Exe besteht dann in alle Ewigkeit und die Nutzer können notfalls selbst auch Änderungen an den Poly´s vornehmen. :-) stahli |
Re: Events zur Designtime
Zitat:
Zitat:
Zitat:
Ich hab bereits das wesentliche Rahmenwerk auf Basis des überlagerten Formulars gebaut, und bislang sieht es noch immer so aus, als könnte ich es so realisieren. Was dieser "Trick" mit sich bringt ist z.B., dass ich ein weiteres auf dem eigentlichen Formular verschiebbares und größenänderbares Fenster mit einem eigenen kleinen Propertyeditor erzeugen kann. Im Grunde wird es also ein Designer, der in dem Fenster des Delphi-Designers zuuur Designtime läuft, auf dem die Komponente eingefügt wurde. Innerhalb dieser Fenster kann ich agieren wie in einem separaten eigenen Programm, nur dass alles in einer Komponente gekapselt ist, und im Delphidesigner dargestellt wird. Ich bin selbst erstaunt, dass das so möglich ist, aber nicht wirklich böse darum. Sobald eine vorzeigbare Version fertig ist, kann ich sie ja mal zur Begutachtung hochladen. Bisher zumindest bin ich noch davon überzeugt, dass das der beste Weg ist für unsere Zwecke, zumal leider alle bisherigen Ansätze Maus-Events aus dem Designer zu erhalten fehlgeschlagen sind. |
Re: Events zur Designtime
Liste der Anhänge anzeigen (Anzahl: 1)
Hier mal der bisherige Stand. Es ist ein absoluter "work in progress", und einiges fehlt noch, aber es zeigt schon ganz gut was ich meinte. Erstellt und getestet hab ich es bislang nur unter Delphi 7 Ent.
Installation: DrawingContainer.pas als neue Komponente registrieren (Darauf achten, dass alle 3 Files im Bibliothekspfad sind) Was bisher geht: Es werden in einer Zeichenfläche zwei bearbeitbare Dreiecke erstellt, dessen Eigenschaften sich in einem eigenen Property-Editor der sich mit öffnet geändert werden können. Multiselektion klappt auch schon. Was fehlt ist Persistenz (beim Starten des Programmes werden nur die 2 Dreiecke in Ausgangsform gezeigt), dynamische Kontextmenues, ein paar Tool-Leisten und weitere Sub-Komponenten, sowie der übliche Feinschliff. Eine Kleinigkeit muss man noch beachten: Damit man das Element via [Entf] auch wieder löschen kann, und zuvor im "internen" Property Editor etwas gemacht hat, muss man kurz etwas anderem den Focus geben (dem Delphi-Propertyeditor z.B.) und dann den roten Rand um die Komponente anklicken damit sie richtig selektiert ist. Ich hab leider bisher keinen sinnvollen Weg gefunden, dem internen Prop-Edit den Fokus zu klauen. |
Re: Events zur Designtime
Liste der Anhänge anzeigen (Anzahl: 1)
Unter BDS2006 erhalte ich beigefügte Meldungen...
Mich würde mal ein kleines Bilchen oder kurzes Video interessieren... stahli |
Re: Events zur Designtime
Liste der Anhänge anzeigen (Anzahl: 1)
Ich hab schon befürchtet, dass mich die RTTI und Konsorten in anderen Versionen ärgern werden. Schade.
Ich hab mir aber mal fix Camtasia angesehen, nettes Progrämmchen! Meinen ersten Film hab ich mal angehängt ;) Das Popupmenu ist da nun schon ansatzweise drin. Was im Video nicht deutlich wird: Es wird dynamisch aufgebaut, je nach dem was gerade für ein Element selektiert ist. Da es derzeit nur das Polygon gibt, schaut es immer gleich aus. |
Re: Events zur Designtime
Das einfügen von csClickEvents, csDesignInteractive oder csDoubleClicks in ControlStyle hat nichts gebracht bezüglich der Eventverarbeitung über die entsprechenden Mouse-Methoden zur Designzeit?
|
Re: Events zur Designtime
Leider nicht. Diese Optionen haben, bis auf der Beschreibung nach csDesignInteractive, nur Auswirkungen auf ein Control zur Laufzeit. Setzen von csDesignInteractive hat allerdings in meinem Test auch keinen Unterschied gemacht, würde aber allein auch nicht ausreichen, da ich auch auf MouseMove, -Down und -Up reagieren will, evtl. mehr.
Was mich etwas stutzig macht ist, dass mir bislang noch keine Komponenten mit ansatzweise ähnlicher Editierbarkeit zur Designtime untergekommen sind. So sehr abwegig find ich das Bedürfnis danach eigentlich nicht. |
Re: Events zur Designtime
Hallo Medium,
die Lösung ist elegant umgesetzt und funktioniert ja auch nicht schlecht. Allerdings kann ich das Ganze nicht so recht einordnen. Du erzeugst sozusagen eine Art Präsentation...!? Die Optik kannst Du (zugegebener Maßen recht elegant) in der IDE zusammenbasteln und diese in eine Exe manifestieren... Anderereseits wäre es m.E. sicher auch nicht aufwändiger gewesen, im Projekt zur Laufzeit eine "Arbeitsfläche (Designer+Palette)" bereitzustellen und ddie Polys dort zu bearbeiten. Das Ganze wird dann gespeichert und mit dem Projekt mitgegeben. Durch Ersetzen der Poly-Datei werden andere Komponenten angezeigt. Der Enduser muss ja keine Bearbeitungsmöglichkeit erhalten. NICHTS gegen Deine Lösung - die ist schon beeindruckend. Nur, ich weiß nicht, ob´s wirklich unbedingt in der IDE sein muss... Jedenfalls fallen mir keine Komponenten ein, bei denen das sonst noch notwendig wäre... stahli |
Re: Events zur Designtime
Es geht dabei um sog. Prozessvisualisierung zur Anlagensteuerung und Überwachung, bei der eine Anlage (Teile eines Produktionsbetriebes o.ä.) visuell stilisiert dargestellt werden, und durch Farben und Ausgabefelder den Zustand der Anlage wiedergeben.
Dabei gibt es zwei Probleme, die ich so löse: 1) Es gibt sehr individuelle Anlagenteile, für die es sich nicht lohnt jeweils eine eigene Komponente zu schreiben. Sie unterscheiden sich jedoch meist nur in der Form von anderen, und daher war es sinnvoll eine generelle Lösung dafür zu finden. 2) Ein einzelnes Element sitzt inmitten von zig anderen, und sollte der Übersicht und Gefäligkeit wegen pixelgenau ordentlich positioniert sein, was zu erreichen eine Tortur ist, wenn man einen externen Editor bemüht. Da Elemente auch ganz normale VCL Komponenten wie Buttons und Edits sein können, ist die direkte Bearbeitung auf dem Designformular das Optimum. Okay, ich gebe zu, die Anforderungen sind evtl. schon recht spezifisch :) |
Re: Events zur Designtime
Zitat:
Wenn Du dort auch VCL-Komponenten einbindest (und vermutlich auch noch Schalterklicks behandelst) wäre es natürlich äußerst umständlich, das alles in der IDE zu organisieren und später zur Laufzeit die Polys hinzuzufügen. Also Respekt nochmal :!: Und gut, dass wir ausführlich drüber gesprochen haben... stahli PS: Als Screenrecorder kann ich übrigens auch den "HyperCam" empfehlen (klein aber fein, erzeugt allerdings nur avi) oder von DataBecker den Stream Catcher (beide 30 Eu). |
Re: Events zur Designtime
Zitat:
Danke dir fürs Mitfiebern, und den Tipp mit den Videoprogrammen! In spätestens 30 Tagen wird eine Vollversion wohl interessant... |
Re: Events zur Designtime
So Geht's
Dein Komponente im protected Abschnitt
Delphi-Quellcode:
Dein Komponente im Implementations-Teil
protected
. procedure WMAreaInternalMouseMove(var Message: TWMMouseMove); message WM_MOUSEMOVE; .
Delphi-Quellcode:
und dann im Desing-Time Package einen Component-Editor ...
procedure TYourDesignInteractiveComponent.WMAreaInternalMouseMove(var Message: TWMMouseMove);
begin inherited; if not(csNoStdEvents in ControlStyle) then begin FMouseScreen.x := Message.XPos; FMouseScreen.y := Message.YPos; if (csDesignInteractive in ControlStyle) then begin {Mach was zur Design-Time} end else begin {Mach was zur Run-Time} end; paint; end; end;
Delphi-Quellcode:
das wars...interface TYourCE = class(TDefaultEditor) public function GetVerb(Index:Integer):string; override; function GetVerbCount: Integer; override; procedure ExecuteVerb(Index: Integer); override; end; procedure Register; implementation procedure Register; begin RegisterComponents('Palette', [TYourDesignInteractiveComponent]); RegisterComponentEditor(TYourDesignInteractiveComponent, TYourCE); . end; function TYourCE.GetVerbCount: Integer; begin result := 2; END; function TYourCE.GetVerb(Index: Integer):STRING; begin case Index of 0 : result := 'DesignTime Interactive ON'; 1 : result := 'DesignTime Interactive OFF'; end; end; procedure TYourCE.ExecuteVerb(Index: Integer); begin case Index of 0: begin with TYourDesignInteractiveComponent(Component) do begin ControlStyle := ControlStyle+[csDesignInteractive]; end; end; 1: begin with TYourDesignInteractiveComponent(Component) do begin ControlStyle := ControlStyle-[csDesignInteractive]; end; end; end; end; . . end. Warum... Du mußt die Win-Messages direkt abfangen. Events treten zur Desing-Time nicht ein.... Edit: Falscher Fehler ;-) |
Re: Events zur Designtime
Da brat mir einer nen Storch! Ich hab csDesignInteractive mit den geerbten Handlern, und eigene Handler ohne csDesignInteractive getestet. Kombiniert man es, geht es! LoCrux, ganz ganz heissen Dank! Damit lässt sich dann nun auch endlich realisieren, dass man ohne extra Formular auskommt, und man Teiltransparenz auch beim Bearbeiten hat. Ein riesen Vorteil! Dann werd ich mal umbauen...
|
Re: Events zur Designtime
Leider zu früh gefreut. MouseMove und ButtonEvents der Rechten Maustaste sind kein Problem, aber die linke und mittlere Maustaste kommen dennoch nicht durch.
Ich hatte meinen Versuch mit csDesignInteractive auch mit Handlern für die linke Maustaste gemacht, womit sich der Kreis irgendwie schließt. Hast du da evtl. auch noch einen Geheimtip? |
Re: Events zur Designtime
Jau....
Delphi-Quellcode:
same as above...
procedure WMAreaInternalLButtonUp(var Message: TWMLButtonUp); message WM_LBUTTONUP;
procedure WMAreaInternalRButtonUp(var Message: TWMRButtonUp); message WM_RBUTTONUP; procedure WMAreaInternalMButtonUp(var Message: TWMMButtonUp); message WM_MBUTTONUP; procedure CMAreaMouseEnter(var Message: TMessage); message CM_MOUSEENTER; procedure CMAreaMouseLeave(var Message: TMessage); message CM_MOUSELEAVE; |
Re: Events zur Designtime
Ja nun, genau das hab ich ja gemacht ;). Aber die Handler wurden nie erreicht. Actions der rechten Maustaste und MouseMove ja, linke und mittlere Taste nein. Alles gleich aufgebaut, alles in ein und der selben Instanz getestet.
Edit: MouseUp hab ich nun nicht getestet, sondern die jeweiligen Down-Ereignisse, aber die brauche ich zwingend auch. |
Re: Events zur Designtime
OOps.. mhhh.. muss mal schaun wie ich das gemacht hatte....
aber probier mal noch csClickEvents und csDoubleClicks im ControlStyle.... |
Re: Events zur Designtime
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:16 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