home *** CD-ROM | disk | FTP | other *** search
/ Program Metropolis - Software Boutique 95 / SOFTWARECD.iso / visio3 / disk4 / generic.c_ / generic.bin
Encoding:
Text File  |  1994-08-09  |  12.2 KB  |  391 lines

  1. /*    GENERIC.C - Source for Automation Demo Code in C
  2.  *  Copyright (C) 1991-1994 Shapeware Corporation. All rights reserved.
  3.  */
  4.  
  5. #include <windows.h>
  6. #include <ole2.h> 
  7. #include <dispatch.h>  
  8.  
  9. #include "ivisauto.h"
  10. #include "ivisreg.h"
  11. #include "resource.h"
  12.  
  13. #ifdef _DLL
  14. #define VAOCB __loadds CALLBACK
  15. #else
  16. #define VAOCB CALLBACK
  17. #endif
  18.  
  19. /*
  20.  *    Forward prototype of dialog procedure.
  21.  */
  22.  
  23. BOOL VAOCB AboutDlgProc(
  24.     HWND,
  25.     UINT,
  26.     WPARAM,
  27.     LPARAM);
  28.  
  29. /**************************************************************************
  30.  *+ RunDemo
  31.  *
  32.  *  This demo will drive Visio through OLE Automation in C and draws a
  33.  *    simple orgizational chart on a Visio page.  Notice that the properties
  34.  *    and methods are no different than those called through VB, it's just
  35.  *    that you have the overhead of variants and pointer validation that VB
  36.  *    does for you.
  37.  *
  38.  *    Comments are spread throughout the code to explain the how and why
  39.  *    of programming Visio through OLE Automation.  Some of these constants
  40.  *    are directed at Visual Basic programmers who are making the transition
  41.  *    from OLE Automation under VB to C/C++.
  42.  *
  43.  *    Besides the detailed comments a small comment will be indicate
  44.  *    exactly what interface property/method is being invoked.
  45.  */
  46.  
  47. int RunDemo() 
  48.     {
  49.     /* Declarations Section
  50.      *
  51.      *    Below is a description of the delcarations we use in the example.
  52.      * 
  53.      * INTERFACES
  54.      *
  55.      *    In this example we're going to work with many different Visio
  56.      *    interfaces so we need a pointer to each one.  If you're coming from
  57.      *    the Visual Basic world you need to get used to the idea of 
  58.      *    releasing interfaces and verifying interface pointers before
  59.      *    invoking a method or property.  Visual Basic automatically does
  60.      *    a release for you whenever Object variables go out of scope or
  61.      *    whenever you do an explicit Set obj = Nothing.  However in C
  62.      *    you must always release an interface when done with it and, when
  63.      *    given an interface, must verify that the pointer is not NULL before
  64.      *    attempting to invoke properties or methods on it.  This is equivalent
  65.      *    to saying, in VB, (obj Is Nothing).
  66.      *
  67.      *    Notice that we use the prefix ipIV for all our interface pointers.
  68.      *    ip stands for "Interface Pointer" and IV stands for
  69.      *    "Interface Visio".  After that we have a descriptive name of the
  70.      *    interface we're pointing to.
  71.      *
  72.      *    An important thing to notice is that for every interface pointer
  73.      *    declared, there is a corresponding Release() call it in the 
  74.      *    clean up (CU:) label at the bottom of the procedure.  This method
  75.      *    should be duplicated in your own code unless you decided to pass
  76.      *    the interface pointers around to other functions.  This is to
  77.      *    ensure that we release our lock upon the interface.  For more
  78.      *    information on the Release function see OLE documentation.
  79.      *
  80.      * STRINGS/VARIANTS
  81.      *
  82.      *    Just like in Visual Basic, we have to pass parameters to our
  83.      *    properties and methods.  Because we are talking to OLE we need to 
  84.      *    pass strings as BSTRs.  These must be allocated using the
  85.      *    SysAllocString and SysFreeString functions provided by OLE.
  86.      *    Furthermore, properties and methods that can take more than one
  87.      *    data type for the same parameter will use the VARIANT type.  These
  88.      *    must be handled through the VariantInit, VariantClear functions and
  89.      *    the V_VT and V_type macros.  See OLE documentation for more
  90.      *    information on these as well as the code below.
  91.      */
  92.      
  93.     LPVISIOAPPLICATION ipIVApp     = NULL;
  94.     LPVISIODOCUMENTS   ipIVDocs    = NULL;
  95.     LPVISIODOCUMENT    ipIVDoc     = NULL;
  96.     LPVISIOPAGES       ipIVPages   = NULL;
  97.     LPVISIOPAGE        ipIVPage    = NULL;
  98.     LPVISIOSHAPE       ipIVShape   = NULL;
  99.     LPVISIOSHAPE       ipIVShape1  = NULL;
  100.     LPVISIOMASTERS     ipIVMasters = NULL;
  101.     LPVISIOMASTER      ipIVMaster  = NULL;
  102.     LPVISIODOCUMENT    ipIVStencil = NULL;
  103.     LPVISIOCELL        ipIVCell    = NULL;
  104.     LPVISIOCELL        ipIVCell1   = NULL;
  105.     BSTR bstr = NULL;       
  106.     VARIANT variant;
  107.     HRESULT hResult;
  108.     
  109.     /*
  110.      * STARTING VISIO
  111.      *
  112.      *    A special utility file is included called IVISREG that does
  113.      *    the work of getting a Visio application interface.  This file
  114.      *    is equivalent to the VISREG.BAS file for Visual Basic.
  115.      *
  116.      *    To see how it works open the file and examine it's function calls.
  117.      *    We use a simple, one parameter function that gets the active
  118.      *    instance if one exists or creates a new one if one is not running.
  119.      */
  120.      
  121.     if ( VAO_SUCCESS != vaoGetObject(&ipIVApp) )
  122.         goto CU;
  123.         
  124.     /*
  125.      *    Next we start the main work of drawing the orgchart.  First
  126.      *    we retrieve the Documents collection and try to add a blank
  127.      *    document based on the ORGCHART.VST template.
  128.      *
  129.      *    To demonstrate an invoke let's look at how we retrieve the 
  130.      *    Documents property of the Application interface.  First off, 
  131.      *    every property and method returns an HRESULT and if we want
  132.      *    to see if the call passed or failed we use the SUCCEEDED macro to
  133.      *    examine the SCODE contained in the HRESULT. If the call fails then
  134.      *    we automatically go to clean up since we can't continue.
  135.      *
  136.      *    If the call succeeds we're still not done.  Next we have to check
  137.      *    that another interface pointer was returned and, if it was not,
  138.      *    we go to clean up once again.  This is the standard convention
  139.      *    that we'll use throughout the rest of the examples:
  140.      *
  141.      *        1) Make sure the call works
  142.      *        2) Verify an interface, if any, was returned.
  143.      *
  144.      *    Remember to check the pointers returned because if a call fails
  145.      *    and you try to call a method or property on a NULL pointer an
  146.      *    error will occur.
  147.      */
  148.      
  149.     // Get App.Documents property
  150.     
  151.     hResult = ipIVApp->lpVtbl->Documents(ipIVApp, &ipIVDocs);
  152.     
  153.     if ( !SUCCEEDED(hResult) )
  154.         goto CU;
  155.         
  156.     if ( !ipIVDocs )
  157.         goto CU;        
  158.     
  159.     /*
  160.      *    For this call notice that we have to allocate a BSTR.  We
  161.      *    always allocate the BSTR before the call and then immediately
  162.      *    after it.  This way we're guaranteed we don't have a memory leak
  163.      *    However, this limits us from jumping straight to clean up as in
  164.      *    the previous example, thus we store the HRESULT in a temporary
  165.      *    variable and check it after deallocating the BSTR.
  166.      */
  167.      
  168.     // Add a blank document with Docs.Add
  169.     
  170.     bstr = SysAllocString("orgchart.vst");
  171.     hResult = ipIVDocs->lpVtbl->Add(ipIVDocs, bstr, &ipIVDoc);
  172.     SysFreeString(bstr);
  173.     
  174.     if ( !SUCCEEDED(hResult) || !ipIVDoc )
  175.         goto CU;
  176.     
  177.     // Get blank document Pages collection using Doc.Pages
  178.     
  179.     hResult = ipIVDoc->lpVtbl->Pages(ipIVDoc, &ipIVPages);
  180.     
  181.     if ( !SUCCEEDED(hResult) || !ipIVPages )
  182.         goto CU;
  183.      
  184.     /*
  185.      *    For this call we need to use a variant for the Pages.Item property.
  186.      *    Because Pages.Item can take either a string containing the page's
  187.      *    name or an integer specifying the page's index we need to put pass
  188.      *    a VARIANT.  Notice that we first init the variant, then set the
  189.      *    type of it with the V_VT macro to I2, meaning 2 byte integer.  Then
  190.      *    we use the V_I2 macro to set the variant's value.  After that we
  191.      *    can make the call.  Once the call has returned, though, we need
  192.      *    to clear the variant.  Read up on VARIANTs in the OLE 2.0 Programmer's
  193.      *    Reference to see exactly how to work with them and for a listing of
  194.      *    their support functions and macros.
  195.      */
  196.      
  197.     // Get first page of blank document using Pages.Item
  198.     
  199.     VariantInit(&variant);
  200.     V_VT(&variant) = VT_I2;
  201.     V_I2(&variant) = 1;
  202.     hResult = ipIVPages->lpVtbl->Item(ipIVPages, variant, &ipIVPage);
  203.     VariantClear(&variant);
  204.     
  205.     if ( !SUCCEEDED(hResult) || !ipIVPage )
  206.         goto CU;
  207.     
  208.     // Get Document interface for orgchart stencil using Docs.Item
  209.     
  210.     VariantInit(&variant);
  211.     V_VT(&variant) = VT_BSTR;
  212.     V_BSTR(&variant) = SysAllocString("orgchart.vss");;
  213.     hResult = ipIVDocs->lpVtbl->Item(ipIVDocs, variant, &ipIVStencil);
  214.     VariantClear(&variant);
  215.     
  216.     if ( !SUCCEEDED(hResult) || !ipIVStencil )
  217.         goto CU;
  218.     
  219.     // Retrieve orgchart Masters interface using Doc.Masters
  220.     
  221.     hResult = ipIVStencil->lpVtbl->Masters(ipIVStencil, &ipIVMasters);
  222.     
  223.     if ( !SUCCEEDED(hResult) || !ipIVMasters )
  224.         goto CU;
  225.     
  226.     // Get Executive master using Masters.Item
  227.     
  228.     VariantInit(&variant);
  229.     V_VT(&variant) = VT_BSTR;
  230.     V_BSTR(&variant) = SysAllocString("Executive");;
  231.     hResult = ipIVMasters->lpVtbl->Item(ipIVMasters, variant, &ipIVMaster);
  232.     VariantClear(&variant);
  233.     
  234.     if ( !SUCCEEDED(hResult) || !ipIVMaster )
  235.         goto CU;
  236.     
  237.     // Drop Executive master using Page.Drop
  238.     
  239.     hResult = ipIVPage->lpVtbl->Drop(ipIVPage,
  240.                                      (LPUNKNOWN)ipIVMaster,
  241.                                      6.0,
  242.                                      6.0,
  243.                                      &ipIVShape );
  244.     
  245.     if ( !SUCCEEDED(hResult) || !ipIVShape )
  246.         goto CU;
  247.         
  248.     /*
  249.      *    At this point we want to re-use the one master interface we
  250.      *    declaraed.  To do it we must first release and then set it
  251.      *    to NULL.  Not setting it to NULL could cause serious problems later
  252.      *    so remember to do this, especially when iterating collections.
  253.      */
  254.      
  255.     if ( ipIVMaster )
  256.         {
  257.         ipIVMaster->lpVtbl->Release(ipIVMaster);
  258.         ipIVMaster = NULL;
  259.         }
  260.         
  261.     // Get Position 1 master using Masters.Item
  262.     
  263.     VariantInit(&variant);
  264.     V_VT(&variant) = VT_BSTR;
  265.     V_BSTR(&variant) = SysAllocString("Position");;
  266.     hResult = ipIVMasters->lpVtbl->Item(ipIVMasters, variant, &ipIVMaster);
  267.     VariantClear(&variant);
  268.     
  269.     if ( !SUCCEEDED(hResult) || !ipIVMaster )
  270.         goto CU;
  271.     
  272.     // Drop Position 1 master using Page.Drop
  273.     
  274.     hResult = ipIVPage->lpVtbl->Drop(ipIVPage,
  275.                                      (LPUNKNOWN)ipIVMaster,
  276.                                      3.0,
  277.                                      3.0,
  278.                                      &ipIVShape1 );
  279.                                      
  280.     if ( !SUCCEEDED(hResult) || !ipIVShape1 )
  281.         goto CU;
  282.     
  283.     // Get Executive's Connection point using Shape.Cells
  284.     
  285.     bstr = SysAllocString("Connections.X4");
  286.     hResult = ipIVShape->lpVtbl->Cells(ipIVShape, bstr, &ipIVCell);
  287.     SysFreeString(bstr);
  288.     
  289.     if ( !SUCCEEDED(hResult) || !ipIVCell )
  290.         goto CU;
  291.     
  292.     // Get Position 1's Control handle using Shape.Cells
  293.     
  294.     bstr = SysAllocString("Controls.X1");
  295.     hResult = ipIVShape1->lpVtbl->Cells(ipIVShape1, bstr, &ipIVCell1);
  296.     SysFreeString(bstr);
  297.     
  298.     if ( !SUCCEEDED(hResult) || !ipIVCell )
  299.         goto CU;
  300.     
  301.    // Glue Position 1 to Executive using Cell.Glue
  302.    
  303.    ipIVCell1->lpVtbl->GlueTo(ipIVCell1, ipIVCell);
  304.     
  305. CU:
  306.     /*
  307.      * CLEANUP
  308.      *
  309.      *    The clean up section is meant to release any interface pointers
  310.      *    that are outstanding at this point.  Our example does not need to
  311.      *    keep any around for later use or to pass back to our caller so we
  312.      *    release every one.  However, if we were going to, say, pass one
  313.      *    back to a calling function as the call vaoGetObject does we would
  314.      *    not want to release it.
  315.      */
  316.      
  317.     if ( ipIVCell1 )
  318.         ipIVCell1->lpVtbl->Release(ipIVCell1);
  319.     if ( ipIVCell )
  320.         ipIVCell->lpVtbl->Release(ipIVCell);
  321.     if ( ipIVStencil )
  322.         ipIVStencil->lpVtbl->Release(ipIVStencil);
  323.     if ( ipIVMaster )
  324.         ipIVMaster->lpVtbl->Release(ipIVMaster);
  325.     if ( ipIVMasters )
  326.         ipIVMasters->lpVtbl->Release(ipIVMasters);
  327.     if ( ipIVShape1 )
  328.         ipIVShape1->lpVtbl->Release(ipIVShape1);
  329.     if ( ipIVShape )
  330.         ipIVShape->lpVtbl->Release(ipIVShape);
  331.     if ( ipIVPage )
  332.         ipIVPage->lpVtbl->Release(ipIVPage);
  333.     if ( ipIVPages )
  334.         ipIVPages->lpVtbl->Release(ipIVPages);
  335.     if ( ipIVDoc )
  336.         ipIVDoc->lpVtbl->Release(ipIVDoc);
  337.     if ( ipIVDocs )
  338.         ipIVDocs->lpVtbl->Release(ipIVDocs);
  339.     if ( ipIVApp )
  340.         ipIVApp->lpVtbl->Release(ipIVApp);
  341.     
  342.     return 0;
  343.     }
  344.     
  345.  
  346. /***********************************************************************
  347.  *+ AboutDlgProc
  348.  *
  349.  */
  350.  
  351. BOOL VAOCB AboutDlgProc(
  352.     HWND hDlg,
  353.     UINT msg,
  354.     WPARAM wParam,
  355.     LPARAM lParam)
  356.     {
  357.     
  358.     switch (msg)
  359.         {
  360.         case WM_COMMAND:
  361.             switch (wParam)
  362.                 {
  363.                 case IDOK:
  364.                 case IDCANCEL:
  365.                     EndDialog(hDlg, TRUE);
  366.                     return (TRUE);
  367.                     break;
  368.                 }
  369.         }
  370.     
  371.     return (FALSE);
  372.     }
  373.  
  374.  
  375. /***********************************************************************
  376.  *+ ShowAboutDialog
  377.  *
  378.  *    Displays the help about dialog.
  379.  */
  380.  
  381. void ShowAboutDialog(HINSTANCE hInstance)
  382.     {
  383.     FARPROC lpProcDlg = NULL;
  384.     
  385.     lpProcDlg = MakeProcInstance((FARPROC)AboutDlgProc, hInstance);
  386.  
  387.     DialogBox(hInstance, "ABOUTBOX", NULL, lpProcDlg);
  388.            
  389.     FreeProcInstance(lpProcDlg);
  390.     };
  391.