home *** CD-ROM | disk | FTP | other *** search
/ Chip 1999 January / Chip_1999-01_cd.bin / zkuste / delphi / D1 / JUSTONE.ZIP / J1_32.ZIP / Just1_32.pas < prev   
Pascal/Delphi Source File  |  1996-03-17  |  7KB  |  225 lines

  1. {
  2. JustOne v1.2
  3. (32 bit version)
  4. By: Steven L. Keyser
  5. March 17, 1996
  6. CompuServe Address:    71214,3117
  7. e-mail                            71214.3117@compuserve.com
  8.  
  9. Purpose:  JustOne is a Delphi component which allows the developer of an
  10. application to easily limit the number of that app's instances to just one.
  11. When a user attempts to start a second instance of the application, JustOne
  12. checks for the existence of a previous instance.  If one is found, JustOne
  13. brings the first instance to the front and stops the second instance from
  14. fully launching.  If the first instance was minimized to an icon, it is
  15. 'RESTORED' to its previous
  16.  
  17. Version 1.2    - This is the first release of the 32 bit version of JustOne.
  18. (3/17/96)            While this version is functionally equivalent to the 16 bit
  19.                             version, the code is significantly different as earlier versions
  20.               relied on Windows 3.1 features not supported in WIN95.
  21.  
  22. Version 1.1 -    16 bit version...
  23. (1/14/96)            - Added the 'About' property
  24.                             - Eliminated the AllowMultInst property
  25.               - Eliminated the Execute property
  26.               - Added help file
  27.               - Added keyword file
  28.  
  29. Version 1.0 -    16 bit version... Original release
  30. (Oct '95)
  31.  
  32. Comments:            This source code includes the support of an 'About' box
  33.                             appearing as a property on the JustOne component in design mode.
  34.               To see how to add 'About' properties to your own components,
  35.               perform a search on this file for the word 'about', then utilze
  36.               those sections and concepts in your own work.
  37.  
  38. }
  39. unit Just1_32;
  40.  
  41. interface
  42.  
  43. uses
  44.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  45.   Dialogs, DsgnIntf;
  46.  
  47. type
  48.   TJustOne32 = class(TComponent)
  49.   private
  50.     FAbout:    string;
  51.   public
  52.     constructor Create(AOwner:TComponent); override;
  53.     destructor Destroy; override;
  54.     procedure ShowAbout;
  55.   published
  56.     property About: string read FAbout write FAbout stored False;
  57.   end;
  58.  
  59. type
  60.     TPreviousInstance = class(TObject)
  61.   private
  62.         FAppName: string;
  63.     FMutexHandle: THandle;
  64.     FhPrevInst: boolean;
  65.     function GetAppName: string;
  66.     procedure SetAppName(filename: string);
  67.   public
  68.     property AppName: string read GetAppName write SetAppName;
  69.     property MutexHandle: THandle read FMutexHandle write FMutexHandle;
  70.     property hPrevInst: boolean read FhPrevInst write FhPrevInst;
  71.        procedure SethPrevInst;
  72.   end;
  73.  
  74. procedure Register;
  75.  
  76. implementation
  77. var
  78.     PreviousInstance1: TPreviousInstance;
  79.  
  80. {########################################################################}
  81. function TPreviousInstance.GetAppName: string;
  82. begin
  83.   GetAppName := FAppName;
  84. end;
  85. {########################################################################}
  86. procedure TPreviousInstance.SetAppName(filename: string);
  87. begin
  88.     {check to see if the filename includes the '.exe' extension}
  89.   if Pos('.EXE', filename) > 0 then
  90.       {delete the extension and reset the AppName field}
  91.        FAppName := Copy(filename, 1, (Length(filename) - 4));
  92.  
  93. end;
  94. {########################################################################}
  95. type
  96.   TAboutProperty = class(TPropertyEditor)
  97.   public
  98.     procedure Edit; override;
  99.     function GetAttributes: TPropertyAttributes; override;
  100.     function GetValue:string; override;
  101.   end;
  102.  
  103. {#############################################################################}
  104. procedure Register;
  105. begin
  106.     {JustOne will appear on a new component palette page called 'SLicK'.  If
  107.   you want it on a different page, replace 'SLicK' below with the page name
  108.   of your choice.}
  109.   RegisterComponents('SLicK', [TJustOne32]);
  110.   {register the 'About' property editor}
  111.   RegisterPropertyEditor(TypeInfo(String), TJustOne32, 'About',
  112.       TAboutProperty);
  113. end;
  114.  
  115. {#############################################################################}
  116. procedure TPreviousInstance.SethPrevInst;
  117. var
  118.      zAppName: array[0..260] of char;
  119. begin
  120.     {get the filename of the current program}
  121.      StrPCopy(zAppName, ExtractFileName(ParamStr(0)));
  122.   {save the filename for future use}
  123.   PreviousInstance1.AppName := StrPas(zAppName);
  124.   {see if the named mutex object existed before this call}
  125.      MutexHandle := CreateMutex(nil, TRUE, zAppName);
  126.      if MutexHandle <> 0 then
  127.       begin
  128.     if GetLastError = ERROR_ALREADY_EXISTS then
  129.         {set hPrevInst property and close the mutex handle}
  130.       begin
  131.           hPrevInst := TRUE;
  132.           CloseHandle(MutexHandle);
  133.       end
  134.        else
  135.         {indicate no previous instance was found}
  136.          hPrevInst := FALSE;
  137.        end
  138.   else
  139.        {indicate no previous instance was found}
  140.          hPrevInst := FALSE;
  141. end;
  142. {########################################################################}
  143. constructor TJustOne32.Create(AOwner:TComponent);
  144. var
  145.   PrevInstHandle: THandle;
  146.   zAppName : array[0..260] of char;
  147. begin
  148.     inherited Create(AOwner);
  149.  
  150.     if PreviousInstance1.hPrevInst = TRUE then
  151.     begin
  152.       {convert the Pascal string filename into a null terminated string}
  153.       StrPCopy(zAppName, PreviousInstance1.AppName);
  154.       {find the current window's handle}
  155.             PrevInstHandle := FindWindow(nil, zAppName);
  156.       {change the current window's name to something else (literally)<g>}
  157.       SetWindowText(PrevInsthandle, 'something else');
  158.       {now, we can find the previous window's handle (the one we really want!)}
  159.             PrevInstHandle := FindWindow(nil, zAppName);
  160.       {bring the first instance to the front}
  161.       if PrevInstHandle <> 0 then
  162.               begin
  163.             if IsIconic(PrevInstHandle) then
  164.               ShowWindow(PrevInstHandle,SW_RESTORE)
  165.           else
  166.               BringWindowToTop(PrevInstHandle);
  167.         end;
  168.       {terminate execution of the second instance}
  169.       halt;
  170.     end;
  171.  
  172. end;
  173. {########################################################################}
  174. destructor TJustOne32.Destroy;
  175. begin
  176.   inherited Destroy;
  177. end;
  178. {########################################################################}
  179. procedure TAboutProperty.Edit;
  180. {call the 'About' dialog window when clicking on ... in the Object Inspector}
  181. begin
  182.   TJustOne32(GetComponent(0)).ShowAbout;
  183. end;
  184.  
  185. {########################################################################}
  186. function TAboutProperty.GetAttributes: TPropertyAttributes;
  187. {set up to display a string in the Object Inspector}
  188. begin
  189.   GetAttributes := [paDialog, paReadOnly];
  190. end;
  191.  
  192. {########################################################################}
  193. function TAboutProperty.GetValue: String;
  194. {set string to appear in the Object Inspector}
  195. begin
  196.   GetValue := '(About)';
  197. end;
  198.  
  199. {########################################################################}
  200. procedure TJustOne32.ShowAbout;
  201. var
  202.     msg: string;
  203. const
  204.   cr = chr(13);
  205. begin
  206.   msg := 'JustOne  v1.2' + cr + 'A Freeware component' + cr;
  207.   msg := msg + '(32 bit version)' + cr + cr;
  208.   msg := msg + 'Copyright ⌐ 1995, 1996 Steven L. Keyser' + cr;
  209.   msg := msg + 'e-mail 71214.3117@compuserve.com' + cr;
  210.   ShowMessage(msg);
  211. end;
  212. {########################################################################}
  213. initialization
  214.     PreviousInstance1 := TPreviousInstance.Create;
  215.   PreviousInstance1.SethPrevInst;
  216. {#############################################################################}
  217. finalization
  218.     CloseHandle(PreviousInstance1.MutexHandle);
  219. {########################################################################}
  220. end.
  221.  
  222.  
  223.  
  224.  
  225.