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

Beitrag von six1 »

Ich benötige noch einen Tipp:

Die Images zu

TMsgDlgType = (mtWarning, mtError, mtInformation, mtConfirmation, mtCustom);

kann ich wie laden?
Gruß, Michael

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

Re: Frage zu QuestionDlg

Beitrag von six1 »

Habe es gefunden:

QImage.Picture.Icon.Handle := LoadIcon(0, PChar(IDI_QUESTION));

hier noch ein paar Konstanten für andere Symbole:
IDI_APPLICATION = 32512;
IDI_WARNING = 32515;
IDI_ERROR = 32513;
IDI_INFORMATION = 32516;
Gruß, Michael

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

Re: Frage zu QuestionDlg

Beitrag von six1 »

Anbei mein persönlicher Lösungsansatz. (Das ist WIN only!)
Ist für meinen Einsatz des QuestionDlg zugeschnitten, aber leicht auf andere Bedürfnisse änderbar.

letzte Version hier downloaden: viewtopic.php?p=124829#p124829
Zuletzt geändert von six1 am Sa 20. Nov 2021, 12:42, insgesamt 3-mal geändert.
Gruß, Michael

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

Re: Frage zu QuestionDlg

Beitrag von wp_xyz »

six1 hat geschrieben:
Do 18. Nov 2021, 14:16
Anbei mein persönlicher Lösungsansatz. (Das ist WIN only!)
Ist für meinen Einsatz des QuestionDlg zugeschnitten, aber leicht auf andere Bedürfnisse änderbar.
Ist schön geworden.

Ich würde aber die Windows-Unit gegen LCLIntf austauschen - damit wird es cross-platform... Und dann möchte ich noch anregen, ein Argument für den HelpContext einzufügen und diesen dem Formular und dem Hilfe-Button zuzuweisen, denn wie soll der Dialog sonst wissen, welcher Hilfetext angezeigt werden soll, wenn "Help" geklickt wird. Dasselbe in überladener Version noch für HelpKeyword.

Und ich würde noch vorschlagen, die Reihenfolge der Argumente zu ändern, so dass deine Version kompatibel zu den LCL-Versionen ist. AX und AY würde ich zu optionalen Parametern machen, so dass man sie für Zentrierung weglassen kann:

Code: Alles auswählen

function QuestionDlgEx(const ACaption, AMsg: string; ADlgType: TMsgDlgType;
  AButtons: array of const; AX: Integer = -1; AY: Integer = -1): TModalResult; overload;
  
function QuestionDlgEx(const ACaption, AMsg: string; ADlgType: TMsgDlgType;
  AButtons: array of const; AHelpCtx: Integer; AX: Integer = -1; AY: Integer = .1): TModalResult; overload;  
  
function QuestionDlgEx(const ACaption, AMsg: string; ADlgType: TMsgDlgType;
  AButtons: array of const; AHelpKeyword: String; AX: Integer = -1; AY: Integer= -1): TModalResult; overload;
QMsg und QButtons musst du am Ende nicht explizit freigeben, da du als Owner QForm angegeben hast. Wenn man das entsprechende Free nicht mehr hat, bietet sich an, die Konstruktion des Dialogs in eine eigene Funktion auszulagern, die ein TForm zurückgibt, analog zur LCL:

Code: Alles auswählen

function CreateQuestionDlgEx(const ACaption, AMsg: string; AX, AY: Integer; ADlgType: TMsgDlgType;
  AButtons: array of const ): TForm;
In den verschiedenen QuestionDlgEx-Aufrufen wäre dann nur noch:

Code: Alles auswählen

function QuestionDlgEx(....): TModalResult;
var
  F: TForm;
begin
  F := CreateQuestionDlgEx(...);
  try
    Result := F.ShowModal;
  finally
    F.Free;
  end;
end;

Damit hätte der User die Möglichkeit, Properties des Formulars noch vor der Anzeige zu ändern, z.B. den Font, oder eine Checkbox einbauen für "Meldung nicht mehr anzeigen":

Ein Punkt müsste noch geklärt werden: Ich bin nicht 100% sicher, aber ich denke, das Icon kommt mit 32x32. Nachdem du dich mit dem Icon näher befasst hast: Kann man es auch größer vom System abfragen? Denn auf einem High-DPI-Screen müsste man es entsprechend der Auflösung vergrößern.

Wenn es dir recht ist, würde ich deine Version gerne in mein Package ExCtrls auf CCR mit aufnehmen. Es gibt dort noch ein paar andere Controls, die einige Einschränkungen durch das LCL-Konzept umgehen, und da würde dieser Dialog gut reinpassen.

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

Re: Frage zu QuestionDlg [gelöst]

Beitrag von six1 »

Hi,
die von Dir aufgezeigten Punkte sind Klasse, würde ich so einbauen.
Klar kannst du verwenden, was du gebrauchen kannst.
Die Icon DPI muss ich mal nachschauen; hatte so etwas an anderer Stelle schon gemacht (muss ich spicken :-) )

- die Function mit AHelpCtx: Integer; funktioniert nicht. Compiler weiß nicht welche Funktion er nehmen soll...
- man könnte das Icon im Image stretchen und über screen.PixelsPerInch/96 die Image Size einstellen. LoadIcon lädt einfach das Systemicon ohne Einfluss auf Size.
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:
Do 18. Nov 2021, 18:22
- die Function mit AHelpCtx: Integer; funktioniert nicht. Compiler weiß nicht welche Funktion er nehmen soll...
Ach so. Wenn man bei dem ersten Aufruf oben (ohne HelpCtx) nur AX angibt, hat man 1 Integer-Argument am Ende - genauso wie bei dem Aufruf mit HelpCtx, wenn man AX und AY weglässt. OK - dann darf man wohl oder übel bei dem Aufruf mit HelpCtx die AX und AY Argumente nicht optional machen.

Noch ein Wunsch: Wenn AMsg sehr lang ist, kann der Dialog sehr breit werden und schlimmstenfalls sogar über den Bildschirm hinausreichen. Da wäre eine Breitenbegrenzung schön. Wird der Dialog breiter als die Grenze sollte der Text umbrochen (umgebrochen?) werden, und die Dialog sollte dann entsprechend höher werden - natürlich auch wieder bis zu einer gewissen Höhe. Wenn diese dann nicht reicht - ok, dann könnte man Scrollbars einblenden. -- Ich seh schon, jetzt wird's kompliziert...

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:
Do 18. Nov 2021, 18:22
- man könnte das Icon im Image stretchen und über screen.PixelsPerInch/96 die Image Size einstellen. LoadIcon lädt einfach das Systemicon ohne Einfluss auf Size.
Das Icon wird dann verpixelt. Eigentlich enthalten Icons immer Bilder verschiedener Größe. TIcon.Count ist die Anzahl der Bilder, mit TIcon.Current kann man von Bild zu Bild gehen, und TIcon.GetBestIndexForSize(ASize: TSize) ergibt den Index für Current, bei dem das Icon am besten in die angegebene Größe passt. Trifft das auch für die per LoadIcon geladenen Icons zu?

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

Re: Frage zu QuestionDlg [gelöst]

Beitrag von six1 »

:lol: ...an der Stelle war ich auch schon.
Eine maximale Breite kann ich vorgeben und einen Umbruch einleiten.
Ich sollte auch noch schauen, ob das Fenster den rechten Bildschirmrand verlässt und es dann am Screen rechtsbündig darstellen... Feinheiten

Wenn ein AHelpKeyword definiert ist, muss ich ja nur den HelpType auf htKeyword und das HelpKeyword mit AHelpKeyword belegen, oder?
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:
Do 18. Nov 2021, 19:57
Wenn ein AHelpKeyword definiert ist, muss ich ja nur den HelpType auf htKeyword und das HelpKeyword mit AHelpKeyword belegen, oder?
Es reicht, das HelpKeyword zu setzen; HelpType schaltet dann automatisch um.

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

Re: Frage zu QuestionDlg [gelöst]

Beitrag von six1 »

Also ich habe alles soweit geändert. Unter Windows kann man mit LoadIconMetric small und large Icons laden.
LoadIconMetric ist aber wieder Windows abhängig.

Ein anderes Problem ist, dass unter Linux z.B. die Resource IDI_WARNING völlig unbekannt ist.
Zwar läuft das Programm unter Linux, jedoch kann kein Icon gefunden werden.

Ich habe im Moment keinen Plan, wie ich an solche "System Icons" kommen soll.
unter /usr/share/icons sind tonnenweise Unterverzeichnisse zum jeweilig installierten Desktop Theme, jedoch denke ich, dass dies bei jeder Installation differiert.
Bleibt eigentlich fast nur übrig, ein Resourcenfile einzubinden mit 16x16 und 32x32 Icons.

Übrigens bekomme ich über
ASize.cx := GetSystemMetrics(SM_CXICON);
ASize.cy := GetSystemMetrics(SM_CYICON);
auf dem Linux (96DPI) System eine 128x128 Größe geliefert! Bisschen groß, oder? :lol:

Andere Ideen?
Vielleicht hat sogar jemand eine Resourcedatei mit Inhalt:
mtWarning, mtError, mtInformation, mtConfirmation Icons in verschiedenen Auflösungen? :mrgreen:
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:
Fr 19. Nov 2021, 09:05
Also ich habe alles soweit geändert. Unter Windows kann man mit LoadIconMetric small und large Icons laden.
LoadIconMetric ist aber wieder Windows abhängig.
Stimmt. In der LCLIntf gibt es nur das LoadIcon...
six1 hat geschrieben:
Fr 19. Nov 2021, 09:05
Ein anderes Problem ist, dass unter Linux z.B. die Resource IDI_WARNING völlig unbekannt ist.
Zwar läuft das Programm unter Linux, jedoch kann kein Icon gefunden werden.
Andererseits wird, wenn ich mit folgendem Code, die Funktion DefaultQuestionDlg verwende, die angeblich eine "widgetset independent implementation" ist, unter Linux durchaus ein Icon angezeigt:

Code: Alles auswählen

uses
  InterfaceBase;

procedure TForm1.Button1Click(Sender: TObject);
var
  btns: TDialogButtons;
begin
  btns := TDialogButtons.Create(TDialogButton);
  with btns.Add do
  begin
    Caption := 'OK';
    ModalResult := mrOK;
  end;
  with btns.Add do
  begin
    Caption := 'Cancel';
    ModalResult := mrcancel;
  end;
  DefaultQuestionDialog('Caption', 'Msg', ord(mterror), btns, 0);
  btns.Free;
end;          
Wenn man in DefaultQuestionDialog reingeht, sieht man, dass das Icon von einer Funktion GetDialogIcon bereitgestellt wird (unit Dialogs) (und die sollte man auch direkt aufrufen können):

Code: Alles auswählen

function GetDialogIcon(idDiag: Integer): TCustomBitmap;
var
  BitmapHandle, MaskHandle: HBitmap;
begin
  if ThemeServices.GetStockImage(idDiag, BitmapHandle, MaskHandle) then
  begin
    Result := TBitmap.Create;
    Result.Handle := BitmapHandle;
    if MaskHandle <> 0 then
      Result.MaskHandle := MaskHandle;
  end
  else
  if (idDiag < Low(DialogResName)) or (idDiag > High(DialogResName)) then
    Result := nil
  else
  begin
    Result := TPortableNetworkGraphic.Create;
    Result.LoadFromResourceName(hInstance, DialogResName[idDiag]);
  end;
end;
Daraus sieht man: Die ThemeServices stellen einen weiteren Zugang zu den Icons zur Verfügung. Oder, wenn dieser nicht möglich ist, findet man die Icons auch in der Resource der Anwendung; die entsprechenden Bilder sind im Ordner lcl/images/dialogs - aber auch nur wieder in einer Größe.

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

Re: Frage zu QuestionDlg [gelöst]

Beitrag von six1 »

Ich habe jetzt Icons in 16,32,48,64,128 Px runtergeladen und erstelle ein Resourcenfile.
das wird dann mit reinkompiliert und alles ist gut 8)

Vielleicht gibt GetDialogIcon automatisch die richtige Auflösung zurück?
Zuletzt geändert von six1 am Fr 19. Nov 2021, 10:06, insgesamt 1-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 »

wp_xyz hat geschrieben:
Fr 19. Nov 2021, 09:56
[...] dass das Icon von einer Funktion GetDialogIcon bereitgestellt wird (unit Dialogs) (und die sollte man auch direkt aufrufen können)
Getestet, das funktioniert:

Code: Alles auswählen

procedure TForm1.FormCreate(Sender: TObject);
begin
  Image1.Picture.Assign(GetDialogIcon(idDialogConfirm));
end;  
wobei man die idXXXX Konstanten in der Unit LCLType findet.

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

Re: Frage zu QuestionDlg [gelöst]

Beitrag von six1 »

:idea: cool! Danke
Gruß, Michael

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Frage zu QuestionDlg [gelöst]

Beitrag von Winni »

Hi!

Guck mal, wie in der unit Buttons die system icons für den TBitBtn geladen werden:

Code: Alles auswählen

function GetButtonIcon(idButton: Integer): TCustomBitmap;
var
  BitmapHandle, MaskHandle: HBitmap;
begin
  if ThemeServices.GetStockImage(idButton, BitmapHandle, MaskHandle) then
  begin
    Result := TBitmap.Create;
    Result.Handle := BitmapHandle;
    if MaskHandle <> 0 then
      Result.MaskHandle := MaskHandle;
  end
  else
    Result := GetDefaultButtonIcon(idButton);
end;  

Winni

Antworten