/units/RxVCLUtils.pas

https://bitbucket.org/stden/rxlib · Pascal · 3048 lines · 2382 code · 255 blank · 411 comment · 207 complexity · 12622ff4455c33e89948da180096c006 MD5 · raw file

Large files are truncated click here to view the full file

  1. {*******************************************************}
  2. { }
  3. { Delphi VCL Extensions (RX) }
  4. { }
  5. { Copyright (c) 1995, 1996 AO ROSNO }
  6. { Copyright (c) 1997, 1998 Master-Bank }
  7. { }
  8. { Patched by Polaris Software }
  9. { Revision and functions added by JB. }
  10. {*******************************************************}
  11. unit RxVCLUtils;
  12. {$I RX.INC}
  13. {$P+,W-,R-,V-}
  14. {$IFDEF RX_D6}
  15. {$WARN SYMBOL_PLATFORM OFF} // Polaris
  16. {$ENDIF}
  17. interface
  18. uses Windows, Classes, Graphics, Forms, Controls, Dialogs, Math, RxMaxMin;
  19. { Windows resources (bitmaps and icons) VCL-oriented routines }
  20. procedure DrawBitmapTransparent(Dest: TCanvas; DstX, DstY: Integer;
  21. Bitmap: TBitmap; TransparentColor: TColor);
  22. procedure DrawBitmapRectTransparent(Dest: TCanvas; DstX, DstY: Integer;
  23. SrcRect: TRect; Bitmap: TBitmap; TransparentColor: TColor);
  24. procedure StretchBitmapRectTransparent(Dest: TCanvas; DstX, DstY, DstW,
  25. DstH: Integer; SrcRect: TRect; Bitmap: TBitmap; TransparentColor: TColor);
  26. function MakeBitmap(ResID: PChar): TBitmap;
  27. function MakeBitmapID(ResID: Word): TBitmap;
  28. function MakeModuleBitmap(Module: THandle; ResID: PChar): TBitmap;
  29. function CreateTwoColorsBrushPattern(Color1, Color2: TColor): TBitmap;
  30. {$IFDEF RX_D9}inline;{$ENDIF}
  31. function CreateDisabledBitmapEx(FOriginal: TBitmap; OutlineColor, BackColor,
  32. HighlightColor, ShadowColor: TColor; DrawHighlight: Boolean): TBitmap;
  33. function CreateDisabledBitmap(FOriginal: TBitmap; OutlineColor: TColor): TBitmap;
  34. {$IFDEF RX_D9}inline;{$ENDIF}
  35. function ChangeBitmapColor(Bitmap: TBitmap; Color, NewColor: TColor): TBitmap;
  36. {$IFDEF RX_D9}inline;{$ENDIF}
  37. procedure AssignBitmapCell(Source: TGraphic; Dest: TBitmap; Cols, Rows,
  38. Index: Integer); {$IFDEF RX_D9}inline;{$ENDIF}
  39. {$IFNDEF VER80}
  40. procedure ImageListDrawDisabled(Images: TImageList; Canvas: TCanvas;
  41. X, Y, Index: Integer; HighlightColor, GrayColor: TColor; DrawHighlight: Boolean);
  42. {$ENDIF}
  43. function MakeIcon(ResID: PChar): TIcon;
  44. function MakeIconID(ResID: Word): TIcon;
  45. function MakeModuleIcon(Module: THandle; ResID: PChar): TIcon;
  46. function CreateBitmapFromIcon(Icon: TIcon; BackColor: TColor): TBitmap;
  47. {$IFNDEF VER80}
  48. function CreateIconFromBitmap(Bitmap: TBitmap; TransparentColor: TColor): TIcon;
  49. {$ENDIF}
  50. { Service routines }
  51. procedure NotImplemented;
  52. procedure ResourceNotFound(ResID: PChar);
  53. function PointInRect(const P: TPoint; const R: TRect): Boolean; {$IFDEF RX_D9}inline;{$ENDIF}
  54. function PointInPolyRgn(const P: TPoint; const Points: array of TPoint): Boolean;
  55. function PaletteColor(Color: TColor): Longint; {$IFDEF RX_D9}inline;{$ENDIF}
  56. function WidthOf(R: TRect): Integer; {$IFDEF RX_D9}inline;{$ENDIF}
  57. function HeightOf(R: TRect): Integer; {$IFDEF RX_D9}inline;{$ENDIF}
  58. procedure PaintInverseRect(const RectOrg, RectEnd: TPoint); {$IFDEF RX_D9}inline;{$ENDIF}
  59. procedure DrawInvertFrame(ScreenRect: TRect; Width: Integer); {$IFDEF RX_D9}inline;{$ENDIF}
  60. procedure CopyParentImage(Control: TControl; Dest: TCanvas);
  61. procedure Delay(MSecs: Longint);
  62. procedure CenterControl(Control: TControl);
  63. {$IFNDEF VER80}
  64. procedure ShowMDIClientEdge(ClientHandle: THandle; ShowEdge: Boolean);
  65. function MakeVariant(const Values: array of Variant): Variant;
  66. {$ENDIF}
  67. function CreateRotatedFont(Font: TFont; Angle: Integer): HFont;
  68. function MsgBox(const Caption, Text: string; Flags: Integer): Integer;
  69. function MsgDlg(const Msg: string; AType: TMsgDlgType;
  70. AButtons: TMsgDlgButtons; HelpCtx: Longint): Word;
  71. {$IFDEF CBUILDER}
  72. function FindPrevInstance(const MainFormClass: ShortString;
  73. const ATitle: string): HWnd;
  74. function ActivatePrevInstance(const MainFormClass: ShortString;
  75. const ATitle: string): Boolean;
  76. {$ELSE}
  77. function FindPrevInstance(const MainFormClass, ATitle: string): HWnd;
  78. function ActivatePrevInstance(const MainFormClass, ATitle: string): Boolean;
  79. {$ENDIF CBUILDER}
  80. function IsForegroundTask: Boolean;
  81. procedure MergeForm(AControl: TWinControl; AForm: TForm; Align: TAlign;
  82. Show: Boolean);
  83. function GetAveCharSize(Canvas: TCanvas): TPoint; {$IFDEF RX_D9}inline;{$ENDIF}
  84. function MinimizeText(const Text: string; Canvas: TCanvas;
  85. MaxWidth: Integer): string; {$IFDEF RX_D9}inline;{$ENDIF}
  86. procedure FreeUnusedOle;
  87. procedure Beep;
  88. function GetWindowsVersion: string;
  89. function LoadDLL(const LibName: string): THandle;
  90. function RegisterServer(const ModuleName: string): Boolean;
  91. {$IFDEF VER80}
  92. function IsLibrary: Boolean;
  93. {$ENDIF}
  94. { Gradient filling routine }
  95. type
  96. TFillDirection = (fdTopToBottom, fdBottomToTop, fdLeftToRight, fdRightToLeft);
  97. procedure GradientFillRect(Canvas: TCanvas; ARect: TRect; StartColor,
  98. EndColor: TColor; Direction: TFillDirection; Colors: Byte); {$IFDEF RX_D9}inline;{$ENDIF}
  99. { String routines }
  100. function GetEnvVar(const VarName: string): string;
  101. function AnsiUpperFirstChar(const S: string): string;
  102. function StringToPChar(var S: string): PChar;
  103. function StrPAlloc(const S: string): PChar;
  104. procedure SplitCommandLine(const CmdLine: string; var ExeName,
  105. Params: string);
  106. function DropT(const S: string): string;
  107. { Memory routines }
  108. function AllocMemo(Size: Longint): Pointer;
  109. function ReallocMemo(fpBlock: Pointer; Size: Longint): Pointer;
  110. procedure FreeMemo(var fpBlock: Pointer);
  111. function GetMemoSize(fpBlock: Pointer): Longint;
  112. function CompareMem(fpBlock1, fpBlock2: Pointer; Size: Cardinal): Boolean;
  113. {$IFNDEF RX_D5}
  114. procedure FreeAndNil(var Obj);
  115. {$ENDIF}
  116. { Manipulate huge pointers routines }
  117. procedure HugeInc(var HugePtr: Pointer; Amount: Longint);
  118. procedure HugeDec(var HugePtr: Pointer; Amount: Longint);
  119. function HugeOffset(HugePtr: Pointer; Amount: Longint): Pointer;
  120. procedure HugeMove(Base: Pointer; Dst, Src, Size: Longint);
  121. {$IFNDEF VER80}
  122. procedure HMemCpy(DstPtr, SrcPtr: Pointer; Amount: Longint);
  123. {$ELSE}
  124. procedure ZeroMemory(Ptr: Pointer; Length: Longint);
  125. procedure FillMemory(Ptr: Pointer; Length: Longint; Fill: Byte);
  126. {$ENDIF}
  127. { Standard Windows colors that are not defined by Delphi }
  128. const
  129. {$IFDEF VER80}
  130. clInfoBk = TColor($02E1FFFF);
  131. clNone = TColor($02FFFFFF);
  132. {$ENDIF}
  133. clCream = TColor($A6CAF0);
  134. clMoneyGreen = TColor($C0DCC0);
  135. clSkyBlue = TColor($FFFBF0);
  136. clMedGray = TColor($A4A0A0);
  137. { ModalResult constants }
  138. {$IFNDEF RX_D3}
  139. const
  140. mrNoToAll = mrAll + 1;
  141. mrYesToAll = mrNoToAll + 1;
  142. {$ENDIF}
  143. {$IFNDEF RX_D4}
  144. { Mouse Wheel message }
  145. {$IFNDEF VER80}
  146. {$IFDEF VER90}
  147. const
  148. WM_MOUSEWHEEL = $020A;
  149. WHEEL_DELTA = 120;
  150. WHEEL_PAGESCROLL = MAXDWORD;
  151. SM_MOUSEWHEELPRESENT = 75;
  152. MOUSEEVENTF_WHEEL = $0800;
  153. SPI_GETWHEELSCROLLLINES = 104;
  154. SPI_SETWHEELSCROLLLINES = 105;
  155. {$ENDIF}
  156. type
  157. TWMMouseWheel = record
  158. Msg: Cardinal;
  159. Keys: Word;
  160. Delta: Word;
  161. case Integer of
  162. 0: (
  163. XPos: Smallint;
  164. YPos: Smallint);
  165. 1: (
  166. Pos: TSmallPoint;
  167. Result: Longint);
  168. end;
  169. {$ENDIF}
  170. {$ENDIF RX_D4}
  171. { Cursor routines }
  172. const
  173. WaitCursor: TCursor = crHourGlass;
  174. procedure StartWait;
  175. procedure StopWait;
  176. function DefineCursor(Instance: THandle; ResID: PChar): TCursor;
  177. {$IFNDEF VER80}
  178. function LoadAniCursor(Instance: THandle; ResID: PChar): HCursor;
  179. {$ENDIF}
  180. { Windows API level routines }
  181. procedure StretchBltTransparent(DstDC: HDC; DstX, DstY, DstW, DstH: Integer;
  182. SrcDC: HDC; SrcX, SrcY, SrcW, SrcH: Integer; Palette: HPalette;
  183. TransparentColor: TColorRef); {$IFDEF RX_D9}inline;{$ENDIF}
  184. procedure DrawTransparentBitmap(DC: HDC; Bitmap: HBitmap;
  185. DstX, DstY: Integer; TransparentColor: TColorRef);
  186. function PaletteEntries(Palette: HPALETTE): Integer;
  187. function WindowClassName(Wnd: HWnd): string;
  188. function ScreenWorkArea: TRect;
  189. {$IFDEF VER80}
  190. procedure MoveWindowOrg(DC: HDC; DX, DY: Integer);
  191. {$ENDIF}
  192. procedure SwitchToWindow(Wnd: HWnd; Restore: Boolean);
  193. procedure ActivateWindow(Wnd: HWnd);
  194. procedure ShowWinNoAnimate(Handle: HWnd; CmdShow: Integer);
  195. procedure CenterWindow(Wnd: HWnd);
  196. procedure ShadeRect(DC: HDC; const Rect: TRect);
  197. procedure KillMessage(Wnd: HWnd; Msg: Cardinal);
  198. { Convert dialog units to pixels and backwards }
  199. function DialogUnitsToPixelsX(DlgUnits: Word): Word;
  200. function DialogUnitsToPixelsY(DlgUnits: Word): Word;
  201. function PixelsToDialogUnitsX(PixUnits: Word): Word;
  202. function PixelsToDialogUnitsY(PixUnits: Word): Word;
  203. { Grid drawing }
  204. type
  205. TVertAlignment = (vaTopJustify, vaCenter, vaBottomJustify);
  206. procedure WriteText(ACanvas: TCanvas; ARect: TRect; DX, DY: Integer;
  207. const Text: string; Alignment: TAlignment; WordWrap: Boolean
  208. {$IFDEF RX_D4}; ARightToLeft: Boolean = False {$ENDIF});
  209. procedure DrawCellText(Control: TCustomControl; ACol, ARow: Longint;
  210. const S: string; const ARect: TRect; Align: TAlignment;
  211. VertAlign: TVertAlignment); {$IFDEF RX_D4} overload; {$ENDIF} {$IFDEF RX_D9}inline;{$ENDIF}
  212. procedure DrawCellTextEx(Control: TCustomControl; ACol, ARow: Longint;
  213. const S: string; const ARect: TRect; Align: TAlignment;
  214. VertAlign: TVertAlignment; WordWrap: Boolean); {$IFDEF RX_D4} overload; {$ENDIF}
  215. {$IFDEF RX_D4}
  216. procedure DrawCellText(Control: TCustomControl; ACol, ARow: Longint;
  217. const S: string; const ARect: TRect; Align: TAlignment;
  218. VertAlign: TVertAlignment; ARightToLeft: Boolean); overload;
  219. procedure DrawCellTextEx(Control: TCustomControl; ACol, ARow: Longint;
  220. const S: string; const ARect: TRect; Align: TAlignment;
  221. VertAlign: TVertAlignment; WordWrap: Boolean; ARightToLeft: Boolean); overload;
  222. {$ENDIF}
  223. procedure DrawCellBitmap(Control: TCustomControl; ACol, ARow: Longint;
  224. Bmp: TGraphic; Rect: TRect);
  225. { TScreenCanvas }
  226. type
  227. TScreenCanvas = class(TCanvas)
  228. private
  229. FDeviceContext: HDC;
  230. protected
  231. procedure CreateHandle; override;
  232. public
  233. destructor Destroy; override;
  234. procedure SetOrigin(X, Y: Integer);
  235. procedure FreeHandle;
  236. end;
  237. {$IFDEF VER80}
  238. { TBits }
  239. TBits = class
  240. private
  241. FSize: Integer;
  242. FBits: Pointer;
  243. procedure SetSize(Value: Integer);
  244. procedure SetBit(Index: Integer; Value: Boolean);
  245. function GetBit(Index: Integer): Boolean;
  246. public
  247. destructor Destroy; override;
  248. function OpenBit: Integer;
  249. property Bits[Index: Integer]: Boolean read GetBit write SetBit; default;
  250. property Size: Integer read FSize write SetSize;
  251. end;
  252. { TMetafileCanvas }
  253. TMetafileCanvas = class(TCanvas)
  254. private
  255. FMetafile: TMetafile;
  256. public
  257. constructor Create(AMetafile: TMetafile; ReferenceDevice: HDC);
  258. destructor Destroy; override;
  259. property Metafile: TMetafile read FMetafile;
  260. end;
  261. { TResourceStream }
  262. TResourceStream = class(THandleStream)
  263. private
  264. FStartPos: LongInt;
  265. FEndPos: LongInt;
  266. protected
  267. constructor CreateFromPChar(Instance: THandle; ResName, ResType: PChar);
  268. public
  269. constructor Create(Instance: THandle; const ResName: string; ResType: PChar);
  270. constructor CreateFromID(Instance: THandle; ResID: Integer; ResType: PChar);
  271. destructor Destroy; override;
  272. function Seek(Offset: Longint; Origin: Word): Longint; override;
  273. function Write(const Buffer; Count: Longint): Longint; override;
  274. end;
  275. function GetCurrentDir: string;
  276. function SetCurrentDir(const Dir: string): Boolean;
  277. {$ENDIF}
  278. {$IFNDEF VER80}
  279. function CheckWin32(OK: Boolean): Boolean; { obsolete, use Win32Check }
  280. {$IFNDEF RX_D3}
  281. function Win32Check(RetVal: Bool): Bool;
  282. {$ENDIF}
  283. procedure RaiseWin32Error(ErrorCode: DWORD);
  284. {$ENDIF}
  285. {$IFNDEF RX_D3} { for Delphi 3.0 and previous versions compatibility }
  286. type
  287. TCustomForm = TForm;
  288. TDate = TDateTime;
  289. TTime = TDateTime;
  290. function ResStr(Ident: Cardinal): string;
  291. {$ELSE}
  292. function ResStr(const Ident: string): string;
  293. {$ENDIF RX_D3}
  294. {$IFNDEF RX_D4}
  295. type
  296. Longword = Longint;
  297. {$ENDIF}
  298. function TextSizeDC(DC: HDC; const Text: string): TSize;
  299. function TextSize(Wnd: HWnd; const Text: string): TSize;
  300. function TextToLinesDC(DC: HDC; const Text: string; MaxLen: Integer): string;
  301. function TextToLines(Wnd: HWnd; const Text: string; MaxLen: Integer): string;
  302. { force OS management}
  303. function LogOffWindows(Force: Boolean): Boolean;
  304. function PowerOffComputer(Force: Boolean): Boolean;
  305. function RebootComputer(Force: Boolean): Boolean;
  306. function ShutdownComputer(Force: Boolean): Boolean;
  307. { low level routine }
  308. function DownWindows(Flags: UINT): Boolean;
  309. implementation
  310. Uses SysUtils, Messages, Consts, RxConst, {$IFDEF RX_V110} SysConst, {$ENDIF}
  311. {$IFDEF RX_D6} RTLConsts, Variants, {$ENDIF} // Polaris
  312. {$IFDEF RX_D12} Character, {$ENDIF} RxStrUtils,
  313. {$IFDEF RX_D16} System.UITypes, {$ENDIF}
  314. {$IFNDEF VER80} CommCtrl, {$ELSE} Str16, {$ENDIF} RxResConst ;
  315. { force OS management}
  316. function DownWindows(Flags: UINT): Boolean;
  317. var
  318. TokenPriv: TTokenPrivileges;
  319. TokenHandle: THandle;
  320. begin
  321. Result := False;
  322. if (Win32Platform = VER_PLATFORM_WIN32_NT) and ((Flags and (EWX_POWEROFF or EWX_REBOOT or EWX_SHUTDOWN)) <> 0) then
  323. begin
  324. if OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES, TokenHandle) then
  325. if LookupPrivilegeValue(nil, 'SeShutdownPrivilege', TokenPriv.Privileges[0].LUID) then
  326. begin
  327. TokenPriv.PrivilegeCount := 1;
  328. TokenPriv.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
  329. if not AdjustTokenPrivileges(TokenHandle, False, TokenPriv, 0, TTokenPrivileges(nil^), DWORD(nil^)) then
  330. exit;
  331. end;
  332. end;
  333. Result := ExitWindowsEx(Flags, 0);
  334. end;
  335. const
  336. ForceFlag: array [Boolean] of UINT = (0, EWX_FORCE);
  337. function LogOffWindows(Force: Boolean): Boolean;
  338. begin
  339. Result := DownWindows(EWX_LOGOFF or ForceFlag[Force]);
  340. end;
  341. function PowerOffComputer(Force: Boolean): Boolean;
  342. begin
  343. Result := DownWindows(EWX_POWEROFF or ForceFlag[Force]);
  344. end;
  345. function RebootComputer(Force: Boolean): Boolean;
  346. begin
  347. Result := DownWindows(EWX_REBOOT or ForceFlag[Force]);
  348. end;
  349. function ShutdownComputer(Force: Boolean): Boolean;
  350. begin
  351. Result := DownWindows(EWX_SHUTDOWN or ForceFlag[Force]);
  352. end;
  353. { Exceptions }
  354. procedure ResourceNotFound(ResID: PChar);
  355. var
  356. S: string;
  357. begin
  358. {$IFDEF WIN64}
  359. if Int64Rec(ResID).Hi = 0 then S := IntToStr(Int64Rec(ResID).Lo)
  360. else S := StrPas(ResID);
  361. {$ELSE}
  362. if LongRec(ResID).Hi = 0 then S := IntToStr(LongRec(ResID).Lo)
  363. else S := StrPas(ResID);
  364. {$ENDIF}
  365. raise EResNotFound.CreateFmt(ResStr(SResNotFound), [S]);
  366. end;
  367. { Bitmaps }
  368. function MakeModuleBitmap(Module: THandle; ResID: PChar): TBitmap;
  369. {$IFDEF VER80}
  370. var
  371. S: TStream;
  372. {$ENDIF}
  373. begin
  374. Result := TBitmap.Create;
  375. try
  376. {$IFNDEF VER80}
  377. if Module <> 0 then
  378. begin
  379. {$IFDEF WIN64}
  380. if Int64Rec(ResID).Hi = 0 then
  381. Result.LoadFromResourceID(Module, Int64Rec(ResID).Lo)
  382. else
  383. Result.LoadFromResourceName(Module, StrPas(ResID));
  384. {$ELSE}
  385. if LongRec(ResID).Hi = 0 then
  386. Result.LoadFromResourceID(Module, LongRec(ResID).Lo)
  387. else
  388. Result.LoadFromResourceName(Module, StrPas(ResID));
  389. {$ENDIF}
  390. end
  391. else begin
  392. Result.Handle := LoadBitmap(Module, ResID);
  393. if Result.Handle = 0 then ResourceNotFound(ResID);
  394. end;
  395. {$ELSE}
  396. Result.Handle := LoadBitmap(Module, ResID);
  397. if Result.Handle = 0 then ResourceNotFound(ResID);
  398. {$ENDIF}
  399. except
  400. Result.Free;
  401. Result := nil;
  402. end;
  403. end;
  404. function MakeBitmap(ResID: PChar): TBitmap;
  405. begin
  406. Result := MakeModuleBitmap(hInstance, ResID);
  407. end;
  408. function MakeBitmapID(ResID: Word): TBitmap;
  409. begin
  410. Result := MakeModuleBitmap(hInstance, MakeIntResource(ResID));
  411. end;
  412. procedure AssignBitmapCell(Source: TGraphic; Dest: TBitmap; Cols, Rows,
  413. Index: Integer);
  414. var
  415. CellWidth, CellHeight: Integer;
  416. begin
  417. if (Source <> nil) and (Dest <> nil) then
  418. begin
  419. if Cols <= 0 then Cols := 1;
  420. if Rows <= 0 then Rows := 1;
  421. if Index < 0 then Index := 0;
  422. CellWidth := Source.Width div Cols;
  423. CellHeight := Source.Height div Rows;
  424. with Dest do
  425. begin
  426. Width := CellWidth; Height := CellHeight;
  427. end;
  428. if Source is TBitmap then
  429. begin
  430. Dest.Canvas.CopyRect(Bounds(0, 0, CellWidth, CellHeight),
  431. TBitmap(Source).Canvas, Bounds((Index mod Cols) * CellWidth,
  432. (Index div Cols) * CellHeight, CellWidth, CellHeight));
  433. {$IFDEF RX_D3}
  434. Dest.TransparentColor := TBitmap(Source).TransparentColor;
  435. {$ENDIF RX_D3}
  436. end
  437. else
  438. begin
  439. Dest.Canvas.Brush.Color := clSilver;
  440. Dest.Canvas.FillRect(Bounds(0, 0, CellWidth, CellHeight));
  441. Dest.Canvas.Draw(-(Index mod Cols) * CellWidth,
  442. -(Index div Cols) * CellHeight, Source);
  443. end;
  444. {$IFDEF RX_D3}
  445. Dest.Transparent := Source.Transparent;
  446. {$ENDIF RX_D3}
  447. end;
  448. end;
  449. type
  450. TParentControl = class(TWinControl);
  451. procedure CopyParentImage(Control: TControl; Dest: TCanvas);
  452. var
  453. I, Count, X, Y, SaveIndex: Integer;
  454. DC: HDC;
  455. R, SelfR, CtlR: TRect;
  456. begin
  457. if (Control = nil) or (Control.Parent = nil) then Exit;
  458. Count := Control.Parent.ControlCount;
  459. DC := Dest.Handle;
  460. {$IFNDEF VER80}
  461. with Control.Parent do ControlState := ControlState + [csPaintCopy];
  462. try
  463. {$ENDIF}
  464. with Control do
  465. begin
  466. SelfR := Bounds(Left, Top, Width, Height);
  467. X := -Left; Y := -Top;
  468. end;
  469. { Copy parent control image }
  470. SaveIndex := SaveDC(DC);
  471. try
  472. SetViewportOrgEx(DC, X, Y, nil);
  473. IntersectClipRect(DC, 0, 0, Control.Parent.ClientWidth,
  474. Control.Parent.ClientHeight);
  475. with TParentControl(Control.Parent) do
  476. begin
  477. Perform(WM_ERASEBKGND, DC, 0);
  478. PaintWindow(DC);
  479. end;
  480. finally
  481. RestoreDC(DC, SaveIndex);
  482. end;
  483. { Copy images of graphic controls }
  484. for I := 0 to Count - 1 do
  485. begin
  486. if Control.Parent.Controls[I] = Control then Break
  487. else if (Control.Parent.Controls[I] <> nil) and (Control.Parent.Controls[I] is TGraphicControl) then
  488. begin
  489. with TGraphicControl(Control.Parent.Controls[I]) do
  490. begin
  491. CtlR := Bounds(Left, Top, Width, Height);
  492. if Bool(IntersectRect(R, SelfR, CtlR)) and Visible then
  493. begin
  494. {$IFNDEF VER80}
  495. ControlState := ControlState + [csPaintCopy];
  496. {$ENDIF}
  497. SaveIndex := SaveDC(DC);
  498. try
  499. SaveIndex := SaveDC(DC);
  500. SetViewportOrgEx(DC, Left + X, Top + Y, nil);
  501. IntersectClipRect(DC, 0, 0, Width, Height);
  502. Perform(WM_PAINT, DC, 0);
  503. finally
  504. RestoreDC(DC, SaveIndex);
  505. {$IFNDEF VER80}
  506. ControlState := ControlState - [csPaintCopy];
  507. {$ENDIF}
  508. end;
  509. end;
  510. end;
  511. end;
  512. end;
  513. {$IFNDEF VER80}
  514. finally
  515. with Control.Parent do ControlState := ControlState - [csPaintCopy];
  516. end;
  517. {$ENDIF}
  518. end;
  519. { Transparent bitmap }
  520. procedure StretchBltTransparent(DstDC: HDC; DstX, DstY, DstW, DstH: Integer;
  521. SrcDC: HDC; SrcX, SrcY, SrcW, SrcH: Integer; Palette: HPalette;
  522. TransparentColor: TColorRef);
  523. var
  524. Color: TColorRef;
  525. bmAndBack, bmAndObject, bmAndMem, bmSave: HBitmap;
  526. bmBackOld, bmObjectOld, bmMemOld, bmSaveOld: HBitmap;
  527. MemDC, BackDC, ObjectDC, SaveDC: HDC;
  528. palDst, palMem, palSave, palObj: HPalette;
  529. begin
  530. { Create some DCs to hold temporary data }
  531. BackDC := CreateCompatibleDC(DstDC);
  532. ObjectDC := CreateCompatibleDC(DstDC);
  533. MemDC := CreateCompatibleDC(DstDC);
  534. SaveDC := CreateCompatibleDC(DstDC);
  535. { Create a bitmap for each DC }
  536. bmAndObject := CreateBitmap(SrcW, SrcH, 1, 1, nil);
  537. bmAndBack := CreateBitmap(SrcW, SrcH, 1, 1, nil);
  538. bmAndMem := CreateCompatibleBitmap(DstDC, DstW, DstH);
  539. bmSave := CreateCompatibleBitmap(DstDC, SrcW, SrcH);
  540. { Each DC must select a bitmap object to store pixel data }
  541. bmBackOld := SelectObject(BackDC, bmAndBack);
  542. bmObjectOld := SelectObject(ObjectDC, bmAndObject);
  543. bmMemOld := SelectObject(MemDC, bmAndMem);
  544. bmSaveOld := SelectObject(SaveDC, bmSave);
  545. { Select palette }
  546. palDst := 0; palMem := 0; palSave := 0; palObj := 0;
  547. if Palette <> 0 then
  548. begin
  549. palDst := SelectPalette(DstDC, Palette, True);
  550. RealizePalette(DstDC);
  551. palSave := SelectPalette(SaveDC, Palette, False);
  552. RealizePalette(SaveDC);
  553. palObj := SelectPalette(ObjectDC, Palette, False);
  554. RealizePalette(ObjectDC);
  555. palMem := SelectPalette(MemDC, Palette, True);
  556. RealizePalette(MemDC);
  557. end;
  558. { Set proper mapping mode }
  559. SetMapMode(SrcDC, GetMapMode(DstDC));
  560. SetMapMode(SaveDC, GetMapMode(DstDC));
  561. { Save the bitmap sent here }
  562. BitBlt(SaveDC, 0, 0, SrcW, SrcH, SrcDC, SrcX, SrcY, SRCCOPY);
  563. { Set the background color of the source DC to the color, }
  564. { contained in the parts of the bitmap that should be transparent }
  565. Color := SetBkColor(SaveDC, PaletteColor(TransparentColor));
  566. { Create the object mask for the bitmap by performing a BitBlt() }
  567. { from the source bitmap to a monochrome bitmap }
  568. BitBlt(ObjectDC, 0, 0, SrcW, SrcH, SaveDC, 0, 0, SRCCOPY);
  569. { Set the background color of the source DC back to the original }
  570. SetBkColor(SaveDC, Color);
  571. { Create the inverse of the object mask }
  572. BitBlt(BackDC, 0, 0, SrcW, SrcH, ObjectDC, 0, 0, NOTSRCCOPY);
  573. { Copy the background of the main DC to the destination }
  574. BitBlt(MemDC, 0, 0, DstW, DstH, DstDC, DstX, DstY, SRCCOPY);
  575. { Mask out the places where the bitmap will be placed }
  576. StretchBlt(MemDC, 0, 0, DstW, DstH, ObjectDC, 0, 0, SrcW, SrcH, SRCAND);
  577. { Mask out the transparent colored pixels on the bitmap }
  578. BitBlt(SaveDC, 0, 0, SrcW, SrcH, BackDC, 0, 0, SRCAND);
  579. { XOR the bitmap with the background on the destination DC }
  580. StretchBlt(MemDC, 0, 0, DstW, DstH, SaveDC, 0, 0, SrcW, SrcH, SRCPAINT);
  581. { Copy the destination to the screen }
  582. BitBlt(DstDC, DstX, DstY, DstW, DstH, MemDC, 0, 0,
  583. SRCCOPY);
  584. { Restore palette }
  585. if Palette <> 0 then
  586. begin
  587. SelectPalette(MemDC, palMem, False);
  588. SelectPalette(ObjectDC, palObj, False);
  589. SelectPalette(SaveDC, palSave, False);
  590. SelectPalette(DstDC, palDst, True);
  591. end;
  592. { Delete the memory bitmaps }
  593. DeleteObject(SelectObject(BackDC, bmBackOld));
  594. DeleteObject(SelectObject(ObjectDC, bmObjectOld));
  595. DeleteObject(SelectObject(MemDC, bmMemOld));
  596. DeleteObject(SelectObject(SaveDC, bmSaveOld));
  597. { Delete the memory DCs }
  598. DeleteDC(MemDC);
  599. DeleteDC(BackDC);
  600. DeleteDC(ObjectDC);
  601. DeleteDC(SaveDC);
  602. end;
  603. procedure DrawTransparentBitmapRect(DC: HDC; Bitmap: HBitmap; DstX, DstY,
  604. DstW, DstH: Integer; SrcRect: TRect; TransparentColor: TColorRef);
  605. var
  606. hdcTemp: HDC;
  607. begin
  608. hdcTemp := CreateCompatibleDC(DC);
  609. try
  610. SelectObject(hdcTemp, Bitmap);
  611. with SrcRect do
  612. StretchBltTransparent(DC, DstX, DstY, DstW, DstH, hdcTemp,
  613. Left, Top, Right - Left, Bottom - Top, 0, TransparentColor);
  614. finally
  615. DeleteDC(hdcTemp);
  616. end;
  617. end;
  618. procedure DrawTransparentBitmap(DC: HDC; Bitmap: HBitmap;
  619. DstX, DstY: Integer; TransparentColor: TColorRef);
  620. var
  621. BM: {$IFNDEF VER80} Windows.TBitmap {$ELSE} WinTypes.TBitmap {$ENDIF};
  622. begin
  623. GetObject(Bitmap, SizeOf(BM), @BM);
  624. DrawTransparentBitmapRect(DC, Bitmap, DstX, DstY, BM.bmWidth, BM.bmHeight,
  625. Rect(0, 0, BM.bmWidth, BM.bmHeight), TransparentColor);
  626. end;
  627. procedure StretchBitmapTransparent(Dest: TCanvas; Bitmap: TBitmap;
  628. TransparentColor: TColor; DstX, DstY, DstW, DstH, SrcX, SrcY,
  629. SrcW, SrcH: Integer);
  630. var
  631. CanvasChanging: TNotifyEvent;
  632. begin
  633. if DstW <= 0 then DstW := Bitmap.Width;
  634. if DstH <= 0 then DstH := Bitmap.Height;
  635. if (SrcW <= 0) or (SrcH <= 0) then
  636. begin
  637. SrcX := 0; SrcY := 0;
  638. SrcW := Bitmap.Width;
  639. SrcH := Bitmap.Height;
  640. end;
  641. if not Bitmap.Monochrome then
  642. SetStretchBltMode(Dest.Handle, STRETCH_DELETESCANS);
  643. CanvasChanging := Bitmap.Canvas.OnChanging;
  644. {$IFDEF RX_D3}
  645. Bitmap.Canvas.Lock;
  646. {$ENDIF}
  647. try
  648. Bitmap.Canvas.OnChanging := nil;
  649. if TransparentColor = clNone then
  650. begin
  651. StretchBlt(Dest.Handle, DstX, DstY, DstW, DstH, Bitmap.Canvas.Handle,
  652. SrcX, SrcY, SrcW, SrcH, Dest.CopyMode);
  653. end
  654. else
  655. begin
  656. {$IFDEF RX_D3}
  657. if TransparentColor = clDefault then
  658. TransparentColor := Bitmap.Canvas.Pixels[0, Bitmap.Height - 1];
  659. {$ENDIF}
  660. if Bitmap.Monochrome then TransparentColor := clWhite
  661. else TransparentColor := ColorToRGB(TransparentColor);
  662. StretchBltTransparent(Dest.Handle, DstX, DstY, DstW, DstH,
  663. Bitmap.Canvas.Handle, SrcX, SrcY, SrcW, SrcH, Bitmap.Palette,
  664. TransparentColor);
  665. end;
  666. finally
  667. Bitmap.Canvas.OnChanging := CanvasChanging;
  668. {$IFDEF RX_D3}
  669. Bitmap.Canvas.Unlock;
  670. {$ENDIF}
  671. end;
  672. end;
  673. procedure StretchBitmapRectTransparent(Dest: TCanvas; DstX, DstY,
  674. DstW, DstH: Integer; SrcRect: TRect; Bitmap: TBitmap;
  675. TransparentColor: TColor);
  676. begin
  677. with SrcRect do
  678. StretchBitmapTransparent(Dest, Bitmap, TransparentColor,
  679. DstX, DstY, DstW, DstH, Left, Top, Right - Left, Bottom - Top);
  680. end;
  681. procedure DrawBitmapRectTransparent(Dest: TCanvas; DstX, DstY: Integer;
  682. SrcRect: TRect; Bitmap: TBitmap; TransparentColor: TColor);
  683. begin
  684. with SrcRect do
  685. StretchBitmapTransparent(Dest, Bitmap, TransparentColor,
  686. DstX, DstY, Right - Left, Bottom - Top, Left, Top, Right - Left,
  687. Bottom - Top);
  688. end;
  689. procedure DrawBitmapTransparent(Dest: TCanvas; DstX, DstY: Integer;
  690. Bitmap: TBitmap; TransparentColor: TColor);
  691. begin
  692. StretchBitmapTransparent(Dest, Bitmap, TransparentColor, DstX, DstY,
  693. Bitmap.Width, Bitmap.Height, 0, 0, Bitmap.Width, Bitmap.Height);
  694. end;
  695. { ChangeBitmapColor. This function create new TBitmap object.
  696. You must destroy it outside by calling TBitmap.Free method. }
  697. function ChangeBitmapColor(Bitmap: TBitmap; Color, NewColor: TColor): TBitmap;
  698. var
  699. R: TRect;
  700. begin
  701. Result := TBitmap.Create;
  702. try
  703. with Result do
  704. begin
  705. Height := Bitmap.Height;
  706. Width := Bitmap.Width;
  707. R := Bounds(0, 0, Width, Height);
  708. Canvas.Brush.Color := NewColor;
  709. Canvas.FillRect(R);
  710. Canvas.BrushCopy(R, Bitmap, R, Color);
  711. end;
  712. except
  713. Result.Free;
  714. raise;
  715. end;
  716. end;
  717. { CreateDisabledBitmap. Creating TBitmap object with disable button glyph
  718. image. You must destroy it outside by calling TBitmap.Free method. }
  719. const
  720. ROP_DSPDxax = $00E20746;
  721. function CreateDisabledBitmapEx(FOriginal: TBitmap; OutlineColor, BackColor,
  722. HighlightColor, ShadowColor: TColor; DrawHighlight: Boolean): TBitmap;
  723. var
  724. MonoBmp: TBitmap;
  725. IRect: TRect;
  726. begin
  727. IRect := Rect(0, 0, FOriginal.Width, FOriginal.Height);
  728. Result := TBitmap.Create;
  729. try
  730. Result.Width := FOriginal.Width;
  731. Result.Height := FOriginal.Height;
  732. MonoBmp := TBitmap.Create;
  733. try
  734. with MonoBmp do
  735. begin
  736. Width := FOriginal.Width;
  737. Height := FOriginal.Height;
  738. Canvas.CopyRect(IRect, FOriginal.Canvas, IRect);
  739. {$IFDEF RX_D3}
  740. HandleType := bmDDB;
  741. {$ENDIF}
  742. Canvas.Brush.Color := OutlineColor;
  743. if Monochrome then
  744. begin
  745. Canvas.Font.Color := clWhite;
  746. Monochrome := False;
  747. Canvas.Brush.Color := clWhite;
  748. end;
  749. Monochrome := True;
  750. end;
  751. with Result.Canvas do
  752. begin
  753. Brush.Color := BackColor;
  754. FillRect(IRect);
  755. if DrawHighlight then
  756. begin
  757. Brush.Color := HighlightColor;
  758. SetTextColor(Handle, clBlack);
  759. SetBkColor(Handle, clWhite);
  760. BitBlt(Handle, 1, 1, WidthOf(IRect), HeightOf(IRect),
  761. MonoBmp.Canvas.Handle, 0, 0, ROP_DSPDxax);
  762. end;
  763. Brush.Color := ShadowColor;
  764. SetTextColor(Handle, clBlack);
  765. SetBkColor(Handle, clWhite);
  766. BitBlt(Handle, 0, 0, WidthOf(IRect), HeightOf(IRect),
  767. MonoBmp.Canvas.Handle, 0, 0, ROP_DSPDxax);
  768. end;
  769. finally
  770. MonoBmp.Free;
  771. end;
  772. except
  773. Result.Free;
  774. raise;
  775. end;
  776. end;
  777. function CreateDisabledBitmap(FOriginal: TBitmap; OutlineColor: TColor): TBitmap;
  778. begin
  779. Result := CreateDisabledBitmapEx(FOriginal, OutlineColor,
  780. clBtnFace, clBtnHighlight, clBtnShadow, True);
  781. end;
  782. {$IFNDEF VER80}
  783. procedure ImageListDrawDisabled(Images: TImageList; Canvas: TCanvas;
  784. X, Y, Index: Integer; HighlightColor, GrayColor: TColor; DrawHighlight: Boolean);
  785. var
  786. Bmp: TBitmap;
  787. SaveColor: TColor;
  788. begin
  789. SaveColor := Canvas.Brush.Color;
  790. Bmp := TBitmap.Create;
  791. try
  792. Bmp.Width := Images.Width;
  793. Bmp.Height := Images.Height;
  794. with Bmp.Canvas do
  795. begin
  796. Brush.Color := clWhite;
  797. FillRect(Rect(0, 0, Images.Width, Images.Height));
  798. ImageList_Draw(Images.Handle, Index, Handle, 0, 0, ILD_MASK);
  799. end;
  800. Bmp.Monochrome := True;
  801. if DrawHighlight then
  802. begin
  803. Canvas.Brush.Color := HighlightColor;
  804. SetTextColor(Canvas.Handle, clWhite);
  805. SetBkColor(Canvas.Handle, clBlack);
  806. BitBlt(Canvas.Handle, X + 1, Y + 1, Images.Width,
  807. Images.Height, Bmp.Canvas.Handle, 0, 0, ROP_DSPDxax);
  808. end;
  809. Canvas.Brush.Color := GrayColor;
  810. SetTextColor(Canvas.Handle, clWhite);
  811. SetBkColor(Canvas.Handle, clBlack);
  812. BitBlt(Canvas.Handle, X, Y, Images.Width,
  813. Images.Height, Bmp.Canvas.Handle, 0, 0, ROP_DSPDxax);
  814. finally
  815. Bmp.Free;
  816. Canvas.Brush.Color := SaveColor;
  817. end;
  818. end;
  819. {$ENDIF}
  820. { Brush Pattern }
  821. function CreateTwoColorsBrushPattern(Color1, Color2: TColor): TBitmap;
  822. var
  823. X, Y: Integer;
  824. begin
  825. Result := TBitmap.Create;
  826. Result.Width := 8;
  827. Result.Height := 8;
  828. with Result.Canvas do
  829. begin
  830. Brush.Style := bsSolid;
  831. Brush.Color := Color1;
  832. FillRect(Rect(0, 0, Result.Width, Result.Height));
  833. for Y := 0 to 7 do
  834. for X := 0 to 7 do
  835. if (Y mod 2) = (X mod 2) then { toggles between even/odd pixles }
  836. Pixels[X, Y] := Color2; { on even/odd rows }
  837. end;
  838. end;
  839. { Icons }
  840. function MakeIcon(ResID: PChar): TIcon;
  841. begin
  842. Result := MakeModuleIcon(hInstance, ResID);
  843. end;
  844. function MakeIconID(ResID: Word): TIcon;
  845. begin
  846. Result := MakeModuleIcon(hInstance, MakeIntResource(ResID));
  847. end;
  848. function MakeModuleIcon(Module: THandle; ResID: PChar): TIcon;
  849. begin
  850. Result := TIcon.Create;
  851. Result.Handle := LoadIcon(Module, ResID);
  852. if Result.Handle = 0 then
  853. begin
  854. Result.Free;
  855. Result := nil;
  856. end;
  857. end;
  858. { Create TBitmap object from TIcon }
  859. function CreateBitmapFromIcon(Icon: TIcon; BackColor: TColor): TBitmap;
  860. var
  861. IWidth, IHeight: Integer;
  862. begin
  863. IWidth := Icon.Width;
  864. IHeight := Icon.Height;
  865. Result := TBitmap.Create;
  866. try
  867. Result.Width := IWidth;
  868. Result.Height := IHeight;
  869. with Result.Canvas do
  870. begin
  871. Brush.Color := BackColor;
  872. FillRect(Rect(0, 0, IWidth, IHeight));
  873. Draw(0, 0, Icon);
  874. end;
  875. {$IFDEF RX_D3}
  876. Result.TransparentColor := BackColor;
  877. Result.Transparent := True;
  878. {$ENDIF}
  879. except
  880. Result.Free;
  881. raise;
  882. end;
  883. end;
  884. {$IFNDEF VER80}
  885. function CreateIconFromBitmap(Bitmap: TBitmap; TransparentColor: TColor): TIcon;
  886. begin
  887. with TImageList.CreateSize(Bitmap.Width, Bitmap.Height) do
  888. try
  889. {$IFDEF RX_D3}
  890. if TransparentColor = clDefault then
  891. TransparentColor := Bitmap.TransparentColor;
  892. {$ENDIF}
  893. AllocBy := 1;
  894. AddMasked(Bitmap, TransparentColor);
  895. Result := TIcon.Create;
  896. try
  897. GetIcon(0, Result);
  898. except
  899. Result.Free;
  900. raise;
  901. end;
  902. finally
  903. Free;
  904. end;
  905. end;
  906. {$ENDIF}
  907. { Dialog units }
  908. function DialogUnitsToPixelsX(DlgUnits: Word): Word;
  909. begin
  910. Result := (DlgUnits * LoWord(GetDialogBaseUnits)) div 4;
  911. end;
  912. function DialogUnitsToPixelsY(DlgUnits: Word): Word;
  913. begin
  914. Result := (DlgUnits * HiWord(GetDialogBaseUnits)) div 8;
  915. end;
  916. function PixelsToDialogUnitsX(PixUnits: Word): Word;
  917. begin
  918. Result := PixUnits * 4 div LoWord(GetDialogBaseUnits);
  919. end;
  920. function PixelsToDialogUnitsY(PixUnits: Word): Word;
  921. begin
  922. Result := PixUnits * 8 div HiWord(GetDialogBaseUnits);
  923. end;
  924. { Service routines }
  925. type
  926. THack = class(TCustomControl);
  927. function LoadDLL(const LibName: string): THandle;
  928. var
  929. ErrMode: Cardinal;
  930. {$IFDEF VER80}
  931. P: array[0..255] of Char;
  932. {$ENDIF}
  933. begin
  934. ErrMode := SetErrorMode(SEM_NOOPENFILEERRORBOX);
  935. {$IFNDEF VER80}
  936. Result := LoadLibrary(PChar(LibName));
  937. {$ELSE}
  938. Result := LoadLibrary(StrPCopy(P, LibName));
  939. {$ENDIF}
  940. SetErrorMode(ErrMode);
  941. if Result < HINSTANCE_ERROR then
  942. {$IFNDEF VER80}
  943. {$IFDEF RX_D6} // Polaris
  944. RaiseLastOSError;
  945. {$ELSE}
  946. Win32Check(False);
  947. {$ENDIF}
  948. {$ELSE}
  949. raise EOutOfResources.CreateResFmt(SLoadLibError, [LibName]);
  950. {$ENDIF}
  951. end;
  952. function RegisterServer(const ModuleName: string): Boolean;
  953. { RegisterServer procedure written by Vladimir Gaitanoff, 2:50/430.2 }
  954. type
  955. TProc = procedure;
  956. var
  957. Handle: THandle;
  958. DllRegServ: Pointer;
  959. begin
  960. Result := False;
  961. Handle := LoadDLL(ModuleName);
  962. try
  963. DllRegServ := GetProcAddress(Handle, 'DllRegisterServer');
  964. if Assigned(DllRegServ) then
  965. begin
  966. TProc(DllRegServ);
  967. Result := True;
  968. end;
  969. finally
  970. FreeLibrary(Handle);
  971. end;
  972. end;
  973. procedure Beep;
  974. begin
  975. MessageBeep(0);
  976. end;
  977. procedure FreeUnusedOle;
  978. begin
  979. {$IFNDEF VER80}
  980. FreeLibrary(GetModuleHandle('OleAut32'));
  981. {$ENDIF}
  982. end;
  983. procedure NotImplemented;
  984. begin
  985. Screen.Cursor := crDefault;
  986. MessageDlg(RxLoadStr(SNotImplemented), mtInformation, [mbOk], 0);
  987. Abort;
  988. end;
  989. {$IFDEF VER80}
  990. procedure MoveWindowOrg(DC: HDC; DX, DY: Integer);
  991. var
  992. P: TPoint;
  993. begin
  994. GetWindowOrgEx(DC, @P);
  995. SetWindowOrgEx(DC, P.X - DX, P.Y - DY, nil);
  996. end;
  997. function IsLibrary: Boolean;
  998. begin
  999. Result := (PrefixSeg = 0);
  1000. end;
  1001. {$ENDIF}
  1002. procedure PaintInverseRect(const RectOrg, RectEnd: TPoint);
  1003. var
  1004. DC: HDC;
  1005. R: TRect;
  1006. begin
  1007. DC := GetDC(0);
  1008. try
  1009. R := Rect(RectOrg.X, RectOrg.Y, RectEnd.X, RectEnd.Y);
  1010. InvertRect(DC, R);
  1011. finally
  1012. ReleaseDC(0, DC);
  1013. end;
  1014. end;
  1015. procedure DrawInvertFrame(ScreenRect: TRect; Width: Integer);
  1016. var
  1017. DC: HDC;
  1018. I: Integer;
  1019. begin
  1020. DC := GetDC(0);
  1021. try
  1022. for I := 1 to Width do
  1023. begin
  1024. DrawFocusRect(DC, ScreenRect);
  1025. InflateRect(ScreenRect, -1, -1);
  1026. end;
  1027. finally
  1028. ReleaseDC(0, DC);
  1029. end;
  1030. end;
  1031. function WidthOf(R: TRect): Integer;
  1032. begin
  1033. Result := R.Right - R.Left;
  1034. end;
  1035. function HeightOf(R: TRect): Integer;
  1036. begin
  1037. Result := R.Bottom - R.Top;
  1038. end;
  1039. function PointInRect(const P: TPoint; const R: TRect): Boolean;
  1040. begin
  1041. with R do
  1042. Result := (Left <= P.X) and (Top <= P.Y) and
  1043. (Right >= P.X) and (Bottom >= P.Y);
  1044. end;
  1045. function PointInPolyRgn(const P: TPoint; const Points: array of TPoint): Boolean;
  1046. type
  1047. PPoints = ^TPoints;
  1048. TPoints = array[0..0] of TPoint;
  1049. var
  1050. Rgn: HRgn;
  1051. begin
  1052. Rgn := CreatePolygonRgn(PPoints(@Points)^, High(Points) + 1, WINDING);
  1053. try
  1054. Result := PtInRegion(Rgn, P.X, P.Y);
  1055. finally
  1056. DeleteObject(Rgn);
  1057. end;
  1058. end;
  1059. function PaletteColor(Color: TColor): Longint;
  1060. begin
  1061. Result := ColorToRGB(Color) or PaletteMask;
  1062. end;
  1063. procedure KillMessage(Wnd: HWnd; Msg: Cardinal);
  1064. { Delete the requested message from the queue, but throw back }
  1065. { any WM_QUIT msgs that PeekMessage may also return. }
  1066. { Copied from DbGrid.pas }
  1067. var
  1068. M: TMsg;
  1069. begin
  1070. M.Message := 0;
  1071. if PeekMessage(M, Wnd, Msg, Msg, PM_REMOVE) and (M.Message = WM_QUIT) then
  1072. PostQuitMessage(M.WParam);
  1073. end;
  1074. function CreateRotatedFont(Font: TFont; Angle: Integer): HFont;
  1075. var
  1076. LogFont: TLogFont;
  1077. begin
  1078. FillChar(LogFont, SizeOf(LogFont), 0);
  1079. with LogFont do begin
  1080. lfHeight := Font.Height;
  1081. lfWidth := 0;
  1082. lfEscapement := Angle * 10;
  1083. lfOrientation := 0;
  1084. if fsBold in Font.Style then lfWeight := FW_BOLD
  1085. else lfWeight := FW_NORMAL;
  1086. lfItalic := Ord(fsItalic in Font.Style);
  1087. lfUnderline := Ord(fsUnderline in Font.Style);
  1088. lfStrikeOut := Byte(fsStrikeOut in Font.Style);
  1089. {$IFDEF RX_D3}
  1090. lfCharSet := Byte(Font.Charset);
  1091. if AnsiCompareText(Font.Name, 'Default') = 0 then
  1092. StrPCopy(lfFaceName, string(DefFontData.Name))
  1093. else
  1094. StrPCopy(lfFaceName, Font.Name);
  1095. {$ELSE}
  1096. {$IFDEF VER93}
  1097. lfCharSet := Byte(Font.Charset);
  1098. {$ELSE}
  1099. lfCharSet := DEFAULT_CHARSET;
  1100. {$ENDIF}
  1101. StrPCopy(lfFaceName, Font.Name);
  1102. {$ENDIF}
  1103. lfQuality := DEFAULT_QUALITY;
  1104. lfOutPrecision := OUT_DEFAULT_PRECIS;
  1105. lfClipPrecision := CLIP_DEFAULT_PRECIS;
  1106. case Font.Pitch of
  1107. fpVariable: lfPitchAndFamily := VARIABLE_PITCH;
  1108. fpFixed: lfPitchAndFamily := FIXED_PITCH;
  1109. else lfPitchAndFamily := DEFAULT_PITCH;
  1110. end;
  1111. end;
  1112. Result := CreateFontIndirect(LogFont);
  1113. end;
  1114. procedure Delay(MSecs: Longint);
  1115. var
  1116. FirstTickCount, Now: Longint;
  1117. begin
  1118. FirstTickCount := GetTickCount;
  1119. repeat
  1120. Application.ProcessMessages;
  1121. { allowing access to other controls, etc. }
  1122. Now := GetTickCount;
  1123. until (Now - FirstTickCount >= MSecs) or (Now < FirstTickCount);
  1124. end;
  1125. function PaletteEntries(Palette: HPALETTE): Integer;
  1126. begin
  1127. GetObject(Palette, SizeOf(Integer), @Result);
  1128. end;
  1129. procedure CenterControl(Control: TControl);
  1130. var
  1131. X, Y: Integer;
  1132. begin
  1133. X := Control.Left;
  1134. Y := Control.Top;
  1135. if Control is TForm then
  1136. begin
  1137. with Control do
  1138. begin
  1139. if (TForm(Control).FormStyle = fsMDIChild) and (Application.MainForm <> nil) then
  1140. begin
  1141. X := (Application.MainForm.ClientWidth - Width) div 2;
  1142. Y := (Application.MainForm.ClientHeight - Height) div 2;
  1143. end
  1144. else
  1145. begin
  1146. X := (Screen.Width - Width) div 2;
  1147. Y := (Screen.Height - Height) div 2;
  1148. end;
  1149. end;
  1150. end
  1151. else if Control.Parent <> nil then
  1152. begin
  1153. with Control do
  1154. begin
  1155. Parent.HandleNeeded;
  1156. X := (Parent.ClientWidth - Width) div 2;
  1157. Y := (Parent.ClientHeight - Height) div 2;
  1158. end;
  1159. end;
  1160. if X < 0 then X := 0;
  1161. if Y < 0 then Y := 0;
  1162. with Control do SetBounds(X, Y, Width, Height);
  1163. end;
  1164. procedure FitRectToScreen(var Rect: TRect);
  1165. var
  1166. X, Y, Delta: Integer;
  1167. begin
  1168. X := GetSystemMetrics(SM_CXSCREEN);
  1169. Y := GetSystemMetrics(SM_CYSCREEN);
  1170. with Rect do
  1171. begin
  1172. if Right > X then
  1173. begin
  1174. Delta := Right - Left;
  1175. Right := X;
  1176. Left := Right - Delta;
  1177. end;
  1178. if Left < 0 then
  1179. begin
  1180. Delta := Right - Left;
  1181. Left := 0;
  1182. Right := Left + Delta;
  1183. end;
  1184. if Bottom > Y then
  1185. begin
  1186. Delta := Bottom - Top;
  1187. Bottom := Y;
  1188. Top := Bottom - Delta;
  1189. end;
  1190. if Top < 0 then
  1191. begin
  1192. Delta := Bottom - Top;
  1193. Top := 0;
  1194. Bottom := Top + Delta;
  1195. end;
  1196. end;
  1197. end;
  1198. procedure CenterWindow(Wnd: HWnd);
  1199. var
  1200. R: TRect;
  1201. begin
  1202. GetWindowRect(Wnd, R);
  1203. R := Rect((GetSystemMetrics(SM_CXSCREEN) - R.Right + R.Left) div 2,
  1204. (GetSystemMetrics(SM_CYSCREEN) - R.Bottom + R.Top) div 2,
  1205. R.Right - R.Left, R.Bottom - R.Top);
  1206. FitRectToScreen(R);
  1207. SetWindowPos(Wnd, 0, R.Left, R.Top, 0, 0, SWP_NOACTIVATE or
  1208. SWP_NOSIZE or SWP_NOZORDER);
  1209. end;
  1210. procedure MergeForm(AControl: TWinControl; AForm: TForm; Align: TAlign;
  1211. Show: Boolean);
  1212. var
  1213. R: TRect;
  1214. AutoScroll: Boolean;
  1215. begin
  1216. AutoScroll := AForm.AutoScroll;
  1217. AForm.Hide;
  1218. THack(AForm).DestroyHandle;
  1219. with AForm do
  1220. begin
  1221. BorderStyle := bsNone;
  1222. BorderIcons := [];
  1223. Parent := AControl;
  1224. end;
  1225. AControl.DisableAlign;
  1226. try
  1227. if Align <> alNone then AForm.Align := Align
  1228. else
  1229. begin
  1230. R := AControl.ClientRect;
  1231. AForm.SetBounds(R.Left + AForm.Left, R.Top + AForm.Top, AForm.Width,
  1232. AForm.Height);
  1233. end;
  1234. AForm.AutoScroll := AutoScroll;
  1235. AForm.Visible := Show;
  1236. finally
  1237. AControl.EnableAlign;
  1238. end;
  1239. end;
  1240. {$IFNDEF VER80}
  1241. { ShowMDIClientEdge function has been copied from Inprise's FORMS.PAS unit,
  1242. Delphi 4 version }
  1243. procedure ShowMDIClientEdge(ClientHandle: THandle; ShowEdge: Boolean);
  1244. var
  1245. Style: Longint;
  1246. begin
  1247. if ClientHandle <> 0 then
  1248. begin
  1249. Style := GetWindowLong(ClientHandle, GWL_EXSTYLE);
  1250. if ShowEdge then
  1251. if Style and WS_EX_CLIENTEDGE = 0 then
  1252. Style := Style or WS_EX_CLIENTEDGE
  1253. else
  1254. Exit
  1255. else if Style and WS_EX_CLIENTEDGE <> 0 then
  1256. Style := Style and not WS_EX_CLIENTEDGE
  1257. else
  1258. Exit;
  1259. SetWindowLong(ClientHandle, GWL_EXSTYLE, Style);
  1260. SetWindowPos(ClientHandle, 0, 0,0,0,0, SWP_FRAMECHANGED or SWP_NOACTIVATE or
  1261. SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER);
  1262. end;
  1263. end;
  1264. function MakeVariant(const Values: array of Variant): Variant;
  1265. begin
  1266. if High(Values) - Low(Values) > 1 then
  1267. Result := VarArrayOf(Values)
  1268. else if High(Values) - Low(Values) = 1 then
  1269. Result := Values[Low(Values)]
  1270. else Result := Null;
  1271. end;
  1272. {$ENDIF}
  1273. { Shade rectangle }
  1274. procedure ShadeRect(DC: HDC; const Rect: TRect);
  1275. const
  1276. HatchBits: array[0..7] of Word = ($11, $22, $44, $88, $11, $22, $44, $88);
  1277. var
  1278. Bitmap: HBitmap;
  1279. SaveBrush: HBrush;
  1280. SaveTextColor, SaveBkColor: TColorRef;
  1281. begin
  1282. Bitmap := CreateBitmap(8, 8, 1, 1, @HatchBits);
  1283. SaveBrush := SelectObject(DC, CreatePatternBrush(Bitmap));
  1284. try
  1285. SaveTextColor := SetTextColor(DC, clWhite);
  1286. SaveBkColor := SetBkColor(DC, clBlack);
  1287. with Rect do PatBlt(DC, Left, Top, Right - Left, Bottom - Top, $00A000C9);
  1288. SetBkColor(DC, SaveBkColor);
  1289. SetTextColor(DC, SaveTextColor);
  1290. finally
  1291. DeleteObject(SelectObject(DC, SaveBrush));
  1292. DeleteObject(Bitmap);
  1293. end;
  1294. end;
  1295. function ScreenWorkArea: TRect;
  1296. {$IFDEF VER80}
  1297. const
  1298. SPI_GETWORKAREA = 48;
  1299. {$ENDIF}
  1300. begin
  1301. if not SystemParametersInfo(SPI_GETWORKAREA, 0, @Result, 0) then
  1302. with Screen do Result := Bounds(0, 0, Width, Height);
  1303. end;
  1304. function WindowClassName(Wnd: HWnd): string;
  1305. var
  1306. Buffer: array[0..255] of Char;
  1307. begin
  1308. SetString(Result, Buffer, GetClassName(Wnd, Buffer, SizeOf(Buffer) - 1));
  1309. end;
  1310. {$IFNDEF VER80}
  1311. function GetAnimation: Boolean;
  1312. var
  1313. Info: TAnimationInfo;
  1314. begin
  1315. Info.cbSize := SizeOf(TAnimationInfo);
  1316. if SystemParametersInfo(SPI_GETANIMATION, SizeOf(Info), @Info, 0) then
  1317. {$IFDEF RX_D3}
  1318. Result := Info.iMinAnimate <> 0
  1319. {$ELSE}
  1320. Result := Info.iMinAnimate
  1321. {$ENDIF}
  1322. else Result := False;
  1323. end;
  1324. procedure SetAnimation(Value: Boolean);
  1325. var
  1326. Info: TAnimationInfo;
  1327. begin
  1328. Info.cbSize := SizeOf(TAnimationInfo);
  1329. BOOL(Info.iMinAnimate) := Value;
  1330. SystemParametersInfo(SPI_SETANIMATION, SizeOf(Info), @Info, 0);
  1331. end;
  1332. procedure ShowWinNoAnimate(Handle: HWnd; CmdShow: Integer);
  1333. var
  1334. Animation: Boolean;
  1335. begin
  1336. Animation := GetAnimation;
  1337. if Animation then SetAnimation(False);
  1338. ShowWindow(Handle, CmdShow);
  1339. if Animation then SetAnimation(True);
  1340. end;
  1341. {$ELSE}
  1342. procedure ShowWinNoAnimate(Handle: HWnd; CmdShow: Integer);
  1343. begin
  1344. ShowWindow(Handle, CmdShow);
  1345. end;
  1346. procedure SwitchToThisWindow(Wnd: HWnd; Restore: Bool); far; external 'USER'
  1347. index 172;
  1348. {$ENDIF}
  1349. procedure SwitchToWindow(Wnd: HWnd; Restore: Boolean);
  1350. begin
  1351. if IsWindowEnabled(Wnd) then
  1352. begin
  1353. {$IFNDEF VER80}
  1354. SetForegroundWindow(Wnd);
  1355. if Restore and IsWindowVisible(Wnd) then
  1356. begin
  1357. if not IsZoomed(Wnd) then
  1358. SendMessage(Wnd, WM_SYSCOMMAND, SC_RESTORE, 0);
  1359. SetFocus(Wnd);
  1360. end;
  1361. {$ELSE}
  1362. SwitchToThisWindow(Wnd, Restore);
  1363. {$ENDIF}
  1364. end;
  1365. end;
  1366. function GetWindowParent(Wnd: HWnd): HWnd;
  1367. begin
  1368. {$IFNDEF VER80}
  1369. Result := GetWindowLong(Wnd, GWL_HWNDPARENT);
  1370. {$ELSE}
  1371. Result := GetWindowWord(Wnd, GWW_HWNDPARENT);
  1372. {$ENDIF}
  1373. end;
  1374. procedure ActivateWindow(Wnd: HWnd);
  1375. begin
  1376. if Wnd <> 0 then
  1377. begin
  1378. ShowWinNoAnimate(Wnd, SW_SHOW);
  1379. {$IFNDEF VER80}
  1380. SetForegroundWindow(Wnd);
  1381. {$ELSE}
  1382. SwitchToThisWindow(Wnd, True);
  1383. {$ENDIF}
  1384. end;
  1385. end;
  1386. {$IFDEF CBUILDER}
  1387. function FindPrevInstance(const MainFormClass: ShortString;
  1388. const ATitle: string): HWnd;
  1389. {$ELSE}
  1390. function FindPrevInstance(const MainFormClass, ATitle: string): HWnd;
  1391. {$ENDIF CBUILDER}
  1392. var
  1393. BufClass, BufTitle: PChar;
  1394. begin
  1395. Result := 0;
  1396. if (MainFormClass = '') and (ATitle = '') then Exit;
  1397. BufClass := nil; BufTitle := nil;
  1398. if (MainFormClass <> '') then BufClass := StrPAlloc(MainFormClass);
  1399. if (ATitle <> '') then BufTitle := StrPAlloc(ATitle);
  1400. try
  1401. Result := FindWindow(BufClass, BufTitle);
  1402. finally
  1403. StrDispose(BufTitle);
  1404. StrDispose(BufClass);
  1405. end;
  1406. end;
  1407. {$IFNDEF VER80}
  1408. function WindowsEnum(Handle: HWnd; Param: Longint): Bool; export; stdcall;
  1409. begin
  1410. if WindowClassName(Handle) = 'TAppBuilder' then
  1411. begin
  1412. Result := False;
  1413. PLongint(Param)^ := 1;
  1414. end
  1415. else Result := True;
  1416. end;
  1417. {$ENDIF}
  1418. {$IFDEF CBUILDER}
  1419. function ActivatePrevInstance(const MainFormClass: ShortString;
  1420. const ATitle: string): Boolean;
  1421. {$ELSE}
  1422. function ActivatePrevInstance(const MainFormClass, ATitle: string): Boolean;
  1423. {$ENDIF CBUILDER}
  1424. var
  1425. PrevWnd, PopupWnd, ParentWnd: HWnd;
  1426. {$IFNDEF VER80}
  1427. IsDelphi: Longint;
  1428. {$ELSE}
  1429. S: array[0..255] of Char;
  1430. {$ENDIF}
  1431. begin
  1432. Result := False;
  1433. PrevWnd := FindPrevInstance(MainFormClass, ATitle);
  1434. if PrevWnd <> 0 then
  1435. begin
  1436. ParentWnd := GetWindowParent(PrevWnd);
  1437. while (ParentWnd <> GetDesktopWindow) and (ParentWnd <> 0) do
  1438. begin
  1439. PrevWnd := ParentWnd;
  1440. ParentWnd := GetWindowParent(PrevWnd);
  1441. end;
  1442. if WindowClassName(PrevWnd) = 'TApplication' then
  1443. begin
  1444. {$IFNDEF VER80}
  1445. IsDelphi := 0;
  1446. EnumThreadWindows(GetWindowTask(PrevWnd), @WindowsEnum, LPARAM(@IsDelphi));
  1447. if Boolean(IsDelphi) then Exit;
  1448. {$ELSE}
  1449. GetModuleFileName(GetWindowTask(PrevWnd), S, SizeOf(S) - 1); //non unicode
  1450. if AnsiUpperCase(ExtractFileName(StrPas(S))) = 'DELPHI.EXE' then Exit;
  1451. {$ENDIF}
  1452. if IsIconic(PrevWnd) then { application is minimized }
  1453. begin
  1454. SendMessage(PrevWnd, WM_SYSCOMMAND, SC_RESTORE, 0);
  1455. Result := True;
  1456. Exit;
  1457. end
  1458. else ShowWinNoAnimate(PrevWnd, SW_SHOWNOACTIVATE);
  1459. end
  1460. else ActivateWindow(PrevWnd);
  1461. PopupWnd := GetLastActivePopup(PrevWnd);
  1462. if (PrevWnd <> PopupWnd) and IsWindowVisible(PopupWnd) and IsWindowEnabled(PopupWnd) then
  1463. begin
  1464. {$IFNDEF VER80}
  1465. SetForegroundWindow(PopupWnd);
  1466. {$ELSE}
  1467. BringWindowToTop(PopupWnd);
  1468. {$ENDIF}
  1469. end
  1470. else ActivateWindow(PopupWnd);
  1471. Result := True;
  1472. end;
  1473. end;
  1474. { Standard Windows MessageBox function }
  1475. function MsgBox(const Caption, Text: string; Flags: Integer): Integer;
  1476. {$IFNDEF VER80}
  1477. begin
  1478. {$IFNDEF RX_D5}
  1479. SetAutoSubClass(True);
  1480. try
  1481. {$ENDIF}
  1482. Result := Application.MessageBox(PChar(Text), PChar(Caption), Flags);
  1483. {$IFNDEF RX_D5}
  1484. finally
  1485. SetAutoSubClass(False);
  1486. end;
  1487. {$ENDIF}
  1488. end;
  1489. {$ELSE}
  1490. var
  1491. BufMsg, BufCaption: PChar;
  1492. begin
  1493. SetAutoSubClass(True);
  1494. BufMsg := StrPAlloc(Text);
  1495. BufCaption := StrPAlloc(Caption);
  1496. try
  1497. Result := Application.MessageBox(BufMsg, BufCaption, Flags);
  1498. finally
  1499. StrDispose(BufCaption);
  1500. StrDispose(BufMsg);
  1501. SetAutoSubClass(False);
  1502. end;
  1503. end;
  1504. {$ENDIF}
  1505. function MsgDlg(const Msg: string; AType: TMsgDlgType;
  1506. AButtons: TMsgDlgButtons; HelpCtx: Longint): Word;
  1507. {$IFNDEF VER80}
  1508. begin
  1509. Result := MessageDlg(Msg, AType, AButtons, HelpCtx);
  1510. end;
  1511. {$ELSE}
  1512. var
  1513. KeepGlyphs: Boolean;
  1514. KeepSize: TPoint;
  1515. begin
  1516. if NewStyleControls then
  1517. begin
  1518. KeepGlyphs := MsgDlgGlyphs;
  1519. KeepSize := MsgDlgBtnSize;
  1520. MsgDlgBtnSize := Point(77, 25);
  1521. MsgDlgGlyphs := False;
  1522. end;
  1523. try
  1524. Result := MessageDlg(Msg, AType, AButtons, HelpCtx);
  1525. finally
  1526. if NewStyleControls then
  1527. begin
  1528. MsgDlgBtnSize := KeepSize;
  1529. MsgDlgGlyphs := KeepGlyphs;
  1530. end;
  1531. end;
  1532. end;
  1533. {$ENDIF}
  1534. { Gradient fill procedure - displays a gradient beginning with a chosen }
  1535. { color and ending with another chosen color. Based on TGradientFill }
  1536. { component source code written by Curtis White, cwhite@teleport.com. }
  1537. procedure GradientFillRect(Canvas: TCanvas; ARect: TRect; StartColor,
  1538. EndColor: TColor; Direction: TFillDirection; Colors: Byte);
  1539. var
  1540. StartRGB: array[0..2] of Byte; { Start RGB values }
  1541. RGBDelta: array[0..2] of Integer; { Difference between start and end RGB values }
  1542. ColorBand: TRect; { Color band rectangular coordinates }
  1543. I, Delta: Integer;
  1544. Brush: HBrush;
  1545. begin
  1546. if IsRectEmpty(ARect) then Exit;
  1547. if Colors < 2 then
  1548. begin
  1549. Brush := CreateSolidBrush(ColorToRGB(StartColor));
  1550. FillRect(Canvas.Handle, ARect, Brush);
  1551. DeleteObject(Brush);
  1552. Exit;
  1553. end;
  1554. StartColor := ColorToRGB(StartColor);
  1555. EndColor := ColorToRGB(EndColor);
  1556. case Direction of
  1557. fdTopToBottom, fdLeftToRight:
  1558. begin
  1559. { Set the Red, Green and Blue colors }
  1560. StartRGB[0] := GetRValue(StartColor);
  1561. StartRGB[1] := GetGValue(StartColor);
  1562. StartRGB[2] := GetBValue(StartColor);
  1563. { Calculate the difference between begin and end RGB values }
  1564. RGBDelta[0] := GetRValue(EndColor) - StartRGB[0];
  1565. RGBDelta[1] := GetGValue(EndColor) - StartRGB[1];
  1566. RGBDelta[2] := GetBValue(EndColor) - StartRGB[2];
  1567. end;
  1568. fdBottomToTop, fdRightToLeft:
  1569. begin
  1570. { Set the Red, Green and Blue colors }
  1571. { Reverse of TopToBottom and LeftToRight directions }
  1572. StartRGB[0] := GetRValue(EndColor);
  1573. StartRGB[1] := GetGValue(EndColor);
  1574. StartRGB[2] := GetBValue(EndColor);
  1575. { Calculate the difference between begin and end RGB values }
  1576. { Reverse of TopToBottom and LeftToRight directions }
  1577. RGBDelta[0] := GetRValue(StartColor) - StartRGB[0];
  1578. RGBDelta[1] := GetGValue(StartColor) - StartRGB[1];
  1579. RGBDelta[2] := GetBValue(StartColor) - StartRGB[2];
  1580. end;
  1581. end; {case}
  1582. { Calculate the color band's coordinates }
  1583. ColorBand := ARect;
  1584. if Direction in [fdTopToBottom, fdBottomToTop] then
  1585. begin
  1586. Colors := Max(2, Min(Colors, HeightOf(ARect)));
  1587. Delta := HeightOf(ARect) div Colors;
  1588. end
  1589. else
  1590. begin
  1591. Colors := Max(2, Min(Colors, WidthOf(ARect)));
  1592. Delta := WidthOf(ARect) div Colors;
  1593. end;
  1594. with Canvas.Pen do
  1595. begin { Set the pen style and mode }
  1596. Style := psSolid;
  1597. Mode := pmCopy;
  1598. end;
  1599. { Perform the fill }
  1600. if Delta > 0 then
  1601. begin
  1602. for I := 0 to Colors do
  1603. begin
  1604. case Direction of
  1605. { Calculate the color band's top and bottom coordinates }
  1606. fdTopToBottom, fdBottomToTop:
  1607. begin
  1608. ColorBand.Top := ARect.Top + I * Delta;
  1609. ColorBand.Bottom := ColorBand.Top + Delta;
  1610. end;
  1611. { Calculate the color band's left and right coordinates }
  1612. fdLeftToRight, fdRightToLeft:
  1613. begin
  1614. ColorBand.Left := ARect.Left + I * Delta;
  1615. ColorBand.Right := Col