home *** CD-ROM | disk | FTP | other *** search
/ Chip 2003 January / Chip_2003-01_cd1.bin / zkuste / delphi / unity / d56 / FNDUTL.ZIP / System / cWindows.pas < prev   
Encoding:
Pascal/Delphi Source File  |  2002-10-29  |  27.2 KB  |  863 lines

  1. {$INCLUDE ..\cDefines.inc}
  2. unit cWindows;
  3.  
  4. {                                                                              }
  5. {                          Windows functions v3.05                             }
  6. {                                                                              }
  7. {      This unit is copyright ⌐ 2000-2002 by David Butler (david@e.co.za)      }
  8. {                                                                              }
  9. {                  This unit is part of Delphi Fundamentals.                   }
  10. {                    Its original file name is cWindows.pas                    }
  11. {       The latest version is available from the Fundamentals home page        }
  12. {                     http://fundementals.sourceforge.net/                     }
  13. {                                                                              }
  14. {                I invite you to use this unit, free of charge.                }
  15. {        I invite you to distibute this unit, but it must be for free.         }
  16. {             I also invite you to contribute to its development,              }
  17. {             but do not distribute a modified copy of this file.              }
  18. {                                                                              }
  19. {          A forum is available on SourceForge for general discussion          }
  20. {             http://sourceforge.net/forum/forum.php?forum_id=2117             }
  21. {                                                                              }
  22. { Description:                                                                 }
  23. {   MS Windows specific functions.                                             }
  24. {                                                                              }
  25. { Revision history:                                                            }
  26. {   2000/10/01  v1.01  Initial version spawned from cUtils.                    }
  27. {   2001/12/12  v2.02  Added AWindowHandle.                                    }
  28. {   2002/03/15  v2.03  Added GetWinOSType.                                     }
  29. {   2002/06/26  v3.04  Refactored for Fundamentals 3.                          }
  30. {   2002/09/22  v3.05  Moved Registry functions to unit cRegistry.             }
  31. {                                                                              }
  32.  
  33. interface
  34.  
  35. uses
  36.   // Delphi
  37.   Windows,
  38.   Messages,
  39.   SysUtils,
  40.   Classes,
  41.  
  42.   // Fundamentals
  43.   cUtils;
  44.  
  45.  
  46.  
  47. {                                                                              }
  48. { Windows API                                                                  }
  49. {                                                                              }
  50. Function  GetWindowsTemporaryPath : String;
  51. Function  GetWindowsPath : String;
  52. Function  GetWindowsSystemPath : String;
  53. Function  GetProgramFilesPath : String;
  54. Function  GetApplicationPath : String;
  55.  
  56. Function  GetUserName : String;
  57. Function  GetLocalComputerName : String;
  58. Function  GetLocalHostName : String;
  59.  
  60. Function  GetEnvironmentStrings : StringArray;
  61.  
  62. Function  ContentTypeFromExtention (Extention : String) : String;
  63.  
  64. Function  IsApplicationAutoRun (const Name : String) : Boolean;
  65. Procedure SetApplicationAutoRun (const Name : String; const AutoRun : Boolean);
  66.  
  67. Function  GetWinPortNames : StringArray;
  68.  
  69. Function  GetKeyPressed (const VKeyCode : Integer) : Boolean;
  70.  
  71. Function  WinExecute (const ExeName, Params : String;
  72.           const ShowWin : Word = SW_SHOWNORMAL;
  73.           const Wait : Boolean = True) : Boolean;
  74.  
  75. Function  GetHardDiskSerialNumber (const DriveLetter : Char) : String;
  76. Function  GetWindowsProductID : String;
  77.  
  78. Function  GetMACAdresses (var Adresses : StringArray;
  79.           const MachineName : String = '') : Integer;
  80.  
  81.  
  82.  
  83. {                                                                              }
  84. { Windows Version Info                                                         }
  85. {                                                                              }
  86. type
  87.   TWinOSType = (win31,
  88.                 win32_95, win32_98, win32_ME,
  89.                 win32_NT, win32_2000, win32_XP,
  90.                 win_UnknownPlatform);
  91.  
  92. Function  GetWinOSType : TWinOSType;
  93. Function  IsWinNTFamily : Boolean;
  94. Function  IsWin95Family : Boolean;
  95.  
  96.  
  97.  
  98. {                                                                              }
  99. { Application Version Info                                                     }
  100. {                                                                              }
  101. type
  102.   TVersionInfo = (viFileVersion, viFileDescription, viLegalCopyright,
  103.                   viComments, viCompanyName, viInternalName,
  104.                   viLegalTrademarks, viOriginalFilename, viProductName,
  105.                   viProductVersion);
  106.  
  107. Function  GetAppVersionInfo (const VersionInfo : TVersionInfo) : String;
  108.  
  109.  
  110.  
  111. {                                                                              }
  112. { Window Handle                                                                }
  113. {   Base class for allocation of a new Window handle that can process its own  }
  114. {   messages.                                                                  }
  115. {                                                                              }
  116. type
  117.   TWindowHandleMessageEvent = Function (const Msg : Cardinal; const wParam, lParam : Integer;
  118.       var Handled : Boolean) : Integer of object;
  119.   TWindowHandle = class;
  120.   TWindowHandleErrorEvent = Procedure (const Sender : TWindowHandle;
  121.       const E : Exception) of object;
  122.   TWindowHandle = class (TComponent)
  123.     protected
  124.     FWindowHandle : HWND;
  125.     FTerminated   : Boolean;
  126.     FOnMessage    : TWindowHandleMessageEvent;
  127.     FOnException  : TWindowHandleErrorEvent;
  128.  
  129.     Procedure RaiseError (const Msg : String);
  130.     Function  AllocateWindowHandle : HWND; virtual;
  131.     Function  HandleWM (const Msg : Cardinal; const wParam, lParam : Integer) : Integer; virtual;
  132.  
  133.     public
  134.     Destructor Destroy; override;
  135.  
  136.     Procedure DestroyWindowHandle; virtual;
  137.     Property  WindowHandle : HWND read FWindowHandle;
  138.     Function  GetWindowHandle : HWND;
  139.  
  140.     Function  ProcessMessage : Boolean;
  141.     Procedure ProcessMessages;
  142.     Function  HandleMessage : Boolean;
  143.     Procedure MessageLoop;
  144.  
  145.     Property  OnMessage : TWindowHandleMessageEvent read FOnMessage write FOnMessage;
  146.     Property  OnException : TWindowHandleErrorEvent read FOnException write FOnException;
  147.  
  148.     Property  Terminated : Boolean read FTerminated;
  149.     Procedure Terminate; virtual;
  150.   end;
  151.   EWindowHandle = class (Exception);
  152.  
  153.   { TfndWindowHandle                                                           }
  154.   TfndWindowHandle = class (TWindowHandle)
  155.     published
  156.     Property  OnMessage;
  157.     Property  OnException;
  158.   end;
  159.  
  160.  
  161.  
  162. {                                                                              }
  163. { TTimerHandle                                                                 }
  164. {                                                                              }
  165. type
  166.   TTimerHandle = class;
  167.   TTimerEvent = Procedure (const Sender : TTimerHandle) of object;
  168.   TTimerHandle = class (TWindowHandle)
  169.     protected
  170.     FTimerInterval : Integer;
  171.     FTimerActive   : Boolean;
  172.     FOnTimer       : TTimerEvent;
  173.  
  174.     Function  HandleWM (const Msg : Cardinal; const wParam, lParam : Integer) : Integer; override;
  175.     Function  DoSetTimer : Boolean;
  176.     Procedure TriggerTimer; virtual;
  177.     Procedure SetTimerActive (const TimerActive : Boolean); virtual;
  178.     Procedure Loaded; override;
  179.  
  180.     public
  181.     Constructor Create (AOwner : TComponent); override;
  182.     Procedure DestroyWindowHandle; override;
  183.  
  184.     Property  TimerInterval : Integer read FTimerInterval write FTimerInterval;
  185.     Property  TimerActive : Boolean read FTimerActive write SetTimerActive;
  186.     Property  OnTimer : TTimerEvent read FOnTimer write FOnTimer;
  187.   end;
  188.  
  189.   { TfndTimerHandle                                                            }
  190.   TfndTimerHandle = class (TTimerHandle)
  191.     published
  192.     Property  OnMessage;
  193.     Property  OnException;
  194.     Property  TimerInterval;
  195.     Property  TimerActive;
  196.     Property  OnTimer;
  197.   end;
  198.  
  199.  
  200.  
  201. {$IFNDEF DELPHI6_UP}
  202. {                                                                              }
  203. { RaiseLastOSError                                                             }
  204. {                                                                              }
  205. Procedure RaiseLastOSError;
  206. {$ENDIF}
  207.  
  208.  
  209.  
  210. {                                                                              }
  211. { Component Register                                                           }
  212. {                                                                              }
  213. Procedure Register;
  214.  
  215.  
  216.  
  217. implementation
  218.  
  219. uses
  220.   // Delphi
  221.   WinSock,
  222.   WinSpool,
  223.   NB30,
  224.  
  225.   // Fundamentals
  226.   cStrings,
  227.   cRegistry;
  228.  
  229.  
  230.  
  231. {$IFNDEF DELPHI6_UP}
  232. {                                                                              }
  233. { RaiseLastOSError                                                             }
  234. {                                                                              }
  235. Procedure RaiseLastOSError;
  236.   Begin
  237.     RaiseLastWin32Error;
  238.   End;
  239. {$ENDIF}
  240.  
  241.  
  242.  
  243. {                                                                              }
  244. { Windows API                                                                  }
  245. {                                                                              }
  246. Function GetWindowsTemporaryPath : String;
  247. const MaxTempPathLen = MAX_PATH + 1;
  248. var I : LongWord;
  249.   Begin
  250.     SetLength (Result, MaxTempPathLen);
  251.     I := GetTempPath (MaxTempPathLen, PChar (Result));
  252.     if I > 0 then
  253.       SetLength (Result, I) else
  254.       Result := '';
  255.   End;
  256.  
  257. Function GetWindowsPath : String;
  258. const MaxWinPathLen = MAX_PATH + 1;
  259. var I : LongWord;
  260.   Begin
  261.     SetLength (Result, MaxWinPathLen);
  262.     I := GetWindowsDirectory (PChar (Result), MaxWinPathLen);
  263.     if I > 0 then
  264.       SetLength (Result, I) else
  265.       Result := '';
  266.   End;
  267.  
  268. Function GetWindowsSystemPath : String;
  269. const MaxWinSysPathLen = MAX_PATH + 1;
  270. var I : LongWord;
  271.   Begin
  272.     SetLength (Result, MaxWinSysPathLen);
  273.     I := GetSystemDirectory (PChar (Result), MaxWinSysPathLen);
  274.     if I > 0 then
  275.       SetLength (Result, I) else
  276.       Result := '';
  277.   End;
  278.  
  279. Function GetProgramFilesPath : String;
  280.   Begin
  281.     Result := GetRegistryString (HKEY_LOCAL_MACHINE,
  282.            'Software\Microsoft\Windows\CurrentVersion', 'ProgramFilesDir');
  283.   End;
  284.  
  285. Function GetApplicationPath : String;
  286.   Begin
  287.     Result := ExtractFilePath (ParamStr (0));
  288.     EnsureSuffix (Result, '\');
  289.   End;
  290.  
  291. Function GetUserName : String;
  292. const MAX_USERNAME_LENGTH = 256;
  293. var L : LongWord;
  294.   Begin
  295.     L := MAX_USERNAME_LENGTH + 2;
  296.     SetLength (Result, L);
  297.     if Windows.GetUserName (PChar (Result), L) and (L > 0) then
  298.       SetLength (Result, StrLen (PChar (Result))) else
  299.       Result := '';
  300.   End;
  301.  
  302. Function GetLocalComputerName : String;
  303. var L : LongWord;
  304.   Begin
  305.     L := MAX_COMPUTERNAME_LENGTH + 2;
  306.     SetLength (Result, L);
  307.     if Windows.GetComputerName (PChar (Result), L) and (L > 0) then
  308.       SetLength (Result, StrLen (PChar (Result))) else
  309.       Result := '';
  310.   End;
  311.  
  312. Function GetLocalHostName : String;
  313. const MAX_HOST_LENGTH = MAX_PATH;
  314. var WSAData : TWSAData;
  315.     L       : LongWord;
  316.   Begin
  317.     if WSAStartup ($0101, WSAData) = 0 then
  318.       try
  319.         L := MAX_HOST_LENGTH + 2;
  320.         SetLengthAndZero (Result, L);
  321.         if GetHostName (PChar (Result), L) = 0 then
  322.           SetLength (Result, StrLen (PChar (Result))) else
  323.           Result := '';
  324.       finally
  325.         WSACleanup;
  326.       end;
  327.   End;
  328.  
  329. Function GetEnvironmentStrings : StringArray;
  330. var P, Q : PChar;
  331.     I : Integer;
  332.     S : String;
  333.   Begin
  334.     P := PChar (Windows.GetEnvironmentStrings);
  335.     try
  336.       if P^ <> #0 then
  337.         Repeat
  338.           Q := P;
  339.           I := 0;
  340.           While Q^ <> #0 do
  341.             begin
  342.               Inc (Q);
  343.               Inc (I);
  344.             end;
  345.           SetLength (S, I);
  346.           if I > 0 then
  347.             Move (P^, Pointer (S)^, I);
  348.           Append (Result, S);
  349.           P := Q;
  350.           Inc (P);
  351.         Until P^ = #0;
  352.     finally
  353.       FreeEnvironmentStrings (P);
  354.     end;
  355.   End;
  356.  
  357. Function ContentTypeFromExtention (Extention : String) : String;
  358.   Begin
  359.     Result := GetRegistryString (HKEY_CLASSES_ROOT, '\' + Extention, 'Content Type');
  360.   End;
  361.  
  362. const
  363.   AutoRunRegistryKey = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Run';
  364.  
  365. Function  IsApplicationAutoRun (const Name : String) : Boolean;
  366. var S : String;
  367.   Begin
  368.     S := ParamStr (0);
  369.     Result := (S <> '') and (Name <> '') and
  370.         IsEqualNoCase (GetRegistryString (HKEY_LOCAL_MACHINE, AutoRunRegistryKey, Name), S);
  371.   End;
  372.  
  373. Procedure SetApplicationAutoRun (const Name : String; const AutoRun : Boolean);
  374.   Begin
  375.     if Name = '' then
  376.       exit;
  377.     if AutoRun then
  378.       SetRegistryString (HKEY_LOCAL_MACHINE, AutoRunRegistryKey, Name, ParamStr (0)) else
  379.       DeleteRegistryValue (HKEY_LOCAL_MACHINE, AutoRunRegistryKey, Name);
  380.   End;
  381.  
  382. Function GetWinPortNames : StringArray;
  383. var BytesNeeded, N, I : LongWord;
  384.     Buf : Pointer;
  385.     InfoPtr : PPortInfo1;
  386.     TempStr : String;
  387.   Begin
  388.     Result := nil;
  389.     if EnumPorts (nil, 1, nil, 0, BytesNeeded, N) then
  390.       exit;
  391.     if GetLastError <> ERROR_INSUFFICIENT_BUFFER then
  392.       RaiseLastOSError;
  393.  
  394.     GetMem (Buf, BytesNeeded);
  395.     try
  396.       if not EnumPorts (nil, 1, Buf, BytesNeeded, BytesNeeded, N) then
  397.         RaiseLastOSError;
  398.       For I := 0 to N - 1 do
  399.         begin
  400.           InfoPtr := PPortInfo1 (LongWord (Buf) + I * SizeOf (TPortInfo1));
  401.           TempStr := InfoPtr^.pName;
  402.           Append (Result, TempStr);
  403.         end;
  404.     finally
  405.       FreeMem(Buf);
  406.     end;
  407.   End;
  408.  
  409. Function GetKeyPressed (const VKeyCode : Integer) : Boolean;
  410.   Begin
  411.     Result := GetKeyState (VKeyCode) and $80 <> 0;
  412.   End;
  413.  
  414.  
  415.  
  416. {                                                                              }
  417. { Windows Version Info                                                         }
  418. {                                                                              }
  419. Function GetWinOSType : TWinOSType;
  420.   Begin
  421.     Case Win32Platform of
  422.       VER_PLATFORM_WIN32s :
  423.         Result := win31;
  424.       VER_PLATFORM_WIN32_WINDOWS :
  425.         begin
  426.           Result := win32_95;
  427.           if Win32MajorVersion = 4 then
  428.             if Win32MinorVersion >= 90 then
  429.               Result := win32_ME else
  430.             if Win32MinorVersion >= 10 then
  431.               Result := win32_98;
  432.         end;
  433.       VER_PLATFORM_WIN32_NT :
  434.         begin
  435.           Result := win32_nt;
  436.           if Win32MajorVersion = 5 then
  437.             if Win32MinorVersion >= 1 then
  438.               Result := win32_xp else
  439.               Result := win32_2000;
  440.         end;
  441.     else
  442.       Result := win_UnknownPlatform;
  443.     end;
  444.   End;
  445.  
  446. Function IsWinNTFamily : Boolean;
  447.   Begin
  448.     Result := Win32Platform = VER_PLATFORM_WIN32_NT;
  449.   End;
  450.  
  451. Function IsWin95Family : Boolean;
  452.   Begin
  453.     Result := Win32Platform = VER_PLATFORM_WIN32_WINDOWS;
  454.   End;
  455.  
  456.  
  457.  
  458. {                                                                              }
  459. { Application Version Info                                                     }
  460. {                                                                              }
  461. var
  462.   VersionInfoBuf : Pointer = nil;
  463.   VerTransStr    : String;
  464.  
  465. Procedure LoadAppVersionInfo;
  466. type TTransBuffer = Array [1..4] of SmallInt;
  467.      PTransBuffer = ^TTransBuffer;
  468. var InfoSize : Integer;
  469.     Size, H : LongWord;
  470.     EXEName : String;
  471.     Trans : PTransBuffer;
  472.   Begin
  473.     if Assigned (VersionInfoBuf) then
  474.       exit;
  475.     EXEName := ParamStr (0);
  476.     InfoSize := GetFileVersionInfoSize (PChar (EXEName), H);
  477.     if InfoSize = 0 then
  478.       exit;
  479.     GetMem (VersionInfoBuf, InfoSize);
  480.     if not GetFileVersionInfo (PChar (EXEName), H, InfoSize, VersionInfoBuf) then
  481.       begin
  482.         FreeMem (VersionInfoBuf);
  483.         VersionInfoBuf := nil;
  484.         exit;
  485.       end;
  486.     VerQueryValue (VersionInfoBuf, PChar ('\VarFileInfo\Translation'),
  487.                    Pointer (Trans), Size);
  488.     VerTransStr := IntToHex (Trans^ [1], 4) + IntToHex (Trans^ [2], 4);
  489.   End;
  490.  
  491. const
  492.   VersionInfoStr : Array [TVersionInfo] of String =
  493.     ('FileVersion', 'FileDescription', 'LegalCopyright', 'Comments',
  494.      'CompanyName', 'InternalName', 'LegalTrademarks',
  495.      'OriginalFilename', 'ProductName', 'ProductVersion');
  496.  
  497. Function GetAppVersionInfo (const VersionInfo : TVersionInfo) : String;
  498. var S : String;
  499.     Size : LongWord;
  500.     Value : PChar;
  501.   Begin
  502.     LoadAppVersionInfo;
  503.     S := 'StringFileInfo\' + VerTransStr + '\' + VersionInfoStr [VersionInfo];
  504.     if not VerQueryvalue (VersionInfoBuf, PChar (S), Pointer (Value), Size) then
  505.       Result := '' else
  506.       Result := Value;
  507.   End;
  508.  
  509. Function WinExecute (const ExeName, Params : String; const ShowWin : Word; const Wait : Boolean) : Boolean;
  510. var StartUpInfo : TStartupInfo;
  511.     ProcessInfo    : TProcessInformation;
  512.     Cmd         : String;
  513.   Begin
  514.     if Params = '' then
  515.       Cmd := ExeName else
  516.       Cmd := ExeName + ' ' + Params;
  517.     FillChar (StartUpInfo, SizeOf (StartUpInfo), #0);
  518.     StartUpInfo.cb := SizeOf (StartUpInfo);
  519.     StartUpInfo.dwFlags := STARTF_USESHOWWINDOW;
  520.     StartUpInfo.wShowWindow := ShowWin;
  521.     Result := CreateProcess(
  522.              nil, PChar (Cmd), nil, nil, False,
  523.              CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil,
  524.              PChar (ExtractFilePath (ExeName)), StartUpInfo, ProcessInfo);
  525.     if Wait then
  526.       WaitForSingleObject (ProcessInfo.hProcess, INFINITE);
  527.   End;
  528.  
  529. Function GetHardDiskSerialNumber (const DriveLetter : Char) : String;
  530. var N, F, S : DWORD;
  531.   Begin
  532.     S := 0;
  533.     GetVolumeInformation (PChar (DriveLetter + ':\'), nil, MAX_PATH + 1, @S,
  534.         N, F, nil, 0);
  535.     Result := LongWordToHex (S, 8);
  536.   End;
  537.  
  538. Function GetWindowsProductID : String;
  539. var S : String;
  540.   Begin
  541.     if IsWinNTFamily then
  542.       S := 'Software\Microsoft\Windows NT\CurrentVersion' else
  543.       S := 'Software\Microsoft\Windows\CurrentVersion';
  544.     Result := GetRegistryString (HKEY_LOCAL_MACHINE, S, 'ProductID');
  545.   End;
  546.  
  547. Function GetMACAdresses (var Adresses : StringArray; const MachineName : String) : Integer;
  548.  
  549.   Function NetBiosCheck (const B : Char) : Boolean;
  550.     Begin
  551.       Result := B = Char (NRC_GOODRET);
  552.     End;
  553.  
  554.   Procedure MachineNameToAdapter (const Name : String; var AdapterName : Array of char);
  555.   var S : String;
  556.     Begin
  557.       if Name = '' then
  558.         S := '*' else
  559.         S := UpperCase (Name);
  560.       FillChar (AdapterName, Length (AdapterName), #0);
  561.       Move (Pointer (S)^, AdapterName [0], Length (S));
  562.     End;
  563.  
  564.   Function AdapterToString (const Adapter : PAdapterStatus) : String;
  565.   var I : Integer;
  566.     Begin
  567.       Result := '';
  568.       With Adapter^ do
  569.         For I := 0 to 5 do
  570.           Result := Result + LongWordToHex (Ord (adapter_address [I]), 2);
  571.   end;
  572.  
  573. var I : Integer;
  574.     NCB : TNCB;
  575.     Adapter : TAdapterStatus;
  576.     Lenum : TLanaEnum;
  577.     RetCode:char;
  578.   Begin
  579.     Adresses := nil;
  580.     FillChar (NCB, SizeOf (TNCB), #0);
  581.     FillChar (Lenum, SizeOf (TLanaEnum), #0);
  582.     NCB.ncb_command := char (NCBENUM);
  583.     NCB.ncb_buffer := @Lenum;
  584.     NCB.ncb_length := SizeOf (Pointer);
  585.     if not NetBiosCheck (Netbios (@NCB)) then
  586.       begin
  587.         Result := 0;
  588.         exit;
  589.       end;
  590.     Result := Ord (Lenum.Length);
  591.     for i := 0 to Result - 1 do
  592.       begin
  593.         FillChar (NCB, SizeOf (TNCB), #0);
  594.         Ncb.ncb_command := Char (NCBRESET);
  595.         Ncb.ncb_lana_num := lenum.lana [i];
  596.         if NetBiosCheck (Netbios (@NCB)) then
  597.           begin
  598.             FillChar (NCB, SizeOf (TNCB), #0);
  599.             FillChar (Adapter, SizeOf (TAdapterStatus), #0);
  600.             Ncb.ncb_command := Char (NCBASTAT);
  601.             Ncb.ncb_lana_num := lenum.lana [i];
  602.             MachineNameToAdapter (MachineName, Ncb.ncb_callname);
  603.             Ncb.ncb_buffer := @Adapter;
  604.             Ncb.ncb_length := SizeOf (TAdapterStatus);
  605.             RetCode := Netbios (@NCB);
  606.             if RetCode in [Char (NRC_GOODRET), Char (NRC_INCOMP)] then
  607.               Append (Adresses, AdapterToString (@Adapter));
  608.           end;
  609.       end;
  610.   End;
  611.  
  612.  
  613.  
  614. {                                                                              }
  615. { TWindowHandle                                                                }
  616. {                                                                              }
  617. Function WindowHandleMessageProc (const WindowHandle : HWND; const Msg : Cardinal;
  618.     const wParam, lParam : Integer) : Integer; stdcall;
  619. var V : TObject;
  620.   Begin
  621.     V := TObject (GetWindowLong (WindowHandle, 0)); // Get user data
  622.     if V is TWindowHandle then
  623.       Result := TWindowHandle (V).HandleWM (Msg, wParam, lParam) else
  624.       Result := DefWindowProc (WindowHandle, Msg, wParam, lParam); // Default handler
  625.   End;
  626.  
  627. var
  628.   WindowClass : TWndClass = (
  629.       style         : 0;
  630.       lpfnWndProc   : @WindowHandleMessageProc;
  631.       cbClsExtra    : 0;
  632.       cbWndExtra    : SizeOf (Pointer); // Size of extra user data
  633.       hInstance     : 0;
  634.       hIcon         : 0;
  635.       hCursor       : 0;
  636.       hbrBackground : 0;
  637.       lpszMenuName  : nil;
  638.       lpszClassName : 'FundamentalsWindowClass');
  639.  
  640. Destructor TWindowHandle.Destroy;
  641.   Begin
  642.     DestroyWindowHandle;
  643.     inherited Destroy;
  644.   End;
  645.  
  646. Procedure TWindowHandle.RaiseError (const Msg : String);
  647.   Begin
  648.     raise EWindowHandle.Create (Msg);
  649.   End;
  650.  
  651. Function TWindowHandle.AllocateWindowHandle : HWND;
  652. var C : TWndClass;
  653.   Begin
  654.     WindowClass.hInstance := HInstance;
  655.     // Register class
  656.     if not GetClassInfo (HInstance, WindowClass.lpszClassName, C) then
  657.       if Windows.RegisterClass (WindowClass) = 0 then
  658.         RaiseError ('Window class registration failed: Windows error #' + IntToStr (GetLastError));
  659.  
  660.     // Allocate handle
  661.     Result := CreateWindowEx (WS_EX_TOOLWINDOW,
  662.                               WindowClass.lpszClassName,
  663.                               '',        { Window name   }
  664.                               WS_POPUP,  { Window Style  }
  665.                               0, 0,      { X, Y          }
  666.                               0, 0,      { Width, Height }
  667.                               0,         { hWndParent    }
  668.                               0,         { hMenu         }
  669.                               HInstance, { hInstance     }
  670.                               nil);      { CreateParam   }
  671.     if Result = 0 then
  672.       RaiseError ('Window handle allocation failed: Windows error #' + IntToStr (GetLastError));
  673.  
  674.     // Set user data
  675.     SetWindowLong (Result, 0, Integer (self));
  676.   End;
  677.  
  678. Function TWindowHandle.HandleWM (const Msg : Cardinal; const wParam, lParam : Integer) : Integer;
  679. var Handled : Boolean;
  680.   Begin
  681.     Result := 0;
  682.     Handled := False;
  683.     try
  684.       if Assigned (FOnMessage) then
  685.         Result := FOnMessage (Msg, wParam, lParam, Handled);
  686.       if not Handled then
  687.         Result := DefWindowProc (FWindowHandle, Msg, wParam, lParam); // Default handler
  688.     except
  689.       on E : Exception do
  690.         begin
  691.           if Assigned (FOnException) then
  692.             FOnException (self, E);
  693.           exit;
  694.         end;
  695.     end;
  696.   End;
  697.  
  698. Function TWindowHandle.GetWindowHandle : HWND;
  699.   Begin
  700.     Result := FWindowHandle;
  701.     if Result = 0 then
  702.       begin
  703.         FWindowHandle := AllocateWindowHandle;
  704.         Result := FWindowHandle;
  705.       end;
  706.   End;
  707.  
  708. Procedure TWindowHandle.DestroyWindowHandle;
  709.   Begin
  710.     if FWindowHandle = 0 then
  711.       exit;
  712.  
  713.     // Clear user data
  714.     SetWindowLong (FWindowHandle, 0, 0);
  715.  
  716.     DestroyWindow (FWindowHandle);
  717.     FWindowHandle := 0;
  718.   End;
  719.  
  720. Function TWindowHandle.ProcessMessage : Boolean;
  721. var Msg : TMsg;
  722.   Begin
  723.     if FTerminated then
  724.       begin
  725.         Result := False;
  726.         exit;
  727.       end;
  728.     Result := PeekMessage (Msg, 0, 0, 0, PM_REMOVE);
  729.     if Result then
  730.       if Msg.Message = WM_QUIT then
  731.         FTerminated := True else
  732.         if FTerminated then
  733.           Result := False else
  734.           begin
  735.             TranslateMessage (Msg);
  736.             DispatchMessage (Msg);
  737.           end;
  738.   End;
  739.  
  740. Procedure TWindowHandle.ProcessMessages;
  741.   Begin
  742.     While ProcessMessage do ;
  743.   End;
  744.  
  745. Function TWindowHandle.HandleMessage : Boolean;
  746. var Msg : TMsg;
  747.   Begin
  748.     if FTerminated then
  749.       begin
  750.         Result := False;
  751.         exit;
  752.       end;
  753.     Result := GetMessage (Msg, 0, 0, 0);
  754.     if not Result then
  755.       FTerminated := True else
  756.       if FTerminated then
  757.         Result := False else
  758.         begin
  759.           TranslateMessage (Msg);
  760.           DispatchMessage (Msg)
  761.         end;
  762.   End;
  763.  
  764. Procedure TWindowHandle.MessageLoop;
  765.   Begin
  766.     While HandleMessage do ;
  767.   End;
  768.  
  769. Procedure TWindowHandle.Terminate;
  770.   Begin
  771.     FTerminated := True;
  772.   End;
  773.  
  774.  
  775.  
  776. {                                                                              }
  777. { TTimerHandle                                                                 }
  778. {                                                                              }
  779. Constructor TTimerHandle.Create (AOwner : TComponent);
  780.   Begin
  781.     inherited Create (AOwner);
  782.     FTimerInterval := 1000;
  783.   End;
  784.  
  785. Procedure TTimerHandle.DestroyWindowHandle;
  786.   Begin
  787.     if not (csDesigning in ComponentState) and (FWindowHandle <> 0) and
  788.         FTimerActive then
  789.       KillTimer (FWindowHandle, 1);
  790.     inherited DestroyWindowHandle;
  791.   End;
  792.  
  793. Function TTimerHandle.DoSetTimer : Boolean;
  794.   Begin
  795.     if FTimerInterval <= 0 then
  796.       Result := False else
  797.       Result := SetTimer (GetWindowHandle, 1, FTimerInterval, nil) = 0;
  798.   End;
  799.  
  800. Procedure TTimerHandle.Loaded;
  801.   Begin
  802.     inherited Loaded;
  803.     if not (csDesigning in ComponentState) and FTimerActive then
  804.       DoSetTimer;
  805.   End;
  806.  
  807. Procedure TTimerHandle.TriggerTimer;
  808.   Begin
  809.     if Assigned (FOnTimer) then
  810.       FOnTimer (self);
  811.   End;
  812.  
  813. Procedure TTimerHandle.SetTimerActive (const TimerActive : Boolean);
  814.   Begin
  815.     if FTimerActive = TimerActive then
  816.       exit;
  817.     if [csDesigning, csLoading] * ComponentState = [] then
  818.       if TimerActive then
  819.         begin
  820.           if not DoSetTimer then
  821.             exit;
  822.         end else
  823.         KillTimer (FWindowHandle, 1);
  824.     FTimerActive := TimerActive;
  825.   End;
  826.  
  827. Function TTimerHandle.HandleWM (const Msg : Cardinal; const wParam, lParam : Integer) : Integer;
  828.   Begin
  829.     if Msg = WM_TIMER then
  830.       try
  831.         Result := 0;
  832.         TriggerTimer;
  833.       except
  834.         on E : Exception do
  835.           begin
  836.             Result := 0;
  837.             if Assigned (FOnException) then
  838.               FOnException (self, E);
  839.             exit;
  840.           end;
  841.       end else
  842.       Result := inherited HandleWM (Msg, wParam, lParam);
  843.   End;
  844.  
  845.  
  846.  
  847. {                                                                              }
  848. { Component Register                                                           }
  849. {                                                                              }
  850. Procedure Register;
  851.   Begin
  852.     RegisterComponents ('Fundamentals', [TfndWindowHandle, TfndTimerHandle]);
  853.   End;
  854.  
  855.  
  856.  
  857. initialization
  858. finalization
  859.   if Assigned (VersionInfoBuf) then
  860.     FreeMem (VersionInfoBuf);
  861. end.
  862.  
  863.