Ausserordentliches Ereignis?
-
Die x/y Angaben hast du doch schon (Parameter von OnMouseDown) und den Pointer auf den Client auch (Sender). Wo ist denn jetzt dein Problem.
-
Also, wenn ich Dich richtig verstehe, dann ist der Ablauf folgender:
1. Ein Benutzer wählt (z.B. im Menü), daß er Hilfe braucht.
2. Ein Klick auf einen Button oder sonstiges TControl bewirkt jetzt vorübergehend nicht,
daß die Aktion ausgeführt wird, die dem OnClick-Ereignis zugeordnet ist, sondern eine
spezielle "Hilfe-OnClick"-Routine.
3. Nach der Hilfe soll wieder die Standard-OnClick-Routine zugeordnet sein.Wenn das so stimmt, ist die Lösung doch relativ einfach.
1. Gehe alle aktiven Formulare Deiner Anwendung durch und biege für alle OnClick-Ereignisse die
Ereignisbehandlungsmethode auf die für die Hilfe um. Merke Dir aber vorher die ursprünglichen
Adressen.
2. In Deiner "globalen" Hilfe-OnClick-Funktion identifiziere das Control über die Sender-Eigenschaft
- wie von Braunstein vorgeschlagen. Die X/Y-Koordinaten bekommst Du auf ähnliche Weise über das
MouseMove-Ereignis o.ä. raus. Vielleicht (Wahrscheinlich) gibt es auch einen Weg über die Win-API
- dazu kannst Du sicherlich WebFritzi fragen.
3. Setze die vorher gemerkten Ereignis-Methoden wieder auf die ursprünglichen Werte zurück.Das ganze funktioniert wahrscheinlich auch über Windows-Hooks, zu denen auch ein FAQ-Eintrag ex-
istiert.Gruß,
Alexander
-
Hallo Alexander!
Erstmal vielen Dank für deine Antwort! Genau so, wie du das beschreibst sollte die Funktionsweise sein.
Nur verstehe ich eines nicht so ganz: Ich gehe also alle Controls durch und setzt die Ereignisbehandlungsroutine auf was anderes, das dann meine Hilfefunktion wird.
Nur, wie kann ich vorher die Events "zwischenspeichern", damit ich diese später wieder zuordnen kann. Damit komme ich nicht so ganz klar.Naja... während ich hier schreibe, kommt mir eigentlich ne Idee:
2 TList Objekte, darin kann ich ja Zeiger zwischenspeichern.
In die 1. Liste packe ich mir alle meine geänderten Controls und in die 2. Liste auf gleicher Höhe packe ich mir den Zeiger zum Event.
Bei Beenden der Hilfe kann ich ja wieder alle meine Controls durchgehen, schaun ob das vielleicht in meiner 1. Liste drin ist - und wenn ja, das Ereignis der 2. Liste wieder zuweisen.Müsste doch so funktionieren?!?

Ob das ne schöne Lösung gibt? Aber funktionieren müsste es...
Danke dir für deinen Denkanstoss!
tschüss
Robert
-
rowisoft schrieb:
2 TList Objekte, darin kann ich ja Zeiger zwischenspeichern.
Das würde wohl gehen, besser würde ich aber finden, nur eine Liste zu verwenden (muß ja nicht TList
sein), um die beiden (die ja zusammengehören) gemeinsam zu speichern. Also sowas wie Key/Value-
Paare zu speichern. Möglich wäre es z.B. den Namen des Controls in eine TStringList zu speichern
und die zugehörige Ereignis-Methode als Objekt (AddObject). Über FindComponent kann man dieses
Control später wieder finden...
Willst Du mehrere Methoden-Zeiger ablegen, würde ich Dir empfehlen, eine kleine Klasse oder Struct
zu schreiben.Gruß,
Alexander
-
Wenn es nur bei der einen Hilfsfunktion bleibt, könnte man bei klicken auf den Hilfebutton (oder Menupunkt etc.) ein Flag setzen welches dann in jeder implementierten OnMouseDown-Funktion (welche eine Hilfe hat) abgefragt wird. Dann entsprechend Flag eine zentrale Hilfsfunktion bzw. die Orginalroutine aufrufen. Dann Flag zurücksetzen.
-
Hallo!
Wenn es nur bei der einen Hilfsfunktion bleibt, könnte man bei klicken auf den Hilfebutton (oder Menupunkt etc.) ein Flag setzen welches dann in jeder implementierten OnMouseDown-Funktion (welche eine Hilfe hat) abgefragt wird. Dann entsprechend Flag eine zentrale Hilfsfunktion bzw. die Orginalroutine aufrufen. Dann Flag zurücksetzen.
Eben genau das wollte ich verhindern. Bei 90 Formularen - und dementsprechend viele TControls ist hier der Ärger vorprogrammiert. Und wenn dann neue Controls hinzugefügt werden (weil eine Software ja nie fertig ist) - wie oft wird da dann wohl vergessen, dieses Flag abzufangen?
tschüss
Robert
-
Hallo!
Irgendwie raff ich das nicht.
Wenn ich sozusagen den Hilfe-Button drücke, habe ich den folgenden Code eingebaut:
MaskenDesignerList = new TList(); MaskenDesignerEvents = new TList(); for ( int i = 0; i < Form1->ActiveMDIChild->ComponentCount; i++) { if (dynamic_cast<TControl*>(Form1->ActiveMDIChild->Components[i])) { TControl *Element = dynamic_cast<TControl*>(Form1->ActiveMDIChild->Components[i]); MaskenDesignerList->Add(Element); TMouseEvent event = (((TButton*)Element)->OnMouseDown); MaskenDesignerEvents->Add(*(((TButton*)Element)->OnMouseDown)); ((TButton*)Element)->OnMouseDown = MaskenDesignerElementMouseDown; } }Irgendwas (ich weiß aber nicht was) muss daran aber falsch sein. Wenn ich nachher sozusagen beim Ausschalten der Hilfefunktion diesen Code reinmache:
for ( int i = 0; i < Form1->ActiveMDIChild->ComponentCount; i++) { if (dynamic_cast<TControl*>(Form1->ActiveMDIChild->Components[i])) { TControl *Element = dynamic_cast<TControl*>(Form1->ActiveMDIChild->Components[i]); for (int x = 0; x < MaskenDesignerList->Count; x++) { if (MaskenDesignerList->Items[x] == Element) { ((TButton*)Element)->OnMouseDown = *((TMouseEvent*)(MaskenDesignerEvents->Items[x])); break; } } } }Bleibt das OnMouseDown - Event immer noch auf auf die "Hilfefunktion". Der Debugger sagt mir auch, dass jedes Element von "MaskenDesignerEvents" meine Hilfefunktion ist.
Daher gehe ich davon aus, dass ich beim Setzen schon was falsch mache, ich weiß aber nicht was...BTW: Wie kann ich denn auf TControl::OnMouseDown zugreifen, ohne jeweils auf irgendein spezielles Control (Button) casten zu müssen? Oder wie kann ich auf den jeweils richtigen Typ casten, das mit (TButton*) funktioniert zwar, kann aber doch auch nicht die optimale Lösung sein??!
Vielleicht kann mir ja nochmal jemand helfen...
Danke & tschüss
Robert
-
Hast Du es schon mal mit MethodName() und MethodAdress() versucht? Diese scheinen mir besser für Dein vorhaben geeignet.
-
Hallo!
Danke für deine Antwort.
Mit MethodName komme ich nicht so ganz zurecht. Wenn ich z.B. mache
ShowMessage(Button1.MethodName(&(Button1->OnMouseDown)));
erhalte ich immer einen leeren String...Aber egal - das Problem ist gelöst. Habe mir in meiner Klasse einen Zeiger TMouseEvents deklariert und beim Starten der Hilfefunktion habe ich dann = new TMouseEvents[AnzahlDerControls] gemacht und diese einzeln gefüllt.
Und diese konnte ich nachher dann auch wieder zurückgeben.
Da war meine Idee mit TList wohl nicht so optimal, obwohl mich immer noch wundert, warum das nicht funktioniert hat. Aber egal, die neue Lösung gefällt mir eh besser...Danke trotzdem euch allen!
tschüss
Robert
-
rowisoft schrieb:
Wie kann ich denn auf TControl::OnMouseDown zugreifen, ohne jeweils auf irgendein spezielles Control (Button) casten zu müssen?
Ja, das fand ich auch toll, als ich damals damit rumexperimentiert hatte. Joe_M. hat die Richtung schon angedeutet.
Man kann das auch dynamisch machen. Das sieht dann ungefähr so aus:for (int i=0; i<form->ComponentCount; ++i) { TMethod method; method.Data = this; method.Code = this->MethodAddress("FormMouseMove"); PPropInfo PropInfo = GetPropInfo((PTypeInfo)form->Components[i]->ClassInfo(), "OnMouseMove"); if (PropInfo && (*PropInfo->PropType)->Kind == tkMethod && (AnsiString)(*PropInfo->PropType)->Name == String("TMouseMoveEvent")) SetMethodProp(static_cast<TObject *>(form->Components[i]), PropInfo, method); }Dabei ist FormMouseMove die Ereignisbehandlungsmethode, die Du neu zuweisen willst. In Deinem Fall also Deine "Hilfe"-
Methode. OnMouseMove ist die Ereignis-Eigenschaft des Controls, der Du Deine Methode zuweisen willst. Vorher solltest Du
aber noch prüfen, ob form->Components[i] auch vom Typ TControl ist.Gruß,
Alexander