Sibyl und Toolbar im Vordergrund halten

(DE) Anwendungen für Office, Multimedia und Spiele, Werkzeuge, Hilfsprogramme, etc
(EN) Applications for Office, Multimedia or Games, Tools, Utilities, e.g.
Antworten
MKH
Beiträge: 119
Registriert: So 1. Jul 2018, 08:18

Sibyl und Toolbar im Vordergrund halten

Beitrag von MKH »

Hallo,

ich experimentiere seit einiger Zeit ein wenig mit Sibyl und komme damit auch schon recht gut klar.

Neulich bin ich auf die DockingToolbar-Komponente gestoßen und frage mich, wie ich eine Toolbar im losen Zustand im Vordergrung der Anwendung halten kann. Nun gibt es ja unter Windows die Möglichkeit, dies mit dem SetWindowLong-Api zu realisieren. Ich nehme mal an, das es zu einfach gedacht wäre, dieses Verhalten unter OS/2 dem mit WinSetWindowULong-Api nachzubauen. Wenn ja, dann fehlen mir die entpsrechenden Konstanten dazu. Leider finde ich nirgends eine Dokumentation, die mich hier weiterbringen könnte.

Hat jemand von euch einen Rat?

Zusätzlich wäre es natürlich von Vorteile, wenn das Fenster auch nicht die Möglichkeit bekommen würde, den Fokus zu erhalten, wenn auf einen Button in der Toolbar geklickt wird.

Für Hinweise wäre ich sehr verbunden.
Vielen Dank,
Michael
Benutzeravatar
aschn
Beiträge: 1363
Registriert: Mi 25. Dez 2013, 22:47

Beitrag von aschn »

Keine Ahnung, ob es ein Always-on-top-Style-Bit bei Windows gibt, da kenne ich mich nicht aus. Für OS/2 gibt es das anscheinend nicht.

Mit WinSetWindowPos, HWND_TOP und den Optionen SWP_ZORDER und SWP_ACTIVATE bringt man ein Fenster einmalig nach oben.

(Für vorher minimierte Fenster fragt man mit WinQueryWindowULong und QWL_STYLE zuerst den aktuellen Style ab. Dann muss man zusätzlich noch SWP_RESTORE setzen.)

Den Fokus müsste man AFAIR getrennt mit WinSetFocus und Parent = HWND_DESKTOP setzen, so dass dieser nicht von WinSetWindowPos verändert wird.

Auf Hobbes gibt es float.zip, mit C-Quellcode. Damit wird zyklisch für ein Fenster aus der Fensterliste WinSetWindowPos ausgeführt. Keine Ahnung, ob das taugt. Nachteilig ist, dass dafür die .exe gestartet sein muss. so etwas könntest Du ja auch in Deine Toolbar einbauen. Ich würd das dann aber auch abstellbar machen, weil das ganz schön nerven kann.
Zuletzt geändert von aschn am Fr 6. Mär 2020, 01:19, insgesamt 2-mal geändert.
Andreas Schnellbacher
Martin Vieregg
Beiträge: 459
Registriert: Di 19. Aug 2014, 09:30

Beitrag von Martin Vieregg »

In WDsibyl ruft man eine Form wie folgt auf:

Form1.WindowState := wsNormal; Form1.Show; Form1.BringToFront;

Das BringToFront ist optional, es gibt Situationen wo der Rahmen nicht aktiv wird, und BringToFront macht das. Das Fenster ist so nicht modal gestartet, d.h. man kann es zur Seite schieben und das vorherige Fenster auch weiter bearbeiten.

Wenn man statt .Show nun .ShowModal schreibt, dann ist das Fenster zwangsweise im Vordergrund, die darunterliegenden Fenster derselben Application lassen sich dann nicht mehr anklicken. Für eine Toolbar ist das aber nicht geeignet.

Was auf alle Fälle geht, ist es, einen Timer zu installieren, der relativ selten (z. B. alles 1000 ms) den Status des Toolbar-Fensters überprüft und dann ein .Show (ohne .BringToFront) ausführt. Theoretisch würde ein .Show ausreichen, aber dann wird überflüssiger Code ausgeführt. Sinnvoller ist es, von der Toolbar Form die ZOrder Property zu setzen. Wie man in wdsibyl\library\source\spcc\forms.pas (dort findet man die Klassen tControl und tForm, tForm ist von tControl abgleleitet) unter tControl.SetZOrder sehen kann, wird kein Code ausgeführt, wenn man dieselbe Property nochmal setzt. Also einfach in den Timer-Event ein Toolbarform.ZOrder := zoTop setzen, das sollte funktionieren.

Mit einem Application.Mainform.BringToFront bzw. MyForm.BringToFront am Ende des OnClick-Events des jeweiligen Toolbar-Buttons erhält das Hauptfenster wieder den Focus zurück.

In WDsibyl sind die Biliotheken recht übersichtlich gestaltet (im Unterschied zu Lazarus, das 20 Betriebssysteme unterstützt und includes von includes und ifdefs hat), es ist immer recht aufschlussreich, in die Bib zu schauen. Praktisch der ganze Fensterkram ist in der einen forms.pas Datei.

Was evtl. auch noch theoretisch geht, ist es, in alle anderen Forms bei OnActivate den zOrder-Befehl für die Toolbar zu schreiben, doch ich habe in allen meinen Programmen Activate nicht verwendet, weil es wohl fehlerhaft ist.

Das dauerhafte Obenbleiben müsste man vermutlich mit OS/2-Mitteln machen. In WDsibyl also SendMsg (Handle, WM_..., mp1, mp2); Handle ist in jedem Form-Objekt definiert, das ist der Window Handle. Hier könnten andere OS/2-API-Kenner Dir weiterhelfen. Evtl. im englischsprachigen Forum fragen. Ich habe das in meinem 4callCalc Taschenrechner (in C) realisiert, und wenn ich es richtig verstehe, habe ich einfach ein einmaliges WinSetFocus (HWND_DESKTOP, MyToolbar.Handle) verwendet. Es könnte sein, dass das dauerhaft geht und nur einmal aufgerufen werden muss, bitte ausprobieren. In einem WDsibyl-Programm habe ich das selbst noch nicht verwendet.
Zuletzt geändert von Martin Vieregg am Fr 6. Mär 2020, 09:04, insgesamt 1-mal geändert.
MKH
Beiträge: 119
Registriert: So 1. Jul 2018, 08:18

Beitrag von MKH »

Herzlichen Dank für eure Vorschläge. Leider habe ich es bislang noch nicht geschafft, mich auf OS2World zu registrieren. Keine Ahnung was da los ist.

Bevor ich alles mögliche (oder auch unmögliche) ausprobiere, möchte ich gerne in Erfahrung bringen, ob es nicht doch mittels API entsprechend zu realisieren geht. Es gibt ja sehr viele Programme, die eine Toolbar im Vordergrund halten können. Ein Timer scheint mir dafür nicht geeignet, da es wohl zu einem unangenehmen flackern kommt.

Ein weiterer Lösungsversuch wäre mir mittels Open32 in den Sinn gekommen. Nur wenn ich dort die WinSetWindowLong-Funktion im Code stehen habe (selbst ohne die Funktion aufzurufen), lässt sich mein Programm nicht mehr starten. Es kommt nicht mal zu einer Fehlermeldung.
Es wäre interessant zu wissen, wie SetWindowLong von Open32 gemappt wird. Dann könnte man das entsprechend nachbauen.
Benutzeravatar
aschn
Beiträge: 1363
Registriert: Mi 25. Dez 2013, 22:47

Beitrag von aschn »

MKH hat geschrieben: So 8. Mär 2020, 09:09 Leider habe ich es bislang noch nicht geschafft, mich auf OS2World zu registrieren.
Ich schlage vor: Mail (Server: gmail.com) an Martin (martiniturbide).
Andreas Schnellbacher
Martin Vieregg
Beiträge: 459
Registriert: Di 19. Aug 2014, 09:30

Beitrag von Martin Vieregg »

Ich habe mir das Problem nochmals angesehen. WinSetFocus führt nur zu einem einmaligen Focus. Interessant ist, dass bei meinem 4allCalc Taschenrechner (für OS/2 und Windows siehe www.hypermake.de) die Zusatzfenster prg fct und reg (Programmierer,- Funktions- und Regressionsdialog) gegenüber dem Hauptfenster automatisch immer oben liegen. Ich habe aber noch nicht herausgefunden, was die entscheidende Zeile im Quellcode ist, die das bewirkt, obwohl ich das (allerdings vor vielen Jahren) selbst geschrieben habe. Im Laufe der Woche würde ich mir das aber nochmals genauer ansehen und dann hier berichten.

Im 4allCalc Systemmenü gibt es eine "float to top" Einstellung, damit das Hauptfenster über allen anderen Fenstern floatet Die ist in Windows über einen einmaligen Aufruf von

Code: Alles auswählen

         if (Floating) SetWindowPos (hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
         else SetWindowPos (hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
gelöst, während ich in OS/2 das über einen Timer gelöst habe. Beim Timer ist nur wichtig, dass der Aufruf nur dann losgeschickt ist, wenn das Fenster wirklich nicht oben liegt. Beim Programm pmvdesk (virtuelle Desktops) scheint es auch über Timer gelöst zu sein, ich bin mir relativ sicher, weil es minimal zeitverzögert passiert. Die Kindfenster beim 4allCalc bleiben dagegen ständig oben, das scheint unter OS/2 nur innerhalb eines Programmes zu gehen (das wäre aber wohl das, was Du suchst.)
MKH
Beiträge: 119
Registriert: So 1. Jul 2018, 08:18

Beitrag von MKH »

Hallo Martin,

vielen Dank für die Mühe!

Unter Windows gibt es im Prinzip 2 Möglichkeiten. Mit SetWindowPos und HWND_TOPMOST wird ein Fenster komplett im Vordergrund gehalten. Also auch vor allen anderen Fenstern und nicht nur dem eigenen Programm. Damit kann man natürlich entsprechend arbeiten, so wie du es im Code-Beispiel stehen hast. Sowas wäre natürlich ideal.

Die 2. Möglichkeit wäre SetWindowLong und GWL_HWNDPARENT. Hier genügt ein Aufruf im Code und das Fenster wird (ausschließlich) vor der eigenen Anwendung gehalten. Optimal für Toolbars oder nichtmodale Dialogfelder.

Ein derartiges Verhalten ist aber auch unter OS/2 gang und gebe. Man nehme z.B. Programme wie VX-Rexx, wo die Toolbox permanent über dem Hauptfenster erscheint...
Benutzeravatar
aschn
Beiträge: 1363
Registriert: Mi 25. Dez 2013, 22:47

Beitrag von aschn »

MKH hat geschrieben: Mo 9. Mär 2020, 20:09 Ein derartiges Verhalten ist aber auch unter OS/2 gang und gebe. Man nehme z.B. Programme wie VX-Rexx, wo die Toolbox permanent über dem Hauptfenster erscheint...
Wenn Du auf die MsgQueue selbst zugreifen kannst, dann mag das ja einfach gehen, für die WPS brauchst Du aber anscheinend einen Hook. Ich hab mir jetzt die Quellcodes von verschiedenen Toolbars (auch XPager) angesehen. Bisher haben alle einen WPS-Hook installiert um "always on top" oder "stay on top" zu erreichen.
Zuletzt geändert von aschn am Mi 11. Mär 2020, 19:43, insgesamt 2-mal geändert.
Andreas Schnellbacher
MKH
Beiträge: 119
Registriert: So 1. Jul 2018, 08:18

Beitrag von MKH »

Danke für den Hinweis. Dann kann ich die Hoffnung auf eine einfache Lösung via API begraben.
Benutzeravatar
ak120
Beiträge: 1044
Registriert: Do 8. Mai 2014, 12:50
Wohnort: Demmin
Kontaktdaten:

Beitrag von ak120 »

MKH hat geschrieben: Sa 14. Mär 2020, 14:36 Danke für den Hinweis. Dann kann ich die Hoffnung auf eine einfache Lösung via API begraben.
Der API-Aufruf SetWindowLong kann doch unter OS/2 Warp 4 verwendet werden. Zumindest funktioniert es unter C und C++. Einfach mal einen Blick auf die Open32-Beispiele aus dem Toolkit werfen. Zur Not kann man das Ganze in eine DLL packen welche auch von Pascal aus nutzbar sein sollte.
ehemaliger
Beiträge: 102
Registriert: Mi 22. Nov 2017, 23:46

Beitrag von ehemaliger »

MKH hat geschrieben: So 8. Mär 2020, 09:09Leider habe ich es bislang noch nicht geschafft, mich auf OS2World zu registrieren. Keine Ahnung was da los ist.
Funktioniert bei mir - trotz mehrerer Versuche - auch nicht. Angeblich wird eine Bestätigungsmail versandt, die aber auf meinem (1&1) - Account nie ankommt. Auch nicht unter Spam.
Martin Vieregg
Beiträge: 459
Registriert: Di 19. Aug 2014, 09:30

Beitrag von Martin Vieregg »

Ich habe jetzt Zeit gefunden, dem Problem auf den Grund zu gehen. Schließlich funktionieren die Zusatzfenster meines 4allCalc Taschenrechners genau so wie hier gewünscht: Sie floaten ständig über dem Hauptfenster.

Sowohl im 4allCalc-Quelltext als auch im beiliegenden Beispiel DIALOG.EXE aus dem Buch "OS/2-Programmierung " von tewi (Langenkamp/Bredno) (siehe Zip-Datei) wird der OS/2-API-Call WinLoadDlg verwendet. Dagegen verwendet WDsibyl ausschließlich den API-Call WinCreateWindow, und zwar in Forms.pas tControl.CreateWnd. Leider fehlt WinLoadDlg in der epm2 Doku im Internet, doch in der OS/2-API Dokumentation als HLP/INF Datei ist er beschrieben, auch in der bei WDsibyl enthaltenen OS2API.HLP.

WinLoadDlg erzeugt ein "dialog window", während WinCreateWindow oder WinCreateStdWindow ein "window" erzeugt. Man kann sie optisch am System-Icon oben links unterscheiden. Wenn es ein Icon gibt, dann ist es ein "window", wenn es nur einen Pfeil nach unten zum Aufklappen des Systemmenüs gibt, ist es ein "dialog window". Dialog windows können entweder modal sein oder nicht-modal.

D.h. man muss in Sibyl entweder API-Code verwenden oder man könnte einmal probieren, ob man mit einer Forms Property eine Form auch über WinLoadDlg starten kann, das wäre natürlich am elegantesten. Momentan ist mir aber nicht klar, ob dann alle Ressourcen usw. noch funktionieren. Ich probiere das in nächster Zeit einmal aus und werde auch schauen, ob das in Freepascal/Lazarus umgesetzt worden ist.
Dateianhänge
dialog_tewi.zip
Beispielsprogramm "Dialog" aus Buch tewi "OS/2-Programmierung", Binary und Quelltext
(25.36 KiB) 119-mal heruntergeladen
Martin Vieregg
Beiträge: 459
Registriert: Di 19. Aug 2014, 09:30

Beitrag von Martin Vieregg »

In Freepascal-Lazarus wurde es tatsächlich umgesetzt:

https://lazarus-ccr.sourceforge.io/docs/lcl/forms/tcustomform.formstyle.html

Wenn ich das in WDsibyl Forms.pas umsetzen sollte, werde ich die genannte Syntax verwenden.
Martin Vieregg
Beiträge: 459
Registriert: Di 19. Aug 2014, 09:30

Beitrag von Martin Vieregg »

WinLoadDlg bzw. WinCreateDlg läßt sich in WDsibyl nicht verwenden. Ich habe jetzt eine Frage im englischsprachigem Programmiererforum gepostet. Die Property "FormStyle" gibt es im Übrigen in WDsibyl schon, aber der spezielle Wert "fsStayOnTop" existiert noch nicht.
Benutzeravatar
aschn
Beiträge: 1363
Registriert: Mi 25. Dez 2013, 22:47

Beitrag von aschn »

Martin, das ist ja 'n bischen was anderes als das, was Michael wollte. Du suchst eine Möglichkeit um diese Funktion anwendungsweit zu erreichen. Michael hat dies Desktop-weit gesucht.

Also, erstmal brauchst Du eine Funktion um ein Fenster topmost zu machen. Das geht ungefähr so:

o Den aktuellen Style eines Fensters (hwnd) mit WinQueryWindowULong abfragen.
o SWP_ZORDER und SWP_ACTIVATE setzen.
o Falls das Fenster minimiert ist (WS_MINIMIZE im Style gesetzt), noch SWP_RESTORE setzen, falls Du das haben willst.
o Den neuen Style mit WinSetWindowPos setzen.

Dann musst Du noch in Deiner MessageLoop bei bestimmten Events diese Funktion aufrufen. Mir fällt da WM_SETFOCUS ein - ungetestet.
Zuletzt geändert von aschn am Fr 3. Apr 2020, 18:45, insgesamt 2-mal geändert.
Andreas Schnellbacher
Martin Vieregg
Beiträge: 459
Registriert: Di 19. Aug 2014, 09:30

Beitrag von Martin Vieregg »

Wie das einmalig geht, ist schon klar. Das ist auch alles in der WDSibyl SPCC Komponentenbibliothek enthalten. Aber eben das ständige Obenbleiben ohne Timer ist nicht implementiert. Ich bin auch nicht sicher, ob das wirklich bei OS/2 geht. Bezogen auf ein Programm geht das mit den Dialogboxen, das sind aber keine normalen Frame Windows. Ich habe die Frage im englischen Forum nun auf systemweites Obenbleiben ausgeweitet. In der Freepascal Lazarus Bibliothek gibt es fsStayOnTop und fsSystemStayOnTop. Es wäre schön, wenn wir das in WDsibyl auch umsetzen könnten. Ich habe schon ein paar Antworten erhalten, aber noch nichts substanzielles.
Benutzeravatar
aschn
Beiträge: 1363
Registriert: Mi 25. Dez 2013, 22:47

Beitrag von aschn »

Martin Vieregg hat geschrieben: Fr 3. Apr 2020, 23:58 Ich bin auch nicht sicher, ob das wirklich bei OS/2 geht.
Doch, das geht innerhalb einer Anwendung mit allen Fenstern, jedenfalls PM-Fenstern.
Zuletzt geändert von aschn am Sa 4. Apr 2020, 00:17, insgesamt 2-mal geändert.
Andreas Schnellbacher
Benutzeravatar
aschn
Beiträge: 1363
Registriert: Mi 25. Dez 2013, 22:47

Beitrag von aschn »

Der zweite Teil ist ja auch der Wichtigere: das Aufrufen der Funktion bei bestimmten Events. Vgl. dazu z.B. den XCenter-Quellcode.
Andreas Schnellbacher
Martin Vieregg
Beiträge: 459
Registriert: Di 19. Aug 2014, 09:30

Beitrag von Martin Vieregg »

Ich habe inzwischen Feedback erhalten, wie es geht und werde nun wenn ich in den nächsten Tagen Zeit habe, das in WDsibyl forms.pas einbauen ... falls es wirlich gehen sollt - doch laut Forum sollte es gehen. Man muss wohl die Eigenschaft schon beim Erzeugen des Fensters übergeben.
Martin Vieregg
Beiträge: 459
Registriert: Di 19. Aug 2014, 09:30

Beitrag von Martin Vieregg »

Zwischenbericht

Ich habe nun das "Float on Top" tatsächlich hinbekommen, erstaunlicherweise aber jetzt erst einmal systemweit. Der Befehl wird lazarus-kompatibel sein:

tForm.FormStyle = fsSystemStayOnTop

Der Befehl geht mit einem nicht dokumentierten OS/2 flag WS_TOPMOST 0x200000 und nur beim Erzeugen des Windows. Man muss also dann schon bei OnCreate bzw. Create den FormStyle setzen. Beim ersten Show wird dann das eigentliche Fenster erzeugt und bis dahin muss die Variable gesetzt sein.

Jetzt hoffe ich dass ich das auch noch "nur" programmweit hinbekomme, so dass andere Programme das Fenster weiterhin abdecken können:

tForm.FormStyle = fsStayOnTop
Zuletzt geändert von Martin Vieregg am Mi 29. Apr 2020, 23:08, insgesamt 2-mal geändert.
Benutzeravatar
aschn
Beiträge: 1363
Registriert: Mi 25. Dez 2013, 22:47

Beitrag von aschn »

Martin Vieregg hat geschrieben: Mi 29. Apr 2020, 23:07 Jetzt hoffe ich dass ich das auch noch "nur" programmweit hinbekomme, so dass andere Programme das Fenster weiterhin abdecken können:
Hast Du mal WS_CLIPCHILDREN probiert?
Andreas Schnellbacher
MKH
Beiträge: 119
Registriert: So 1. Jul 2018, 08:18

Beitrag von MKH »

Erstaunlich. Also gibt es doch eine entsprechende Möglichkeit.
Kurios dass das nicht dokumentiert ist.

Ein "programmweites" OnTop könnte man dann ja auch entsprechend umsetzen, indem man das Fenster nur einblendet, wenn die Anwendung den Fokus hat.

Vielen Dank vorerst für die Unterstützung!!!
ehemaliger
Beiträge: 102
Registriert: Mi 22. Nov 2017, 23:46

Beitrag von ehemaliger »

MKH hat geschrieben: Do 30. Apr 2020, 20:21Kurios dass das nicht dokumentiert ist.
Vielleicht weil es eigentlich keiner Applikation zusteht, sich derart in den Vordergrund zu drängen. So etwas sollte nur dem System selbst (sprich der WPS) vorbehalten sein. Programmweises "ontop" dürfte ja durch geeignetes Setzen von "owner" bzw. "parent" des jeweiligen Fensters möglich sein. Aber jeder dahergelaufenen Applikation zu erlauben, permanent ein Fenster über den Desktop zu legen, halte ich für problematisch.
Martin Vieregg
Beiträge: 459
Registriert: Di 19. Aug 2014, 09:30

Beitrag von Martin Vieregg »

So, ich habe jetzt die gewünschten Properties in die WDsibyl Library in Lazarus lcl Syntax integrieren können:

tForm.Formstyle = fsSystemStayOnTop
tForm.Formstyle = fsStayOnTop


"fsSystemStayOnTop" bedeutet systemweit, das Fenster geht über alle anderen Fenster.
"fsStayOnTop" macht es nur für das jeweilige Programm. Es spielt keine Rolle, ob man die Eigenschaft vor oder nach der Generierung des Fensters (das erste Show) setzt.

Die erste Einstellung ging über einen unkommentierten OS/2-Flag WS_TOPMOST und bei der zweiten ist es indirekt umgesetzt: Wenn eine andere Form durch den User ganz nach oben geht, bekommen alle Fenster des Programms mit der fsStayOnTop Eigenschaft die Anweisung, sich wieder darüberzusetzen. Es konnte somit ohne Timer Messages umgesetzt werden.

Die Modifikationen schicke ich an Rolf, sie werden dann im nächsten Update enthalten sein. Alle Änderungen hierfür sind in nur einer Datei spcc\forms.pas enthalten.

Das systemweite Floaten muss natürlich mit Vorsicht genossen werden. Aber das Fenster bekommt natürlich nicht den Focus, sondern floatet nur nach oben. Es gibt tatsächlich Anwendungen, wo das sinnvoll ist, etwa bei einem virtuellen Bildschirmmanager, einer Uhr oder einer Toolbar - natürlich immer nur bei Fenstern mit geringer Größe. Kritisch sehe ich vor allem Programme, die ungefragt den Fokus an sich reißen und dann die Benutzereingaben auf einmal in das andere Fenster gehen.
Antworten