2009-07-08 4 views

답변

10

내 자신의 질문에 대답 .... 나는 잘 작동하는 아래의 단위를 썼습니다.

Delphi는 표시하기 전에 수정할 수있는 대화 상자 템플릿을 제공하기 위해 CreateMessageDialog()을 제공합니다. MessageDlgCustom이라는 함수를 생성하기 위해이 함수를 사용했습니다.이 함수는 표준 MessageDlg와 동일한 매개 변수를 사용하지만 대체 버튼 제목에 하나를 더합니다.

사용자 지정 글꼴을 올바르게 처리하고 메시지에 맞게 단추를 자동으로 조정합니다. 버튼이 대화 상자를 오버플로하면 너무 조정됩니다.

는 장치를 사용 후, 아래의 샘플은 작동합니다

다른 사람이 더 좋은 방법을 알고 있다면
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

적어도 델파이 2007을 사용하고 있다면 완전히 새로운 MessageDlg() 함수를 만들고, 먼저 Windows 버전을 확인하고, Vista에서 새 대화 상자 클래스를 사용하고, 원래 MessageDlg의 수정 된 버전을 사용합니다.) 함수를 사용합니다. 그러면 "다시 표시하지 않음"확인란을 쉽게 추가 할 수 있습니다. – mghie

+1

현재 코드가 컴파일되지 않습니다. 몇 가지 방법을 재구성해야합니다. GetTextWidth는 구현의 맨 위로 올라와야하고 구현의 MessageDlgCustom 메서드 위에있는 ModifiyDialog를 이동하면 인터페이스 섹션에서 선언을 제거 할 수 있습니다. WinXP에서 수정 된 대화 상자는 마지막 단추를 사용하여 예제 호출을 사용하여 거의 창 테두리의 가장자리에 위치합니다. 몇 가지 이유로이 메서드는 대화 상자의 너비를 올바르게 다시 계산하지 않습니다. –

+0

@ 라이언 (Ranan) - 덕분에, 가장 중요한 것을 맨 위에 놓고 재구성하여 컴파일을 망칠 수 있음을 잊어 버렸습니다. 원래 주문을 복원했습니다. 지금 컴파일해야합니다. XP 컴퓨터에서 사용해보아야합니다. Vista를 사용하고 있습니다. 다행히도 당신이 설명하는 문제는 극단적 인 경우에만 발생합니다 ... – JosephStyons

1

또한, 귀하의 제 3 자 컨트롤도 사용자 정의 메시지 DLG가 아닌 표준 는 MessageDlg 함수를 호출 있는지 확인하십시오. 그것은 실제로 그들이 을 사용하고있는 경우입니다. 타사 컨트롤 은 Delphi messagedlg를 사용하지 않고 MessageBox API를 직접 호출 할 수 있습니다. 이 경우 메시지가 상자에 표시되는 데 불일치가 발생할 수 있습니다.

2

다른 방법으로 오픈 소스 SynTaskDialog 단위를 사용할 수 있습니다. SynTaskDialog는 새로운 Windows 버전에서 Windows TaskDialog API를 기본적으로 사용하고 이전 버전에서 에뮬레이트합니다. 당신도 use it with FireMonkey 일 수 있습니다.

사용자 지정 가능한 MessageDlg 함수의 예는 this answer입니다.

관련 문제