In einem EXE-Dialog die Rechte Maustaste von einer DLL aus sperren
-
Zur Zeit schreibe ich eine DLL für ein Programm großen Umfangs, das ein von Borland 5.1 stammendes ToolBar-Control enthält. Das Control ist unter XP fehlerhaft. Mit dieser DLL soll unter anderem verhindert werden, daß bei einem Rechtklick auf den unbenutzten Bereich des ToolBar-Controls das Programm in eine Endlosschleife fährt. Dies geschieht allerdings nur ab XP aufwärts.
Ich beschreibe den gewünschten Code am besten mal im Pseudoverfahren:1.Bei DLL-Start Handle des ToolBar-Controls ermitteln
2.Die Cursorposition verfolgen und überstrichene Fensterhandles ermitteln.
3.Der Cursor bewegt sich in den Fensterbereich des ToolBar-Controls:
4.Überprüfen, ob das gefundene Handle mit dem zuvor ermittelten übereinstimmt.
5.Wenn ja, dann auf Systemebene RButtonDown solange sperren, bis der Cursor sich wieder außerhalb des ToolBar-Bereichs befindet.Es gibt dafür drei Methoden:
1. die zuvor beschriebene
2. SubClassing des ToolBar-Controls, was mit neuen Fehlern verbunden sein kann.
3. Patch auf Binärebene des Controls, aber mit dem Risiko neuer Inkompatibilität.Ich habe mich darum für die erstere entschieden.
Wer hat die zündende Idee, über den oben beschriebenen PseudoCode von der DLL aus über die Systemebene RButtenDown zeitweilig zu sperren? Es sollte möglich sein, weil sich ja die DLL im gleichen Adressraum wie die EXE befindet.
-
mach doch subclassing wenn das geht. aber geht das mit diesen komischen borland controls?

-
Ja, es geht schon, nur ist die Sache sehr recht verzwickt, weshalb ich auch lieber auf Code beim Einstieg verzichtet habe ;-).
Es gelingt z.B. auch, in den Borland Dialog der EXE eine Combobox, die in der Dll erstellt wurde, von der Dll aus einzufügen und dann in der Exe zu benutzen.
Doch ist das hier kaum darstellbar, weil es Kilometer Platz verbraucht.
Mit dem Subclassing ist das so eine Sache. Ich müßte es bei einem Wechsel der Betriebssystems stets zu- oder abschalten. Gut ist so eine Lösung gewiß nicht.
Es wäre schließlich recht einfach, über WM_NCHITTEST von der DLL aus zunächst den Mouse-Event abzufangen und dann s0 vorzugehen wie eingangs beschrieben. Nur habe ich dafür keine Syntax parat und hoffe darauf, daß Irgendwer noch einen Brocken Code unter dem Schreibtisch liegen hat, den er für einen ähnlichen Fall benutzt hat. Wenn ich z.B. so vorgehe, dann erhalte ich, obwohl ich das TabControl-Handle korrekt erfasen kann, nur dann mit WM_NCHITTEST einen Result, wenn das Hauptfenster des EXE-Programms berührt wird, nicht aber wenn der Curser dem Dialogstreifen einen Besuch abstattet. Ansonsten wäre die Angelegenheit längst auch schon unter dem Schreibtisch gelandet.
Mir fehlt also die Verbindung von dem mit WM_NCHITTEST erreichbaren Hauptfenster und dem Handle des aktuell angefragten Fensters, daß sich ja schließlich innerhalb des Hauptfensters befindet.....
-
Um die WM_NCHITTEST Nachricht eines Fensters abzufangen, werden Wie es wohl oder über subclassen müssen, wie soll es sonst von statten gehen! Allerdings wird Ihre Methode nicht funktionieren, da das Childfenster, also in diesem Fall Ihre Toolbar, die WM_NCHITTEST Nachricht erhält, wenn sich der Cursor über ihr befindet und nicht das Parentfenster. Untersuchen Sie das Programm doch einmal mit Spy++.
-
Achso, Ich vergaß, handelt es sich bei besagter Toolbar tatsächlich um ein von dem Programm selbst verwaltetes Control, kann Ihre Vorgehensweise natürlich sehr wohl funktionieren. Sie sollten dann die WM_NCRBUTTONDOWN Nachricht des Parentfensters abfangen und die nötigen Berechnungen dort durchführen.
Mit freundlichen Grüßen,
Dipl.Inf.(FH) real_rofler
-
Die Sachlage ist nur deshalb verzwickt, weil ich ja den Grenzübertritt hin zum ToolBar-Control primär abfangen muß, um erst danach den RButtonDown Klick zu verhindern, solange, bis der Cursor wieder im erlaubten Bereich herumturnt.
Wenn ich so programmiere, dann hat das ToolBar-Control ja bereits sozusagen den Focus. Wenn jetzt der rechte Mausknopf geklickt wird, wird der Event im ToolBar-Control ausgelöst. Doch bevor er programmatisch erlaubt, darauf zu programmatisch zu reagieren, hat ja bereits das System auf stur geschaltet und geht in die Endlossschleife.
Ich muß also unmittelbar nach dem Übergang des Cursors in das ToolBar-Fenster mit WM_NCHITTEST in einer Msg-Schleife den System-RButtonDown Event abfangen, bevor er überhaupt an das ToolBar-Control weitergereicht werden kann.
Ich weiß, daß es dafür eine Lösung gibt. Ich weiß aber augenblicklich nicht, wie ich es lösen kann. Da muß ich wohl noch etwas recherchieren.Zur Zeit stellt es sich so dar, daß, wenn ich genau wie beschrieben mit WM_NCHITTEST vorgehe, die Prozedur nicht etwa auf den Übergang des Cursors ins ToolBar-Fenster reagiert, obwohl das Handle korrekt angegeben ist, sondern nur auf den Übergang des Cursors vom Desktop auf das MainFrame-Fenster des Programms.
Ich müßte mal ein mit der WinAPI erzeugtes vergleichbares Modell auf sein Verhalten testen. Es kann ja durchaus sein, daß Borland da mit seiner Unkonventionalität seine Finger im Spiel hat. Doch damit habe ich mich bislang wenig befaßt, und wie bereits beschrieben, es handelt sich hier um einen kleinen operativen Eingriff von außen in die EXE.
Mit WinSpy kommt man auf dieser Ebene nicht sehr weit. Ich binde zu diesem Zweck einen kleinen Echtzeit-Debugger in die DLL ein, der mich an Alles heranlassen soll, das sich im selben Speicherbereich befindet.
Manchmal müssen die nicht selbstverwalteten Gehirnzellen einfach mal von Registry-Schrott befreit werden, um wieder den Durchblick zu erhalten.
-
Kaum habe ich den persönlichen Speicher durchfegen lassen, ist die Lösung des Problems da!
Ich starte die msg-Routine mit WM_NCHITTEST nicht erst durch den hoover-event des ToolBar-Controls, sondern lasse die Routine global in der DLL mitlaufen, triggere aber die Sperrung von RButtonDown mit einer in der Msg-Routine befindlichen globalen True/False-Variablen, sobald der Cursor das Grenzübertritt-Event mit dem ToolBar-Control auslöst. Damit ist immer der korrekte Status der Maus über die Systemroutinen im voraus bekannt. Das war's.
Manchmal reicht es, wenn man sich auf das Niederschreiben des Problems konzentriert. Vielen dank für's 'Zulesen'.