![]() |
"Don't ask again" Messagedialog ?
Hi!
Oftmals wär's ja praktisch dem Benutzer bei Warnungen/Bestätigungen die per MessageDlg erledigt werden eine "Never ask again" checkbox mitanzubieten. Ein Standardproblem. Bevor ich jetzt das Rad neu erfinde (bzw. programmiere): Gibt's für das Problem empfohlene Problemlösungen / fertige, halbwegs etablierte Komponenten? Oder anders: Wo wird das Messagedialog-Fenster denn zusammengebaut? (Das ist ja meines wissens nach keine Kapselung sondern was Delphi-spezifisches, oder lieg' ich da falsch?) Danke! Ralf |
Re: "Don't ask again" Messagedialog ?
Ich hab da beim Zauberer etwas gefunden:
![]() |
Re: "Don't ask again" Messagedialog ?
Meinst du sowas:
![]() |
Re: "Don't ask again" Messagedialog ?
Das Beispiel vom Zauberer funktioniert über die WinAPI und Registry.
Ich hatte mal das gleiche Problem, wollte aber ohne die Registry auskommen. Deshalb hab ich mir selbst etwas gebastelt.
Delphi-Quellcode:
Das ganze ist zwar (noch) nicht der Stein des Weißen, aber für mich erfüllt es seine Zwecke.
function MyMsgBoxx (psText,psTitle : string; AShowAgainChecked : boolean = false; AIcon : Integer ) : boolean;
VAR AMsgDialog : TForm; ACheckBox : TCheckBox; AImg : TComponent; bShowAgain : boolean; btnOk : TControl; nHeigth : integer; BEGIN bShowAgain := true; AMsgDialog := CreateMessageDialog(psText, mtWarning, [mbOk]); AMsgDialog.FormStyle := fsStayOnTop; AImg := AMsgDialog.FindComponent('Image'); if AImg <> nil then begin // eigene Icon-Lade-Funktion TImage(AImg).Picture.Icon := GetIconByName(IntToStr(AIcon)); end; btnOk := AMsgDialog.FindChildControl('OK'); if btnOk <> nil then begin nHeigth := btnOk.top + btnOk.Height + 24; end else begin nHeigth := 169; end; ACheckBox := TCheckBox.Create(AMsgDialog); WITH AMsgDialog DO begin TRY Caption := psTitle; ClientHeight := nHeigth; WITH ACheckBox DO BEGIN Parent := AMsgDialog; Caption := 'Diesen Hinweis nicht mehr anzeigen.'; width := 190; top := nHeigth - 20; Left := 8; Checked := AShowAgainChecked; END; ShowModal; bShowAgain := Not (ACheckBox.Checked); FINALLY ACheckBox.Free; Free; END; END; Result := bShowAgain; end; |
Re: "Don't ask again" Messagedialog ?
Registry aber nur dann, wenn Du den Dialog wieder anzeigen lassen möchtest, da Du ja dann den Wert löschen musst.
|
Re: "Don't ask again" Messagedialog ?
Da finde ich das, was Luckie gepostet hat, aber kürzer. :wink:
|
Re: "Don't ask again" Messagedialog ?
Zitat:
Tragischerweise ist die M$ MessageBoxCheck Implementierung ziemlich dämlich, Man kann z.B: nur merken ob das Erscheinen eines Dialogs erwünscht ist, nicht aber das Ergebnis. Eine typische Frage wäre ja: "Wollen Sie das Programm wirklich beenden?" - OK, Cancel. In dem Fall sollte sich der Dialog "OK" merken, Cancel nicht (sonst kann ich das Programm ja nie mehr beenden) Oder, noch ausgefeilter: "Wollen sie vor dem beenden die Daten speichern?" (Ja, Nein, Abbrechen). Ja und nein sollte sich das Ding merken und beim nächsten Aufruf den selben Wert zurückgeben, bei Abbruch natürlich nicht. ...ich schätze das muss man noch was dazustricken. |
Re: "Don't ask again" Messagedialog ?
Zitat:
Cheers, |
Re: "Don't ask again" Messagedialog ?
Zitat:
Das kam leider zu spät. Hier eine Lösung:
Delphi-Quellcode:
// MessageDialog with "Don't ask again" checkbox
// Based on code from [url]http://www.dbrsoftware.de/delphi/nichtdlg.php[/url] // Discussion: [url]http://www.delphipraxis.net/post1023099.html[/url] // // ATT: Could return unexpected values if the list of possible results // was changed between versions and such an unexpected value was // stored in registry by an older version of the software // Take standard window captions from Consts.pas, e.g. SMsgDlgConfirm function DsaMessageDlg(h: THandle; Text, Caption, DsaDialogId: string; uType: Uint): integer; var HL: THandle; Dlg: function(h: THandle; Txt, Title: PChar; dw: DWORD; nll: integer; GStr: PChar): integer; stdcall; DSA : boolean; const SxDsaBaseKey = '\Software\SpoonworX\DontShowAgain'; MsDsaKey = '\Software\Microsoft\Windows\CurrentVersion\Explorer\DontShowMeThisDialogAgain'; begin with TRegIniFile.Create(SxDsaBaseKey, KEY_READ or Key_Write) do begin // by holding down CTRL -> unlock! if GetAsyncKeyState(VK_CONTROL) and $8000<>0 then DeleteKey('', DsaDialogId); // Check if a default result is already defined result:=ReadInteger('', DsaDialogId, -1); Free; end; // Show Messagedialog if result=-1 then begin // Maintain dialog is shown // (clean old preferences - depends only from value in with TRegIniFile.Create(MsDsaKey, Key_Write) do begin DeleteKey('', DsaDialogId); Free; end; // Use standard "hidden" dialog with checkbox result := maxint; HL := LoadLibrary('shlwapi.dll'); if HL <> 0 then begin @Dlg := GetProcAddress(HL, MAKEINTRESOURCE($B9)); if Assigned(Dlg) then result := Dlg(h, PChar(Text), PChar(Caption), uType, 0, PChar(DsaDialogId)); FreeLibrary(HL); end; // Determine if "don't show again" checkbox was visible with TRegIniFile.Create(MsDsaKey, KEY_READ or Key_Write) do begin DSA:=ValueExists(DsaDialogId); if DSA then DeleteKey('', DsaDialogId); Free; end; // If DSA-checkbox was checked -> store defautl result of dialog if DSA and (result<>IDCANCEL) then with TRegIniFile.Create(SxDsaBaseKey, Key_Write) do begin WriteInteger('', DsaDialogId, result); Free; end; end; end; |
Re: "Don't ask again" Messagedialog ?
Hallo,
und unter Windows Vista kann man sogar den ![]() MfG xZise PS: Cooler Artikel :thumb: |
AW: "Don't ask again" Messagedialog ?
Ich hole den Thread jetzt mal wieder nach oben. Unter Delphi 2010 funktioniert das nämlich nicht mehr. Es wird nur der erste Buchstabe des Text und der Caption angezeigt.
Taskdialog kann ich nicht nehmen, da das Programm unter XP auch noch arbeiten soll. Hat einer eine Idee ? |
AW: "Don't ask again" Messagedialog ?
|
AW: "Don't ask again" Messagedialog ?
Das schon, aber die Kosten 85 bzw. 185 Euro. Das ist es mir nicht Wert.
Da bau ich mir lieber selber ein Fenster |
AW: "Don't ask again" Messagedialog ?
Hallo,
Zitat:
Ändere beim Bsp.-Code auf Seite 1 alles von String auf AnsiString, und übergib auch nur einen solchen. Heiko |
AW: "Don't ask again" Messagedialog ?
Zitat:
|
AW: "Don't ask again" Messagedialog ?
bau dir einen mit ner form zusammen. wo ist das problem? das dauert höchstens 5 minuten.
|
AW: "Don't ask again" Messagedialog ?
Haben wir nicht auch irgendwo soeinen Dialog als OpenSource in der DP rumliegen?
Dachte ich hätte sowas mal gesehn. |
AW: "Don't ask again" Messagedialog ?
Ich finde es schon schöner, wenn sich die Messagebox dem Design von Windows anpasst, was bei einem selbstgebauten Formular nicht so schön ist.
Zitat:
So funktioniert es auch mit Delphi 2010
Delphi-Quellcode:
function MessageBoxCheck; external 'shlwapi.dll' index 191;
function MessageBoxCheck(hWnd: THandle; Text: PWideChar; Title: PWideChar; dwType: DWORD; Default: Integer; RegVal: PChar): Integer; stdcall; |
AW: "Don't ask again" Messagedialog ?
Zitat:
|
AW: "Don't ask again" Messagedialog ?
noch eine selbstgebastelte Version:
Delphi-Quellcode:
Diese paßt sich zumindestens an das Aussehn der Delphi-Dialoge an.
uses Dialogs, StdCtrls, Math;
var MessageDlgExList: TStringList; const mbAuto = TMsgDlgBtn(Ord(High(TMsgDlgBtn)) + 1); function MessageDlgEx(const DlgID, Msg: String; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; DefaultButton: TMsgDlgBtn = mbAuto): Integer; var Dialog: TForm; i, X, Y: Integer; C: TWinControl; Query: TCheckBox; begin if (DlgID <> '') and (MessageDlgExList.IndexOfName(DlgID) >= 0) then begin Result := StrToInt(MessageDlgExList.Values[DlgID]); Exit; end; if DefaultButton = mbAuto then if mbOk in Buttons then DefaultButton := mbOk else if mbYes in Buttons then DefaultButton := mbYes else DefaultButton := mbRetry; Dialog := CreateMessageDialog(Msg, DlgType, Buttons, DefaultButton); try if DlgID <> '' then begin X := 999; Y := 0; for i := Dialog.ComponentCount - 1 downto 0 do if Dialog.Components[i] is TWinControl then begin C := TWinControl(Dialog.Components[i]); if C.Visible then begin X := Min(C.Left, X); Y := Max(C.Top + C.Height, Y); end; end; Query := TCheckBox.Create(Dialog); Query.Parent := Dialog; Query.Left := X; Query.Top := Dialog.ClientHeight; Query.Width := 100; Query.Caption := 'merken'; Dialog.ClientHeight := Dialog.ClientHeight + Query.Height + (Dialog.ClientHeight - Y); end; Result := Dialog.ShowModal; if Query.Checked and (Result <> MB_ABORTRETRYIGNORE) then MessageDlgExList.Add(DlgID + MessageDlgExList.NameValueSeparator + IntToStr(Result)); finally Dialog.Free; end; end; initialization MessageDlgExList := TStringList.Create; MessageDlgExList.Sorted := True; finalization MessageDlgExList.Free; end. MessageDlgExList kann man bei Programmstart laden und beim Beenden speichern (oder sofort über MessageDlgExList.OnChange speichern) Die DlgID muß für jeden Dialog vergeben werden. Wurde der Dialog gespeichert/gemerkt, dann wird beim nächsen Aufruf das letzte Result zurückgegeben und nichts angezeigt. Will man einen/alle Dialoge wieder anzeigen, dann einfach die MessageDlgExList bearbeiten. |
AW: "Don't ask again" Messagedialog ?
@v2afrank: bei deinem RegVal solltest du noch aufpassen ... PChar ist ja dynamisch
Aber die API würde ich besser so implementieren, dann klappts hoffentlich überall
Delphi-Quellcode:
PS:
function MessageBoxCheck(hWnd: HWND; Text, Title: PChar; dwType: LongWord;
Default: Integer; RegVal: PChar): Integer; stdcall; function MessageBoxCheckA(hWnd: HWND; Text, Title: PAnsiChar; dwType: LongWord; Default: Integer; RegVal: PAnsiChar): Integer; stdcall; function MessageBoxCheckW(hWnd: HWND; Text, Title: PWideChar; dwType: LongWord; Default: Integer; RegVal: PWideChar): Integer; stdcall; function MessageBoxCheck; external 'shlwapi.dll' index {$IF SizeOf(Char) = 1}185{$ELSE}191{$IFEND}; function MessageBoxCheckA; external 'shlwapi.dll' index 185; function MessageBoxCheckW; external 'shlwapi.dll' index 191; ![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:07 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz