2 {*****************************************************************************}
4 { Tnt Delphi Unicode Controls }
5 { http://www.tntware.com/delphicontrols/unicode/ }
8 { Copyright (c) 2002-2007, Troy Wolbrink (troy.wolbrink@tntware.com) }
10 {*****************************************************************************}
14 {$INCLUDE TntCompilers.inc}
18 { TODO: TFindDialog and TReplaceDialog. }
19 { TODO: Property editor for TTntOpenDialog.Filter }
22 Classes
, Messages
, CommDlg
, Windows
, Dialogs
,
23 TntClasses
, TntForms
, TntSysUtils
;
26 {TNT-WARN TIncludeItemEvent}
27 TIncludeItemEventW
= procedure (const OFN
: TOFNotifyExW
; var Include
: Boolean) of object;
29 {TNT-WARN TOpenDialog}
30 TTntOpenDialog
= class(TOpenDialog
{TNT-ALLOW TOpenDialog})
32 FDefaultExt
: WideString
;
33 FFileName
: TWideFileName
;
35 FInitialDir
: WideString
;
38 FOnIncludeItem
: TIncludeItemEventW
;
39 function GetDefaultExt
: WideString
;
40 procedure SetInheritedDefaultExt(const Value
: AnsiString
);
41 procedure SetDefaultExt(const Value
: WideString
);
42 function GetFileName
: TWideFileName
;
43 procedure SetFileName(const Value
: TWideFileName
);
44 function GetFilter
: WideString
;
45 procedure SetInheritedFilter(const Value
: AnsiString
);
46 procedure SetFilter(const Value
: WideString
);
47 function GetInitialDir
: WideString
;
48 procedure SetInheritedInitialDir(const Value
: AnsiString
);
49 procedure SetInitialDir(const Value
: WideString
);
50 function GetTitle
: WideString
;
51 procedure SetInheritedTitle(const Value
: AnsiString
);
52 procedure SetTitle(const Value
: WideString
);
53 function GetFiles
: TTntStrings
;
55 FProxiedOpenFilenameA
: TOpenFilenameA
;
57 FAllowDoCanClose
: Boolean;
58 procedure DefineProperties(Filer
: TFiler
); override;
59 function CanCloseW(var OpenFileName
: TOpenFileNameW
): Boolean;
60 function DoCanClose
: Boolean; override;
61 procedure GetFileNamesW(var OpenFileName
: TOpenFileNameW
);
62 procedure DoIncludeItem(const OFN
: TOFNotifyEx
; var Include
: Boolean); override;
63 procedure WndProc(var Message: TMessage
); override;
64 function DoExecuteW(Func
: Pointer; ParentWnd
: HWND
): Bool
; overload
;
65 function DoExecuteW(Func
: Pointer): Bool
; overload
;
67 constructor Create(AOwner
: TComponent
); override;
68 destructor Destroy
; override;
69 function Execute
: Boolean; override;
70 {$IFDEF COMPILER_9_UP}
71 function Execute(ParentWnd
: HWND
): Boolean; override;
73 property Files
: TTntStrings read GetFiles
;
75 property DefaultExt
: WideString read GetDefaultExt write SetDefaultExt
;
76 property FileName
: TWideFileName read GetFileName write SetFileName
;
77 property Filter
: WideString read GetFilter write SetFilter
;
78 property InitialDir
: WideString read GetInitialDir write SetInitialDir
;
79 property Title
: WideString read GetTitle write SetTitle
;
80 property OnIncludeItem
: TIncludeItemEventW read FOnIncludeItem write FOnIncludeItem
;
83 {TNT-WARN TSaveDialog}
84 TTntSaveDialog
= class(TTntOpenDialog
)
86 function Execute
: Boolean; override;
87 {$IFDEF COMPILER_9_UP}
88 function Execute(ParentWnd
: HWND
): Boolean; override;
94 {TNT-WARN CreateMessageDialog}
95 function WideCreateMessageDialog(const Msg
: WideString
; DlgType
: TMsgDlgType
;
96 Buttons
: TMsgDlgButtons
): TTntForm
;overload
;
97 function WideCreateMessageDialog(const Msg
: WideString
; DlgType
: TMsgDlgType
;
98 Buttons
: TMsgDlgButtons
; DefaultButton
: TMsgDlgBtn
): TTntForm
; overload
;
100 {TNT-WARN MessageDlg}
101 function WideMessageDlg(const Msg
: WideString
; DlgType
: TMsgDlgType
;
102 Buttons
: TMsgDlgButtons
; HelpCtx
: Longint): Integer; overload
;
103 function WideMessageDlg(const Msg
: WideString
; DlgType
: TMsgDlgType
;
104 Buttons
: TMsgDlgButtons
; HelpCtx
: Longint; DefaultButton
: TMsgDlgBtn
): Integer; overload
;
106 {TNT-WARN MessageDlgPos}
107 function WideMessageDlgPos(const Msg
: WideString
; DlgType
: TMsgDlgType
;
108 Buttons
: TMsgDlgButtons
; HelpCtx
: Longint; X
, Y
: Integer): Integer; overload
;
109 function WideMessageDlgPos(const Msg
: WideString
; DlgType
: TMsgDlgType
;
110 Buttons
: TMsgDlgButtons
; HelpCtx
: Longint; X
, Y
: Integer; DefaultButton
: TMsgDlgBtn
): Integer; overload
;
112 {TNT-WARN MessageDlgPosHelp}
113 function WideMessageDlgPosHelp(const Msg
: WideString
; DlgType
: TMsgDlgType
;
114 Buttons
: TMsgDlgButtons
; HelpCtx
: Longint; X
, Y
: Integer;
115 const HelpFileName
: WideString
): Integer; overload
;
116 function WideMessageDlgPosHelp(const Msg
: WideString
; DlgType
: TMsgDlgType
;
117 Buttons
: TMsgDlgButtons
; HelpCtx
: Longint; X
, Y
: Integer;
118 const HelpFileName
: WideString
; DefaultButton
: TMsgDlgBtn
): Integer; overload
;
120 {TNT-WARN ShowMessage}
121 procedure WideShowMessage(const Msg
: WideString
);
122 {TNT-WARN ShowMessageFmt}
123 procedure WideShowMessageFmt(const Msg
: WideString
; Params
: array of const);
124 {TNT-WARN ShowMessagePos}
125 procedure WideShowMessagePos(const Msg
: WideString
; X
, Y
: Integer);
129 {TNT-WARN InputQuery}
130 function WideInputQuery(const ACaption
, APrompt
: WideString
;
131 var Value
: WideString
): Boolean;
133 function WideInputBox(const ACaption
, APrompt
, ADefault
: WideString
): WideString
;
135 {TNT-WARN PromptForFileName}
136 function WidePromptForFileName(var AFileName
: WideString
; const AFilter
: WideString
= '';
137 const ADefaultExt
: WideString
= ''; const ATitle
: WideString
= '';
138 const AInitialDir
: WideString
= ''; SaveDialog
: Boolean = False): Boolean;
140 function GetModalParentWnd
: HWND
;
145 Controls
, Forms
, Types
, SysUtils
, Graphics
, Consts
, Math
,
146 TntWindows
, TntStdCtrls
, TntClipBrd
, TntExtCtrls
,
147 {$IFDEF COMPILER_9_UP} WideStrUtils
, {$ENDIF} TntWideStrUtils
;
149 function GetModalParentWnd
: HWND
;
152 Result
:= Application
.ActiveFormHandle
;
156 {$IFDEF COMPILER_10_UP}
157 if Application
.ModalPopupMode
<> pmNone
then
159 Result
:= Application
.ActiveFormHandle
;
162 if Result
= 0 then begin
163 Result
:= Application
.Handle
;
168 ProxyExecuteDialog
: TTntOpenDialog
;
170 function ProxyGetOpenFileNameA(var OpenFile
: TOpenFilename
): Bool
; stdcall;
172 ProxyExecuteDialog
.FProxiedOpenFilenameA
:= OpenFile
;
173 Result
:= False; { as if user hit "Cancel". }
178 constructor TTntOpenDialog
.Create(AOwner
: TComponent
);
181 FFiles
:= TTntStringList
.Create
;
184 destructor TTntOpenDialog
.Destroy
;
190 procedure TTntOpenDialog
.DefineProperties(Filer
: TFiler
);
193 TntPersistent_AfterInherited_DefineProperties(Filer
, Self
);
196 function TTntOpenDialog
.GetDefaultExt
: WideString
;
198 Result
:= GetSyncedWideString(FDefaultExt
, inherited DefaultExt
);
201 procedure TTntOpenDialog
.SetInheritedDefaultExt(const Value
: AnsiString
);
203 inherited DefaultExt
:= Value
;
206 procedure TTntOpenDialog
.SetDefaultExt(const Value
: WideString
);
208 SetSyncedWideString(Value
, FDefaultExt
, inherited DefaultExt
, SetInheritedDefaultExt
);
211 function TTntOpenDialog
.GetFileName
: TWideFileName
;
213 Path
: array[0..MAX_PATH
] of WideChar
;
215 if Win32PlatformIsUnicode
and NewStyleControls
and (Handle
<> 0) then begin
216 // get filename from handle
217 SendMessageW(GetParent(Handle
), CDM_GETFILEPATH
, SizeOf(Path
), Integer(@Path
));
220 Result
:= GetSyncedWideString(WideString(FFileName
), inherited FileName
);
223 procedure TTntOpenDialog
.SetFileName(const Value
: TWideFileName
);
226 inherited FileName
:= Value
;
229 function TTntOpenDialog
.GetFilter
: WideString
;
231 Result
:= GetSyncedWideString(FFilter
, inherited Filter
);
234 procedure TTntOpenDialog
.SetInheritedFilter(const Value
: AnsiString
);
236 inherited Filter
:= Value
;
239 procedure TTntOpenDialog
.SetFilter(const Value
: WideString
);
241 SetSyncedWideString(Value
, FFilter
, inherited Filter
, SetInheritedFilter
);
244 function TTntOpenDialog
.GetInitialDir
: WideString
;
246 Result
:= GetSyncedWideString(FInitialDir
, inherited InitialDir
);
249 procedure TTntOpenDialog
.SetInheritedInitialDir(const Value
: AnsiString
);
251 inherited InitialDir
:= Value
;
254 procedure TTntOpenDialog
.SetInitialDir(const Value
: WideString
);
256 function RemoveTrailingPathDelimiter(const Value
: WideString
): WideString
;
260 // remove trailing path delimiter (except 'C:\')
262 if (L
> 1) and WideIsPathDelimiter(Value
, L
) and not WideIsDelimiter(':', Value
, L
- 1) then
264 Result
:= Copy(Value
, 1, L
);
268 SetSyncedWideString(RemoveTrailingPathDelimiter(Value
), FInitialDir
,
269 inherited InitialDir
, SetInheritedInitialDir
);
272 function TTntOpenDialog
.GetTitle
: WideString
;
274 Result
:= GetSyncedWideString(FTitle
, inherited Title
)
277 procedure TTntOpenDialog
.SetInheritedTitle(const Value
: AnsiString
);
279 inherited Title
:= Value
;
282 procedure TTntOpenDialog
.SetTitle(const Value
: WideString
);
284 SetSyncedWideString(Value
, FTitle
, inherited Title
, SetInheritedTitle
);
287 function TTntOpenDialog
.GetFiles
: TTntStrings
;
289 if (not Win32PlatformIsUnicode
) then
290 FFiles
.Assign(inherited Files
);
294 function TTntOpenDialog
.DoCanClose
: Boolean;
296 if FAllowDoCanClose
then
297 Result
:= inherited DoCanClose
302 function TTntOpenDialog
.CanCloseW(var OpenFileName
: TOpenFileNameW
): Boolean;
304 GetFileNamesW(OpenFileName
);
305 FAllowDoCanClose
:= True;
307 Result
:= DoCanClose
;
309 FAllowDoCanClose
:= False;
312 inherited Files
.Clear
;
315 procedure TTntOpenDialog
.DoIncludeItem(const OFN
: TOFNotifyEx
; var Include
: Boolean);
317 // CDN_INCLUDEITEM -> DoIncludeItem() is only be available on Windows 2000 +
318 // Therefore, just cast OFN as a TOFNotifyExW, since that's what it really is.
319 if Win32PlatformIsUnicode
and Assigned(FOnIncludeItem
) then
320 FOnIncludeItem(TOFNotifyExW(OFN
), Include
)
323 procedure TTntOpenDialog
.WndProc(var Message: TMessage
);
326 if (Message.Msg
= WM_INITDIALOG
) and not (ofOldStyleDialog
in Options
) then begin
327 { If not ofOldStyleDialog then DoShow on CDN_INITDONE, not WM_INITDIALOG }
330 if Win32PlatformIsUnicode
331 and (Message.Msg
= WM_NOTIFY
) then begin
332 case (POFNotify(Message.LParam
)^.hdr
.code
) of
334 if not CanCloseW(POFNotifyW(Message.LParam
)^.lpOFN
^) then
337 SetWindowLong(Handle
, DWL_MSGRESULT
, Message.Result
);
342 inherited WndProc(Message);
345 function TTntOpenDialog
.DoExecuteW(Func
: Pointer): Bool
;
347 Result
:= DoExecuteW(Func
, GetModalParentWnd
);
350 function TTntOpenDialog
.DoExecuteW(Func
: Pointer; ParentWnd
: HWND
): Bool
;
352 OpenFilename
: TOpenFilenameW
;
354 function GetResNamePtr(var ScopedStringStorage
: WideString
; lpszName
: PAnsiChar
): PWideChar
;
355 // duplicated from TntTrxResourceUtils.pas
357 if Tnt_Is_IntResource(PWideChar(lpszName
)) then
358 Result
:= PWideChar(lpszName
)
360 ScopedStringStorage
:= lpszName
;
361 Result
:= PWideChar(ScopedStringStorage
);
365 function AllocFilterStr(const S
: WideString
): WideString
;
372 Result
:= S
+ #0#0; // double null terminators (an additional zero added in case Description/Filter pair not even.)
373 P
:= WStrScan(PWideChar(Result
), '|');
378 P
:= WStrScan(P
, '|');
384 TempTemplate
, TempFilter
, TempFilename
, TempExt
: WideString
;
388 // 1. Init inherited dialog defaults.
389 // 2. Populate OpenFileName record with ansi defaults
390 ProxyExecuteDialog
:= Self
;
392 DoExecute(@ProxyGetOpenFileNameA
);
394 ProxyExecuteDialog
:= nil;
396 OpenFileName
:= TOpenFilenameW(FProxiedOpenFilenameA
);
400 if not IsWindow(hWndOwner
) then begin
401 hWndOwner
:= ParentWnd
;
403 // Filter (PChar -> PWideChar)
404 TempFilter
:= AllocFilterStr(Filter
);
405 lpstrFilter
:= PWideChar(TempFilter
);
406 // FileName (PChar -> PWideChar)
407 SetLength(TempFilename
, nMaxFile
+ 2);
408 lpstrFile
:= PWideChar(TempFilename
);
409 FillChar(lpstrFile
^, (nMaxFile
+ 2) * SizeOf(WideChar
), 0);
410 WStrLCopy(lpstrFile
, PWideChar(FileName
), nMaxFile
);
411 // InitialDir (PChar -> PWideChar)
412 if (InitialDir
= '') and ForceCurrentDirectory
then
413 lpstrInitialDir
:= '.'
415 lpstrInitialDir
:= PWideChar(InitialDir
);
416 // Title (PChar -> PWideChar)
417 lpstrTitle
:= PWideChar(Title
);
418 // DefaultExt (PChar -> PWideChar)
419 TempExt
:= DefaultExt
;
420 if (TempExt
= '') and (Flags
and OFN_EXPLORER
= 0) then
422 TempExt
:= WideExtractFileExt(Filename
);
423 Delete(TempExt
, 1, 1);
425 if TempExt
<> '' then
426 lpstrDefExt
:= PWideChar(TempExt
);
427 // resource template (PChar -> PWideChar)
428 lpTemplateName
:= GetResNamePtr(TempTemplate
, Template
);
429 // start modal dialog
430 Result
:= TaskModalDialog(Func
, OpenFileName
);
433 GetFileNamesW(OpenFilename
);
434 if (Flags
and OFN_EXTENSIONDIFFERENT
) <> 0 then
435 Options
:= Options
+ [ofExtensionDifferent
]
437 Options
:= Options
- [ofExtensionDifferent
];
438 if (Flags
and OFN_READONLY
) <> 0 then
439 Options
:= Options
+ [ofReadOnly
]
441 Options
:= Options
- [ofReadOnly
];
442 FilterIndex
:= nFilterIndex
;
447 procedure TTntOpenDialog
.GetFileNamesW(var OpenFileName
: TOpenFileNameW
);
451 procedure ExtractFileNamesW(P
: PWideChar
);
453 DirName
, FileName
: TWideFileName
;
454 FileList
: TWideStringDynArray
;
457 FileList
:= ExtractStringsFromStringArray(P
, Separator
);
458 if Length(FileList
) = 0 then
461 DirName
:= FileList
[0];
462 if Length(FileList
) = 1 then
466 if WideLastChar(DirName
) <> WideString(PathDelim
) then
467 DirName
:= DirName
+ PathDelim
;
469 for i
:= 1 {second item} to High(FileList
) do begin
470 FileName
:= FileList
[i
];
472 if (FileName
[1] <> PathDelim
)
473 and ((Length(FileName
) <= 3) or (FileName
[2] <> DriveDelim
) or (FileName
[3] <> PathDelim
))
475 FileName
:= DirName
+ FileName
;
477 FFiles
.Add(FileName
);
487 if (ofAllowMultiSelect
in Options
) and
488 ((ofOldStyleDialog
in Options
) or not NewStyleControls
) then
492 if ofAllowMultiSelect
in Options
then
494 ExtractFileNamesW(lpstrFile
);
495 FileName
:= FFiles
[0];
499 FileName
:= ExtractStringFromStringArray(P
, Separator
);
500 FFiles
.Add(FileName
);
504 // Sync inherited Files
505 inherited Files
.Assign(FFiles
);
508 function TTntOpenDialog
.Execute
: Boolean;
510 if (not Win32PlatformIsUnicode
) then
511 Result
:= DoExecute(@GetOpenFileNameA
)
513 Result
:= DoExecuteW(@GetOpenFileNameW
);
516 {$IFDEF COMPILER_9_UP}
517 function TTntOpenDialog
.Execute(ParentWnd
: HWND
): Boolean;
519 if (not Win32PlatformIsUnicode
) then
520 Result
:= DoExecute(@GetOpenFileNameA
, ParentWnd
)
522 Result
:= DoExecuteW(@GetOpenFileNameW
, ParentWnd
);
528 function TTntSaveDialog
.Execute
: Boolean;
530 if (not Win32PlatformIsUnicode
) then
531 Result
:= DoExecute(@GetSaveFileNameA
)
533 Result
:= DoExecuteW(@GetSaveFileNameW
);
536 {$IFDEF COMPILER_9_UP}
537 function TTntSaveDialog
.Execute(ParentWnd
: HWND
): Boolean;
539 if (not Win32PlatformIsUnicode
) then
540 Result
:= DoExecute(@GetSaveFileNameA
, ParentWnd
)
542 Result
:= DoExecuteW(@GetSaveFileNameW
, ParentWnd
);
548 function GetAveCharSize(Canvas
: TCanvas
): TPoint
;
551 Buffer
: array[0..51] of WideChar
;
554 for I
:= 0 to 25 do Buffer
[I
] := WideChar(I
+ Ord('A'));
555 for I
:= 0 to 25 do Buffer
[I
+ 26] := WideChar(I
+ Ord('a'));
556 GetTextMetrics(Canvas
.Handle
, tm
);
557 GetTextExtentPointW(Canvas
.Handle
, Buffer
, 52, TSize(Result
));
558 Result
.X
:= (Result
.X
div 26 + 1) div 2;
559 Result
.Y
:= tm
.tmHeight
;
563 TTntMessageForm
= class(TTntForm
)
566 procedure HelpButtonClick(Sender
: TObject
);
568 procedure CustomKeyDown(Sender
: TObject
; var Key
: Word; Shift
: TShiftState
);
569 function GetFormText
: WideString
;
571 constructor CreateNew(AOwner
: TComponent
); reintroduce
;
574 constructor TTntMessageForm
.CreateNew(AOwner
: TComponent
);
576 NonClientMetrics
: TNonClientMetrics
;
578 inherited CreateNew(AOwner
);
579 NonClientMetrics
.cbSize
:= sizeof(NonClientMetrics
);
580 if SystemParametersInfo(SPI_GETNONCLIENTMETRICS
, 0, @NonClientMetrics
, 0) then
581 Font
.Handle
:= CreateFontIndirect(NonClientMetrics
.lfMessageFont
);
584 procedure TTntMessageForm
.HelpButtonClick(Sender
: TObject
);
586 Application
.HelpContext(HelpContext
);
589 procedure TTntMessageForm
.CustomKeyDown(Sender
: TObject
; var Key
: Word; Shift
: TShiftState
);
591 if (Shift
= [ssCtrl
]) and (Key
= Word('C')) then
594 TntClipboard
.AsWideText
:= GetFormText
;
598 function TTntMessageForm
.GetFormText
: WideString
;
600 DividerLine
, ButtonCaptions
: WideString
;
603 DividerLine
:= StringOfChar('-', 27) + sLineBreak
;
604 for I
:= 0 to ComponentCount
- 1 do
605 if Components
[I
] is TTntButton
then
606 ButtonCaptions
:= ButtonCaptions
+ TTntButton(Components
[I
]).Caption
+
607 StringOfChar(' ', 3);
608 ButtonCaptions
:= Tnt_WideStringReplace(ButtonCaptions
,'&','', [rfReplaceAll
]);
609 Result
:= DividerLine
+ Caption
+ sLineBreak
+ DividerLine
+ Message.Caption
+ sLineBreak
610 + DividerLine
+ ButtonCaptions
+ sLineBreak
+ DividerLine
;
613 function GetMessageCaption(MsgType
: TMsgDlgType
): WideString
;
616 mtWarning
: Result
:= SMsgDlgWarning
;
617 mtError
: Result
:= SMsgDlgError
;
618 mtInformation
: Result
:= SMsgDlgInformation
;
619 mtConfirmation
: Result
:= SMsgDlgConfirm
;
620 mtCustom
: Result
:= '';
622 raise ETntInternalError
.Create('Unexpected MsgType in GetMessageCaption.');
626 function GetButtonCaption(MsgDlgBtn
: TMsgDlgBtn
): WideString
;
629 mbYes
: Result
:= SMsgDlgYes
;
630 mbNo
: Result
:= SMsgDlgNo
;
631 mbOK
: Result
:= SMsgDlgOK
;
632 mbCancel
: Result
:= SMsgDlgCancel
;
633 mbAbort
: Result
:= SMsgDlgAbort
;
634 mbRetry
: Result
:= SMsgDlgRetry
;
635 mbIgnore
: Result
:= SMsgDlgIgnore
;
636 mbAll
: Result
:= SMsgDlgAll
;
637 mbNoToAll
: Result
:= SMsgDlgNoToAll
;
638 mbYesToAll
: Result
:= SMsgDlgYesToAll
;
639 mbHelp
: Result
:= SMsgDlgHelp
;
641 raise ETntInternalError
.Create('Unexpected MsgDlgBtn in GetButtonCaption.');
646 IconIDs
: array[TMsgDlgType
] of PAnsiChar
= (IDI_EXCLAMATION
, IDI_HAND
,
647 IDI_ASTERISK
, IDI_QUESTION
, nil);
648 ButtonNames
: array[TMsgDlgBtn
] of WideString
= (
649 'Yes', 'No', 'OK', 'Cancel', 'Abort', 'Retry', 'Ignore', 'All', 'NoToAll',
651 ModalResults
: array[TMsgDlgBtn
] of Integer = (
652 mrYes
, mrNo
, mrOk
, mrCancel
, mrAbort
, mrRetry
, mrIgnore
, mrAll
, mrNoToAll
,
655 function WideCreateMessageDialog(const Msg
: WideString
; DlgType
: TMsgDlgType
;
656 Buttons
: TMsgDlgButtons
; DefaultButton
: TMsgDlgBtn
): TTntForm
;
667 HorzMargin
, VertMargin
, HorzSpacing
, VertSpacing
, ButtonWidth
,
668 ButtonHeight
, ButtonSpacing
, ButtonCount
, ButtonGroupWidth
,
669 IconTextWidth
, IconTextHeight
, X
, ALeft
: Integer;
670 B
, CancelButton
: TMsgDlgBtn
;
673 ThisButtonWidth
: integer;
676 Result
:= TTntMessageForm
.CreateNew(Application
);
679 BorderStyle
:= bsDialog
; // By doing this first, it will work on WINE.
680 BiDiMode
:= Application
.BiDiMode
;
683 Position
:= poDesigned
;
684 OnKeyDown
:= TTntMessageForm(Result
).CustomKeyDown
;
685 DialogUnits
:= GetAveCharSize(Canvas
);
686 HorzMargin
:= MulDiv(mcHorzMargin
, DialogUnits
.X
, 4);
687 VertMargin
:= MulDiv(mcVertMargin
, DialogUnits
.Y
, 8);
688 HorzSpacing
:= MulDiv(mcHorzSpacing
, DialogUnits
.X
, 4);
689 VertSpacing
:= MulDiv(mcVertSpacing
, DialogUnits
.Y
, 8);
690 ButtonWidth
:= MulDiv(mcButtonWidth
, DialogUnits
.X
, 4);
691 for B
:= Low(TMsgDlgBtn
) to High(TMsgDlgBtn
) do
695 ATextRect
:= Rect(0,0,0,0);
696 Tnt_DrawTextW(Canvas
.Handle
,
697 PWideChar(GetButtonCaption(B
)), -1,
698 ATextRect
, DT_CALCRECT
or DT_LEFT
or DT_SINGLELINE
or
699 DrawTextBiDiModeFlagsReadingOnly
);
700 with ATextRect
do ThisButtonWidth
:= Right
- Left
+ 8;
701 if ThisButtonWidth
> ButtonWidth
then
702 ButtonWidth
:= ThisButtonWidth
;
705 ButtonHeight
:= MulDiv(mcButtonHeight
, DialogUnits
.Y
, 8);
706 ButtonSpacing
:= MulDiv(mcButtonSpacing
, DialogUnits
.X
, 4);
707 SetRect(ATextRect
, 0, 0, Screen
.Width
div 2, 0);
708 Tnt_DrawTextW(Canvas
.Handle
, PWideChar(Msg
), Length(Msg
) + 1, ATextRect
,
709 DT_EXPANDTABS
or DT_CALCRECT
or DT_WORDBREAK
or
710 DrawTextBiDiModeFlagsReadingOnly
);
711 IconID
:= IconIDs
[DlgType
];
712 IconTextWidth
:= ATextRect
.Right
;
713 IconTextHeight
:= ATextRect
.Bottom
;
714 if IconID
<> nil then
716 Inc(IconTextWidth
, 32 + HorzSpacing
);
717 if IconTextHeight
< 32 then IconTextHeight
:= 32;
720 for B
:= Low(TMsgDlgBtn
) to High(TMsgDlgBtn
) do
721 if B
in Buttons
then Inc(ButtonCount
);
722 ButtonGroupWidth
:= 0;
723 if ButtonCount
<> 0 then
724 ButtonGroupWidth
:= ButtonWidth
* ButtonCount
+
725 ButtonSpacing
* (ButtonCount
- 1);
726 ClientWidth
:= Max(IconTextWidth
, ButtonGroupWidth
) + HorzMargin
* 2;
727 ClientHeight
:= IconTextHeight
+ ButtonHeight
+ VertSpacing
+
729 Left
:= (Screen
.Width
div 2) - (Width
div 2);
730 Top
:= (Screen
.Height
div 2) - (Height
div 2);
731 if DlgType
<> mtCustom
then
732 Caption
:= GetMessageCaption(DlgType
)
734 Caption
:= TntApplication
.Title
;
735 if IconID
<> nil then
736 with TTntImage
.Create(Result
) do
740 Picture
.Icon
.Handle
:= LoadIcon(0, IconID
);
741 SetBounds(HorzMargin
, VertMargin
, 32, 32);
743 TTntMessageForm(Result
).Message := TTntLabel
.Create(Result
);
744 with TTntMessageForm(Result
).Message do
750 BoundsRect
:= ATextRect
;
751 BiDiMode
:= Result
.BiDiMode
;
752 ALeft
:= IconTextWidth
- ATextRect
.Right
+ HorzMargin
;
753 if UseRightToLeftAlignment
then
754 ALeft
:= Result
.ClientWidth
- ALeft
- Width
;
755 SetBounds(ALeft
, VertMargin
,
756 ATextRect
.Right
, ATextRect
.Bottom
);
758 if mbCancel
in Buttons
then CancelButton
:= mbCancel
else
759 if mbNo
in Buttons
then CancelButton
:= mbNo
else
760 CancelButton
:= mbOk
;
761 X
:= (ClientWidth
- ButtonGroupWidth
) div 2;
762 for B
:= Low(TMsgDlgBtn
) to High(TMsgDlgBtn
) do
765 LButton
:= TTntButton
.Create(Result
);
768 Name
:= ButtonNames
[B
];
770 Caption
:= GetButtonCaption(B
);
771 ModalResult
:= ModalResults
[B
];
772 if B
= DefaultButton
then
775 ActiveControl
:= LButton
;
777 if B
= CancelButton
then
779 SetBounds(X
, IconTextHeight
+ VertMargin
+ VertSpacing
,
780 ButtonWidth
, ButtonHeight
);
781 Inc(X
, ButtonWidth
+ ButtonSpacing
);
783 OnClick
:= TTntMessageForm(Result
).HelpButtonClick
;
789 function WideCreateMessageDialog(const Msg
: WideString
; DlgType
: TMsgDlgType
;
790 Buttons
: TMsgDlgButtons
): TTntForm
;
792 DefaultButton
: TMsgDlgBtn
;
794 if mbOk
in Buttons
then DefaultButton
:= mbOk
else
795 if mbYes
in Buttons
then DefaultButton
:= mbYes
else
796 DefaultButton
:= mbRetry
;
797 Result
:= WideCreateMessageDialog(Msg
, DlgType
, Buttons
, DefaultButton
);
800 function WideMessageDlg(const Msg
: WideString
; DlgType
: TMsgDlgType
;
801 Buttons
: TMsgDlgButtons
; HelpCtx
: Longint; DefaultButton
: TMsgDlgBtn
): Integer;
803 Result
:= WideMessageDlgPosHelp(Msg
, DlgType
, Buttons
, HelpCtx
, -1, -1, '', DefaultButton
);
806 function WideMessageDlg(const Msg
: WideString
; DlgType
: TMsgDlgType
;
807 Buttons
: TMsgDlgButtons
; HelpCtx
: Longint): Integer;
809 Result
:= WideMessageDlgPosHelp(Msg
, DlgType
, Buttons
, HelpCtx
, -1, -1, '');
812 function WideMessageDlgPos(const Msg
: WideString
; DlgType
: TMsgDlgType
;
813 Buttons
: TMsgDlgButtons
; HelpCtx
: Longint; X
, Y
: Integer; DefaultButton
: TMsgDlgBtn
): Integer;
815 Result
:= WideMessageDlgPosHelp(Msg
, DlgType
, Buttons
, HelpCtx
, X
, Y
, '', DefaultButton
);
818 function WideMessageDlgPos(const Msg
: WideString
; DlgType
: TMsgDlgType
;
819 Buttons
: TMsgDlgButtons
; HelpCtx
: Longint; X
, Y
: Integer): Integer;
821 Result
:= WideMessageDlgPosHelp(Msg
, DlgType
, Buttons
, HelpCtx
, X
, Y
, '');
824 function _Internal_WideMessageDlgPosHelp(Dlg
: TTntForm
; HelpCtx
: Longint; X
, Y
: Integer;
825 const HelpFileName
: WideString
): Integer;
829 HelpContext
:= HelpCtx
;
830 HelpFile
:= HelpFileName
;
831 if X
>= 0 then Left
:= X
;
832 if Y
>= 0 then Top
:= Y
;
833 if (Y
< 0) and (X
< 0) then Position
:= poScreenCenter
;
840 function WideMessageDlgPosHelp(const Msg
: WideString
; DlgType
: TMsgDlgType
;
841 Buttons
: TMsgDlgButtons
; HelpCtx
: Longint; X
, Y
: Integer;
842 const HelpFileName
: WideString
; DefaultButton
: TMsgDlgBtn
): Integer;
844 Result
:= _Internal_WideMessageDlgPosHelp(
845 WideCreateMessageDialog(Msg
, DlgType
, Buttons
, DefaultButton
), HelpCtx
, X
, Y
, HelpFileName
);
848 function WideMessageDlgPosHelp(const Msg
: WideString
; DlgType
: TMsgDlgType
;
849 Buttons
: TMsgDlgButtons
; HelpCtx
: Longint; X
, Y
: Integer;
850 const HelpFileName
: WideString
): Integer;
852 Result
:= _Internal_WideMessageDlgPosHelp(
853 WideCreateMessageDialog(Msg
, DlgType
, Buttons
), HelpCtx
, X
, Y
, HelpFileName
);
856 procedure WideShowMessage(const Msg
: WideString
);
858 WideShowMessagePos(Msg
, -1, -1);
861 procedure WideShowMessageFmt(const Msg
: WideString
; Params
: array of const);
863 WideShowMessage(WideFormat(Msg
, Params
));
866 procedure WideShowMessagePos(const Msg
: WideString
; X
, Y
: Integer);
868 WideMessageDlgPos(Msg
, mtCustom
, [mbOK
], 0, X
, Y
);
873 function WideInputQuery(const ACaption
, APrompt
: WideString
; var Value
: WideString
): Boolean;
879 ButtonTop
, ButtonWidth
, ButtonHeight
: Integer;
882 Form
:= TTntForm
.Create(Application
);
885 BorderStyle
:= bsDialog
; // By doing this first, it will work on WINE.
887 DialogUnits
:= GetAveCharSize(Canvas
);
889 ClientWidth
:= MulDiv(180, DialogUnits
.X
, 4);
890 Position
:= poScreenCenter
;
891 Prompt
:= TTntLabel
.Create(Form
);
896 Left
:= MulDiv(8, DialogUnits
.X
, 4);
897 Top
:= MulDiv(8, DialogUnits
.Y
, 8);
898 Constraints
.MaxWidth
:= MulDiv(164, DialogUnits
.X
, 4);
901 Edit
:= TTntEdit
.Create(Form
);
906 Top
:= Prompt
.Top
+ Prompt
.Height
+ 5;
907 Width
:= MulDiv(164, DialogUnits
.X
, 4);
912 ButtonTop
:= Edit
.Top
+ Edit
.Height
+ 15;
913 ButtonWidth
:= MulDiv(50, DialogUnits
.X
, 4);
914 ButtonHeight
:= MulDiv(14, DialogUnits
.Y
, 8);
915 with TTntButton
.Create(Form
) do
918 Caption
:= SMsgDlgOK
;
921 SetBounds(MulDiv(38, DialogUnits
.X
, 4), ButtonTop
, ButtonWidth
,
924 with TTntButton
.Create(Form
) do
927 Caption
:= SMsgDlgCancel
;
928 ModalResult
:= mrCancel
;
930 SetBounds(MulDiv(92, DialogUnits
.X
, 4), Edit
.Top
+ Edit
.Height
+ 15, ButtonWidth
,
932 Form
.ClientHeight
:= Top
+ Height
+ 13;
934 if ShowModal
= mrOk
then
945 function WideInputBox(const ACaption
, APrompt
, ADefault
: WideString
): WideString
;
948 WideInputQuery(ACaption
, APrompt
, Result
);
951 function WidePromptForFileName(var AFileName
: WideString
; const AFilter
: WideString
= '';
952 const ADefaultExt
: WideString
= ''; const ATitle
: WideString
= '';
953 const AInitialDir
: WideString
= ''; SaveDialog
: Boolean = False): Boolean;
955 Dialog
: TTntOpenDialog
;
959 Dialog
:= TTntSaveDialog
.Create(nil);
960 Dialog
.Options
:= Dialog
.Options
+ [ofOverwritePrompt
];
963 Dialog
:= TTntOpenDialog
.Create(nil);
967 DefaultExt
:= ADefaultExt
;
969 Filter
:= SDefaultFilter
else
971 InitialDir
:= AInitialDir
;
972 FileName
:= AFileName
;
975 AFileName
:= FileName
;