home *** CD-ROM | disk | FTP | other *** search
/ PC Open 19 / pcopen19.iso / Zipped / CALMIR21.ZIP / SOURCE.ZIP / UTILS / MISCUTIL.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1998-02-20  |  14.2 KB  |  582 lines

  1. {*********************************************************}
  2. {                                                         }
  3. {    Calmira System Library 2.1                           }
  4. {    by Li-Hsin Huang,                                    }
  5. {    released into the public domain January 1998         }
  6. {                                                         }
  7. {*********************************************************}
  8.                                      
  9. unit MiscUtil;
  10.  
  11. { Some useful Delphi and Windows routines }
  12.  
  13. interface
  14.  
  15. uses Classes, SysUtils, Forms, WinTypes, IniFiles, Menus,
  16.   StdCtrls, Dialogs, ExtCtrls, Graphics, TabNotBk;
  17.  
  18. const
  19.   MsgDialogSounds : Boolean = False;
  20.   MaxHistorySize  : Integer = 24;
  21.  
  22. function Min(a, b: Integer): Integer;
  23. function Max(a, b: Integer): Integer;
  24. { Returns the smaller and larger of two values respectively }
  25.  
  26. function Range(n, lower, upper: Integer): Integer;
  27. { Constrains n to a lower and upper limit }
  28.  
  29. function Sign(x: Integer) : Integer;
  30. { Returns 1 if x > 0, -1 if x < 0 and 0 if x = 0 }
  31.  
  32. procedure Border3d(Canvas : TCanvas; Width, Height: Integer);
  33. { Draws a raised 3D border on a canvas, typically used in an
  34.   OnPaint method of a TForm }
  35.  
  36. procedure ErrorMsg(const msg: string);
  37. { Displays a message dialog box indicating an error }
  38.  
  39. procedure ErrorMsgRes(Ident: Word);
  40.  
  41. procedure ErrorMsgResFmt(Ident: Word; const Args : array of const);
  42.  
  43. procedure PlaySound(const filename: TFilename);
  44. { Plays the specified WAV file as a sound effect.  If the filename
  45.   is <None>, nothing is played }
  46.  
  47. function Intersects(const R, S: TRect): Boolean;
  48. { Returns True if the two rectangles intersect }
  49.  
  50. function NormalizeRect(p, q: TPoint): TRect;
  51. { Returns a rectangle defined by any two points.  When dragging a
  52.   selection box with a mouse, the fixed corner and the moving
  53.   corner may not always be top left and bottom right respectively.
  54.   This function creates a valid TRect out of them }
  55.  
  56. function TimeStampToDate(FileDate: Longint): TDateTime;
  57. { Converts a DOS timestamp to TDateTime.  If the timestamp is invalid
  58.   (some programs use invalid stamps as markers), the current date
  59.   is returned instead of raising EConvertError }
  60.  
  61. function GetRegValue(key : string): string;
  62. { Returns a value from the Windows registration database, with the
  63.   specified key from HKEY_CLASSES_ROOT }
  64.  
  65. function GetRadioIndex(const R: array of TRadioButton): Integer;
  66. procedure SetRadioIndex(const R: array of TRadioBUtton; index: Integer);
  67. function GetMenuCheck(const M: array of TMenuItem): Integer;
  68. procedure SetMenuCheck(const M: array of TMenuItem; index: Integer);
  69. { These routines are useful for setting and querying the state of
  70.   several controls.  Use them to simulate arrays and as an alternative
  71.   to TRadioGroup. }
  72.  
  73. procedure RefreshCursor;
  74. { Updates the cursor image when you have changed the Cursor or DragCursor
  75.   property of a control }
  76.  
  77. procedure UpdateScreen;
  78.  
  79. procedure ShowHourGlass;
  80. { Displays the hourglass cursor immediately }
  81.  
  82. procedure ShowArrow;
  83. { Displays the standard arrow }
  84.  
  85. function AddHistory(Combo : TComboBox): Boolean;
  86. { Adds a combo box's Text string to its listbox, but only if the
  87.   string is not empty and not already present in the list.  The item is
  88.   inserted at the top of the list, and if there are more than 24 items,
  89.   the bottom one is removed.  Returns true if the list is modified }
  90.  
  91. procedure AssignHistoryText(Combo : TCombobox; const NewText: string);
  92.  
  93. function MsgDialog(const Msg: string; AType: TMsgDlgType;
  94.   AButtons: TMsgDlgButtons; HelpCtx: Longint): Word;
  95. { Calls the MessageDialog function, but also plays a suitable sound
  96.   effect from the Control Panel settings.  The MsgDialogSounds variable
  97.   enables the sounds }
  98.  
  99. function MsgDialogRes(Ident : Word; AType: TMsgDlgType;
  100.   AButtons: TMsgDlgButtons; HelpCtx: Longint): Word;
  101.  
  102. function MsgDialogResFmt(Ident : Word; const Args: array of const;
  103.   AType: TMsgDlgType; AButtons: TMsgDlgButtons; HelpCtx: Longint): Word;
  104.  
  105. function ShowModalDialog(FormClass : TFormClass): TModalResult;
  106. { A very simple way of displaying a dynamic modal form -- just pass the
  107.   form's class name e.g. TForm1, and an instance will be created,
  108.   shown as a modal dialog and then destroyed. }
  109.  
  110. function InitBitmap(ABitmap: TBitmap;
  111.   AWidth, AHeight : Integer; Color : TColor) : TBitmap;
  112. { Initialises the bitmap's dimensions and fills it with the chosen colour }
  113.  
  114. procedure ShrinkIcon(H : HIcon; Glyph : TBitmap);
  115. { Shrinks a 32 x 32 icon down to a 16 x 16 bitmap }
  116.  
  117. procedure CopyStringsToClipboard(strings : TStrings);
  118.  
  119. function ShortTimeToStr(Time : TDateTime) : string;
  120.  
  121. procedure FreePageHandles(Notebook : TTabbedNotebook);
  122.  
  123. function GetTimerCount : Longint;
  124.  
  125. procedure RecessBevel(Canvas: TCanvas; R: TRect);
  126.  
  127. function GetMinPosition(Wnd: HWND): TPoint;
  128.  
  129. procedure MoveDesktopIcon(Wnd: HWND; pt: TPoint);
  130.  
  131. procedure GetHeaderDivisions(H: THeader; A: array of PInteger);
  132.  
  133. const
  134.   RepaintBeforeHourglass : Integer = 1;
  135.   DarkIconStretch : Boolean = False;
  136.  
  137. implementation
  138.  
  139. uses WinProcs, MMSystem, ShellAPI, Strings, Controls,
  140.   FileCtrl, Clipbrd, ToolHelp;
  141.  
  142.  
  143. function Min(a, b: Integer): Integer; assembler;
  144. asm
  145.   MOV    AX, a
  146.   CMP    AX, b
  147.   JLE    @@1
  148.   MOV    AX, b
  149. @@1:
  150. end;
  151.  
  152.  
  153. function Max(a, b: Integer): Integer; assembler;
  154. asm
  155.   MOV    AX, a
  156.   CMP    AX, b
  157.   JGE    @@1
  158.   MOV    AX, b
  159. @@1:
  160. end;
  161.  
  162. function Range(n, lower, upper: Integer): Integer; assembler;
  163. asm
  164.    MOV  AX, n
  165.    CMP  AX, lower
  166.    JGE  @@1
  167.    MOV  AX, lower
  168.    JMP  @finish
  169. @@1:
  170.    CMP  AX, upper
  171.    JLE  @finish
  172.    MOV  AX, upper
  173.    JMP  @finish
  174. @@2:
  175.    MOV  AX, lower
  176. @finish:
  177. end;
  178.  
  179.  
  180. function Sign(x: Integer) : Integer; assembler;
  181. asm
  182.    MOV  AX, X
  183.    CMP  AX, 0
  184.    JL   @@1
  185.    JG   @@2
  186.    XOR  AX, AX
  187.    JMP  @finish
  188. @@1:
  189.    MOV  AX, -1
  190.    JMP  @finish
  191. @@2:
  192.    MOV  AX, 1
  193. @finish:
  194. end;
  195.  
  196.  
  197.  
  198. procedure Border3d(Canvas : TCanvas; Width, Height: Integer);
  199. begin
  200.   with Canvas do begin
  201.     Pen.Color := clBtnHighLight;
  202.     MoveTo(0, Height);
  203.     LineTo(0, 0);
  204.     LineTo(Width, 0);
  205.     Pen.Color := clBtnShadow;
  206.     LineTo(Width, Height);
  207.     LineTo(0, Height);
  208.   end;
  209. end;
  210.  
  211.  
  212. procedure ErrorMsg(const msg: string);
  213. begin
  214.   MsgDialog(msg, mtError, [mbOK], 0);
  215. end;
  216.  
  217. procedure ErrorMsgRes(Ident: Word);
  218. begin
  219.   MsgDialog(LoadStr(Ident), mtError, [mbOK], 0);
  220. end;
  221.  
  222. procedure ErrorMsgResFmt(Ident: Word; const Args : array of const);
  223. begin
  224.   MsgDialog(FmtLoadStr(Ident, Args), mtError, [mbOK], 0);
  225. end;
  226.  
  227.  
  228.  
  229.  
  230.  
  231. procedure PlaySound(const filename: TFilename);
  232. var s: TFilename;
  233. begin
  234.   if CompareText(filename, '<None>') <> 0 then
  235.     SndPlaySound(StrPCopy(@s, filename), SND_ASYNC or SND_NODEFAULT);
  236. end;
  237.  
  238.  
  239.  
  240. function Intersects(const R, S: TRect): Boolean;
  241. var dummy: TRect;
  242. begin
  243.   Result := IntersectRect(dummy, R, S) <> 0;
  244. end;
  245.  
  246. function NormalizeRect(p, q: TPoint): TRect; assembler;
  247. asm
  248.   MOV  AX, p.x
  249.   MOV  BX, p.y
  250.   MOV  CX, q.x
  251.   MOV  DX, q.y
  252.   CMP  AX, CX
  253.   JLE  @@1
  254.   XCHG AX, CX
  255. @@1:
  256.   CMP  BX, DX
  257.   JLE  @@2
  258.   XCHG BX, DX
  259. @@2:
  260.   LES  DI, @Result
  261.   MOV  TRect(ES:[DI]).Left, AX
  262.   MOV  TRect(ES:[DI]).Top, BX
  263.   MOV  TRect(ES:[DI]).Right, CX
  264.   MOV  TRect(ES:[DI]).Bottom, DX
  265. end;
  266.  
  267.  
  268.  
  269. function TimeStampToDate(FileDate: Longint): TDateTime;
  270. begin
  271.   try Result := FileDateToDateTime(FileDate)
  272.   except on EConvertError do Result := Date;
  273.   end;
  274. end;
  275.  
  276. function GetRegValue(key : string): string;
  277. var cb : Longint;
  278. begin
  279.   cb := 255;
  280.   if RegQueryValue(HKEY_CLASSES_ROOT, StringAsPChar(key),
  281.      @Result[1], cb) = ERROR_SUCCESS then
  282.     Result[0] := Chr(cb-1)
  283.   else
  284.     Result := '';
  285. end;
  286.  
  287.  
  288. function GetRadioIndex(const R: array of TRadioButton): Integer;
  289. var i: Integer;
  290. begin
  291.   for i := 0 to High(R) do
  292.     if R[i].Checked then begin
  293.       Result := i;
  294.       exit;
  295.     end;
  296.   Result := 0;
  297. end;
  298.  
  299.  
  300. procedure SetRadioIndex(const R: array of TRadioBUtton; index: Integer);
  301. var i: Integer;
  302. begin
  303.   for i := 0 to High(R) do R[i].Checked := i = index;
  304. end;
  305.  
  306.  
  307. function GetMenuCheck(const M: array of TMenuItem): Integer;
  308. begin
  309.   for Result := 0 to High(M) do if M[Result].Checked then Exit;
  310.   Result := 0;
  311. end;
  312.  
  313.  
  314. procedure SetMenuCheck(const M: array of TMenuItem; index: Integer);
  315. var i: Integer;
  316. begin
  317.   for i := 0 to High(M) do M[i].Checked := i = index;
  318. end;
  319.  
  320.  
  321. procedure RefreshCursor;
  322. var p: TPoint;
  323. begin
  324.   GetCursorPos(p);
  325.   SetCursorPos(p.x, p.y);
  326. end;
  327.  
  328.  
  329. function DoUpdateWindow(Wnd: HWND; lParam : Longint): Bool ; export;
  330. begin
  331.   UpdateWindow(Wnd);
  332.   Result := True;
  333. end;
  334.  
  335. procedure UpdateScreen;
  336. begin
  337.   case RepaintBeforeHourglass of
  338.     1: EnumTaskWindows(GetCurrentTask, @DoUpdateWindow, 0);
  339.     2: EnumWindows(@DoUpdateWindow, 0);
  340.   end;
  341. end;
  342.  
  343.  
  344. procedure ShowHourGlass;
  345. begin
  346.   UpdateScreen;
  347.   SetCursor(LoadCursor(0, IDC_WAIT));
  348. end;
  349.  
  350. procedure ShowArrow;
  351. begin
  352.   SetCursor(LoadCursor(0, IDC_ARROW));
  353. end;
  354.  
  355.  
  356.  
  357. function AddHistory(Combo : TComboBox): Boolean;
  358. var
  359.   i : Integer;
  360.   s : string;
  361. begin
  362.   Result := False;
  363.   with Combo, Combo.Items do
  364.     if Text <> '' then begin
  365.       i := IndexOf(Text);
  366.       if i = -1 then begin
  367.         Result := True;
  368.         Insert(0, Text)
  369.       end
  370.       else if i > 0 then begin
  371.         Result := True;
  372.         s := Text;
  373.         Delete(i);
  374.         Insert(0, s);
  375.         Text := s;
  376.         { same as Exchange(i, 0), but Exchange can clear the
  377.           Text property if the text is the string at i }
  378.       end;
  379.  
  380.       while (Count > 0) and (Count > MaxHistorySize) do begin
  381.         Result := True;
  382.         Delete(Count-1);
  383.       end;
  384.     end;
  385. end;
  386.  
  387. procedure AssignHistoryText(Combo : TCombobox; const NewText: string);
  388. begin
  389.   with Combo do begin
  390.     if NewText > '' then Text := NewText;
  391.     if (Text = '') and (Items.Count >= 1) then Text := Items[0];
  392.   end;
  393. end;
  394.  
  395.  
  396. function MsgDialog(const Msg: string; AType: TMsgDlgType;
  397.   AButtons: TMsgDlgButtons; HelpCtx: Longint): Word;
  398. const
  399.   Sound : array[TMsgDlgType] of Word =
  400.     (MB_ICONEXCLAMATION, MB_ICONHAND, MB_OK, MB_ICONQUESTION, 0);
  401. begin
  402.   if MsgDialogSounds and (AType < mtCustom) then MessageBeep(Sound[AType]);
  403.   Result := MessageDlg(Msg, AType, AButtons, HelpCtx);
  404. end;
  405.  
  406. function MsgDialogRes(Ident : Word; AType: TMsgDlgType;
  407.   AButtons: TMsgDlgButtons; HelpCtx: Longint): Word;
  408. begin
  409.   Result := MsgDialog(LoadStr(Ident), AType, AButtons, HelpCtx);
  410. end;
  411.  
  412. function MsgDialogResFmt(Ident : Word; const Args: array of const;
  413.   AType: TMsgDlgType; AButtons: TMsgDlgButtons; HelpCtx: Longint): Word;
  414. begin
  415.   Result := MsgDialog(FmtLoadStr(Ident, Args), AType, AButtons, HelpCtx);
  416. end;
  417.  
  418.  
  419.  
  420. function ShowModalDialog(FormClass : TFormClass): TModalResult;
  421. begin
  422.   ShowHourGlass;
  423.   with FormClass.Create(Application) do
  424.   try
  425.     Result := ShowModal;
  426.   finally
  427.     Free;
  428.   end;
  429. end;
  430.  
  431.  
  432. function InitBitmap(ABitmap: TBitmap;
  433.   AWidth, AHeight : Integer; Color : TColor) : TBitmap;
  434. begin
  435.   { initializes a bitmap with width, height and background colour }
  436.  
  437.   with ABitmap do begin
  438.     Width := AWidth;
  439.     Height := AHeight;
  440.     Canvas.Brush.Color := Color;
  441.     Canvas.FillRect(Rect(0, 0, Width, Height));
  442.   end;
  443.   Result := ABitmap;
  444. end;
  445.  
  446.  
  447. procedure ShrinkIcon(H : HIcon; Glyph : TBitmap);
  448. const
  449.   DarkStretch : array[Boolean] of Integer =
  450.     (STRETCH_DELETESCANS, STRETCH_ANDSCANS);
  451. var
  452.   bmp : TBitmap;
  453.   i, j : Integer;
  454.   src, dest : HDC;
  455.   OldStretch : Integer;
  456. begin
  457.   bmp := InitBitmap(TBitmap.Create, 32, 32, clSilver);
  458.   DrawIcon(bmp.Canvas.Handle, 0, 0, H);
  459.  
  460.   try
  461.     with Glyph do begin
  462.       Width := 16;
  463.       Height := 16;
  464.  
  465.       src := bmp.Canvas.Handle;
  466.       dest := Canvas.Handle;
  467.  
  468.       OldStretch := SetStretchBltMode(dest, DarkStretch[DarkIconStretch]);
  469.       StretchBlt(dest, 0, 0, 16, 16, src, 0, 0, 32, 32, SRCCOPY);
  470.  
  471.       for i := 0 to 15 do
  472.         for j := 0 to 15 do
  473.          if GetPixel(dest, i, j) = clSilver then
  474.            SetPixel(dest, i, j, GetPixel(src, i shl 1, j shl 1));
  475.  
  476.       Canvas.Pixels[0, 15] := clBtnFace;
  477.       SetStretchBltMode(dest, OldStretch);
  478.     end;
  479.   finally
  480.     bmp.Free;
  481.   end;
  482. end;
  483.  
  484. procedure CopyStringsToClipboard(strings : TStrings);
  485. var
  486.   P: PChar;
  487. begin
  488.   P := strings.GetText;
  489.   Clipboard.SetTextBuf(P);
  490.   StrDispose(P);
  491. end;
  492.  
  493. function ShortTimeToStr(Time : TDateTime) : string;
  494. begin
  495.   DateTimeToString(Result, ShortTimeFormat, Time);
  496. end;
  497.  
  498.  
  499. type
  500.   TSurfaceWin = class(TWinControl);
  501.  
  502. procedure FreePageHandles(Notebook : TTabbedNotebook);
  503. begin
  504.   with Notebook do begin
  505.     LockWindowUpdate(Handle);
  506.     try
  507.       TSurfaceWin(Pages.Objects[PageIndex]).DestroyHandle;
  508.     finally
  509.       LockWindowUpdate(0);
  510.     end;
  511.   end;
  512. end;
  513.  
  514. function GetTimerCount : Longint;
  515. var
  516.   TI : TTimerInfo;
  517. begin
  518.   TI.dwSize := SizeOf(TI);
  519.   TimerCount(@TI);
  520.   Result := TI.dwmsThisVM;
  521. end;
  522.  
  523. procedure RecessBevel(Canvas: TCanvas; R: TRect);
  524. begin
  525.   Frame3D(Canvas, R, clBtnShadow, clBtnHighlight, 1);
  526. end;
  527.  
  528. { Returns minimized icon coordinates.  Those which haven't been minimized
  529.   before can have -1 values, in which case Windows picks a suitable
  530.   position when required }
  531.  
  532. function GetMinPosition(Wnd: HWND): TPoint;
  533. var place: TWindowPlacement;
  534. begin
  535.   place.Length := sizeof(place);
  536.   GetWindowPlacement(Wnd, @place);
  537.   Result := place.ptMinPosition;
  538. end;
  539.  
  540.  
  541. procedure MoveDesktopIcon(Wnd: HWND; pt: TPoint);
  542. var
  543.   place: TWindowPlacement;
  544. begin
  545.   { Repositions a window's icon.  If the window is minimized,
  546.     it must be hidden before being moved to ensure that the
  547.     desktop background is updated }
  548.  
  549.   place.Length := sizeof(place);
  550.   GetWindowPlacement(Wnd, @place);
  551.   with place.ptMinPosition do
  552.     if (x = pt.x) and (y = pt.y) then Exit;
  553.   place.ptMinPosition := pt;
  554.   place.Flags := place.Flags or WPF_SETMINPOSITION;
  555.  
  556.   if IsIconic(Wnd) then begin
  557.     ShowWindow(Wnd, SW_HIDE);
  558.     place.ShowCmd := SW_SHOWMINNOACTIVE;
  559.   end
  560.   else
  561.     place.ShowCmd := SW_SHOWNA;
  562.   SetWindowPlacement(Wnd, @place);
  563. end;
  564.  
  565. procedure GetHeaderDivisions(H: THeader; A: array of PInteger);
  566. var
  567.   i, w: Integer;
  568. begin
  569.   with H do begin
  570.     i := 0;
  571.     w := 0;
  572.     while (i <= High(A)) and (i < Sections.Count) do begin
  573.       Inc(w, SectionWidth[i]);
  574.       if A[i] <> nil then A[i]^ := w;
  575.       Inc(i);
  576.     end;
  577.   end;
  578. end;
  579.  
  580.  
  581. end.
  582.