Frage zu QuestionDlg [gelöst]

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.
Benutzeravatar
six1
Beiträge: 782
Registriert: Do 1. Jul 2010, 19:01

Re: Frage zu QuestionDlg [gelöst]

Beitrag von six1 »

Also ich bin deinem Vorschlag gefolgt.
Funktioniert prima, auch unter Linux einwandfrei compilier und ausführbar!

Aufruf:

Code: Alles auswählen

  
  QuestionDlgEx('Meine Abfrage',
                'Was soll ich machen?',
                mtWarning,
                [mbYes, 'Ja', mbYesToAll, 'Ja zu allen', mbNo, 'Nein', 'IsDefault', mbHelp, 'Hilfe', mbCancel, 'Abbruch'],
                mouse.CursorPos.X,mouse.CursorPos.Y
               );
  
  QuestionDlgEx('Meine Abfrage',
                'Was soll ich machen?',
                mtWarning,
                [mbYes, 'Ja', mbYesToAll, 'Ja zu allen', mbNo, 'Nein', 'IsDefault', mbHelp, 'Hilfe', mbCancel, 'Abbruch'],
                2,
                mouse.CursorPos.X,mouse.CursorPos.Y
               );
               
  QuestionDlgEx('Meine Abfrage',
                'Was soll ich machen?',
                mtWarning,
                [mbYes, 'Ja', mbYesToAll, 'Ja zu allen', mbNo, 'Nein', 'IsDefault', mbHelp, 'Hilfe', mbCancel, 'Abbruch'],
                'QuestiondlgEx,
                mouse.CursorPos.X,mouse.CursorPos.Y
               );
               
letzte Version: viewtopic.php?p=124829#p124829
Zuletzt geändert von six1 am Sa 20. Nov 2021, 12:44, insgesamt 2-mal geändert.
Gruß, Michael

Benutzeravatar
Ally
Beiträge: 263
Registriert: Do 11. Jun 2009, 09:25
OS, Lazarus, FPC: Win und Lazarus Stable release
CPU-Target: x64

Re: Frage zu QuestionDlg [gelöst]

Beitrag von Ally »

Hallo six1,

im Anhang habe ich mal einen Satz mt-Icons beigelegt.
Wenn das so "mehrheitsfähig" wäre, würde ich auch noch die mb-Icons beisteuern.

Gruß Roland
Dateianhänge
mtDialogIcons.zip
(48.99 KiB) 74-mal heruntergeladen

Benutzeravatar
six1
Beiträge: 782
Registriert: Do 1. Jul 2010, 19:01

Re: Frage zu QuestionDlg [gelöst]

Beitrag von six1 »

das ist nett Ally! Icons sehen spitze aus!
Dank wp_xyz konnte ich über GetDialogIcon alle Icons vom System nehmen.
Das ist natürlich einfacher, als eine Resource einzubinden.
Gruß, Michael

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Frage zu QuestionDlg [gelöst]

Beitrag von wp_xyz »

Schön. Noch ein paar Kleinigkeiten:
  • TMyButton wird im Interface-Teil nicht benötigt --> nach Implementation verschieben.
  • Die Funktion GetBKType kann man mit RTTI (uses TypInfo) vereinfachen zu

    Code: Alles auswählen

    function GetBKType(str:string):TBitBtnKind;
    var
      value: Integer;
    begin
      value := GetEnumValue(TypeInfo(TBitBtnKind), 'bk' + str);
      if value > -1 then
        Result := TBitBtnKind(value)
      else
        Result := bkCancel; 
    end;
  • Lizenz: Du möchtest Creative Commons. ok. Aber wenn ich die Unit in mein ExCtrls Package aufnehme, in der ich "LGPL2 with linking exception (like Lazarus LCL)" festgelegt habe, hätte ich ein Lizenz-Chaos, das ich vermeiden möchte. Wärst du damit einverstanden, LGPL2/Linking Exception mit als zweite Lizenz in deinen Text aufzunehmen?
  • Font des Dialogs: Ich würde den in "meiner" Version auf "default" und Größe 0 zurücksetzen, damit das Meldungsfenster bei einer Standard-Anwendung nicht aus dem Rahmen fällt. Der User kann ja beim Aufruf über CreateQuestionDialogEx den Font nach Belieben ändern (er muss sich halt sinnvollerweise eine eigene Aufruf-Prozedur a la QuestionDialogEx schreiben).
  • QuestionDialogEx: Es ist m.E. nicht nötig zu prüfen, ob ein Help-Button vorhanden ist, denn der User kann immer F1 drücken, auch ohne Help-Button. Das Hilfe-System ist so ausgelegt, dass mit F1 der per HelpContext oder HelpKeyword festgelegte Hilfetext erscheint.
  • Zentrierung des Dialogs: Ich habe keine zwei Monitore, aber ich bin ziemlich sicher, dass Screen.Width die gesamte Monitorbreite umfasst. Mit Screen.Width div 2 wäre der Dialog dann genau zwischen beiden Monitoren aufgeteilt... --> Statt Screen QForm.Monitor verwenden. Außerdem haben ist am Rand oft noch die Taskleiste --> WorkAreaRect verwenden.
  • Idee: Man könnte z.B. negative Werte von X/Y als ord(TPosition) interpretieren, so dass man den Dialog z.B. über dem Hauptformular zentrieren könnte (X = ord(poMainFormCenter). Also

    Code: Alles auswählen

     if (X < 0) and (Y = -1) then QForm.Position := TPosition(-X); 
  • Die Prüfung, ob der Dialog horizontal über den rechten Bildschirmrand (Screen.Width, besser: Monitor.WorkArea.Right) hinausragt, müsste noch um die Vertikale (Monitor.WorkArea.Bottom) ergänzt werden.

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Frage zu QuestionDlg [gelöst]

Beitrag von wp_xyz »

Ally hat geschrieben:
Fr 19. Nov 2021, 12:00
im Anhang habe ich mal einen Satz mt-Icons beigelegt.
Wenn das so "mehrheitsfähig" wäre, würde ich auch noch die mb-Icons beisteuern.
Danke. Ich werden die Icons wie üblich in Lazarus aufnehmen. Man könnte ja sogar die Prozedur GetDialogIcon so überarbeiten, dass die zur aktuellen Auflösung passende Größe genommen wird.

Die mbIcons sind meiner Meinung nach schon von dir (lcl/images/buttons).

Benutzeravatar
Ally
Beiträge: 263
Registriert: Do 11. Jun 2009, 09:25
OS, Lazarus, FPC: Win und Lazarus Stable release
CPU-Target: x64

Re: Frage zu QuestionDlg [gelöst]

Beitrag von Ally »

Hallo wp_xyz,
wp_xyz hat geschrieben:
Fr 19. Nov 2021, 12:17
Ich werden die Icons wie üblich in Lazarus aufnehmen.
prima, dann hat sich meine Arbeit ja gelohnt. :)

Benutzeravatar
six1
Beiträge: 782
Registriert: Do 1. Jul 2010, 19:01

Re: Frage zu QuestionDlg [gelöst]

Beitrag von six1 »

Also mit der Hilfe, das ist mir nicht klar.
Soll ich AHelpKeyword oder AHelpCtx der QForm zuweisen?
Ich habe mir zuerst das Sample htmlhelp in Lazarus angeschaut, dann in Google gesucht nach "Lazarus bkhelp bitbtn" und kein einziges Beispiel gefunden.
Soll ich dem Help Button ein onClick zuweisen und ShowHelpOrErrorForKeyword('','HTML/index.html'); aufrufen?

Beim setzen eines Font NACH dem Erstellen der QForm, darf man den Font nicht der QForm (als Parent Font) zuweisen, da dann die Positionierung der Buttons nicht mehr stimmt.
Hier kann man lediglich den Label Font ändern über z.B. (QForm.findcomponent('QMsg') as TLabel).Font.Name:='Consolas'; (was eigentlich auch nicht geht, da die Schriftgröße entscheidet, was in der vorberechneten Zeichenfläche noch sichtbar ist!)
Wird eine einheitliche Schrift gewünscht, muss man das bei der Erzeugung der Qform in CreateQuestionDlgEx erledigen.

Die anderen Punkte habe ich soweit umgesetzt...
Gruß, Michael

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Frage zu QuestionDlg [gelöst]

Beitrag von wp_xyz »

Hast recht. Ich hatte da nichts ausprobiert, als ich das geschrieben habe...

Es sieht so aus, als ob bkHelp nur provisorisch implementiert ist. Bei einem "Search in Files" finde ich keine Stellen, aus denen hervorgeht, was bei Klicken eines Help-Buttons passiert. Man könnte natürlich dem Help-Button in dem QuestionDlg-Formular einen OnClick-Handler zuweisen, der ShowHelpOrErrorForKeyword('...) mit dem HelpCtx/HelpKeyword aufruft. Allerdings sollte bei einem allgemein verwendbaren Dialog die Option offen bleiben, etwas ganz anderes zu tun, z.b. ein eigenes Hilfe-System aufzurufen.

Daher würde ich die Methode ShowHelp des aktuell fokussierten Controls (hier: der Help-Button) aufrufen - der weiß sicher nicht, was alles intern passiert, und man hat alle Möglichkeiten offen; insbesondere kann man über Application.OnHelp eine eigene Hilfe-Routine einbauen.

Damit der Help-Button auf einen Klick reagiert, brauchen wir einen OnClick-Handler. Nur: wir arbeiten hier innerhalb einer Prozedur, keine Möglichkeit für einen Event-Handler. Ich habe daher kurzerhand eine Hilfsklasse THelpClickHandler deklariert, die einen OnClick-Handler bereitstellt, der dem Help-Button zugewiesen wird. THelpClickHandler habe ich von TComponent abgeleitet, Owner ist das Formular (QForm), das die Instanz erzeugt und daher auch wieder freigibt. Damit kennt die Instanz das Formular und kann dessen ShowHelp-Methode aufrufen.

Beim Testen auf Speicherlecks bin ich auf eine üble Falle gestoßen, in die du getappt bist: QImage.Picture.Assign(GetDialogIcon(IconKind)) - das macht ein Speicherleck, weil GetDialogIcon ein Bitmap erzeugt, das hier nicht wieder mehr freigegeben werden kann, weil der Funktionswert von GetDialogIcon bei dem Assign verloren geht.

Und wie macht man das mit dem HelpContext/HelpKeyword? Ich hatte mir gedacht, man könnte das CreateQuestionDlgEx einmal für HelpContext und einmal für HelpKeyword bereitstellen. Damit man nicht jedesmal den ganzen Code duplizieren muss, würde ich alles in eine interne Prozedur InternalCreateQuestionDlgEx auslagern, die als zusätzliche Parameter den HelpCtx und das HelpKeyword hat. Wenn das HelpKeyword kein Leerstring ist, wird dieses in InternalCreateQuestionDlgEx dem Formular zugewiesen, andernfalls wird der HelpCtx zugewiesen. CreateQuestionDlgEx ruft dann InternalCreateQuestionDlgEx auf und setzt entweder den HelpCtx oder das HelpKeyword und lässt das jeweils andere auf dem Default-Wert.
--------
Um den Font auch nach dem Erstellen des Formulars verändern zu können, solltest du die Button-Positionen nicht selbst berechnen, sondern Anchoring und AutoSizing verwenden. Ich habe das in dem beigefügten Projekt (das auch die Hilfe mit implementiert) versucht zu realisieren. (Beachte aber, dass meine Version deiner Unit auf dem Stand des letzten Posts hier ist).
Dateianhänge
questiondlgex_help.zip
(7.32 KiB) 64-mal heruntergeladen

Sieben
Beiträge: 202
Registriert: Mo 24. Aug 2020, 14:16
OS, Lazarus, FPC: Ubuntu Xenial 32, Lazarus 2.2.0, FPC 3.2.2
CPU-Target: i386

Re: Frage zu QuestionDlg [gelöst]

Beitrag von Sieben »

Wäre es nicht auch ausreichend, auf QForm einen Eventhandler für HelpButton.OnClick einzurichten, zuzuweisen und in diesem dann je nachdem Application.HelpContext oder Application.HelpKeyword aufzurufen? Application.OnHelp stünde dann für den äußeren, dem User zugänglichen Eventhandler zur Verfügung. Dazu müsste man nur eine entsprechende Klasse zB TQForm definieren, die anstelle von TForm.Create() mit TQForm.CreateNew() aufgerufen würde.

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Frage zu QuestionDlg [gelöst]

Beitrag von wp_xyz »

Richtig. Hab den Wald vor lauter Bäumen nicht gesehen...

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Frage zu QuestionDlg [gelöst]

Beitrag von wp_xyz »

Ally hat geschrieben:
Fr 19. Nov 2021, 12:34
wp_xyz hat geschrieben:
Fr 19. Nov 2021, 12:17
Ich werden die Icons wie üblich in Lazarus aufnehmen.
prima, dann hat sich meine Arbeit ja gelohnt. :)
Erledigt.

Leider führen diese Dialog-Icons ein Schatten-Dasein, da in der Regel die System-Icons genommen werden (zumindest unter Windows). Ich konnte die neuen Icons nur zu Gesicht bekommen, nachdem ich in GetDialogIcon (unit Dialogs) temporär das erste "if" zu einem "if not" gemacht habe, so dass die Icons aus der Resource geladen wurden und nicht von den ThemeServices.

In dem lcl/images/dialogs-Ordner gibt es noch ein Shield-Icon. Um das zu sehen, waren zusätzlich noch ein paar Änderungen nötig (--> Laz/main). Im Screenshot sieht man das System-Shield-Icon für Win 11 und Win 7.

Mit dem beigefügten Test-Programm kann man die vier Standard-MessageDialoge für alle Msg-Typen aufrufen.
Dateianhänge
shield_icon_win7.png
shield_icon_win7.png (12.52 KiB) 1563 mal betrachtet
shield_icon_Win11.png
shield_icon_Win11.png (5.47 KiB) 1563 mal betrachtet
msgdlgs.zip
(2.58 KiB) 62-mal heruntergeladen

Benutzeravatar
Ally
Beiträge: 263
Registriert: Do 11. Jun 2009, 09:25
OS, Lazarus, FPC: Win und Lazarus Stable release
CPU-Target: x64

Re: Frage zu QuestionDlg [gelöst]

Beitrag von Ally »

wp_xyz hat geschrieben:
Fr 19. Nov 2021, 23:53
In dem lcl/images/dialogs-Ordner gibt es noch ein Shield-Icon.
Hallo wp_xyz,

um das Ganze zu vervollständigen, anbei noch mal der komplette Iconsatz mit den Shield-Icons, der Iconliste und den entsprechenden SVG's.

Gruß Roland
Dateianhänge
2021-11-20 Lazarus-lcl-images-dialogs.zip
(60.27 KiB) 67-mal heruntergeladen

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Frage zu QuestionDlg [gelöst]

Beitrag von wp_xyz »

Vielen Dank. Hab' das Shield-Icon ergänzt.

Benutzeravatar
six1
Beiträge: 782
Registriert: Do 1. Jul 2010, 19:01

Re: Frage zu QuestionDlg [gelöst]

Beitrag von six1 »

Hi wp_xyz,
Deine Änderungen gefallen mir gut, insbesondere die Korrektur zum Speicherleck! 8)
Ein kleiner Fehler ist beim Vorbelegen des Focus auf einen BitBtn noch drin:

in Zeile 226 einfügen: btn.Name:='BitBtn'+inttostr(i);

Zeile 318 ersezen:
if setfocus > -1 then
QForm.ActiveControl:=(QForm.FindComponent('BitBtn'+inttostr(setfocus)) as TBitBtn);

Die Positionierung innerhalb des Bildschirms habe ich ergänzt.

Windows Ansicht
Image5.jpg
Image5.jpg (10.3 KiB) 1510 mal betrachtet
Linux Ansicht (Debian 9, XFCE)
Image2.jpg
Image2.jpg (11.46 KiB) 1510 mal betrachtet
Ich werde das jetzt produktiv einsetzen.
Es erfüllt ALLE meine Ansprüche und ergibt ein einheitliches Bild in meiner Anwendung.
Endlich erscheint ein Dialogfeld so, wie man das erwartet und hat dabei die Möglichkeit der freien Beschriftung!
Danke wp_xyz!
Dateianhänge
unitquestiondlgex.pas
(12.34 KiB) 66-mal heruntergeladen
Zuletzt geändert von six1 am Sa 20. Nov 2021, 17:18, insgesamt 4-mal geändert.
Gruß, Michael

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Frage zu QuestionDlg [gelöst]

Beitrag von wp_xyz »

six1 hat geschrieben:
Sa 20. Nov 2021, 12:34
in Zeile 226 einfügen: btn.Name:='BitBtn'+inttostr(i);

Zeile 318 ersezen:
if setfocus > -1 then
QForm.ActiveControl:=(QForm.FindComponent('BitBtn'+inttostr(setfocus)) as TBitBtn);
Warum so kompliziert? Die Buttons stehen doch im Array QButtonArray, und der Index, nach dem FindComponent suchen soll, ist gerade der Array-Index. Daher kannst du einfach auf die Zuweisung des Namens verzichten (was man sich wegen Problemen bei Namensgleichheit gar nicht angewöhnen sollte) und QForm.ActiveControl direkt auf QButtonArray[setFocus] setzen (letzteres hatte ich in meinem Code übersehen).

Es gibt noch eine weitere Optimierungsstelle:
Wenn die Buttons erzeugt und ins QButtonArray geschrieben werden, ist eigentlich schon bekannt, wieviele Buttons es gibt, und du kannst außerhalb der Schleife SetLength(QButtonArray, Length(PreButton)) setzen (statt das Array bei jedem Schleifen-Durchlauf um ein Element länger zu machen), und du kannst dann am Ende jedes Durchlaufs QButtonsArray[ i ] mit dem aktuell erzeugten btn besetzen.

Was mich noch stört, ist das der Dialog beim Erscheinen flackert. Ich habe das Gefühl, er erscheint, wird sofort wieder ausgeblendet oder verkleinert und erscheint erst dann endgültig. Ob das mit meinen AutoSize-Änderungen zu tun hat? Leider habe ich die alte Version nicht mehr, und finde sie auch hier nicht mehr zum Runterladen (Hinweis an mich selbst: eigentlich sollte man jede noch so kleine Entwicklung unter Versionskontrolle machen (git, svn, ...) ).

Antworten