2009-07-08 12 views

答えて

10

私自身の質問に答える...私は私のためにうまくいく以下のユニットを書いた。

Delphiはダイアログテンプレートを表示するためにCreateMessageDialog()を提供しています。ダイアログテンプレートは表示する前に変更することができます。私はこれを使ってMessageDlgCustomと呼ばれる関数を作成しました。これは標準のMessageDlgと同じパラメータを取りますが、置き換えボタンのタイトルを1つ追加します。

カスタムフォントを正しく処理し、メッセージに十分な幅のボタンを自動的に調整します。ボタンがダイアログをオーバーフローすると、それも調整されます。そのユニットを使用した後

、以下のサンプルは動作します:

case MessageDlgCustom('Save your changes?',mtConfirmation, 
    [mbYes,mbNo,mbCancel], 
    ['&Yes, I would like to save them with this absurdly long button', 
    '&No, I do not care about my stupid changes', 
    '&Arg! What are you talking about? Do not close the form!'], 
    nil) //nil = no custom font 
of 
    mrYes: 
    begin 
     SaveChanges; 
     CloseTheForm; 
    end; //mrYes (save & close) 
    mrNo: 
    begin 
     CloseForm; 
    end; //mrNo (close w/o saving) 
    mrCancel: 
    begin 
     //do nothing 
    end; //mrCancel (neither save nor close) 
end; //case 

他の誰かがより良い方法を知っている場合、それを共有してください。

unit CustomDialog; 

interface 

uses 
    Dialogs, Forms, Graphics, StdCtrls; 

function MessageDlgCustom(const Msg: string; DlgType: TMsgDlgType; 
    Buttons: TMsgDlgButtons; ToCaptions: array of string; 
    customFont: TFont) : integer; 
procedure ModifyDialog(var frm: TForm; ToCaptions : array of string; 
    customFont : TFont = nil); 


implementation 

uses 
    Windows, SysUtils; 

function GetTextWidth(s: string; fnt: TFont; HWND: THandle): integer; 
var 
    canvas: TCanvas; 
begin 
    canvas := TCanvas.Create; 
    try 
    canvas.Handle := GetWindowDC(HWND); 
    canvas.Font := fnt; 
    Result := canvas.TextWidth(s); 
    finally 
    ReleaseDC(HWND,canvas.Handle); 
    FreeAndNil(canvas); 
    end; //try-finally 
end; 

function MessageDlgCustom(const Msg: string; 
    DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; ToCaptions: array of string; 
    customFont: TFont): integer; 
var 
    dialog : TForm; 
begin 
    try 
    dialog := CreateMessageDialog(Msg, DlgType, Buttons); 
    dialog.Position := poScreenCenter; 
    ModifyDialog(dialog,ToCaptions,customFont); 
    Result := dialog.ShowModal; 
    finally 
    dialog.Release; 
    end; //try-finally 
end; 

procedure ModifyDialog(var frm: TForm; ToCaptions: array of string; 
    customFont: TFont); 
const 
    c_BtnMargin = 10; //margin of button around caption text 
var 
    i,oldButtonWidth,newButtonWidth,btnCnt : integer; 
begin 
    oldButtonWidth := 0; 
    newButtonWidth := 0; 
    btnCnt := 0; 
    for i := 0 to frm.ComponentCount - 1 do begin 
    //if they asked for a custom font, assign it here 
    if customFont <> nil then begin 
     if frm.Components[i] is TLabel then begin 
     TLabel(frm.Components[i]).Font := customFont; 
     end; 
     if frm.Components[i] is TButton then begin 
     TButton(frm.Components[i]).Font := customFont; 
     end; 
    end; 
    if frm.Components[i] is TButton then begin 
     //check buttons for a match with a "from" (default) string 
     //if found, replace with a "to" (custom) string 
     Inc(btnCnt); 

     //record the button width *before* we changed the caption 
     oldButtonWidth := oldButtonWidth + TButton(frm.Components[i]).Width; 

     //if a custom caption has been provided use that instead, 
     //or just leave the default caption if the custom caption is empty 
     if ToCaptions[btnCnt - 1]<>'' then 
     TButton(frm.Components[i]).Caption := ToCaptions[btnCnt - 1]; 

     //auto-size the button for the new caption 
     TButton(frm.Components[i]).Width := 
     GetTextWidth(TButton(frm.Components[i]).Caption, 
      TButton(frm.Components[i]).Font,frm.Handle) + c_BtnMargin; 

     //the first button can stay where it is. 
     //all other buttons need to slide over to the right of the one b4. 
     if (1 < btnCnt) and (0 < i) then begin 
     TButton(frm.Components[i]).Left := 
      TButton(frm.Components[i-1]).Left + 
      TButton(frm.Components[i-1]).Width + c_BtnMargin; 
     end; 

     //record the button width *after* changing the caption 
     newButtonWidth := newButtonWidth + TButton(frm.Components[i]).Width; 
    end; //if TButton 
    end; //for i 

    //whatever we changed the buttons by, widen/shrink the form accordingly 
    frm.Width := Round(frm.Width + (newButtonWidth - oldButtonWidth) + 
    (c_BtnMargin * btnCnt)); 
end; 

end. 
+0

少なくとも、Delphi 2007を使用している場合は、完全に新しいMessageDlg()関数を作成し、まずWindowsバージョンをチェックし、Vistaで新しいダイアログクラスを使用し、元のMessageDlgの修正バージョンを使用します)関数を使用します。これにより、「再度表示しない」チェックボックスも簡単に追加できます。 – mghie

+1

現在のコードはコンパイルされません。いくつかの方法を再構成する必要があります。 GetTextWidthは実装の先頭に移動する必要があります。実装でMessageDlgCustomメソッドの上にあるModifiyDialogを移動すると、インターフェイスセクションから宣言を削除できます。 WinXPでは、変更されたダイアログボックスが最後のボタンとして表示されます。例の呼び出しを使用すると、ほとんどウィンドウ境界の端に位置します。何らかの理由で、このメソッドはダイアログの幅を正しく再計算しません。 –

+0

@ライアン - ありがとう、私はそれがコンパイルを壊すことを忘れて、一番重要なものを一番上に置くように再編成した。元の注文を復元しました。今すぐコンパイルする必要があります。 私はXPマシンで試してみる必要があります - 私はVistaを使用しています。うまくいけば、あなたが記述する問題は、とにかく極端な場合にのみ発生します。 – JosephStyons

1

また、お使いのサードパーティ製のコントロールも カスタムメッセージDLGはなく、標準 MessageDlg関数を呼び出すことを確認してください。つまり、実際には を使用している場合です。サードパーティのコントロール は、Delphi messagedlgを使用せず、 MessageBox APIを直接呼び出すことが可能です。その場合、メッセージ が表示されると、 が矛盾してしまうことがあります。

2

また、オープンソースSynTaskDialogを使用することもできます。 SynTaskDialogはWindowsのTaskDialog APIを新しいWindowsバージョンでネイティブに使用し、古いバージョンでエミュレートします。あなたもuse it with FireMonkeyすることができます。

カスタマイズ可能なMessageDlg関数の例は、this answerです。

関連する問題