home *** CD-ROM | disk | FTP | other *** search
/ PC Plus SuperCD (UK) 2000 March / pcp161b.iso / full / delphi / RUNIMAGE / DELPHI30 / SOURCE / VCL / DIALOGS.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1997-08-03  |  51.6 KB  |  1,749 lines

  1.  
  2. {*******************************************************}
  3. {                                                       }
  4. {       Delphi Visual Component Library                 }
  5. {                                                       }
  6. {       Copyright (c) 1995,97 Borland International     }
  7. {                                                       }
  8. {*******************************************************}
  9.  
  10. unit Dialogs;
  11.  
  12. {$R-}
  13.  
  14. interface
  15.  
  16. uses Windows, Messages, SysUtils, CommDlg, Classes, Graphics, Controls,
  17.   Forms, StdCtrls;
  18.  
  19. const
  20.  
  21. { Maximum number of custom colors in color dialog }
  22.  
  23.   MaxCustomColors = 16;
  24.  
  25. type
  26.  
  27. { TCommonDialog }
  28.  
  29.   TCommonDialog = class(TComponent)
  30.   private
  31.     FCtl3D: Boolean;
  32.     FDefWndProc: Pointer;
  33.     FHelpContext: THelpContext;
  34.     FHandle: HWnd;
  35.     FObjectInstance: Pointer;
  36.     FTemplate: PChar;
  37.     FOnClose: TNotifyEvent;
  38.     FOnShow: TNotifyEvent;
  39.     procedure WMDestroy(var Message: TWMDestroy); message WM_DESTROY;
  40.     procedure WMInitDialog(var Message: TWMInitDialog); message WM_INITDIALOG;
  41.     procedure WMNCDestroy(var Message: TWMNCDestroy); message WM_NCDESTROY;
  42.   protected
  43.     procedure DefaultHandler(var Message); override;
  44.     procedure WndProc(var Message: TMessage); virtual;
  45.     function MessageHook(var Msg: TMessage): Boolean; virtual;
  46.     function TaskModalDialog(DialogFunc: Pointer; var DialogData): Bool; virtual;
  47.     procedure DoClose; dynamic;
  48.     procedure DoShow; dynamic;
  49.     function Execute: Boolean; virtual; abstract;
  50.     property Template: PChar read FTemplate write FTemplate;
  51.   public
  52.     constructor Create(AOwner: TComponent); override;
  53.     destructor Destroy; override;
  54.     property Handle: HWnd read FHandle;
  55.   published
  56.     property Ctl3D: Boolean read FCtl3D write FCtl3D default True;
  57.     property HelpContext: THelpContext read FHelpContext write FHelpContext default 0;
  58.     property OnClose: TNotifyEvent read FOnClose write FOnClose;
  59.     property OnShow: TNotifyEvent read FOnShow write FOnShow;
  60.   end;
  61.  
  62. { TOpenDialog }
  63.  
  64.   TOpenOption = (ofReadOnly, ofOverwritePrompt, ofHideReadOnly,
  65.     ofNoChangeDir, ofShowHelp, ofNoValidate, ofAllowMultiSelect,
  66.     ofExtensionDifferent, ofPathMustExist, ofFileMustExist, ofCreatePrompt,
  67.     ofShareAware, ofNoReadOnlyReturn, ofNoTestFileCreate, ofNoNetworkButton,
  68.     ofNoLongNames, ofOldStyleDialog, ofNoDereferenceLinks);
  69.   TOpenOptions = set of TOpenOption;
  70.  
  71.   TFileEditStyle = (fsEdit, fsComboBox);
  72.  
  73.   TOpenDialog = class(TCommonDialog)
  74.   private
  75.     FHistoryList: TStrings;
  76.     FOptions: TOpenOptions;
  77.     FFilter: string;
  78.     FFilterIndex: Integer;
  79.     FCurrentFilterIndex: Integer;
  80.     FInitialDir: string;
  81.     FTitle: string;
  82.     FDefaultExt: string;
  83.     FFileName: TFileName;
  84.     FFiles: TStrings;
  85.     FFileEditStyle: TFileEditStyle;
  86.     FOnSelectionChange: TNotifyEvent;
  87.     FOnFolderChange: TNotifyEvent;
  88.     FOnTypeChange: TNotifyEvent;
  89.     function GetFileName: string;
  90.     function GetFilterIndex: Integer;
  91.     procedure ReadFileEditStyle(Reader: TReader);
  92.     procedure SetHistoryList(Value: TStrings);
  93.     procedure SetInitialDir(const Value: string);
  94.     procedure WndProc(var Message: TMessage); override;
  95.   protected
  96.     procedure DefineProperties(Filer: TFiler); override;
  97.     function DoExecute(Func: Pointer): Bool;
  98.     procedure DoSelectionChange; dynamic;
  99.     procedure DoFolderChange; dynamic;
  100.     procedure DoTypeChange; dynamic;
  101.     function GetStaticRect: TRect; virtual;
  102.   public
  103.     constructor Create(AOwner: TComponent); override;
  104.     destructor Destroy; override;
  105.     function Execute: Boolean; override;
  106.     property FileEditStyle: TFileEditStyle read FFileEditStyle write FFileEditStyle;
  107.     property Files: TStrings read FFiles;
  108.     property HistoryList: TStrings read FHistoryList write SetHistoryList;
  109.   published
  110.     property DefaultExt: string read FDefaultExt write FDefaultExt;
  111.     property FileName: TFileName read GetFileName write FFileName;
  112.     property Filter: string read FFilter write FFilter;
  113.     property FilterIndex: Integer read GetFilterIndex write FFilterIndex default 1;
  114.     property InitialDir: string read FInitialDir write SetInitialDir;
  115.     property Options: TOpenOptions read FOptions write FOptions default [ofHideReadOnly];
  116.     property Title: string read FTitle write FTitle;
  117.     property OnFolderChange: TNotifyEvent read FOnFolderChange write FOnFolderChange;
  118.     property OnSelectionChange: TNotifyEvent read FOnSelectionChange write FOnSelectionChange;
  119.     property OnTypeChange: TNotifyEvent read FOnTypeChange write FOnTypeChange;
  120.   end;
  121.  
  122. { TSaveDialog }
  123.  
  124.   TSaveDialog = class(TOpenDialog)
  125.     function Execute: Boolean; override;
  126.   end;
  127.  
  128. { TColorDialog }
  129.  
  130.   TColorDialogOption = (cdFullOpen, cdPreventFullOpen, cdShowHelp,
  131.     cdSolidColor, cdAnyColor);
  132.   TColorDialogOptions = set of TColorDialogOption;
  133.  
  134.   TCustomColors = array[0..MaxCustomColors - 1] of Longint;
  135.  
  136.   TColorDialog = class(TCommonDialog)
  137.   private
  138.     FColor: TColor;
  139.     FOptions: TColorDialogOptions;
  140.     FCustomColors: TStrings;
  141.     procedure SetCustomColors(Value: TStrings);
  142.   public
  143.     constructor Create(AOwner: TComponent); override;
  144.     destructor Destroy; override;
  145.     function Execute: Boolean; override;
  146.   published
  147.     property Color: TColor read FColor write FColor default clBlack;
  148.     property Ctl3D default False;
  149.     property CustomColors: TStrings read FCustomColors write SetCustomColors;
  150.     property Options: TColorDialogOptions read FOptions write FOptions default [];
  151.   end;
  152.  
  153. { TFontDialog }
  154.  
  155.   TFontDialogOption = (fdAnsiOnly, fdTrueTypeOnly, fdEffects,
  156.     fdFixedPitchOnly, fdForceFontExist, fdNoFaceSel, fdNoOEMFonts,
  157.     fdNoSimulations, fdNoSizeSel, fdNoStyleSel,  fdNoVectorFonts,
  158.     fdShowHelp, fdWysiwyg, fdLimitSize, fdScalableOnly, fdApplyButton);
  159.   TFontDialogOptions = set of TFontDialogOption;
  160.  
  161.   TFontDialogDevice = (fdScreen, fdPrinter, fdBoth);
  162.  
  163.   TFDApplyEvent = procedure(Sender: TObject; Wnd: HWND) of object;
  164.  
  165.   TFontDialog = class(TCommonDialog)
  166.   private
  167.     FFont: TFont;
  168.     FDevice: TFontDialogDevice;
  169.     FOptions: TFontDialogOptions;
  170.     FOnApply: TFDApplyEvent;
  171.     FMinFontSize: Integer;
  172.     FMaxFontSize: Integer;
  173.     FFontCharsetModified: Boolean;
  174.     FFontColorModified: Boolean;
  175.     procedure DoApply(Wnd: HWND);
  176.     procedure SetFont(Value: TFont);
  177.     procedure UpdateFromLogFont(const LogFont: TLogFont);
  178.   protected
  179.     procedure Apply(Wnd: HWND); dynamic;
  180.     procedure WndProc(var Message: TMessage); override;
  181.   public
  182.     constructor Create(AOwner: TComponent); override;
  183.     destructor Destroy; override;
  184.     function Execute: Boolean; override;
  185.   published
  186.     property Font: TFont read FFont write SetFont;
  187.     property Device: TFontDialogDevice read FDevice write FDevice default fdScreen;
  188.     property MinFontSize: Integer read FMinFontSize write FMinFontSize;
  189.     property MaxFontSize: Integer read FMaxFontSize write FMaxFontSize;
  190.     property Options: TFontDialogOptions read FOptions write FOptions default [fdEffects];
  191.     property OnApply: TFDApplyEvent read FOnApply write FOnApply;
  192.   end;
  193.  
  194. { TPrinterSetupDialog }
  195.  
  196.   TPrinterSetupDialog = class(TCommonDialog)
  197.   public
  198.     function Execute: Boolean; override;
  199.   end;
  200.  
  201. { TPrintDialog }
  202.  
  203.   TPrintRange = (prAllPages, prSelection, prPageNums);
  204.   TPrintDialogOption = (poPrintToFile, poPageNums, poSelection, poWarning,
  205.     poHelp, poDisablePrintToFile);
  206.   TPrintDialogOptions = set of TPrintDialogOption;
  207.  
  208.   TPrintDialog = class(TCommonDialog)
  209.   private
  210.     FFromPage: Integer;
  211.     FToPage: Integer;
  212.     FCollate: Boolean;
  213.     FOptions: TPrintDialogOptions;
  214.     FPrintToFile: Boolean;
  215.     FPrintRange: TPrintRange;
  216.     FMinPage: Integer;
  217.     FMaxPage: Integer;
  218.     FCopies: Integer;
  219.     procedure SetNumCopies(Value: Integer);
  220.   public
  221.     function Execute: Boolean; override;
  222.   published
  223.     property Collate: Boolean read FCollate write FCollate default False;
  224.     property Copies: Integer read FCopies write SetNumCopies default 0;
  225.     property FromPage: Integer read FFromPage write FFromPage default 0;
  226.     property MinPage: Integer read FMinPage write FMinPage default 0;
  227.     property MaxPage: Integer read FMaxPage write FMaxPage default 0;
  228.     property Options: TPrintDialogOptions read FOptions write FOptions default [];
  229.     property PrintToFile: Boolean read FPrintToFile write FPrintToFile default False;
  230.     property PrintRange: TPrintRange read FPrintRange write FPrintRange default prAllPages;
  231.     property ToPage: Integer read FToPage write FToPage default 0;
  232.   end;
  233.  
  234. { TFindDialog }
  235.  
  236.   TFindOption = (frDown, frFindNext, frHideMatchCase, frHideWholeWord,
  237.     frHideUpDown, frMatchCase, frDisableMatchCase, frDisableUpDown,
  238.     frDisableWholeWord, frReplace, frReplaceAll, frWholeWord, frShowHelp);
  239.   TFindOptions = set of TFindOption;
  240.  
  241.   TFindReplaceFunc = function(var FindReplace: TFindReplace): HWnd stdcall;
  242.  
  243.   TFindDialog = class(TCommonDialog)
  244.   private
  245.     FOptions: TFindOptions;
  246.     FPosition: TPoint;
  247.     FFindReplaceFunc: TFindReplaceFunc;
  248.     FRedirector: TWinControl;
  249.     FOnFind: TNotifyEvent;
  250.     FOnReplace: TNotifyEvent;
  251.     FFindHandle: HWnd;
  252.     FFindReplace: TFindReplace;
  253.     FFindText: array[0..255] of Char;
  254.     FReplaceText: array[0..255] of Char;
  255.     function GetFindText: string;
  256.     function GetLeft: Integer;
  257.     function GetPosition: TPoint;
  258.     function GetReplaceText: string;
  259.     function GetTop: Integer;
  260.     procedure SetFindText(const Value: string);
  261.     procedure SetLeft(Value: Integer);
  262.     procedure SetPosition(const Value: TPoint);
  263.     procedure SetReplaceText(const Value: string);
  264.     procedure SetTop(Value: Integer);
  265.   protected
  266.     function MessageHook(var Msg: TMessage): Boolean; override;
  267.     procedure Find; dynamic;
  268.     procedure Replace; dynamic;
  269.   public
  270.     constructor Create(AOwner: TComponent); override;
  271.     destructor Destroy; override;
  272.     procedure CloseDialog;
  273.     function Execute: Boolean; override;
  274.     property Left: Integer read GetLeft write SetLeft;
  275.     property Position: TPoint read GetPosition write SetPosition;
  276.     property Top: Integer read GetTop write SetTop;
  277.   published
  278.     property FindText: string read GetFindText write SetFindText;
  279.     property Options: TFindOptions read FOptions write FOptions default [frDown];
  280.     property OnFind: TNotifyEvent read FOnFind write FOnFind;
  281.   end;
  282.  
  283. { TReplaceDialog }
  284.  
  285.   TReplaceDialog = class(TFindDialog)
  286.   public
  287.     constructor Create(AOwner: TComponent); override;
  288.   published
  289.     property ReplaceText: string read GetReplaceText write SetReplaceText;
  290.     property OnReplace: TNotifyEvent read FOnReplace write FOnReplace;
  291.   end;
  292.  
  293. { Message dialog }
  294.  
  295. type
  296.   TMsgDlgType = (mtWarning, mtError, mtInformation, mtConfirmation, mtCustom);
  297.   TMsgDlgBtn = (mbYes, mbNo, mbOK, mbCancel, mbAbort, mbRetry, mbIgnore,
  298.     mbAll, mbNoToAll, mbYesToAll, mbHelp);
  299.   TMsgDlgButtons = set of TMsgDlgBtn;
  300.  
  301. const
  302.   mbYesNoCancel = [mbYes, mbNo, mbCancel];
  303.   mbOKCancel = [mbOK, mbCancel];
  304.   mbAbortRetryIgnore = [mbAbort, mbRetry, mbIgnore];
  305.  
  306. function CreateMessageDialog(const Msg: string; DlgType: TMsgDlgType;
  307.   Buttons: TMsgDlgButtons): TForm;
  308.  
  309. function MessageDlg(const Msg: string; DlgType: TMsgDlgType;
  310.   Buttons: TMsgDlgButtons; HelpCtx: Longint): Integer;
  311. function MessageDlgPos(const Msg: string; DlgType: TMsgDlgType;
  312.   Buttons: TMsgDlgButtons; HelpCtx: Longint; X, Y: Integer): Integer;
  313. function MessageDlgPosHelp(const Msg: string; DlgType: TMsgDlgType;
  314.   Buttons: TMsgDlgButtons; HelpCtx: Longint; X, Y: Integer;
  315.   const HelpFileName: string): Integer;
  316.  
  317. procedure ShowMessage(const Msg: string);
  318. procedure ShowMessageFmt(const Msg: string; Params: array of const);
  319. procedure ShowMessagePos(const Msg: string; X, Y: Integer);
  320.  
  321. { Input dialog }
  322.  
  323. function InputBox(const ACaption, APrompt, ADefault: string): string;
  324. function InputQuery(const ACaption, APrompt: string;
  325.   var Value: string): Boolean;
  326.  
  327. implementation
  328.  
  329. uses ExtCtrls, Consts, Printers, Dlgs;
  330.  
  331. { Private globals }
  332.  
  333. var
  334.   CreationControl: TCommonDialog = nil;
  335.   HelpMsg: Integer;
  336.   FindMsg: Integer;
  337.   WndProcPtrAtom: TAtom = 0;
  338.   HookCtl3D: Boolean;
  339.  
  340. { Center the given window on the screen }
  341.  
  342. procedure CenterWindow(Wnd: HWnd);
  343. var
  344.   Rect: TRect;
  345. begin
  346.   GetWindowRect(Wnd, Rect);
  347.   SetWindowPos(Wnd, 0,
  348.     (GetSystemMetrics(SM_CXSCREEN) - Rect.Right + Rect.Left) div 2,
  349.     (GetSystemMetrics(SM_CYSCREEN) - Rect.Bottom + Rect.Top) div 3,
  350.     0, 0, SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOZORDER);
  351. end;
  352.  
  353. { Generic dialog hook. Centers the dialog on the screen in response to
  354.   the WM_INITDIALOG message }
  355.  
  356. function DialogHook(Wnd: HWnd; Msg: UINT; WParam: WPARAM; LParam: LPARAM): UINT; stdcall;
  357. begin
  358.   Result := 0;
  359.   case Msg of
  360.     WM_INITDIALOG:
  361.       begin
  362.         if HookCtl3D then
  363.         begin
  364.           Subclass3DDlg(Wnd, CTL3D_ALL);
  365.           SetAutoSubClass(True);
  366.         end;
  367.         CenterWindow(Wnd);
  368.         CreationControl.FHandle := Wnd;
  369.         CreationControl.FDefWndProc := Pointer(SetWindowLong(Wnd, GWL_WNDPROC,
  370.           Longint(CreationControl.FObjectInstance)));
  371.         CallWindowProc(CreationControl.FObjectInstance, Wnd, Msg, WParam, LParam);
  372.         CreationControl := nil;
  373.       end;
  374.     WM_DESTROY:
  375.       if HookCtl3D then SetAutoSubClass(False);
  376.   end;
  377. end;
  378.  
  379. { TCommonDialog }
  380.  
  381. constructor TCommonDialog.Create(AOwner: TComponent);
  382. begin
  383.   inherited Create(AOwner);
  384.   FCtl3D := True;
  385.   FObjectInstance := MakeObjectInstance(WndProc);
  386. end;
  387.  
  388. destructor TCommonDialog.Destroy;
  389. begin
  390.   if FObjectInstance <> nil then FreeObjectInstance(FObjectInstance);
  391.   inherited Destroy;
  392. end;
  393.  
  394. function TCommonDialog.MessageHook(var Msg: TMessage): Boolean;
  395. begin
  396.   Result := False;
  397.   if (Msg.Msg = HelpMsg) and (FHelpContext <> 0) then
  398.   begin
  399.     Application.HelpContext(FHelpContext);
  400.     Result := True;
  401.   end;
  402. end;
  403.  
  404. procedure TCommonDialog.DefaultHandler(var Message);
  405. begin
  406.   if FHandle <> 0 then
  407.     with TMessage(Message) do
  408.       Result := CallWindowProc(FDefWndProc, FHandle, Msg, WParam, LParam)
  409.   else inherited DefaultHandler(Message);
  410. end;
  411.  
  412. procedure TCommonDialog.WndProc(var Message: TMessage);
  413. begin
  414.   Dispatch(Message);
  415. end;
  416.  
  417. procedure TCommonDialog.WMDestroy(var Message: TWMDestroy);
  418. begin
  419.   inherited;
  420.   DoClose;
  421. end;
  422.  
  423. procedure TCommonDialog.WMInitDialog(var Message: TWMInitDialog);
  424. begin
  425.   { Called only by non-explorer style dialogs }
  426.   DoShow;
  427.   { Prevent any further processing }
  428.   Message.Result := 0;
  429. end;
  430.  
  431. procedure TCommonDialog.WMNCDestroy(var Message: TWMNCDestroy);
  432. begin
  433.   inherited;
  434.   FHandle := 0;
  435. end;
  436.  
  437. function TCommonDialog.TaskModalDialog(DialogFunc: Pointer; var DialogData): Bool;
  438. type
  439.   TDialogFunc = function(var DialogData): Bool stdcall;
  440. var
  441.   ActiveWindow: HWnd;
  442.   WindowList: Pointer;
  443. begin
  444.   ActiveWindow := GetActiveWindow;
  445.   WindowList := DisableTaskWindows(0);
  446.   try
  447.     Application.HookMainWindow(MessageHook);
  448.     try
  449.       CreationControl := Self;
  450.       Result := TDialogFunc(DialogFunc)(DialogData);
  451.     finally
  452.       Application.UnhookMainWindow(MessageHook);
  453.     end;
  454.   finally
  455.     EnableTaskWindows(WindowList);
  456.     SetActiveWindow(ActiveWindow);
  457.   end;
  458. end;
  459.  
  460. procedure TCommonDialog.DoClose;
  461. begin
  462.   if Assigned(FOnClose) then FOnClose(Self);
  463. end;
  464.  
  465. procedure TCommonDialog.DoShow;
  466. begin
  467.   if Assigned(FOnShow) then FOnShow(Self);
  468. end;
  469.  
  470. { Open and Save dialog routines }
  471.  
  472. function ExplorerHook(Wnd: HWnd; Msg: UINT; WParam: WPARAM; LParam: LPARAM): UINT; stdcall;
  473. begin
  474.   Result := 0;
  475.   if Msg = WM_INITDIALOG then
  476.   begin
  477.     CreationControl.FHandle := Wnd;
  478.     CreationControl.FDefWndProc := Pointer(SetWindowLong(Wnd, GWL_WNDPROC,
  479.       Longint(CreationControl.FObjectInstance)));
  480.     CallWindowProc(CreationControl.FObjectInstance, Wnd, Msg, WParam, LParam);
  481.     CreationControl := nil;    
  482.   end
  483.   else if (Msg = WM_NOTIFY) and (POFNotify(LParam)^.hdr.code = CDN_INITDONE) then
  484.     CenterWindow(GetWindowLong(Wnd, GWL_HWNDPARENT));
  485. end;
  486.  
  487. { TOpenDialog }
  488.  
  489. constructor TOpenDialog.Create(AOwner: TComponent);
  490. begin
  491.   inherited Create(AOwner);
  492.   FHistoryList := TStringList.Create;
  493.   FOptions := [ofHideReadOnly];
  494.   FFiles := TStringList.Create;
  495.   FFilterIndex := 1;
  496.   FFileEditStyle := fsEdit;
  497. end;
  498.  
  499. destructor TOpenDialog.Destroy;
  500. begin
  501.   FFiles.Free;
  502.   FHistoryList.Free;
  503.   inherited Destroy;
  504. end;
  505.  
  506. procedure TOpenDialog.WndProc(var Message: TMessage);
  507. var
  508.   Index: Integer;
  509. begin
  510.   Message.Result := 0;
  511.   { If not ofOldStyleDialog then DoShow on CDN_INITDONE, not WM_INITDIALOG }
  512.   if (Message.Msg = WM_INITDIALOG) and not (ofOldStyleDialog in Options) then Exit
  513.   else if (Message.Msg = WM_NOTIFY) then
  514.     case (POFNotify(Message.LParam)^.hdr.code) of
  515.       CDN_INITDONE: DoShow;
  516.       CDN_SELCHANGE: DoSelectionChange;
  517.       CDN_FOLDERCHANGE: DoFolderChange;
  518.       CDN_TYPECHANGE:
  519.         begin
  520.           Index := POFNotify(Message.LParam)^.lpOFN^.nFilterIndex;
  521.           if Index <> FCurrentFilterIndex then
  522.           begin
  523.             FCurrentFilterIndex := Index;
  524.             DoTypeChange;
  525.           end;
  526.         end;
  527.     end;
  528.   inherited WndProc(Message);
  529. end;
  530.  
  531. procedure TOpenDialog.DoSelectionChange;
  532. begin
  533.   if Assigned(FOnSelectionChange) then FOnSelectionChange(Self);
  534. end;
  535.  
  536. procedure TOpenDialog.DoFolderChange;
  537. begin
  538.   if Assigned(FOnFolderChange) then FOnFolderChange(Self);
  539. end;
  540.  
  541. procedure TOpenDialog.DoTypeChange;
  542. begin
  543.   if Assigned(FOnTypeChange) then FOnTypeChange(Self);
  544. end;
  545.  
  546. procedure TOpenDialog.ReadFileEditStyle(Reader: TReader);
  547. begin
  548.   { Ignore FileEditStyle }
  549.   Reader.ReadIdent;
  550. end;
  551.  
  552. procedure TOpenDialog.DefineProperties(Filer: TFiler);
  553. begin
  554.   inherited DefineProperties(Filer);
  555.   Filer.DefineProperty('FileEditStyle', ReadFileEditStyle, nil, False);
  556. end;
  557.  
  558. function TOpenDialog.DoExecute(Func: Pointer): Bool;
  559. const
  560.   MultiSelectBufferSize = 8192;
  561.   OpenOptions: array [TOpenOption] of Longint = (
  562.     OFN_READONLY, OFN_OVERWRITEPROMPT, OFN_HIDEREADONLY,
  563.     OFN_NOCHANGEDIR, OFN_SHOWHELP, OFN_NOVALIDATE, OFN_ALLOWMULTISELECT,
  564.     OFN_EXTENSIONDIFFERENT, OFN_PATHMUSTEXIST, OFN_FILEMUSTEXIST,
  565.     OFN_CREATEPROMPT, OFN_SHAREAWARE, OFN_NOREADONLYRETURN,
  566.     OFN_NOTESTFILECREATE, OFN_NONETWORKBUTTON, OFN_NOLONGNAMES,
  567.     OFN_EXPLORER, OFN_NODEREFERENCELINKS);
  568. var
  569.   Option: TOpenOption;
  570.   OpenFilename: TOpenFilename;
  571.   Separator: Char;
  572.  
  573.   function AllocFilterStr(const S: string): string;
  574.   var
  575.     P: PChar;
  576.   begin
  577.     Result := '';
  578.     if S <> '' then
  579.     begin
  580.       Result := S + #0;  // double null terminators
  581.       P := AnsiStrScan(PChar(Result), '|');
  582.       while P <> nil do
  583.       begin
  584.         P^ := #0;
  585.         Inc(P);
  586.         P := AnsiStrScan(P, '|');
  587.       end;
  588.     end;
  589.   end;
  590.  
  591.   function ExtractFileName(P: PChar; var S: string): PChar;
  592.   begin
  593.     Result := AnsiStrScan(P, Separator);
  594.     if Result = nil then
  595.     begin
  596.       S := P;
  597.       Result := StrEnd(P);
  598.     end
  599.     else
  600.     begin
  601.       SetString(S, P, Result - P);
  602.       Inc(Result);
  603.     end;
  604.   end;
  605.  
  606.   procedure ExtractFileNames(P: PChar);
  607.   var
  608.     DirName, FileName: string;
  609.   begin
  610.     P := ExtractFileName(P, DirName);
  611.     P := ExtractFileName(P, FileName);
  612.     if FileName = '' then
  613.       FFiles.Add(DirName)
  614.     else
  615.     begin
  616.       if AnsiLastChar(DirName)^ <> '\' then
  617.         DirName := DirName + '\';
  618.       repeat
  619.         if (FileName[1] <> '\') and ((Length(FileName) <= 3) or
  620.           (FileName[2] <> ':') or (FileName[3] <> '\')) then
  621.           FileName := DirName + FileName;
  622.         FFiles.Add(FileName);
  623.         P := ExtractFileName(P, FileName);
  624.       until FileName = '';
  625.     end;
  626.   end;
  627.  
  628. var
  629.   TempFilter, TempFilename, TempExt: string;
  630. begin
  631.   Separator := #0;
  632.   if (ofAllowMultiSelect in FOptions) and
  633.     ((ofOldStyleDialog in FOptions) or not NewStyleControls) then
  634.     Separator := ' ';
  635.   FFiles.Clear;
  636.   FillChar(OpenFileName, SizeOf(OpenFileName), 0);
  637.   with OpenFilename do
  638.   begin
  639.     lStructSize := SizeOf(TOpenFilename);
  640.     hInstance := SysInit.HInstance;
  641.     TempFilter := AllocFilterStr(FFilter);
  642.     lpstrFilter := PChar(TempFilter);
  643.     nFilterIndex := FFilterIndex;
  644.     FCurrentFilterIndex := FFilterIndex;
  645.     if ofAllowMultiSelect in FOptions then
  646.       nMaxFile := MultiSelectBufferSize else
  647.       nMaxFile := MAX_PATH;
  648.     SetLength(TempFilename, nMaxFile + 2);
  649.     lpstrFile := PChar(TempFilename);
  650.     FillChar(lpstrFile^, nMaxFile + 2, 0);
  651.     StrLCopy(lpstrFile, PChar(FFileName), nMaxFile);
  652.     lpstrInitialDir := PChar(FInitialDir);
  653.     lpstrTitle := PChar(FTitle);
  654.     HookCtl3D := FCtl3D;
  655.     Flags := OFN_ENABLEHOOK;
  656.     for Option := Low(Option) to High(Option) do
  657.       if Option in FOptions then
  658.         Flags := Flags or OpenOptions[Option];
  659.     if NewStyleControls then
  660.       Flags := Flags xor OFN_EXPLORER
  661.     else
  662.       Flags := Flags and not OFN_EXPLORER;
  663.     TempExt := FDefaultExt;
  664.     if (TempExt = '') and (Flags and OFN_EXPLORER = 0) then
  665.     begin
  666.       TempExt := ExtractFileExt(FFilename);
  667.       Delete(TempExt, 1, 1);
  668.     end;
  669.     if TempExt <> '' then lpstrDefExt := PChar(TempExt);
  670.     if (ofOldStyleDialog in Options) or not NewStyleControls then
  671.       lpfnHook := DialogHook
  672.     else
  673.     begin
  674.       lpfnHook := ExplorerHook;
  675.     end;
  676.       if Template <> nil then
  677.       begin
  678.         Flags := Flags or OFN_ENABLETEMPLATE;
  679.         lpTemplateName := Template;
  680.       end;
  681.     hWndOwner := Application.Handle;
  682.     Result := TaskModalDialog(Func, OpenFileName);
  683.     if Result then
  684.     begin
  685.       if ofAllowMultiSelect in FOptions then
  686.       begin
  687.         ExtractFileNames(lpstrFile);
  688.         FFileName := FFiles[0];
  689.       end else
  690.       begin
  691.         ExtractFileName(lpstrFile, FFileName);
  692.         FFiles.Add(FFileName);
  693.       end;
  694.       if (Flags and OFN_EXTENSIONDIFFERENT) <> 0 then
  695.         Include(FOptions, ofExtensionDifferent) else
  696.         Exclude(FOptions, ofExtensionDifferent);
  697.       if (Flags and OFN_READONLY) <> 0 then
  698.         Include(FOptions, ofReadOnly) else
  699.         Exclude(FOptions, ofReadOnly);
  700.       FFilterIndex := nFilterIndex;
  701.     end;
  702.   end;
  703. end;
  704.  
  705. function TOpenDialog.GetStaticRect: TRect;
  706. begin
  707.   if FHandle <> 0 then
  708.   begin
  709.     if not (ofOldStyleDialog in Options) then
  710.     begin
  711.       GetWindowRect(GetDlgItem(FHandle, stc32), Result);
  712.       MapWindowPoints(0, FHandle, Result, 2);
  713.     end
  714.     else GetClientRect(FHandle, Result)
  715.   end
  716.   else Result := Rect(0,0,0,0);
  717. end;
  718.  
  719. function TOpenDialog.GetFileName: string;
  720. var
  721.   Path: array[0..MAX_PATH] of Char;
  722. begin
  723.   if NewStyleControls and (FHandle <> 0) then
  724.   begin
  725.     SendMessage(GetParent(FHandle), CDM_GETFILEPATH, SizeOf(Path), Integer(@Path));
  726.     Result := StrPas(Path);
  727.   end
  728.   else Result := FFileName;
  729. end;
  730.  
  731. function TOpenDialog.GetFilterIndex: Integer;
  732. begin
  733.   if FHandle <> 0 then
  734.     Result := FCurrentFilterIndex
  735.   else
  736.     Result := FFilterIndex;
  737. end;
  738.  
  739. procedure TOpenDialog.SetHistoryList(Value: TStrings);
  740. begin
  741.   FHistoryList.Assign(Value);
  742. end;
  743.  
  744. procedure TOpenDialog.SetInitialDir(const Value: string);
  745. var
  746.   L: Integer;
  747. begin
  748.   L := Length(Value);
  749.   if (L > 1) and IsPathDelimiter(Value, L)
  750.     and not IsDelimiter(':', Value, L - 1) then Dec(L);
  751.   FInitialDir := Copy(Value, 1, L);
  752. end;
  753.  
  754. function TOpenDialog.Execute: Boolean;
  755. begin
  756.   Result := DoExecute(@GetOpenFileName);
  757. end;
  758.  
  759. { TSaveDialog }
  760.  
  761. function TSaveDialog.Execute: Boolean;
  762. begin
  763.   Result := DoExecute(@GetSaveFileName);
  764. end;
  765.  
  766. { TColorDialog }
  767.  
  768. constructor TColorDialog.Create(AOwner: TComponent);
  769. begin
  770.   inherited Create(AOwner);
  771.   FCustomColors := TStringList.Create;
  772. end;
  773.  
  774. destructor TColorDialog.Destroy;
  775. begin
  776.   FCustomColors.Free;
  777.   inherited Destroy;
  778. end;
  779.  
  780. function TColorDialog.Execute: Boolean;
  781. const
  782.   DialogOptions: array[TColorDialogOption] of LongInt = (
  783.     CC_FULLOPEN, CC_PREVENTFULLOPEN, CC_SHOWHELP, CC_SOLIDCOLOR,
  784.     CC_ANYCOLOR);
  785. var
  786.   ChooseColorRec: TChooseColor;
  787.   Option: TColorDialogOption;
  788.   CustomColorsArray: TCustomColors;
  789.   ColorPrefix, ColorTags: string;
  790.  
  791.   procedure GetCustomColorsArray;
  792.   var
  793.     I: Integer;
  794.   begin
  795.     for I := 0 to MaxCustomColors - 1 do
  796.       FCustomColors.Values[ColorPrefix + ColorTags[I + 1]] :=
  797.         Format('%.6x', [CustomColorsArray[I]]);
  798.   end;
  799.  
  800.   procedure SetCustomColorsArray;
  801.   var
  802.     Value: string;
  803.     I: Integer;
  804.   begin
  805.     for I := 0 to MaxCustomColors - 1 do
  806.     begin
  807.       Value := FCustomColors.Values[ColorPrefix + ColorTags[I + 1]];
  808.       if Value <> '' then
  809.         CustomColorsArray[I] := StrToInt('$' + Value) else
  810.         CustomColorsArray[I] := -1;
  811.     end;
  812.   end;
  813.  
  814. begin
  815.   ColorPrefix := SColorPrefix;
  816.   ColorTags := SColorTags;
  817.   with ChooseColorRec do
  818.   begin
  819.     SetCustomColorsArray;
  820.     lStructSize := SizeOf(ChooseColorRec);
  821.     hInstance := SysInit.HInstance;
  822.     rgbResult := ColorToRGB(FColor);
  823.     lpCustColors := @CustomColorsArray;
  824.     Flags := CC_RGBINIT or CC_ENABLEHOOK;
  825.     for Option := Low(Option) to High(Option) do
  826.       if Option in FOptions then
  827.         Flags := Flags or DialogOptions[Option];
  828.     if Template <> nil then
  829.     begin
  830.       Flags := Flags or CC_ENABLETEMPLATE;
  831.       lpTemplateName := Template;
  832.     end;
  833.     HookCtl3D := FCtl3D;
  834.     lpfnHook := DialogHook;
  835.     hWndOwner := Application.Handle;
  836.     Result := TaskModalDialog(@ChooseColor, ChooseColorRec);
  837.     if Result then
  838.     begin
  839.       FColor := rgbResult;
  840.       GetCustomColorsArray;
  841.     end;
  842.   end;
  843. end;
  844.  
  845. procedure TColorDialog.SetCustomColors(Value: TStrings);
  846. begin
  847.   FCustomColors.Assign(Value);
  848. end;
  849.  
  850. { TFontDialog }
  851.  
  852. const
  853.   IDAPPLYBTN = $402;
  854.  
  855. var
  856.   FontDialog: TFontDialog;
  857.  
  858. function FontDialogHook(Wnd: HWnd; Msg: UINT; WParam: WPARAM; LParam: LPARAM): UINT; stdcall;
  859. begin
  860.   if (Msg = WM_COMMAND) and (LongRec(WParam).Lo = IDAPPLYBTN) and
  861.     (LongRec(WParam).Hi = BN_CLICKED) then
  862.   begin
  863.     FontDialog.DoApply(Wnd);
  864.     Result := 1;
  865.   end else
  866.     Result := DialogHook(Wnd, Msg, wParam, lParam);
  867. end;
  868.  
  869. constructor TFontDialog.Create(AOwner: TComponent);
  870. begin
  871.   inherited Create(AOwner);
  872.   FFont := TFont.Create;
  873.   FOptions := [fdEffects];
  874. end;
  875.  
  876. destructor TFontDialog.Destroy;
  877. begin
  878.   FFont.Free;
  879.   inherited Destroy;
  880. end;
  881.  
  882. procedure TFontDialog.WndProc(var Message: TMessage);
  883. begin
  884.   { Make sure we only take values from the color combobox and script combobox
  885.     if they have been changed. }
  886.   if (Message.Msg = WM_COMMAND) and (Message.WParamHi = CBN_SELENDOK) then
  887.     if (Message.WParamLo = cmb4) then FFontColorModified := True
  888.     else if (Message.WParamLo = cmb5) then FFontCharsetModified := True;
  889.   inherited WndProc(Message);
  890. end;
  891.  
  892. procedure TFontDialog.Apply(Wnd: HWND);
  893. begin
  894.   if Assigned(FOnApply) then FOnApply(Self, Wnd);
  895. end;
  896.  
  897. procedure TFontDialog.DoApply(Wnd: HWND);
  898. const
  899.   IDCOLORCMB = $473;
  900. var
  901.   I: Integer;
  902.   LogFont: TLogFont;
  903. begin
  904.   SendMessage(Wnd, WM_CHOOSEFONT_GETLOGFONT, 0, LongInt(@LogFont));
  905.   UpdateFromLogFont(LogFont);
  906.   I := SendDlgItemMessage(Wnd, IDCOLORCMB, CB_GETCURSEL, 0, 0);
  907.   if I <> CB_ERR then
  908.     Font.Color := SendDlgItemMessage(Wnd, IDCOLORCMB, CB_GETITEMDATA, I, 0);
  909.   try
  910.     Apply(Wnd);
  911.   except
  912.     Application.HandleException(Self);
  913.   end;
  914. end;
  915.  
  916. function TFontDialog.Execute: Boolean;
  917. const
  918.   FontOptions: array[TFontDialogOption] of Longint = (
  919.     CF_ANSIONLY, CF_TTONLY, CF_EFFECTS, CF_FIXEDPITCHONLY, CF_FORCEFONTEXIST,
  920.     CF_NOFACESEL, CF_NOOEMFONTS, CF_NOSIMULATIONS, CF_NOSIZESEL,
  921.     CF_NOSTYLESEL, CF_NOVECTORFONTS, CF_SHOWHELP, CF_WYSIWYG, CF_LIMITSIZE,
  922.     CF_SCALABLEONLY, CF_APPLY);
  923.   Devices: array[TFontDialogDevice] of Longint = (
  924.     CF_SCREENFONTS, CF_PRINTERFONTS, CF_BOTH);
  925. var
  926.   ChooseFontRec: TChooseFont;
  927.   LogFont: TLogFont;
  928.   Option: TFontDialogOption;
  929.   SaveFontDialog: TFontDialog;
  930.   OriginalFaceName: string;
  931. begin
  932.   with ChooseFontRec do
  933.   begin
  934.     lStructSize := SizeOf(ChooseFontRec);
  935.     hDC := 0;
  936.     if FDevice <> fdScreen then hDC := Printer.Handle;
  937.     lpLogFont := @LogFont;
  938.     GetObject(Font.Handle, SizeOf(LogFont), @LogFont);
  939.     OriginalFaceName := LogFont.lfFaceName;
  940.     Flags := Devices[FDevice] or (CF_INITTOLOGFONTSTRUCT or CF_ENABLEHOOK);
  941.     for Option := Low(Option) to High(Option) do
  942.       if Option in FOptions then
  943.         Flags := Flags or FontOptions[Option];
  944.     if Assigned(FOnApply) then Flags := Flags or CF_APPLY;
  945.     if Template <> nil then
  946.     begin
  947.       Flags := Flags or CF_ENABLETEMPLATE;
  948.       lpTemplateName := Template;
  949.     end;
  950.     rgbColors := Font.Color;
  951.     lCustData := 0;
  952.     HookCtl3D := Ctl3D;
  953.     lpfnHook := FontDialogHook;
  954.     nSizeMin := FMinFontSize;
  955.     nSizeMax := FMaxFontSize;
  956.     if nSizeMin > nSizeMax then Flags := Flags and (not CF_LIMITSIZE);
  957.     hWndOwner := Application.Handle;
  958.     SaveFontDialog := FontDialog;
  959.     FontDialog := Self;
  960.     FFontColorModified := False;
  961.     FFontCharsetModified := False;
  962.     Result := TaskModalDialog(@ChooseFont, ChooseFontRec);
  963.     FontDialog := SaveFontDialog;
  964.     if Result then
  965.     begin
  966.       if AnsiCompareText(OriginalFaceName, LogFont.lfFaceName) <> 0 then
  967.         FFontCharsetModified := True;
  968.       UpdateFromLogFont(LogFont);
  969.       if FFontColorModified then Font.Color := rgbColors;
  970.     end;
  971.   end;
  972. end;
  973.  
  974. procedure TFontDialog.SetFont(Value: TFont);
  975. begin
  976.   FFont.Assign(Value);
  977. end;
  978.  
  979. procedure TFontDialog.UpdateFromLogFont(const LogFont: TLogFont);
  980. var
  981.   Style: TFontStyles;
  982. begin
  983.   with LogFont do
  984.   begin
  985.     Font.Name := LogFont.lfFaceName;
  986.     Font.Height := LogFont.lfHeight;
  987.     if FFontCharsetModified then
  988.       Font.Charset := TFontCharset(LogFont.lfCharSet);
  989.     Style := [];
  990.     with LogFont do
  991.     begin
  992.       if lfWeight > FW_REGULAR then Include(Style, fsBold);
  993.       if lfItalic <> 0 then Include(Style, fsItalic);
  994.       if lfUnderline <> 0 then Include(Style, fsUnderline);
  995.       if lfStrikeOut <> 0 then Include(Style, fsStrikeOut);
  996.     end;
  997.     Font.Style := Style;
  998.   end;
  999. end;
  1000.  
  1001. { Printer dialog routines }
  1002.  
  1003. procedure GetPrinter(var DeviceMode, DeviceNames: THandle);
  1004. var
  1005.   Device, Driver, Port: array[0..79] of char;
  1006.   DevNames: PDevNames;
  1007.   Offset: PChar;
  1008. begin
  1009.   Printer.GetPrinter(Device, Driver, Port, DeviceMode);
  1010.   if DeviceMode <> 0 then
  1011.   begin
  1012.     DeviceNames := GlobalAlloc(GHND, SizeOf(TDevNames) +
  1013.      StrLen(Device) + StrLen(Driver) + StrLen(Port) + 3);
  1014.     DevNames := PDevNames(GlobalLock(DeviceNames));
  1015.     try
  1016.       Offset := PChar(DevNames) + SizeOf(TDevnames);
  1017.       with DevNames^ do
  1018.       begin
  1019.         wDriverOffset := Longint(Offset) - Longint(DevNames);
  1020.         Offset := StrECopy(Offset, Driver) + 1;
  1021.         wDeviceOffset := Longint(Offset) - Longint(DevNames);
  1022.         Offset := StrECopy(Offset, Device) + 1;
  1023.         wOutputOffset := Longint(Offset) - Longint(DevNames);;
  1024.         StrCopy(Offset, Port);
  1025.       end;
  1026.     finally
  1027.       GlobalUnlock(DeviceNames);
  1028.     end;
  1029.   end;
  1030. end;
  1031.  
  1032. procedure SetPrinter(DeviceMode, DeviceNames: THandle);
  1033. var
  1034.   DevNames: PDevNames;
  1035. begin
  1036.   DevNames := PDevNames(GlobalLock(DeviceNames));
  1037.   try
  1038.     with DevNames^ do
  1039.       Printer.SetPrinter(PChar(DevNames) + wDeviceOffset,
  1040.         PChar(DevNames) + wDriverOffset,
  1041.         PChar(DevNames) + wOutputOffset, DeviceMode);
  1042.   finally
  1043.     GlobalUnlock(DeviceNames);
  1044.     GlobalFree(DeviceNames);
  1045.   end;
  1046. end;
  1047.  
  1048. function CopyData(Handle: THandle): THandle;
  1049. var
  1050.   Src, Dest: PChar;
  1051.   Size: Integer;
  1052. begin
  1053.   if Handle <> 0 then
  1054.   begin
  1055.     Size := GlobalSize(Handle);
  1056.     Result := GlobalAlloc(GHND, Size);
  1057.     if Result <> 0 then
  1058.       try
  1059.         Src := GlobalLock(Handle);
  1060.         Dest := GlobalLock(Result);
  1061.         if (Src <> nil) and (Dest <> nil) then Move(Src^, Dest^, Size);
  1062.       finally
  1063.         GlobalUnlock(Handle);
  1064.         GlobalUnlock(Result);
  1065.       end
  1066.   end
  1067.   else Result := 0;
  1068. end;
  1069.  
  1070. { TPrinterSetupDialog }
  1071.  
  1072. function TPrinterSetupDialog.Execute: Boolean;
  1073. var
  1074.   PrintDlgRec: TPrintDlg;
  1075.   DevHandle: THandle;
  1076. begin
  1077.   FillChar(PrintDlgRec, SizeOf(PrintDlgRec), 0);
  1078.   with PrintDlgRec do
  1079.   begin
  1080.     lStructSize := SizeOf(PrintDlgRec);
  1081.     hInstance := SysInit.HInstance;
  1082.     GetPrinter(DevHandle, hDevNames);
  1083.     hDevMode := CopyData(DevHandle);
  1084.     Flags := PD_ENABLESETUPHOOK or PD_PRINTSETUP;
  1085.     HookCtl3D := Ctl3D;
  1086.     lpfnSetupHook := DialogHook;
  1087.     hWndOwner := Application.Handle;
  1088.     Result := TaskModalDialog(@PrintDlg, PrintDlgRec);
  1089.     if Result then
  1090.       SetPrinter(hDevMode, hDevNames)
  1091.     else begin
  1092.       if hDevMode <> 0 then GlobalFree(hDevMode);
  1093.       if hDevNames <> 0 then GlobalFree(hDevNames);
  1094.     end;
  1095.   end;
  1096. end;
  1097.  
  1098. { TPrintDialog }
  1099.  
  1100. procedure TPrintDialog.SetNumCopies(Value: Integer);
  1101. begin
  1102.   FCopies := Value;
  1103.   Printer.Copies := Value;
  1104. end;
  1105.  
  1106. function TPrintDialog.Execute: Boolean;
  1107. const
  1108.   PrintRanges: array[TPrintRange] of Integer =
  1109.     (PD_ALLPAGES, PD_SELECTION, PD_PAGENUMS);
  1110. var
  1111.   PrintDlgRec: TPrintDlg;
  1112.   DevHandle: THandle;
  1113. begin
  1114.   FillChar(PrintDlgRec, SizeOf(PrintDlgRec), 0);
  1115.   with PrintDlgRec do
  1116.   begin
  1117.     lStructSize := SizeOf(PrintDlgRec);
  1118.     hInstance := SysInit.HInstance;
  1119.     GetPrinter(DevHandle, hDevNames);
  1120.     hDevMode := CopyData(DevHandle);
  1121.     Flags := PrintRanges[FPrintRange] or (PD_ENABLEPRINTHOOK or
  1122.       PD_ENABLESETUPHOOK);
  1123.     if FCollate then Inc(Flags, PD_COLLATE);
  1124.     if not (poPrintToFile in FOptions) then Inc(Flags, PD_HIDEPRINTTOFILE);
  1125.     if not (poPageNums in FOptions) then Inc(Flags, PD_NOPAGENUMS);
  1126.     if not (poSelection in FOptions) then Inc(Flags, PD_NOSELECTION);
  1127.     if poDisablePrintToFile in FOptions then Inc(Flags, PD_DISABLEPRINTTOFILE);
  1128.     if FPrintToFile then Inc(Flags, PD_PRINTTOFILE);
  1129.     if poHelp in FOptions then Inc(Flags, PD_SHOWHELP);
  1130.     if not (poWarning in FOptions) then Inc(Flags, PD_NOWARNING);
  1131.     nFromPage := FFromPage;
  1132.     nToPage := FToPage;
  1133.     nMinPage := FMinPage;
  1134.     nMaxPage := FMaxPage;
  1135.     HookCtl3D := Ctl3D;
  1136.     lpfnPrintHook := DialogHook;
  1137.     lpfnSetupHook := DialogHook;
  1138.     hWndOwner := Application.Handle;
  1139.     Result := TaskModalDialog(@PrintDlg, PrintDlgRec);
  1140.     if Result then
  1141.     begin
  1142.       SetPrinter(hDevMode, hDevNames);
  1143.       FCollate := Flags and PD_COLLATE <> 0;
  1144.       FPrintToFile := Flags and PD_PRINTTOFILE <> 0;
  1145.       if Flags and PD_SELECTION <> 0 then FPrintRange := prSelection else
  1146.         if Flags and PD_PAGENUMS <> 0 then FPrintRange := prPageNums else
  1147.           FPrintRange := prAllPages;
  1148.       FFromPage := nFromPage;
  1149.       FToPage := nToPage;
  1150.       if nCopies = 1 then
  1151.         Copies := Printer.Copies else
  1152.         Copies := nCopies;
  1153.     end
  1154.     else begin
  1155.       if hDevMode <> 0 then GlobalFree(hDevMode);
  1156.       if hDevNames <> 0 then GlobalFree(hDevNames);
  1157.     end;
  1158.   end;
  1159. end;
  1160.  
  1161. { TRedirectorWindow }
  1162. { A redirector window is used to put the find/replace dialog into the
  1163.   ownership chain of a form, but intercept messages that CommDlg.dll sends
  1164.   exclusively to the find/replace dialog's owner.  TRedirectorWindow
  1165.   creates its hidden window handle as owned by the target form, and the
  1166.   find/replace dialog handle is created as owned by the redirector.  The
  1167.   redirector wndproc forwards all messages to the find/replace component.
  1168. }
  1169.  
  1170. type
  1171.   TRedirectorWindow = class(TWinControl)
  1172.   private
  1173.     FFindReplaceDialog: TFindDialog;
  1174.     FFormHandle: THandle;
  1175.     procedure CMRelease(var Message); message CM_Release;
  1176.   protected
  1177.     procedure CreateParams(var Params: TCreateParams); override;
  1178.     procedure WndProc(var Message: TMessage); override;
  1179.   end;
  1180.  
  1181. procedure TRedirectorWindow.CreateParams(var Params: TCreateParams);
  1182. begin
  1183.   inherited CreateParams(Params);
  1184.   with Params do
  1185.   begin
  1186.     Style := WS_VISIBLE or WS_POPUP;
  1187.     WndParent := FFormHandle;
  1188.   end;
  1189. end;
  1190.  
  1191. procedure TRedirectorWindow.WndProc(var Message: TMessage);
  1192. begin
  1193.   inherited WndProc(Message);
  1194.   if (Message.Result = 0) and Assigned(FFindReplaceDialog) then
  1195.     Message.Result := Integer(FFindReplaceDialog.MessageHook(Message));
  1196. end;
  1197.  
  1198. procedure TRedirectorWindow.CMRelease(var Message);
  1199. begin
  1200.   Free;
  1201. end;
  1202.  
  1203. { Find and Replace dialog routines }
  1204.  
  1205. function FindReplaceWndProc(Wnd: HWND; Msg, WParam, LParam: Longint): Longint; stdcall;
  1206.  
  1207.   function CallDefWndProc: Longint;
  1208.   begin
  1209.     Result := CallWindowProc(Pointer(GetProp(Wnd,
  1210.       MakeIntAtom(WndProcPtrAtom))), Wnd, Msg, WParam, LParam);
  1211.   end;
  1212.  
  1213. begin
  1214.   case Msg of
  1215.     WM_DESTROY:
  1216.       if Application.DialogHandle = Wnd then Application.DialogHandle := 0;
  1217.     WM_NCACTIVATE:
  1218.       if WParam <> 0 then
  1219.       begin
  1220.         if Application.DialogHandle = 0 then Application.DialogHandle := Wnd;
  1221.       end else
  1222.       begin
  1223.         if Application.DialogHandle = Wnd then Application.DialogHandle := 0;
  1224.       end;
  1225.     WM_NCDESTROY:
  1226.       begin
  1227.         Result := CallDefWndProc;
  1228.         RemoveProp(Wnd, MakeIntAtom(WndProcPtrAtom));
  1229.         Exit;
  1230.       end;
  1231.    end;
  1232.    Result := CallDefWndProc;
  1233. end;
  1234.  
  1235. function FindReplaceDialogHook(Wnd: HWnd; Msg: UINT; WParam: WPARAM; LParam: LPARAM): UINT; stdcall;
  1236. begin
  1237.   Result := DialogHook(Wnd, Msg, wParam, lParam);
  1238.   if Msg = WM_INITDIALOG then
  1239.   begin
  1240.     with TFindDialog(PFindReplace(LParam)^.lCustData) do
  1241.       if (Left <> -1) or (Top <> -1) then
  1242.         SetWindowPos(Wnd, 0, Left, Top, 0, 0, SWP_NOACTIVATE or
  1243.           SWP_NOSIZE or SWP_NOZORDER);
  1244.     SetProp(Wnd, MakeIntAtom(WndProcPtrAtom), GetWindowLong(Wnd, GWL_WNDPROC));
  1245.     SetWindowLong(Wnd, GWL_WNDPROC, Longint(@FindReplaceWndProc));
  1246.     Result := 1;
  1247.   end;
  1248. end;
  1249.  
  1250. const
  1251.   FindOptions: array[TFindOption] of Longint = (
  1252.     FR_DOWN, FR_FINDNEXT, FR_HIDEMATCHCASE, FR_HIDEWHOLEWORD,
  1253.     FR_HIDEUPDOWN, FR_MATCHCASE, FR_NOMATCHCASE, FR_NOUPDOWN, FR_NOWHOLEWORD,
  1254.     FR_REPLACE, FR_REPLACEALL, FR_WHOLEWORD, FR_SHOWHELP);
  1255.  
  1256. { TFindDialog }
  1257.  
  1258. constructor TFindDialog.Create(AOwner: TComponent);
  1259. begin
  1260.   inherited Create(AOwner);
  1261.   FOptions := [frDown];
  1262.   FPosition.X := -1;
  1263.   FPosition.Y := -1;
  1264.   with FFindReplace do
  1265.   begin
  1266.     lStructSize := SizeOf(TFindReplace);
  1267.     hWndOwner := Application.Handle;
  1268.     hInstance := SysInit.HInstance;
  1269.     lpstrFindWhat := FFindText;
  1270.     wFindWhatLen := SizeOf(FFindText);
  1271.     lpstrReplaceWith := FReplaceText;
  1272.     wReplaceWithLen := SizeOf(FReplaceText);
  1273.     lCustData := Longint(Self);
  1274.     lpfnHook := FindReplaceDialogHook;
  1275.   end;
  1276.   FFindReplaceFunc := @CommDlg.FindText;
  1277. end;
  1278.  
  1279. destructor TFindDialog.Destroy;
  1280. begin
  1281.   if FFindHandle <> 0 then SendMessage(FFindHandle, WM_CLOSE, 0, 0);
  1282.   FRedirector.Free;
  1283.   inherited Destroy;
  1284. end;
  1285.  
  1286. procedure TFindDialog.CloseDialog;
  1287. begin
  1288.   if FFindHandle <> 0 then PostMessage(FFindHandle, WM_CLOSE, 0, 0);
  1289. end;
  1290.  
  1291. function GetTopWindow(Wnd: THandle; var ReturnVar: THandle):Bool; stdcall;
  1292. var
  1293.   Test: TWinControl;
  1294. begin
  1295.   Test := FindControl(Wnd);
  1296.   Result := True;
  1297.   if Assigned(Test) and (Test is TForm) then
  1298.   begin
  1299.     ReturnVar := Wnd;
  1300.     Result := False;
  1301.    end;
  1302. end;
  1303.  
  1304. function TFindDialog.Execute: Boolean;
  1305. var
  1306.   Option: TFindOption;
  1307. begin
  1308.   if FFindHandle <> 0 then
  1309.   begin
  1310.     BringWindowToTop(FFindHandle);
  1311.     Result := True;
  1312.   end else
  1313.   begin
  1314.     HookCtl3D := Ctl3D;
  1315.     FFindReplace.Flags := FR_ENABLEHOOK;
  1316.     FFindReplace.lpfnHook := FindReplaceDialogHook;
  1317.     FRedirector := TRedirectorWindow.Create(nil);
  1318.     with TRedirectorWindow(FRedirector) do
  1319.     begin
  1320.       FFindReplaceDialog := Self;
  1321.       EnumThreadWindows(GetCurrentThreadID, @GetTopWindow, LPARAM(@FFormHandle));
  1322.     end;
  1323.     FFindReplace.hWndOwner := FRedirector.Handle;
  1324.     for Option := Low(Option) to High(Option) do
  1325.       if Option in FOptions then
  1326.         FFindReplace.Flags := FFindReplace.Flags or FindOptions[Option];
  1327.     if Template <> nil then
  1328.     begin
  1329.       FFindReplace.Flags := FFindReplace.Flags or FR_ENABLETEMPLATE;
  1330.       FFindReplace.lpTemplateName := Template;
  1331.     end;
  1332.     CreationControl := Self;
  1333.     FFindHandle := FFindReplaceFunc(FFindReplace);
  1334.     Result := FFindHandle <> 0;
  1335.   end;
  1336. end;
  1337.  
  1338. procedure TFindDialog.Find;
  1339. begin
  1340.   if Assigned(FOnFind) then FOnFind(Self);
  1341. end;
  1342.  
  1343. function TFindDialog.GetFindText: string;
  1344. begin
  1345.   Result := FFindText;
  1346. end;
  1347.  
  1348. function TFindDialog.GetLeft: Integer;
  1349. begin
  1350.   Result := Position.X;
  1351. end;
  1352.  
  1353. function TFindDialog.GetPosition: TPoint;
  1354. var
  1355.   Rect: TRect;
  1356. begin
  1357.   Result := FPosition;
  1358.   if FFindHandle <> 0 then
  1359.   begin
  1360.     GetWindowRect(FFindHandle, Rect);
  1361.     Result := Rect.TopLeft;
  1362.   end;
  1363. end;
  1364.  
  1365. function TFindDialog.GetReplaceText: string;
  1366. begin
  1367.   Result := FReplaceText;
  1368. end;
  1369.  
  1370. function TFindDialog.GetTop: Integer;
  1371. begin
  1372.   Result := Position.Y;
  1373. end;
  1374.  
  1375. function TFindDialog.MessageHook(var Msg: TMessage): Boolean;
  1376. var
  1377.   Option: TFindOption;
  1378.   Rect: TRect;
  1379. begin
  1380.   Result := inherited MessageHook(Msg);
  1381.   if not Result then
  1382.     if (Msg.Msg = FindMsg) and (Pointer(Msg.LParam) = @FFindReplace) then
  1383.     begin
  1384.       FOptions := [];
  1385.       for Option := Low(Option) to High(Option) do
  1386.         if (FFindReplace.Flags and FindOptions[Option]) <> 0 then
  1387.           Include(FOptions, Option);
  1388.       if (FFindReplace.Flags and FR_FINDNEXT) <> 0 then
  1389.         Find
  1390.       else
  1391.       if (FFindReplace.Flags and (FR_REPLACE or FR_REPLACEALL)) <> 0 then
  1392.         Replace
  1393.       else
  1394.       if (FFindReplace.Flags and FR_DIALOGTERM) <> 0 then
  1395.       begin
  1396.         GetWindowRect(FFindHandle, Rect);
  1397.         FPosition := Rect.TopLeft;
  1398.         FFindHandle := 0;
  1399.         PostMessage(FRedirector.Handle,CM_RELEASE,0,0); // free redirector later
  1400.         FRedirector := nil;
  1401.       end;
  1402.       Result := True;
  1403.     end;
  1404. end;
  1405.  
  1406. procedure TFindDialog.Replace;
  1407. begin
  1408.   if Assigned(FOnReplace) then FOnReplace(Self);
  1409. end;
  1410.  
  1411. procedure TFindDialog.SetFindText(const Value: string);
  1412. begin
  1413.   StrLCopy(FFindText, PChar(Value), SizeOf(FFindText) - 1);
  1414. end;
  1415.  
  1416. procedure TFindDialog.SetLeft(Value: Integer);
  1417. begin
  1418.   SetPosition(Point(Value, Top));
  1419. end;
  1420.  
  1421. procedure TFindDialog.SetPosition(const Value: TPoint);
  1422. begin
  1423.   if (FPosition.X <> Value.X) or (FPosition.Y <> Value.Y) then
  1424.   begin
  1425.     FPosition := Value;
  1426.     if FFindHandle <> 0 then
  1427.       SetWindowPos(FFindHandle, 0, Value.X, Value.Y, 0, 0,
  1428.         SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOZORDER);
  1429.   end;
  1430. end;
  1431.  
  1432. procedure TFindDialog.SetReplaceText(const Value: string);
  1433. begin
  1434.   StrLCopy(FReplaceText, PChar(Value), SizeOf(FReplaceText) - 1);
  1435. end;
  1436.  
  1437. procedure TFindDialog.SetTop(Value: Integer);
  1438. begin
  1439.   SetPosition(Point(Left, Value));
  1440. end;
  1441.  
  1442. { TReplaceDialog }
  1443.  
  1444. constructor TReplaceDialog.Create(AOwner: TComponent);
  1445. begin
  1446.   inherited Create(AOwner);
  1447.   FFindReplaceFunc := CommDlg.ReplaceText;
  1448. end;
  1449.  
  1450. { Message dialog }
  1451.  
  1452. function Max(I, J: Integer): Integer;
  1453. begin
  1454.   if I > J then Result := I else Result := J;
  1455. end;
  1456.  
  1457. function GetAveCharSize(Canvas: TCanvas): TPoint;
  1458. var
  1459.   I: Integer;
  1460.   Buffer: array[0..51] of Char;
  1461. begin
  1462.   for I := 0 to 25 do Buffer[I] := Chr(I + Ord('A'));
  1463.   for I := 0 to 25 do Buffer[I + 26] := Chr(I + Ord('a'));
  1464.   GetTextExtentPoint(Canvas.Handle, Buffer, 52, TSize(Result));
  1465.   Result.X := Result.X div 52;
  1466. end;
  1467.  
  1468.  
  1469. type
  1470.   TMessageForm = class(TForm)
  1471.   private
  1472.     procedure HelpButtonClick(Sender: TObject);
  1473.   public
  1474.     constructor CreateNew(AOwner: TComponent);
  1475.   end;
  1476.  
  1477. constructor TMessageForm.CreateNew(AOwner: TComponent);
  1478. var
  1479.   NonClientMetrics: TNonClientMetrics;
  1480. begin
  1481.   inherited CreateNew(AOwner);
  1482.   NonClientMetrics.cbSize := sizeof(NonClientMetrics);
  1483.   if SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, @NonClientMetrics, 0) then
  1484.     Font.Handle := CreateFontIndirect(NonClientMetrics.lfMessageFont);
  1485. end;
  1486.  
  1487. procedure TMessageForm.HelpButtonClick(Sender: TObject);
  1488. begin
  1489.   Application.HelpContext(HelpContext);
  1490. end;
  1491.  
  1492. var
  1493.   Captions: array[TMsgDlgType] of Pointer = (@SMsgDlgWarning, @SMsgDlgError,
  1494.     @SMsgDlgInformation, @SMsgDlgConfirm, nil);
  1495.   IconIDs: array[TMsgDlgType] of PChar = (IDI_EXCLAMATION, IDI_HAND,
  1496.     IDI_ASTERISK, IDI_QUESTION, nil);
  1497.   ButtonNames: array[TMsgDlgBtn] of string = (
  1498.     'Yes', 'No', 'OK', 'Cancel', 'Abort', 'Retry', 'Ignore', 'All', 'NoToAll',
  1499.     'YesToAll', 'Help');
  1500.   ButtonCaptions: array[TMsgDlgBtn] of Pointer = (
  1501.     @SMsgDlgYes, @SMsgDlgNo, @SMsgDlgOK, @SMsgDlgCancel, @SMsgDlgAbort,
  1502.     @SMsgDlgRetry, @SMsgDlgIgnore, @SMsgDlgAll, @SMsgDlgNoToAll, @SMsgDlgYesToAll,
  1503.     @SMsgDlgHelp);
  1504.   ModalResults: array[TMsgDlgBtn] of Integer = (
  1505.     mrYes, mrNo, mrOk, mrCancel, mrAbort, mrRetry, mrIgnore, mrAll, mrNoToAll,
  1506.     mrYesToAll, 0);
  1507.  
  1508. function CreateMessageDialog(const Msg: string; DlgType: TMsgDlgType;
  1509.   Buttons: TMsgDlgButtons): TForm;
  1510. const
  1511.   mcHorzMargin = 8;
  1512.   mcVertMargin = 8;
  1513.   mcHorzSpacing = 10;
  1514.   mcVertSpacing = 10;
  1515.   mcButtonWidth = 50;
  1516.   mcButtonHeight = 14;
  1517.   mcButtonSpacing = 4;
  1518. var
  1519.   DialogUnits: TPoint;
  1520.   HorzMargin, VertMargin, HorzSpacing, VertSpacing, ButtonWidth,
  1521.   ButtonHeight, ButtonSpacing, ButtonCount, ButtonGroupWidth,
  1522.   IconTextWidth, IconTextHeight, X: Integer;
  1523.   B, DefaultButton, CancelButton: TMsgDlgBtn;
  1524.   IconID: PChar;
  1525.   TextRect: TRect;
  1526. begin
  1527.   Result := TMessageForm.CreateNew(Application);
  1528.   with Result do
  1529.   begin
  1530.     BorderStyle := bsDialog;
  1531.     Canvas.Font := Font;
  1532.     DialogUnits := GetAveCharSize(Canvas);
  1533.     HorzMargin := MulDiv(mcHorzMargin, DialogUnits.X, 4);
  1534.     VertMargin := MulDiv(mcVertMargin, DialogUnits.Y, 8);
  1535.     HorzSpacing := MulDiv(mcHorzSpacing, DialogUnits.X, 4);
  1536.     VertSpacing := MulDiv(mcVertSpacing, DialogUnits.Y, 8);
  1537.     ButtonWidth := MulDiv(mcButtonWidth, DialogUnits.X, 4);
  1538.     ButtonHeight := MulDiv(mcButtonHeight, DialogUnits.Y, 8);
  1539.     ButtonSpacing := MulDiv(mcButtonSpacing, DialogUnits.X, 4);
  1540.     SetRect(TextRect, 0, 0, Screen.Width div 2, 0);
  1541.     DrawText(Canvas.Handle, PChar(Msg), Length(Msg), TextRect,
  1542.       DT_EXPANDTABS or DT_CALCRECT or DT_WORDBREAK);
  1543.     IconID := IconIDs[DlgType];
  1544.     IconTextWidth := TextRect.Right;
  1545.     IconTextHeight := TextRect.Bottom;
  1546.     if IconID <> nil then
  1547.     begin
  1548.       Inc(IconTextWidth, 32 + HorzSpacing);
  1549.       if IconTextHeight < 32 then IconTextHeight := 32;
  1550.     end;
  1551.     ButtonCount := 0;
  1552.     for B := Low(TMsgDlgBtn) to High(TMsgDlgBtn) do
  1553.       if B in Buttons then Inc(ButtonCount);
  1554.     ButtonGroupWidth := 0;
  1555.     if ButtonCount <> 0 then
  1556.       ButtonGroupWidth := ButtonWidth * ButtonCount +
  1557.         ButtonSpacing * (ButtonCount - 1);
  1558.     ClientWidth := Max(IconTextWidth, ButtonGroupWidth) + HorzMargin * 2;
  1559.     ClientHeight := IconTextHeight + ButtonHeight + VertSpacing +
  1560.       VertMargin * 2;
  1561.     Left := (Screen.Width div 2) - (Width div 2);
  1562.     Top := (Screen.Height div 2) - (Height div 2);
  1563.     if DlgType <> mtCustom then
  1564.       Caption := LoadResString(Captions[DlgType]) else
  1565.       Caption := Application.Title;
  1566.     if IconID <> nil then
  1567.       with TImage.Create(Result) do
  1568.       begin
  1569.         Name := 'Image';
  1570.         Parent := Result;
  1571.         Picture.Icon.Handle := LoadIcon(0, IconID);
  1572.         SetBounds(HorzMargin, VertMargin, 32, 32);
  1573.       end;
  1574.     with TLabel.Create(Result) do
  1575.     begin
  1576.       Name := 'Message';
  1577.       Parent := Result;
  1578.       WordWrap := True;
  1579.       Caption := Msg;
  1580.       BoundsRect := TextRect;
  1581.       SetBounds(IconTextWidth - TextRect.Right + HorzMargin, VertMargin,
  1582.         TextRect.Right, TextRect.Bottom);
  1583.     end;
  1584.     if mbOk in Buttons then DefaultButton := mbOk else
  1585.       if mbYes in Buttons then DefaultButton := mbYes else
  1586.         DefaultButton := mbRetry;
  1587.     if mbCancel in Buttons then CancelButton := mbCancel else
  1588.       if mbNo in Buttons then CancelButton := mbNo else
  1589.         CancelButton := mbOk;
  1590.     X := (ClientWidth - ButtonGroupWidth) div 2;
  1591.     for B := Low(TMsgDlgBtn) to High(TMsgDlgBtn) do
  1592.       if B in Buttons then
  1593.         with TButton.Create(Result) do
  1594.         begin
  1595.           Name := ButtonNames[B];
  1596.           Parent := Result;
  1597.           Caption := LoadResString(ButtonCaptions[B]);
  1598.           ModalResult := ModalResults[B];
  1599.           if B = DefaultButton then Default := True;
  1600.           if B = CancelButton then Cancel := True;
  1601.           SetBounds(X, IconTextHeight + VertMargin + VertSpacing,
  1602.             ButtonWidth, ButtonHeight);
  1603.           Inc(X, ButtonWidth + ButtonSpacing);
  1604.           if B = mbHelp then
  1605.             OnClick := TMessageForm(Result).HelpButtonClick;
  1606.         end;
  1607.   end;
  1608. end;
  1609.  
  1610. function MessageDlg(const Msg: string; DlgType: TMsgDlgType;
  1611.   Buttons: TMsgDlgButtons; HelpCtx: Longint): Integer;
  1612. begin
  1613.   Result := MessageDlgPosHelp(Msg, DlgType, Buttons, HelpCtx, -1, -1, '');
  1614. end;
  1615.  
  1616. function MessageDlgPos(const Msg: string; DlgType: TMsgDlgType;
  1617.   Buttons: TMsgDlgButtons; HelpCtx: Longint; X, Y: Integer): Integer;
  1618. begin
  1619.   Result := MessageDlgPosHelp(Msg, DlgType, Buttons, HelpCtx, X, Y, '');
  1620. end;
  1621.  
  1622. function MessageDlgPosHelp(const Msg: string; DlgType: TMsgDlgType;
  1623.   Buttons: TMsgDlgButtons; HelpCtx: Longint; X, Y: Integer;
  1624.   const HelpFileName: string): Integer;
  1625. begin
  1626.   with CreateMessageDialog(Msg, DlgType, Buttons) do
  1627.     try
  1628.       HelpContext := HelpCtx;
  1629.       HelpFile := HelpFileName;
  1630.       if X >= 0 then Left := X;
  1631.       if Y >= 0 then Top := Y;
  1632.       Result := ShowModal;
  1633.     finally
  1634.       Free;
  1635.     end;
  1636. end;
  1637.  
  1638. procedure ShowMessage(const Msg: string);
  1639. begin
  1640.   ShowMessagePos(Msg, -1, -1);
  1641. end;
  1642.  
  1643. procedure ShowMessageFmt(const Msg: string; Params: array of const);
  1644. begin
  1645.   ShowMessage(Format(Msg, Params));
  1646. end;
  1647.  
  1648. procedure ShowMessagePos(const Msg: string; X, Y: Integer);
  1649. begin
  1650.   MessageDlgPos(Msg, mtCustom, [mbOK], 0, X, Y);
  1651. end;
  1652.  
  1653. { Input dialog }
  1654.  
  1655. function InputQuery(const ACaption, APrompt: string;
  1656.   var Value: string): Boolean;
  1657. var
  1658.   Form: TForm;
  1659.   Prompt: TLabel;
  1660.   Edit: TEdit;
  1661.   DialogUnits: TPoint;
  1662.   ButtonTop, ButtonWidth, ButtonHeight: Integer;
  1663. begin
  1664.   Result := False;
  1665.   Form := TForm.Create(Application);
  1666.   with Form do
  1667.     try
  1668.       Canvas.Font := Font;
  1669.       DialogUnits := GetAveCharSize(Canvas);
  1670.       BorderStyle := bsDialog;
  1671.       Caption := ACaption;
  1672.       ClientWidth := MulDiv(180, DialogUnits.X, 4);
  1673.       ClientHeight := MulDiv(63, DialogUnits.Y, 8);
  1674.       Position := poScreenCenter;
  1675.       Prompt := TLabel.Create(Form);
  1676.       with Prompt do
  1677.       begin
  1678.         Parent := Form;
  1679.         AutoSize := True;
  1680.         Left := MulDiv(8, DialogUnits.X, 4);
  1681.         Top := MulDiv(8, DialogUnits.Y, 8);
  1682.         Caption := APrompt;
  1683.       end;
  1684.       Edit := TEdit.Create(Form);
  1685.       with Edit do
  1686.       begin
  1687.         Parent := Form;
  1688.         Left := Prompt.Left;
  1689.         Top := MulDiv(19, DialogUnits.Y, 8);
  1690.         Width := MulDiv(164, DialogUnits.X, 4);
  1691.         MaxLength := 255;
  1692.         Text := Value;
  1693.         SelectAll;
  1694.       end;
  1695.       ButtonTop := MulDiv(41, DialogUnits.Y, 8);
  1696.       ButtonWidth := MulDiv(50, DialogUnits.X, 4);
  1697.       ButtonHeight := MulDiv(14, DialogUnits.Y, 8);
  1698.       with TButton.Create(Form) do
  1699.       begin
  1700.         Parent := Form;
  1701.         Caption := SMsgDlgOK;
  1702.         ModalResult := mrOk;
  1703.         Default := True;
  1704.         SetBounds(MulDiv(38, DialogUnits.X, 4), ButtonTop, ButtonWidth,
  1705.           ButtonHeight);
  1706.       end;
  1707.       with TButton.Create(Form) do
  1708.       begin
  1709.         Parent := Form;
  1710.         Caption := SMsgDlgCancel;
  1711.         ModalResult := mrCancel;
  1712.         Cancel := True;
  1713.         SetBounds(MulDiv(92, DialogUnits.X, 4), ButtonTop, ButtonWidth,
  1714.           ButtonHeight);
  1715.       end;
  1716.       if ShowModal = mrOk then
  1717.       begin
  1718.         Value := Edit.Text;
  1719.         Result := True;
  1720.       end;
  1721.     finally
  1722.       Form.Free;
  1723.     end;
  1724. end;
  1725.  
  1726. function InputBox(const ACaption, APrompt, ADefault: string): string;
  1727. begin
  1728.   Result := ADefault;
  1729.   InputQuery(ACaption, APrompt, Result);
  1730. end;
  1731.  
  1732. { Initialization and cleanup }
  1733.  
  1734. procedure InitGlobals;
  1735. var
  1736.   AtomText: array[0..31] of Char;
  1737. begin
  1738.   HelpMsg := RegisterWindowMessage(HelpMsgString);
  1739.   FindMsg := RegisterWindowMessage(FindMsgString);
  1740.   WndProcPtrAtom := GlobalAddAtom(StrFmt(AtomText,
  1741.     'WndProcPtr%.8X%.8X', [HInstance, GetCurrentThreadID]));
  1742. end;
  1743.  
  1744. initialization
  1745.   InitGlobals;
  1746. finalization
  1747.   if WndProcPtrAtom <> 0 then GlobalDeleteAtom(WndProcPtrAtom);
  1748. end.
  1749.