Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
swdev:howto:develop_com_components_and_automation [2009/10/06 10:54]
smayr
swdev:howto:develop_com_components_and_automation [2009/11/05 11:12] (current)
smayr
Line 78: Line 78:
 procedure TfrmClientMain.btnLaunchSvrClick(Sender: TObject); procedure TfrmClientMain.btnLaunchSvrClick(Sender: TObject);
 begin begin
-  svr    := CoMySvr.Create();+  if not Assigned(svr) then begin 
 +    svr := CoMySvr.Create()
 +  end;
   if Assigned(svr) then begin   if Assigned(svr) then begin
     btnGetSvrVersion.Enabled := True;     btnGetSvrVersion.Enabled := True;
Line 91: Line 93:
  
 == Wrapping an Existing Application Functionality in an Automation Object == == Wrapping an Existing Application Functionality in an Automation Object ==
 +Especially use this method for Out-of-process automation servers:
  * Open an existing Delphi application project.   * Open an existing Delphi application project. 
     * Select New > ActiveX > Automation Object.     * Select New > ActiveX > Automation Object.
Line 98: Line 101:
       * Select ''IMySvr'', then add Method or Property.       * Select ''IMySvr'', then add Method or Property.
  * Register the COM Server.  Perform one of these:  * Register the COM Server.  Perform one of these:
-    * Select Run > Register ActiveX Server. +    * In-process (DLL) automation server: 
-    * Setup project to auto register server, to avoid littering the Windows Registry while developing.  +      * Select Run > Register ActiveX Server. 
-      * Select Project > Options > Linker > Auto register type library.+      * Setup project to auto register server, to avoid littering the Windows Registry while developing.  
 +        * Select Project > Options > Linker > Auto register type library. 
 +      * Register from command line: <code>C:\> regsvr32 myServer.dll </code> or <code>C:\> tregsvr myServer.dll</code> 
 +    * Out-of-process (EXE) automation server: 
 +      * To register, run this from command line: <code>C:\> myapp.exe /regserver </code> 
 +      * To unregister, run this from command line: <code>C:\> myapp.exe /unregserver </code>
  
 == Linking Multiple Clients to a Single Instance of a COM Object == == Linking Multiple Clients to a Single Instance of a COM Object ==
Line 182: Line 190:
 <code delphi> <code delphi>
 //----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
-// description: Initialize a safearray to 99, using SafeArrayAccessData().+// description: Print the contents of a safearray, using SafeArrayAccessData().
 // parameters : sfArr: PSafeArray (assumed the array has been allocated already). // parameters : sfArr: PSafeArray (assumed the array has been allocated already).
 // return     : None // return     : None
 //----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
-procedure PrnSafearray(sfArr: PSafeArray); +procedure PrnSafearray(sfArr: PSafeArray);
 var var
-  LBound, HBound: integer;+  LBound, UBound: integer
 +  sfArrData: pointer; 
 +  ElemData: integer; 
 +  i: integer; 
 +  str: string;
 begin begin
   // get PSafeArray boundaries   // get PSafeArray boundaries
   SafeArrayGetLBound(sfArr, 1, LBound);   SafeArrayGetLBound(sfArr, 1, LBound);
-  SafeArrayGetUBound(sfArr, 1, HBound); +  SafeArrayGetUBound(sfArr, 1, UBound); 
- +
   // read data from safearray   // read data from safearray
 +  str := '';
 +  for i := LBound to UBound do begin
   if SafeArrayAccessData( sfArr, sfArrData ) = S_OK then begin   if SafeArrayAccessData( sfArr, sfArrData ) = S_OK then begin
     for i := LBound to UBound do begin     for i := LBound to UBound do begin
-        format('sfArr[%d] = %d', [i, TIntegerArray(sfArrData)[i]); // get data from safearray and print it+        ElemData := TIntegerArray(sfArrData)[i];              // get data from safearray 
 +        str := str + format('sfArr[%d] = %d'+#13#10, [i, ElemData]); // save it for later
     end;     end;
   end;   end;
   SafeArrayUnAccessData(sfArr);   SafeArrayUnAccessData(sfArr);
-  ...+  ShowMessage(str);
 end; end;
 +
    
 //----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
-// description: Initialize a safearray to 99, using SafearrayPutElement().+// description: Print the contents of a safearray, using SafearrayGutElement().
 // parameters : sfArr: PSafeArray (assumed the array has been allocated already). // parameters : sfArr: PSafeArray (assumed the array has been allocated already).
 // return     : None // return     : None
Line 211: Line 227:
 procedure PrnSafearray(sfArr: PSafeArray);  procedure PrnSafearray(sfArr: PSafeArray); 
 var var
-  LBound, HBound: integer;+  LBound, UBound : integer;
   ElemData: integer;   ElemData: integer;
 +  i: integer;
 +  str: string;
 begin begin
   // get PSafeArray boundaries   // get PSafeArray boundaries
   SafeArrayGetLBound(sfArr, 1, LBound);   SafeArrayGetLBound(sfArr, 1, LBound);
-  SafeArrayGetUBound(sfArr, 1, HBound);+  SafeArrayGetUBound(sfArr, 1, UBound );
    
   // read data from safearray   // read data from safearray
 +  str := '';
   for i := LBound to UBound do begin   for i := LBound to UBound do begin
     SafearrayGetElement(sfArr, i, ElemData);     SafearrayGetElement(sfArr, i, ElemData);
-    format('sfArr[%d] = %d', [i, ElemData]); // get data from safearray and print it+    str := str + format('sfArr[%d] = %d'+#13#10, [i, ElemData]); // get data from safearray and print it
   end;   end;
-  ...+  ShowMessage(str);
 end; end;
 </code> </code>
Line 236: Line 255:
 function SafeArrayToIntArr(sfArr: PSafeArray): TIntegerArray; function SafeArrayToIntArr(sfArr: PSafeArray): TIntegerArray;
 var var
-  ArrayBounds: TSafeArrayBound; 
-  ArrayData: pointer; 
-  i: integer; 
   LBound, UBound: integer;   LBound, UBound: integer;
 +  sfArrData: pointer;
 +  i: integer;
   Arr: TIntegerArray;   Arr: TIntegerArray;
 begin begin
Line 250: Line 268:
  
   // copy data from safearray to integer array   // copy data from safearray to integer array
-  if SafeArrayAccessData( sfArr, ArrayData ) = S_OK then begin+  if SafeArrayAccessData( sfArr, sfArrData ) = S_OK then begin
     for i:= LBound to UBound do begin     for i:= LBound to UBound do begin
-       arr[i] := TIntegerArray(ArrayData)[i];+       arr[i] := TIntegerArray(sfArrData)[i];
     end;     end;
     SafeArrayUnAccessData(sfArr);     SafeArrayUnAccessData(sfArr);
Line 270: Line 288:
 procedure InitSafearrayTo99(var sfArr: PSafeArray);  procedure InitSafearrayTo99(var sfArr: PSafeArray); 
 var var
-  LBound, HBound: integer;+  LBound, UBound: integer
 +  sfArrData: pointer;
 begin begin
   // get PSafeArray boundaries   // get PSafeArray boundaries
   SafeArrayGetLBound(sfArr, 1, LBound);   SafeArrayGetLBound(sfArr, 1, LBound);
-  SafeArrayGetUBound(sfArr, 1, HBound);+  SafeArrayGetUBound(sfArr, 1, UBound);
  
   // copy data to safearray   // copy data to safearray
Line 295: Line 314:
   LBound, HBound: integer;   LBound, HBound: integer;
   i: integer;   i: integer;
 +  ElemData: integer;
 begin begin
-  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
-  // Fill safearray 
-  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
   // get PSafeArray boundaries   // get PSafeArray boundaries
   SafeArrayGetLBound(sfArr, 1, LBound);   SafeArrayGetLBound(sfArr, 1, LBound);
Line 304: Line 321:
  
   // copy data to safearray   // copy data to safearray
 +  ElemData := 99;
   for i := LBound to UBound do begin   for i := LBound to UBound do begin
-    SafearrayPutElement(sfArr, i,  99);+    SafearrayPutElement(sfArr, i, ElemData);
   end;   end;
   ...   ...
Line 343: Line 361:
  * [[http://www.delphi3000.com/articles/article_2479.asp?SK=|How to do SafeArray access]] - Delphi3000  * [[http://www.delphi3000.com/articles/article_2479.asp?SK=|How to do SafeArray access]] - Delphi3000
  * [[http://blog.virtec.org/category/delphi/|The Mysteries of PSafeArray]] - Virtech.org  * [[http://blog.virtec.org/category/delphi/|The Mysteries of PSafeArray]] - Virtech.org
 + * [[http://msdn2.microsoft.com/en-us/library/ms221145.aspx|MSDN Safearray Manipulation Functions]] - Microsoft MSDN
 + * [[http://www.gekko-software.nl/Delphi/art08.htm|Automation Arrays (Safearray, Variant arrays)]] - Gekko Software
 + * [[http://www.gekko-software.nl/Delphi/art10.htm|Server Events for Two-way Communication]] - Gekko Software
 + * [[http://www.techvanguards.com/com/|COM Tutorials and Concepts]] - TechVanguards
 + * [[http://podgeretsky.com/ftp/docs/Delphi/D5/dg/autosrvr.html#3201|Delphi 5 Dev Guide: Creating an Automation Server]]