home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1997 April
/
Chip_1997-04_cd.bin
/
prezent
/
cb
/
data.z
/
DIALOGS.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1997-01-16
|
44KB
|
1,493 lines
{*******************************************************}
{ }
{ Delphi Visual Component Library }
{ }
{ Copyright (c) 1995,96 Borland International }
{ }
{*******************************************************}
unit Dialogs;
{$R-}
interface
uses Windows, Messages, SysUtils, CommDlg, Classes, Graphics, Controls,
Forms;
const
{ Maximum number of custom colors in color dialog }
MaxCustomColors = 16;
type
{ TCommonDialog }
TCommonDialog = class(TComponent)
private
FCtl3D: Boolean;
FHelpContext: THelpContext;
protected
function Message(var Msg: TMessage): Boolean; virtual;
function TaskModalDialog(DialogFunc: Pointer; var DialogData): Bool; virtual;
public
constructor Create(AOwner: TComponent); override;
published
property Ctl3D: Boolean read FCtl3D write FCtl3D default True;
property HelpContext: THelpContext read FHelpContext write FHelpContext default 0;
end;
{ TOpenDialog }
TOpenOption = (ofReadOnly, ofOverwritePrompt, ofHideReadOnly,
ofNoChangeDir, ofShowHelp, ofNoValidate, ofAllowMultiSelect,
ofExtensionDifferent, ofPathMustExist, ofFileMustExist, ofCreatePrompt,
ofShareAware, ofNoReadOnlyReturn, ofNoTestFileCreate, ofNoNetworkButton,
ofNoLongNames, ofOldStyleDialog, ofNoDereferenceLinks);
TOpenOptions = set of TOpenOption;
TFileEditStyle = (fsEdit, fsComboBox);
TOpenDialog = class(TCommonDialog)
private
FHistoryList: TStrings;
FOptions: TOpenOptions;
FFilter: string;
FFilterIndex: Integer;
FInitialDir: string;
FTitle: string;
FDefaultExt: string;
FFileName: TFileName;
FFiles: TStrings;
FFileEditStyle: TFileEditStyle;
procedure SetHistoryList(Value: TStrings);
procedure SetInitialDir(const Value: string);
function DoExecute(Func: Pointer): Bool;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function Execute: Boolean; virtual;
property Files: TStrings read FFiles;
published
property DefaultExt: string read FDefaultExt write FDefaultExt;
property FileEditStyle: TFileEditStyle read FFileEditStyle write FFileEditStyle;
property FileName: TFileName read FFileName write FFileName;
property Filter: string read FFilter write FFilter;
property FilterIndex: Integer read FFilterIndex write FFilterIndex default 1;
property HistoryList: TStrings read FHistoryList write SetHistoryList;
property InitialDir: string read FInitialDir write SetInitialDir;
property Options: TOpenOptions read FOptions write FOptions default [];
property Title: string read FTitle write FTitle;
end;
{ TSaveDialog }
TSaveDialog = class(TOpenDialog)
function Execute: Boolean; override;
end;
{ TColorDialog }
TColorDialogOption = (cdFullOpen, cdPreventFullOpen, cdShowHelp,
cdSolidColor, cdAnyColor);
TColorDialogOptions = set of TColorDialogOption;
TCustomColors = array[0..MaxCustomColors - 1] of Longint;
TColorDialog = class(TCommonDialog)
private
FColor: TColor;
FOptions: TColorDialogOptions;
FCustomColors: TStrings;
procedure SetCustomColors(Value: TStrings);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function Execute: Boolean;
published
property Color: TColor read FColor write FColor default clBlack;
property Ctl3D default False;
property CustomColors: TStrings read FCustomColors write SetCustomColors;
property Options: TColorDialogOptions read FOptions write FOptions default [];
end;
{ TFontDialog }
TFontDialogOption = (fdAnsiOnly, fdTrueTypeOnly, fdEffects,
fdFixedPitchOnly, fdForceFontExist, fdNoFaceSel, fdNoOEMFonts,
fdNoSimulations, fdNoSizeSel, fdNoStyleSel, fdNoVectorFonts,
fdShowHelp, fdWysiwyg, fdLimitSize, fdScalableOnly, fdApplyButton);
TFontDialogOptions = set of TFontDialogOption;
TFontDialogDevice = (fdScreen, fdPrinter, fdBoth);
TFDApplyEvent = procedure(Sender: TObject; Wnd: HWND) of object;
TFontDialog = class(TCommonDialog)
private
FFont: TFont;
FDevice: TFontDialogDevice;
FOptions: TFontDialogOptions;
FOnApply: TFDApplyEvent;
FMinFontSize: Integer;
FMaxFontSize: Integer;
procedure DoApply(Wnd: HWND);
procedure SetFont(Value: TFont);
procedure UpdateFromLogFont(const LogFont: TLogFont);
protected
procedure Apply(Wnd: HWND); dynamic;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function Execute: Boolean;
published
property Font: TFont read FFont write SetFont;
property Device: TFontDialogDevice read FDevice write FDevice default fdScreen;
property MinFontSize: Integer read FMinFontSize write FMinFontSize;
property MaxFontSize: Integer read FMaxFontSize write FMaxFontSize;
property Options: TFontDialogOptions read FOptions write FOptions default [fdEffects];
property OnApply: TFDApplyEvent read FOnApply write FOnApply;
end;
{ TPrinterSetupDialog }
TPrinterSetupDialog = class(TCommonDialog)
public
procedure Execute;
end;
{ TPrintDialog }
TPrintRange = (prAllPages, prSelection, prPageNums);
TPrintDialogOption = (poPrintToFile, poPageNums, poSelection, poWarning,
poHelp, poDisablePrintToFile);
TPrintDialogOptions = set of TPrintDialogOption;
TPrintDialog = class(TCommonDialog)
private
FFromPage: Integer;
FToPage: Integer;
FCollate: Boolean;
FOptions: TPrintDialogOptions;
FPrintToFile: Boolean;
FPrintRange: TPrintRange;
FMinPage: Integer;
FMaxPage: Integer;
FCopies: Integer;
procedure SetNumCopies(Value: Integer);
public
function Execute: Boolean;
published
property Collate: Boolean read FCollate write FCollate default False;
property Copies: Integer read FCopies write SetNumCopies default 0;
property FromPage: Integer read FFromPage write FFromPage default 0;
property MinPage: Integer read FMinPage write FMinPage default 0;
property MaxPage: Integer read FMaxPage write FMaxPage default 0;
property Options: TPrintDialogOptions read FOptions write FOptions default [];
property PrintToFile: Boolean read FPrintToFile write FPrintToFile default False;
property PrintRange: TPrintRange read FPrintRange write FPrintRange default prAllPages;
property ToPage: Integer read FToPage write FToPage default 0;
end;
{ TFindDialog }
TFindOption = (frDown, frFindNext, frHideMatchCase, frHideWholeWord,
frHideUpDown, frMatchCase, frDisableMatchCase, frDisableUpDown,
frDisableWholeWord, frReplace, frReplaceAll, frWholeWord, frShowHelp);
TFindOptions = set of TFindOption;
TFindReplaceFunc = function(var FindReplace: TFindReplace): HWnd stdcall;
TFindDialog = class(TCommonDialog)
private
FOptions: TFindOptions;
FPosition: TPoint;
FHandle: HWnd;
FFindReplaceFunc: TFindReplaceFunc;
FRedirector: TWinControl;
FOnFind: TNotifyEvent;
FOnReplace: TNotifyEvent;
FFindReplace: TFindReplace;
FFindText: array[0..255] of Char;
FReplaceText: array[0..255] of Char;
function GetFindText: string;
function GetLeft: Integer;
function GetPosition: TPoint;
function GetReplaceText: string;
function GetTop: Integer;
procedure SetFindText(const Value: string);
procedure SetLeft(Value: Integer);
procedure SetPosition(const Value: TPoint);
procedure SetReplaceText(const Value: string);
procedure SetTop(Value: Integer);
property ReplaceText: string read GetReplaceText write SetReplaceText;
property OnReplace: TNotifyEvent read FOnReplace write FOnReplace;
protected
function Message(var Msg: TMessage): Boolean; override;
procedure Find; dynamic;
procedure Replace; dynamic;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure CloseDialog;
function Execute: Boolean;
property Handle: HWnd read FHandle;
property Left: Integer read GetLeft write SetLeft;
property Position: TPoint read GetPosition write SetPosition;
property Top: Integer read GetTop write SetTop;
published
property FindText: string read GetFindText write SetFindText;
property Options: TFindOptions read FOptions write FOptions default [frDown];
property OnFind: TNotifyEvent read FOnFind write FOnFind;
end;
{ TReplaceDialog }
TReplaceDialog = class(TFindDialog)
public
constructor Create(AOwner: TComponent); override;
published
property ReplaceText;
property OnReplace;
end;
{ Message dialog }
type
TMsgDlgType = (mtWarning, mtError, mtInformation, mtConfirmation, mtCustom);
TMsgDlgBtn = (mbYes, mbNo, mbOK, mbCancel, mbAbort, mbRetry, mbIgnore,
mbAll, mbHelp);
TMsgDlgButtons = set of TMsgDlgBtn;
const
mbYesNoCancel = [mbYes, mbNo, mbCancel];
mbOKCancel = [mbOK, mbCancel];
mbAbortRetryIgnore = [mbAbort, mbRetry, mbIgnore];
function CreateMessageDialog(const Msg: string; DlgType: TMsgDlgType;
Buttons: TMsgDlgButtons): TForm;
function MessageDlg(const Msg: string; DlgType: TMsgDlgType;
Buttons: TMsgDlgButtons; HelpCtx: Longint): Integer;
function MessageDlgPos(const Msg: string; DlgType: TMsgDlgType;
Buttons: TMsgDlgButtons; HelpCtx: Longint; X, Y: Integer): Integer;
procedure ShowMessage(const Msg: string);
procedure ShowMessagePos(const Msg: string; X, Y: Integer);
{ Input dialog }
function InputBox(const ACaption, APrompt, ADefault: string): string;
function InputQuery(const ACaption, APrompt: string;
var Value: string): Boolean;
implementation
uses StdCtrls, ExtCtrls, Consts, Printers;
{ Private globals }
var
HelpMsg: Integer;
FindMsg: Integer;
WndProcPtrAtom: TAtom = 0;
HookCtl3D: Boolean;
{ Center the given window on the screen }
procedure CenterWindow(Wnd: HWnd);
var
Rect: TRect;
begin
GetWindowRect(Wnd, Rect);
SetWindowPos(Wnd, 0,
(GetSystemMetrics(SM_CXSCREEN) - Rect.Right + Rect.Left) div 2,
(GetSystemMetrics(SM_CYSCREEN) - Rect.Bottom + Rect.Top) div 3,
0, 0, SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOZORDER);
end;
{ Generic dialog hook. Centers the dialog on the screen in response to
the WM_INITDIALOG message }
function DialogHook(Wnd: HWnd; Msg: UINT; WParam: WPARAM; LParam: LPARAM): UINT; stdcall;
begin
Result := 0;
case Msg of
WM_INITDIALOG:
begin
if HookCtl3D then
begin
Subclass3DDlg(Wnd, CTL3D_ALL);
SetAutoSubClass(True);
end;
CenterWindow(Wnd);
Result := 1;
end;
WM_DESTROY:
if HookCtl3D then SetAutoSubClass(False);
end;
end;
{ TCommonDialog }
constructor TCommonDialog.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FCtl3D := True;
end;
function TCommonDialog.Message(var Msg: TMessage): Boolean;
begin
Result := False;
if (Msg.Msg = HelpMsg) and (FHelpContext <> 0) then
begin
Application.HelpContext(FHelpContext);
Result := True;
end;
end;
function TCommonDialog.TaskModalDialog(DialogFunc: Pointer; var DialogData): Bool;
type
TDialogFunc = function(var DialogData): Bool stdcall;
var
ActiveWindow: HWnd;
WindowList: Pointer;
begin
ActiveWindow := GetActiveWindow;
WindowList := DisableTaskWindows(0);
try
Application.HookMainWindow(Message);
try
Result := TDialogFunc(DialogFunc)(DialogData);
finally
Application.UnhookMainWindow(Message);
end;
finally
EnableTaskWindows(WindowList);
SetActiveWindow(ActiveWindow);
end;
end;
{ Open and Save dialog routines }
function ExplorerHook(Wnd: HWnd; Msg: UINT; WParam: WPARAM; LParam: LPARAM): UINT; stdcall;
begin
Result := 0;
if (Msg = WM_NOTIFY) and (POFNotify(LParam)^.hdr.code = CDN_INITDONE) then
CenterWindow(GetWindowLong(Wnd, GWL_HWNDPARENT));
end;
{ TOpenDialog }
constructor TOpenDialog.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FHistoryList := TStringList.Create;
FFiles := TStringList.Create;
FFilterIndex := 1;
FFileEditStyle := fsEdit;
end;
destructor TOpenDialog.Destroy;
begin
FFiles.Free;
FHistoryList.Free;
inherited Destroy;
end;
function TOpenDialog.DoExecute(Func: Pointer): Bool;
const
MultiSelectBufferSize = 8192;
OpenOptions: array [TOpenOption] of Longint = (
OFN_READONLY, OFN_OVERWRITEPROMPT, OFN_HIDEREADONLY,
OFN_NOCHANGEDIR, OFN_SHOWHELP, OFN_NOVALIDATE, OFN_ALLOWMULTISELECT,
OFN_EXTENSIONDIFFERENT, OFN_PATHMUSTEXIST, OFN_FILEMUSTEXIST,
OFN_CREATEPROMPT, OFN_SHAREAWARE, OFN_NOREADONLYRETURN,
OFN_NOTESTFILECREATE, OFN_NONETWORKBUTTON, OFN_NOLONGNAMES,
OFN_EXPLORER, OFN_NODEREFERENCELINKS);
var
Option: TOpenOption;
P: PChar;
CDefaultExt: array[0..3] of Char;
OpenFilename: TOpenFilename;
function AllocFilterStr(const S: string): PChar;
var
P: PChar;
begin
Result := nil;
if S <> '' then
begin
Result := StrCopy(StrAlloc(Length(S) + 2), PChar(S));
P := Result;
while P^ <> #0 do
begin
if (P^ in LeadBytes) and ((P+1)^ <> #0) then Inc(P)
else if P^ = '|' then P^ := #0;
Inc(P);
end;
Inc(P);
P^ := #0;
end;
end;
function FindExtension(P: PChar): PChar;
begin
Result := '';
while P^ <> #0 do
begin
if (P^ in LeadBytes) and ((P+1)^ <> #0) then Inc(P)
else if P^ = '.' then Result := P + 1
else if P^ = '\' then Result := '';
Inc(P);
end;
end;
function ExtractFileName(P: PChar; var S: string): PChar;
var
Separator: Char;
begin
Separator := #0;
if (ofAllowMultiSelect in FOptions) and
((ofOldStyleDialog in FOptions) or not NewStyleControls) then
Separator := ' ';
Result := P;
while (Result[0] <> #0) and (Result[0] <> Separator) do Inc(Result);
SetString(S, P, Result - P);
if Result[0] = Separator then Inc(Result);
end;
procedure ExtractFileNames(P: PChar);
var
DirName, FileName: string;
begin
P := ExtractFileName(P, DirName);
P := ExtractFileName(P, FileName);
if FileName = '' then
FFiles.Add(DirName)
else
begin
if not IsPathDelimiter(DirName, Length(DirName)) then
DirName := DirName + '\';
repeat
if (FileName[1] <> '\') and ((Length(FileName) <= 3) or
(FileName[2] <> ':') or (FileName[3] <> '\')) then
FileName := DirName + FileName;
FFiles.Add(FileName);
P := ExtractFileName(P, FileName);
until FileName = '';
end;
end;
begin
FFiles.Clear;
FillChar(OpenFileName, SizeOf(OpenFileName), 0);
with OpenFilename do
try
lStructSize := SizeOf(TOpenFilename);
hInstance := System.HInstance;
lpstrFilter := AllocFilterStr(FFilter);
nFilterIndex := FFilterIndex;
if ofAllowMultiSelect in FOptions then
nMaxFile := MultiSelectBufferSize else
nMaxFile := MAX_PATH;
GetMem(lpstrFile, nMaxFile + 2);
FillChar(lpstrFile^, nMaxFile + 2, 0);
StrLCopy(lpstrFile, PChar(FFileName), nMaxFile);
lpstrInitialDir := PChar(FInitialDir);
lpstrTitle := PChar(FTitle);
HookCtl3D := FCtl3D;
Flags := OFN_ENABLEHOOK;
for Option := Low(Option) to High(Option) do
if Option in FOptions then
Flags := Flags or OpenOptions[Option];
if NewStyleControls then
Flags := Flags xor OFN_EXPLORER
else
Flags := Flags and not OFN_EXPLORER;
if FDefaultExt <> '' then
begin
P := PChar(FDefaultExt);
if (P^ = #0) and (Flags and OFN_EXPLORER = 0) then
P := FindExtension(PChar(FFileName));
lpstrDefExt := StrLCopy(CDefaultExt, P, 3)
end;
if (ofOldStyleDialog in Options) or not NewStyleControls then
lpfnHook := DialogHook
else
lpfnHook := ExplorerHook;
hWndOwner := Application.Handle;
Result := TaskModalDialog(Func, OpenFileName);
if Result then
begin
if ofAllowMultiSelect in FOptions then
begin
ExtractFileNames(lpstrFile);
FFileName := FFiles[0];
end else
begin
ExtractFileName(lpstrFile, FFileName);
FFiles.Add(FFileName);
end;
if (Flags and OFN_EXTENSIONDIFFERENT) <> 0 then
Include(FOptions, ofExtensionDifferent) else
Exclude(FOptions, ofExtensionDifferent);
if (Flags and OFN_READONLY) <> 0 then
Include(FOptions, ofReadOnly) else
Exclude(FOptions, ofReadOnly);
FFilterIndex := nFilterIndex;
end;
finally
if lpstrFile <> nil then FreeMem(lpstrFile, nMaxFile + 2);
if lpstrFilter <> nil then StrDispose(lpstrFilter);
end;
end;
procedure TOpenDialog.SetHistoryList(Value: TStrings);
begin
FHistoryList.Assign(Value);
end;
procedure TOpenDialog.SetInitialDir(const Value: string);
var
L: Integer;
begin
L := Length(Value);
if (L > 1) and IsPathDelimiter(Value, L)
and not IsDelimiter(':', Value, L - 1) then Dec(L);
FInitialDir := Copy(Value, 1, L);
end;
function TOpenDialog.Execute: Boolean;
begin
Result := DoExecute(@GetOpenFileName);
end;
{ TSaveDialog }
function TSaveDialog.Execute: Boolean;
begin
Result := DoExecute(@GetSaveFileName);
end;
{ TColorDialog }
constructor TColorDialog.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FCustomColors := TStringList.Create;
end;
destructor TColorDialog.Destroy;
begin
FCustomColors.Free;
inherited Destroy;
end;
function TColorDialog.Execute: Boolean;
const
DialogOptions: array[TColorDialogOption] of LongInt = (
CC_FULLOPEN, CC_PREVENTFULLOPEN, CC_SHOWHELP, CC_SOLIDCOLOR,
CC_ANYCOLOR);
var
ChooseColorRec: TChooseColor;
Option: TColorDialogOption;
CustomColorsArray: TCustomColors;
ColorPrefix, ColorTags: string;
procedure GetCustomColorsArray;
var
I: Integer;
begin
for I := 0 to MaxCustomColors - 1 do
FCustomColors.Values[ColorPrefix + ColorTags[I + 1]] :=
Format('%.6x', [CustomColorsArray[I]]);
end;
procedure SetCustomColorsArray;
var
Value: string;
I: Integer;
begin
for I := 0 to MaxCustomColors - 1 do
begin
Value := FCustomColors.Values[ColorPrefix + ColorTags[I + 1]];
if Value <> '' then
CustomColorsArray[I] := StrToInt('$' + Value) else
CustomColorsArray[I] := -1;
end;
end;
begin
ColorPrefix := LoadStr(SColorPrefix);
ColorTags := LoadStr(SColorTags);
with ChooseColorRec do
begin
SetCustomColorsArray;
lStructSize := SizeOf(ChooseColorRec);
rgbResult := ColorToRGB(FColor);
lpCustColors := @CustomColorsArray;
Flags := CC_RGBINIT or CC_ENABLEHOOK;
for Option := Low(Option) to High(Option) do
if Option in FOptions then
Flags := Flags or DialogOptions[Option];
HookCtl3D := FCtl3D;
lpfnHook := DialogHook;
hWndOwner := Application.Handle;
Result := TaskModalDialog(@ChooseColor, ChooseColorRec);
if Result then
begin
FColor := rgbResult;
GetCustomColorsArray;
end;
end;
end;
procedure TColorDialog.SetCustomColors(Value: TStrings);
begin
FCustomColors.Assign(Value);
end;
{ TFontDialog }
const
IDAPPLYBTN = $402;
var
FontDialog: TFontDialog;
function FontDialogHook(Wnd: HWnd; Msg: UINT; WParam: WPARAM; LParam: LPARAM): UINT; stdcall;
begin
if (Msg = WM_COMMAND) and (LongRec(WParam).Lo = IDAPPLYBTN) and
(LongRec(WParam).Hi = BN_CLICKED) then
begin
FontDialog.DoApply(Wnd);
Result := 1;
end else
Result := DialogHook(Wnd, Msg, wParam, lParam);
end;
constructor TFontDialog.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FFont := TFont.Create;
FOptions := [fdEffects];
end;
destructor TFontDialog.Destroy;
begin
FFont.Free;
inherited Destroy;
end;
procedure TFontDialog.Apply(Wnd: HWND);
begin
if Assigned(FOnApply) then FOnApply(Self, Wnd);
end;
procedure TFontDialog.DoApply(Wnd: HWND);
const
IDCOLORCMB = $473;
var
I: Integer;
LogFont: TLogFont;
begin
SendMessage(Wnd, WM_CHOOSEFONT_GETLOGFONT, 0, LongInt(@LogFont));
UpdateFromLogFont(LogFont);
I := SendDlgItemMessage(Wnd, IDCOLORCMB, CB_GETCURSEL, 0, 0);
if I <> CB_ERR then
Font.Color := SendDlgItemMessage(Wnd, IDCOLORCMB, CB_GETITEMDATA, I, 0);
try
Apply(Wnd);
except
Application.HandleException(Self);
end;
end;
function TFontDialog.Execute: Boolean;
const
FontOptions: array[TFontDialogOption] of Longint = (
CF_ANSIONLY, CF_TTONLY, CF_EFFECTS, CF_FIXEDPITCHONLY, CF_FORCEFONTEXIST,
CF_NOFACESEL, CF_NOOEMFONTS, CF_NOSIMULATIONS, CF_NOSIZESEL,
CF_NOSTYLESEL, CF_NOVECTORFONTS, CF_SHOWHELP, CF_WYSIWYG, CF_LIMITSIZE,
CF_SCALABLEONLY, CF_APPLY);
Devices: array[TFontDialogDevice] of Longint = (
CF_SCREENFONTS, CF_PRINTERFONTS, CF_BOTH);
var
ChooseFontRec: TChooseFont;
LogFont: TLogFont;
Option: TFontDialogOption;
SaveFontDialog: TFontDialog;
begin
with ChooseFontRec do
begin
lStructSize := SizeOf(ChooseFontRec);
hDC := 0;
lpLogFont := @LogFont;
GetObject(Font.Handle, SizeOf(LogFont), @LogFont);
Flags := Devices[FDevice] or (CF_INITTOLOGFONTSTRUCT or CF_ENABLEHOOK);
for Option := Low(Option) to High(Option) do
if Option in FOptions then
Flags := Flags or FontOptions[Option];
if Assigned(FOnApply) then Flags := Flags or CF_APPLY;
rgbColors := Font.Color;
lCustData := 0;
HookCtl3D := Ctl3D;
lpfnHook := FontDialogHook;
nSizeMin := FMinFontSize;
nSizeMax := FMaxFontSize;
if nSizeMin > nSizeMax then Flags := Flags and (not CF_LIMITSIZE);
hWndOwner := Application.Handle;
SaveFontDialog := FontDialog;
FontDialog := Self;
Result := TaskModalDialog(@ChooseFont, ChooseFontRec);
FontDialog := SaveFontDialog;
if Result then
begin
UpdateFromLogFont(LogFont);
Font.Color := rgbColors;
end;
end;
end;
procedure TFontDialog.SetFont(Value: TFont);
begin
FFont.Assign(Value);
end;
procedure TFontDialog.UpdateFromLogFont(const LogFont: TLogFont);
var
Style: TFontStyles;
begin
with LogFont do
begin
Font.Name := LogFont.lfFaceName;
Font.Height := LogFont.lfHeight;
Font.Charset := TFontCharset(LogFont.lfCharSet);
Style := [];
with LogFont do
begin
if lfWeight > FW_REGULAR then Include(Style, fsBold);
if lfItalic <> 0 then Include(Style, fsItalic);
if lfUnderline <> 0 then Include(Style, fsUnderline);
if lfStrikeOut <> 0 then Include(Style, fsStrikeOut);
end;
Font.Style := Style;
end;
end;
{ Printer dialog routines }
procedure GetPrinter(var DeviceMode, DeviceNames: THandle);
var
Device, Driver, Port: array[0..79] of char;
DevNames: PDevNames;
Offset: PChar;
begin
Printer.GetPrinter(Device, Driver, Port, DeviceMode);
if DeviceMode <> 0 then
begin
DeviceNames := GlobalAlloc(GHND, SizeOf(TDevNames) +
StrLen(Device) + StrLen(Driver) + StrLen(Port) + 3);
DevNames := PDevNames(GlobalLock(DeviceNames));
try
Offset := PChar(DevNames) + SizeOf(TDevnames);
with DevNames^ do
begin
wDriverOffset := Longint(Offset) - Longint(DevNames);
Offset := StrECopy(Offset, Driver) + 1;
wDeviceOffset := Longint(Offset) - Longint(DevNames);
Offset := StrECopy(Offset, Device) + 1;
wOutputOffset := Longint(Offset) - Longint(DevNames);;
StrCopy(Offset, Port);
end;
finally
GlobalUnlock(DeviceNames);
end;
end;
end;
procedure SetPrinter(DeviceMode, DeviceNames: THandle);
var
DevNames: PDevNames;
begin
DevNames := PDevNames(GlobalLock(DeviceNames));
try
with DevNames^ do
Printer.SetPrinter(PChar(DevNames) + wDeviceOffset,
PChar(DevNames) + wDriverOffset,
PChar(DevNames) + wOutputOffset, DeviceMode);
finally
GlobalUnlock(DeviceNames);
GlobalFree(DeviceNames);
end;
end;
function CopyData(Handle: THandle): THandle;
var
Src, Dest: PChar;
Size: Integer;
begin
if Handle <> 0 then
begin
Size := GlobalSize(Handle);
Result := GlobalAlloc(GHND, Size);
if Result <> 0 then
try
Src := GlobalLock(Handle);
Dest := GlobalLock(Result);
if (Src <> nil) and (Dest <> nil) then Move(Src^, Dest^, Size);
finally
GlobalUnlock(Handle);
GlobalUnlock(Result);
end
end
else Result := 0;
end;
{ TPrinterSetupDialog }
procedure TPrinterSetupDialog.Execute;
var
PrintDlgRec: TPrintDlg;
DevHandle: THandle;
begin
FillChar(PrintDlgRec, SizeOf(PrintDlgRec), 0);
with PrintDlgRec do
begin
lStructSize := SizeOf(PrintDlgRec);
hInstance := System.HInstance;
GetPrinter(DevHandle, hDevNames);
hDevMode := CopyData(DevHandle);
Flags := PD_ENABLESETUPHOOK or PD_PRINTSETUP;
HookCtl3D := Ctl3D;
lpfnSetupHook := DialogHook;
hWndOwner := Application.Handle;
if TaskModalDialog(@PrintDlg, PrintDlgRec) then
SetPrinter(hDevMode, hDevNames)
else begin
if hDevMode <> 0 then GlobalFree(hDevMode);
if hDevNames <> 0 then GlobalFree(hDevNames);
end;
end;
end;
{ TPrintDialog }
procedure TPrintDialog.SetNumCopies(Value: Integer);
begin
FCopies := Value;
Printer.Copies := Value;
end;
function TPrintDialog.Execute: Boolean;
const
PrintRanges: array[TPrintRange] of Integer =
(PD_ALLPAGES, PD_SELECTION, PD_PAGENUMS);
var
PrintDlgRec: TPrintDlg;
DevHandle: THandle;
begin
FillChar(PrintDlgRec, SizeOf(PrintDlgRec), 0);
with PrintDlgRec do
begin
lStructSize := SizeOf(PrintDlgRec);
hInstance := System.HInstance;
GetPrinter(DevHandle, hDevNames);
hDevMode := CopyData(DevHandle);
Flags := PrintRanges[FPrintRange] or (PD_ENABLEPRINTHOOK or
PD_ENABLESETUPHOOK);
if FCollate then Inc(Flags, PD_COLLATE);
if not (poPrintToFile in FOptions) then Inc(Flags, PD_HIDEPRINTTOFILE);
if not (poPageNums in FOptions) then Inc(Flags, PD_NOPAGENUMS);
if not (poSelection in FOptions) then Inc(Flags, PD_NOSELECTION);
if poDisablePrintToFile in FOptions then Inc(Flags, PD_DISABLEPRINTTOFILE);
if FPrintToFile then Inc(Flags, PD_PRINTTOFILE);
if poHelp in FOptions then Inc(Flags, PD_SHOWHELP);
if not (poWarning in FOptions) then Inc(Flags, PD_NOWARNING);
nFromPage := FFromPage;
nToPage := FToPage;
nMinPage := FMinPage;
nMaxPage := FMaxPage;
HookCtl3D := Ctl3D;
lpfnPrintHook := DialogHook;
lpfnSetupHook := DialogHook;
hWndOwner := Application.Handle;
Result := TaskModalDialog(@PrintDlg, PrintDlgRec);
if Result then
begin
SetPrinter(hDevMode, hDevNames);
FCollate := Flags and PD_COLLATE <> 0;
FPrintToFile := Flags and PD_PRINTTOFILE <> 0;
if Flags and PD_SELECTION <> 0 then FPrintRange := prSelection else
if Flags and PD_PAGENUMS <> 0 then FPrintRange := prPageNums else
FPrintRange := prAllPages;
FFromPage := nFromPage;
FToPage := nToPage;
if nCopies = 1 then
Copies := Printer.Copies else
Copies := nCopies;
end
else begin
if hDevMode <> 0 then GlobalFree(hDevMode);
if hDevNames <> 0 then GlobalFree(hDevNames);
end;
end;
end;
{ TRedirectorWindow }
{ A redirector window is used to put the find/replace dialog into the
ownership chain of a form, but intercept messages that CommDlg.dll sends
exclusively to the find/replace dialog's owner. TRedirectorWindow
creates its hidden window handle as owned by the target form, and the
find/replace dialog handle is created as owned by the redirector. The
redirector wndproc forwards all messages to the find/replace component.
}
type
TRedirectorWindow = class(TWinControl)
private
FFindReplaceDialog: TFindDialog;
FFormHandle: THandle;
procedure CMRelease(var Message); message CM_Release;
protected
procedure CreateParams(var Params: TCreateParams); override;
procedure WndProc(var Message: TMessage); override;
end;
procedure TRedirectorWindow.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
with Params do
begin
Style := WS_VISIBLE or WS_POPUP;
WndParent := FFormHandle;
end;
end;
procedure TRedirectorWindow.WndProc(var Message: TMessage);
begin
inherited WndProc(Message);
if (Message.Result = 0) and Assigned(FFindReplaceDialog) then
Message.Result := Integer(FFindReplaceDialog.Message(Message));
end;
procedure TRedirectorWindow.CMRelease(var Message);
begin
Free;
end;
{ Find and Replace dialog routines }
function FindReplaceWndProc(Wnd: HWND; Msg, WParam, LParam: Longint): Longint; stdcall;
function CallDefWndProc: Longint;
begin
Result := CallWindowProc(Pointer(GetProp(Wnd,
MakeIntAtom(WndProcPtrAtom))), Wnd, Msg, WParam, LParam);
end;
begin
case Msg of
WM_DESTROY:
if Application.DialogHandle = Wnd then Application.DialogHandle := 0;
WM_NCACTIVATE:
if WParam <> 0 then
begin
if Application.DialogHandle = 0 then Application.DialogHandle := Wnd;
end else
begin
if Application.DialogHandle = Wnd then Application.DialogHandle := 0;
end;
WM_NCDESTROY:
begin
Result := CallDefWndProc;
RemoveProp(Wnd, MakeIntAtom(WndProcPtrAtom));
Exit;
end;
end;
Result := CallDefWndProc;
end;
function FindReplaceDialogHook(Wnd: HWnd; Msg: UINT; WParam: WPARAM; LParam: LPARAM): UINT; stdcall;
begin
Result := DialogHook(Wnd, Msg, wParam, lParam);
if Msg = WM_INITDIALOG then
begin
with TFindDialog(PFindReplace(LParam)^.lCustData) do
if (Left <> -1) or (Top <> -1) then
SetWindowPos(Wnd, 0, Left, Top, 0, 0, SWP_NOACTIVATE or
SWP_NOSIZE or SWP_NOZORDER);
SetProp(Wnd, MakeIntAtom(WndProcPtrAtom), GetWindowLong(Wnd, GWL_WNDPROC));
SetWindowLong(Wnd, GWL_WNDPROC, Longint(@FindReplaceWndProc));
Result := 1;
end;
end;
const
FindOptions: array[TFindOption] of Longint = (
FR_DOWN, FR_FINDNEXT, FR_HIDEMATCHCASE, FR_HIDEWHOLEWORD,
FR_HIDEUPDOWN, FR_MATCHCASE, FR_NOMATCHCASE, FR_NOUPDOWN, FR_NOWHOLEWORD,
FR_REPLACE, FR_REPLACEALL, FR_WHOLEWORD, FR_SHOWHELP);
{ TFindDialog }
constructor TFindDialog.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FOptions := [frDown];
FPosition.X := -1;
FPosition.Y := -1;
with FFindReplace do
begin
lStructSize := SizeOf(TFindReplace);
hWndOwner := Application.Handle;
hInstance := System.HInstance;
lpstrFindWhat := FFindText;
wFindWhatLen := SizeOf(FFindText);
lpstrReplaceWith := FReplaceText;
wReplaceWithLen := SizeOf(FReplaceText);
lCustData := Longint(Self);
lpfnHook := FindReplaceDialogHook;
end;
FFindReplaceFunc := @CommDlg.FindText;
end;
destructor TFindDialog.Destroy;
begin
if FHandle <> 0 then SendMessage(FHandle, WM_CLOSE, 0, 0);
FRedirector.Free;
inherited Destroy;
end;
procedure TFindDialog.CloseDialog;
begin
if FHandle <> 0 then PostMessage(FHandle, WM_CLOSE, 0, 0);
end;
function GetTopWindow(Wnd: THandle; var ReturnVar: THandle):Bool; stdcall;
var
Test: TWinControl;
begin
Test := FindControl(Wnd);
Result := True;
if Assigned(Test) and (Test is TForm) then
begin
ReturnVar := Wnd;
Result := False;
end;
end;
function TFindDialog.Execute: Boolean;
var
Option: TFindOption;
begin
if FHandle <> 0 then
begin
BringWindowToTop(FHandle);
Result := True;
end else
begin
HookCtl3D := Ctl3D;
FFindReplace.Flags := FR_ENABLEHOOK;
FFindReplace.lpfnHook := FindReplaceDialogHook;
FRedirector := TRedirectorWindow.Create(nil);
with TRedirectorWindow(FRedirector) do
begin
FFindReplaceDialog := Self;
EnumThreadWindows(GetCurrentThreadID, @GetTopWindow, LPARAM(@FFormHandle));
end;
FFindReplace.hWndOwner := FRedirector.Handle;
for Option := Low(Option) to High(Option) do
if Option in FOptions then
FFindReplace.Flags := FFindReplace.Flags or FindOptions[Option];
FHandle := FFindReplaceFunc(FFindReplace);
Result := FHandle <> 0;
end;
end;
procedure TFindDialog.Find;
begin
if Assigned(FOnFind) then FOnFind(Self);
end;
function TFindDialog.GetFindText: string;
begin
Result := FFindText;
end;
function TFindDialog.GetLeft: Integer;
begin
Result := Position.X;
end;
function TFindDialog.GetPosition: TPoint;
var
Rect: TRect;
begin
Result := FPosition;
if FHandle <> 0 then
begin
GetWindowRect(FHandle, Rect);
Result := Rect.TopLeft;
end;
end;
function TFindDialog.GetReplaceText: string;
begin
Result := FReplaceText;
end;
function TFindDialog.GetTop: Integer;
begin
Result := Position.Y;
end;
function TFindDialog.Message(var Msg: TMessage): Boolean;
var
Option: TFindOption;
Rect: TRect;
begin
Result := inherited Message(Msg);
if not Result then
if (Msg.Msg = FindMsg) and (Pointer(Msg.LParam) = @FFindReplace) then
begin
FOptions := [];
for Option := Low(Option) to High(Option) do
if (FFindReplace.Flags and FindOptions[Option]) <> 0 then
Include(FOptions, Option);
if (FFindReplace.Flags and FR_FINDNEXT) <> 0 then
Find
else
if (FFindReplace.Flags and (FR_REPLACE or FR_REPLACEALL)) <> 0 then
Replace
else
if (FFindReplace.Flags and FR_DIALOGTERM) <> 0 then
begin
GetWindowRect(FHandle, Rect);
FPosition := Rect.TopLeft;
FHandle := 0;
PostMessage(FRedirector.Handle,CM_RELEASE,0,0); // free redirector later
FRedirector := nil;
end;
Result := True;
end;
end;
procedure TFindDialog.Replace;
begin
if Assigned(FOnReplace) then FOnReplace(Self);
end;
procedure TFindDialog.SetFindText(const Value: string);
begin
StrLCopy(FFindText, PChar(Value), SizeOf(FFindText) - 1);
end;
procedure TFindDialog.SetLeft(Value: Integer);
begin
SetPosition(Point(Value, Top));
end;
procedure TFindDialog.SetPosition(const Value: TPoint);
begin
if (FPosition.X <> Value.X) or (FPosition.Y <> Value.Y) then
begin
FPosition := Value;
if FHandle <> 0 then
SetWindowPos(FHandle, 0, Value.X, Value.Y, 0, 0,
SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOZORDER);
end;
end;
procedure TFindDialog.SetReplaceText(const Value: string);
begin
StrLCopy(FReplaceText, PChar(Value), SizeOf(FReplaceText) - 1);
end;
procedure TFindDialog.SetTop(Value: Integer);
begin
SetPosition(Point(Left, Value));
end;
{ TReplaceDialog }
constructor TReplaceDialog.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FFindReplaceFunc := CommDlg.ReplaceText;
end;
{ Message dialog }
function Max(I, J: Integer): Integer;
begin
if I > J then Result := I else Result := J;
end;
function GetAveCharSize(Canvas: TCanvas): TPoint;
var
I: Integer;
Buffer: array[0..51] of Char;
begin
for I := 0 to 25 do Buffer[I] := Chr(I + Ord('A'));
for I := 0 to 25 do Buffer[I + 26] := Chr(I + Ord('a'));
GetTextExtentPoint(Canvas.Handle, Buffer, 52, TSize(Result));
Result.X := Result.X div 52;
end;
type
TMessageForm = class(TForm)
private
procedure HelpButtonClick(Sender: TObject);
end;
procedure TMessageForm.HelpButtonClick(Sender: TObject);
begin
Application.HelpContext(HelpContext);
end;
function CreateMessageDialog(const Msg: string; DlgType: TMsgDlgType;
Buttons: TMsgDlgButtons): TForm;
const
mcHorzMargin = 8;
mcVertMargin = 8;
mcHorzSpacing = 10;
mcVertSpacing = 10;
mcButtonWidth = 50;
mcButtonHeight = 14;
mcButtonSpacing = 4;
const
Captions: array[TMsgDlgType] of Word = (SMsgDlgWarning, SMsgDlgError,
SMsgDlgInformation, SMsgDlgConfirm, 0);
IconIDs: array[TMsgDlgType] of PChar = (IDI_EXCLAMATION, IDI_HAND,
IDI_ASTERISK, IDI_QUESTION, nil);
ButtonNames: array[TMsgDlgBtn] of string = (
'Yes', 'No', 'OK', 'Cancel', 'Abort', 'Retry', 'Ignore', 'All', 'Help');
ButtonCaptions: array[TMsgDlgBtn] of Word = (
SMsgDlgYes, SMsgDlgNo, SMsgDlgOK, SMsgDlgCancel, SMsgDlgAbort,
SMsgDlgRetry, SMsgDlgIgnore, SMsgDlgAll, SMsgDlgHelp);
ModalResults: array[TMsgDlgBtn] of Integer = (
mrYes, mrNo, mrOk, mrCancel, mrAbort, mrRetry, mrIgnore, mrAll, 0);
var
DialogUnits: TPoint;
HorzMargin, VertMargin, HorzSpacing, VertSpacing, ButtonWidth,
ButtonHeight, ButtonSpacing, ButtonCount, ButtonGroupWidth,
IconTextWidth, IconTextHeight, X: Integer;
B, DefaultButton, CancelButton: TMsgDlgBtn;
IconID: PChar;
TextRect: TRect;
begin
Result := TMessageForm.CreateNew(Application, 1);
with Result do
begin
BorderStyle := bsDialog;
Canvas.Font := Font;
DialogUnits := GetAveCharSize(Canvas);
HorzMargin := MulDiv(mcHorzMargin, DialogUnits.X, 4);
VertMargin := MulDiv(mcVertMargin, DialogUnits.Y, 8);
HorzSpacing := MulDiv(mcHorzSpacing, DialogUnits.X, 4);
VertSpacing := MulDiv(mcVertSpacing, DialogUnits.Y, 8);
ButtonWidth := MulDiv(mcButtonWidth, DialogUnits.X, 4);
ButtonHeight := MulDiv(mcButtonHeight, DialogUnits.Y, 8);
ButtonSpacing := MulDiv(mcButtonSpacing, DialogUnits.X, 4);
SetRect(TextRect, 0, 0, Screen.Width div 2, 0);
DrawText(Canvas.Handle, PChar(Msg), -1, TextRect,
DT_CALCRECT or DT_WORDBREAK);
IconID := IconIDs[DlgType];
IconTextWidth := TextRect.Right;
IconTextHeight := TextRect.Bottom;
if IconID <> nil then
begin
Inc(IconTextWidth, 32 + HorzSpacing);
if IconTextHeight < 32 then IconTextHeight := 32;
end;
ButtonCount := 0;
for B := Low(TMsgDlgBtn) to High(TMsgDlgBtn) do
if B in Buttons then Inc(ButtonCount);
ButtonGroupWidth := 0;
if ButtonCount <> 0 then
ButtonGroupWidth := ButtonWidth * ButtonCount +
ButtonSpacing * (ButtonCount - 1);
ClientWidth := Max(IconTextWidth, ButtonGroupWidth) + HorzMargin * 2;
ClientHeight := IconTextHeight + ButtonHeight + VertSpacing +
VertMargin * 2;
Left := (Screen.Width div 2) - (Width div 2);
Top := (Screen.Height div 2) - (Height div 2);
if DlgType <> mtCustom then
Caption := LoadStr(Captions[DlgType]) else
Caption := Application.Title;
if IconID <> nil then
with TImage.Create(Result) do
begin
Name := 'Image';
Parent := Result;
Picture.Icon.Handle := LoadIcon(0, IconID);
SetBounds(HorzMargin, VertMargin, 32, 32);
end;
with TLabel.Create(Result) do
begin
Name := 'Message';
Parent := Result;
WordWrap := True;
Caption := Msg;
BoundsRect := TextRect;
SetBounds(IconTextWidth - TextRect.Right + HorzMargin, VertMargin,
TextRect.Right, TextRect.Bottom);
end;
if mbOk in Buttons then DefaultButton := mbOk else
if mbYes in Buttons then DefaultButton := mbYes else
DefaultButton := mbRetry;
if mbCancel in Buttons then CancelButton := mbCancel else
if mbNo in Buttons then CancelButton := mbNo else
CancelButton := mbOk;
X := (ClientWidth - ButtonGroupWidth) div 2;
for B := Low(TMsgDlgBtn) to High(TMsgDlgBtn) do
if B in Buttons then
with TButton.Create(Result) do
begin
Name := ButtonNames[B];
Parent := Result;
Caption := LoadStr(ButtonCaptions[B]);
ModalResult := ModalResults[B];
if B = DefaultButton then Default := True;
if B = CancelButton then Cancel := True;
SetBounds(X, IconTextHeight + VertMargin + VertSpacing,
ButtonWidth, ButtonHeight);
Inc(X, ButtonWidth + ButtonSpacing);
if B = mbHelp then
OnClick := TMessageForm(Result).HelpButtonClick;
end;
end;
end;
function MessageDlg(const Msg: string; DlgType: TMsgDlgType;
Buttons: TMsgDlgButtons; HelpCtx: Longint): Integer;
begin
Result := MessageDlgPos(Msg, DlgType, Buttons, HelpCtx, -1, -1);
end;
function MessageDlgPos(const Msg: string; DlgType: TMsgDlgType;
Buttons: TMsgDlgButtons; HelpCtx: Longint; X, Y: Integer): Integer;
begin
with CreateMessageDialog(Msg, DlgType, Buttons) do
try
HelpContext := HelpCtx;
if X >= 0 then Left := X;
if Y >= 0 then Top := Y;
Result := ShowModal;
finally
Free;
end;
end;
procedure ShowMessage(const Msg: string);
begin
ShowMessagePos(Msg, -1, -1);
end;
procedure ShowMessagePos(const Msg: string; X, Y: Integer);
begin
MessageDlgPos(Msg, mtCustom, [mbOK], 0, X, Y);
end;
{ Input dialog }
function InputQuery(const ACaption, APrompt: string;
var Value: string): Boolean;
var
Form: TForm;
Prompt: TLabel;
Edit: TEdit;
DialogUnits: TPoint;
ButtonTop, ButtonWidth, ButtonHeight: Integer;
begin
Result := False;
Form := TForm.Create(Application);
with Form do
try
Canvas.Font := Font;
DialogUnits := GetAveCharSize(Canvas);
BorderStyle := bsDialog;
Caption := ACaption;
ClientWidth := MulDiv(180, DialogUnits.X, 4);
ClientHeight := MulDiv(63, DialogUnits.Y, 8);
Position := poScreenCenter;
Prompt := TLabel.Create(Form);
with Prompt do
begin
Parent := Form;
AutoSize := True;
Left := MulDiv(8, DialogUnits.X, 4);
Top := MulDiv(8, DialogUnits.Y, 8);
Caption := APrompt;
end;
Edit := TEdit.Create(Form);
with Edit do
begin
Parent := Form;
Left := Prompt.Left;
Top := MulDiv(19, DialogUnits.Y, 8);
Width := MulDiv(164, DialogUnits.X, 4);
MaxLength := 255;
Text := Value;
SelectAll;
end;
ButtonTop := MulDiv(41, DialogUnits.Y, 8);
ButtonWidth := MulDiv(50, DialogUnits.X, 4);
ButtonHeight := MulDiv(14, DialogUnits.Y, 8);
with TButton.Create(Form) do
begin
Parent := Form;
Caption := LoadStr(SMsgDlgOK);
ModalResult := mrOk;
Default := True;
SetBounds(MulDiv(38, DialogUnits.X, 4), ButtonTop, ButtonWidth,
ButtonHeight);
end;
with TButton.Create(Form) do
begin
Parent := Form;
Caption := LoadStr(SMsgDlgCancel);
ModalResult := mrCancel;
Cancel := True;
SetBounds(MulDiv(92, DialogUnits.X, 4), ButtonTop, ButtonWidth,
ButtonHeight);
end;
if ShowModal = mrOk then
begin
Value := Edit.Text;
Result := True;
end;
finally
Form.Free;
end;
end;
function InputBox(const ACaption, APrompt, ADefault: string): string;
begin
Result := ADefault;
InputQuery(ACaption, APrompt, Result);
end;
{ Initialization and cleanup }
procedure InitGlobals;
var
AtomText: array[0..31] of Char;
begin
HelpMsg := RegisterWindowMessage(HelpMsgString);
FindMsg := RegisterWindowMessage(FindMsgString);
WndProcPtrAtom := GlobalAddAtom(StrFmt(AtomText,
'WndProcPtr%.8X%.8X', [HInstance, GetCurrentThreadID]));
end;
initialization
InitGlobals;
finalization
if WndProcPtrAtom <> 0 then GlobalDeleteAtom(WndProcPtrAtom);
end.