home *** CD-ROM | disk | FTP | other *** search
- /* GENERIC.C - Source for Automation Demo Code in C
- * Copyright (C) 1991-1994 Shapeware Corporation. All rights reserved.
- */
-
- #include <windows.h>
- #include <ole2.h>
- #include <dispatch.h>
-
- #include "ivisauto.h"
- #include "ivisreg.h"
- #include "resource.h"
-
- #ifdef _DLL
- #define VAOCB __loadds CALLBACK
- #else
- #define VAOCB CALLBACK
- #endif
-
- /*
- * Forward prototype of dialog procedure.
- */
-
- BOOL VAOCB AboutDlgProc(
- HWND,
- UINT,
- WPARAM,
- LPARAM);
-
- /**************************************************************************
- *+ RunDemo
- *
- * This demo will drive Visio through OLE Automation in C and draws a
- * simple orgizational chart on a Visio page. Notice that the properties
- * and methods are no different than those called through VB, it's just
- * that you have the overhead of variants and pointer validation that VB
- * does for you.
- *
- * Comments are spread throughout the code to explain the how and why
- * of programming Visio through OLE Automation. Some of these constants
- * are directed at Visual Basic programmers who are making the transition
- * from OLE Automation under VB to C/C++.
- *
- * Besides the detailed comments a small comment will be indicate
- * exactly what interface property/method is being invoked.
- */
-
- int RunDemo()
- {
- /* Declarations Section
- *
- * Below is a description of the delcarations we use in the example.
- *
- * INTERFACES
- *
- * In this example we're going to work with many different Visio
- * interfaces so we need a pointer to each one. If you're coming from
- * the Visual Basic world you need to get used to the idea of
- * releasing interfaces and verifying interface pointers before
- * invoking a method or property. Visual Basic automatically does
- * a release for you whenever Object variables go out of scope or
- * whenever you do an explicit Set obj = Nothing. However in C
- * you must always release an interface when done with it and, when
- * given an interface, must verify that the pointer is not NULL before
- * attempting to invoke properties or methods on it. This is equivalent
- * to saying, in VB, (obj Is Nothing).
- *
- * Notice that we use the prefix ipIV for all our interface pointers.
- * ip stands for "Interface Pointer" and IV stands for
- * "Interface Visio". After that we have a descriptive name of the
- * interface we're pointing to.
- *
- * An important thing to notice is that for every interface pointer
- * declared, there is a corresponding Release() call it in the
- * clean up (CU:) label at the bottom of the procedure. This method
- * should be duplicated in your own code unless you decided to pass
- * the interface pointers around to other functions. This is to
- * ensure that we release our lock upon the interface. For more
- * information on the Release function see OLE documentation.
- *
- * STRINGS/VARIANTS
- *
- * Just like in Visual Basic, we have to pass parameters to our
- * properties and methods. Because we are talking to OLE we need to
- * pass strings as BSTRs. These must be allocated using the
- * SysAllocString and SysFreeString functions provided by OLE.
- * Furthermore, properties and methods that can take more than one
- * data type for the same parameter will use the VARIANT type. These
- * must be handled through the VariantInit, VariantClear functions and
- * the V_VT and V_type macros. See OLE documentation for more
- * information on these as well as the code below.
- */
-
- LPVISIOAPPLICATION ipIVApp = NULL;
- LPVISIODOCUMENTS ipIVDocs = NULL;
- LPVISIODOCUMENT ipIVDoc = NULL;
- LPVISIOPAGES ipIVPages = NULL;
- LPVISIOPAGE ipIVPage = NULL;
- LPVISIOSHAPE ipIVShape = NULL;
- LPVISIOSHAPE ipIVShape1 = NULL;
- LPVISIOMASTERS ipIVMasters = NULL;
- LPVISIOMASTER ipIVMaster = NULL;
- LPVISIODOCUMENT ipIVStencil = NULL;
- LPVISIOCELL ipIVCell = NULL;
- LPVISIOCELL ipIVCell1 = NULL;
- BSTR bstr = NULL;
- VARIANT variant;
- HRESULT hResult;
-
- /*
- * STARTING VISIO
- *
- * A special utility file is included called IVISREG that does
- * the work of getting a Visio application interface. This file
- * is equivalent to the VISREG.BAS file for Visual Basic.
- *
- * To see how it works open the file and examine it's function calls.
- * We use a simple, one parameter function that gets the active
- * instance if one exists or creates a new one if one is not running.
- */
-
- if ( VAO_SUCCESS != vaoGetObject(&ipIVApp) )
- goto CU;
-
- /*
- * Next we start the main work of drawing the orgchart. First
- * we retrieve the Documents collection and try to add a blank
- * document based on the ORGCHART.VST template.
- *
- * To demonstrate an invoke let's look at how we retrieve the
- * Documents property of the Application interface. First off,
- * every property and method returns an HRESULT and if we want
- * to see if the call passed or failed we use the SUCCEEDED macro to
- * examine the SCODE contained in the HRESULT. If the call fails then
- * we automatically go to clean up since we can't continue.
- *
- * If the call succeeds we're still not done. Next we have to check
- * that another interface pointer was returned and, if it was not,
- * we go to clean up once again. This is the standard convention
- * that we'll use throughout the rest of the examples:
- *
- * 1) Make sure the call works
- * 2) Verify an interface, if any, was returned.
- *
- * Remember to check the pointers returned because if a call fails
- * and you try to call a method or property on a NULL pointer an
- * error will occur.
- */
-
- // Get App.Documents property
-
- hResult = ipIVApp->lpVtbl->Documents(ipIVApp, &ipIVDocs);
-
- if ( !SUCCEEDED(hResult) )
- goto CU;
-
- if ( !ipIVDocs )
- goto CU;
-
- /*
- * For this call notice that we have to allocate a BSTR. We
- * always allocate the BSTR before the call and then immediately
- * after it. This way we're guaranteed we don't have a memory leak
- * However, this limits us from jumping straight to clean up as in
- * the previous example, thus we store the HRESULT in a temporary
- * variable and check it after deallocating the BSTR.
- */
-
- // Add a blank document with Docs.Add
-
- bstr = SysAllocString("orgchart.vst");
- hResult = ipIVDocs->lpVtbl->Add(ipIVDocs, bstr, &ipIVDoc);
- SysFreeString(bstr);
-
- if ( !SUCCEEDED(hResult) || !ipIVDoc )
- goto CU;
-
- // Get blank document Pages collection using Doc.Pages
-
- hResult = ipIVDoc->lpVtbl->Pages(ipIVDoc, &ipIVPages);
-
- if ( !SUCCEEDED(hResult) || !ipIVPages )
- goto CU;
-
- /*
- * For this call we need to use a variant for the Pages.Item property.
- * Because Pages.Item can take either a string containing the page's
- * name or an integer specifying the page's index we need to put pass
- * a VARIANT. Notice that we first init the variant, then set the
- * type of it with the V_VT macro to I2, meaning 2 byte integer. Then
- * we use the V_I2 macro to set the variant's value. After that we
- * can make the call. Once the call has returned, though, we need
- * to clear the variant. Read up on VARIANTs in the OLE 2.0 Programmer's
- * Reference to see exactly how to work with them and for a listing of
- * their support functions and macros.
- */
-
- // Get first page of blank document using Pages.Item
-
- VariantInit(&variant);
- V_VT(&variant) = VT_I2;
- V_I2(&variant) = 1;
- hResult = ipIVPages->lpVtbl->Item(ipIVPages, variant, &ipIVPage);
- VariantClear(&variant);
-
- if ( !SUCCEEDED(hResult) || !ipIVPage )
- goto CU;
-
- // Get Document interface for orgchart stencil using Docs.Item
-
- VariantInit(&variant);
- V_VT(&variant) = VT_BSTR;
- V_BSTR(&variant) = SysAllocString("orgchart.vss");;
- hResult = ipIVDocs->lpVtbl->Item(ipIVDocs, variant, &ipIVStencil);
- VariantClear(&variant);
-
- if ( !SUCCEEDED(hResult) || !ipIVStencil )
- goto CU;
-
- // Retrieve orgchart Masters interface using Doc.Masters
-
- hResult = ipIVStencil->lpVtbl->Masters(ipIVStencil, &ipIVMasters);
-
- if ( !SUCCEEDED(hResult) || !ipIVMasters )
- goto CU;
-
- // Get Executive master using Masters.Item
-
- VariantInit(&variant);
- V_VT(&variant) = VT_BSTR;
- V_BSTR(&variant) = SysAllocString("Executive");;
- hResult = ipIVMasters->lpVtbl->Item(ipIVMasters, variant, &ipIVMaster);
- VariantClear(&variant);
-
- if ( !SUCCEEDED(hResult) || !ipIVMaster )
- goto CU;
-
- // Drop Executive master using Page.Drop
-
- hResult = ipIVPage->lpVtbl->Drop(ipIVPage,
- (LPUNKNOWN)ipIVMaster,
- 6.0,
- 6.0,
- &ipIVShape );
-
- if ( !SUCCEEDED(hResult) || !ipIVShape )
- goto CU;
-
- /*
- * At this point we want to re-use the one master interface we
- * declaraed. To do it we must first release and then set it
- * to NULL. Not setting it to NULL could cause serious problems later
- * so remember to do this, especially when iterating collections.
- */
-
- if ( ipIVMaster )
- {
- ipIVMaster->lpVtbl->Release(ipIVMaster);
- ipIVMaster = NULL;
- }
-
- // Get Position 1 master using Masters.Item
-
- VariantInit(&variant);
- V_VT(&variant) = VT_BSTR;
- V_BSTR(&variant) = SysAllocString("Position");;
- hResult = ipIVMasters->lpVtbl->Item(ipIVMasters, variant, &ipIVMaster);
- VariantClear(&variant);
-
- if ( !SUCCEEDED(hResult) || !ipIVMaster )
- goto CU;
-
- // Drop Position 1 master using Page.Drop
-
- hResult = ipIVPage->lpVtbl->Drop(ipIVPage,
- (LPUNKNOWN)ipIVMaster,
- 3.0,
- 3.0,
- &ipIVShape1 );
-
- if ( !SUCCEEDED(hResult) || !ipIVShape1 )
- goto CU;
-
- // Get Executive's Connection point using Shape.Cells
-
- bstr = SysAllocString("Connections.X4");
- hResult = ipIVShape->lpVtbl->Cells(ipIVShape, bstr, &ipIVCell);
- SysFreeString(bstr);
-
- if ( !SUCCEEDED(hResult) || !ipIVCell )
- goto CU;
-
- // Get Position 1's Control handle using Shape.Cells
-
- bstr = SysAllocString("Controls.X1");
- hResult = ipIVShape1->lpVtbl->Cells(ipIVShape1, bstr, &ipIVCell1);
- SysFreeString(bstr);
-
- if ( !SUCCEEDED(hResult) || !ipIVCell )
- goto CU;
-
- // Glue Position 1 to Executive using Cell.Glue
-
- ipIVCell1->lpVtbl->GlueTo(ipIVCell1, ipIVCell);
-
- CU:
- /*
- * CLEANUP
- *
- * The clean up section is meant to release any interface pointers
- * that are outstanding at this point. Our example does not need to
- * keep any around for later use or to pass back to our caller so we
- * release every one. However, if we were going to, say, pass one
- * back to a calling function as the call vaoGetObject does we would
- * not want to release it.
- */
-
- if ( ipIVCell1 )
- ipIVCell1->lpVtbl->Release(ipIVCell1);
- if ( ipIVCell )
- ipIVCell->lpVtbl->Release(ipIVCell);
- if ( ipIVStencil )
- ipIVStencil->lpVtbl->Release(ipIVStencil);
- if ( ipIVMaster )
- ipIVMaster->lpVtbl->Release(ipIVMaster);
- if ( ipIVMasters )
- ipIVMasters->lpVtbl->Release(ipIVMasters);
- if ( ipIVShape1 )
- ipIVShape1->lpVtbl->Release(ipIVShape1);
- if ( ipIVShape )
- ipIVShape->lpVtbl->Release(ipIVShape);
- if ( ipIVPage )
- ipIVPage->lpVtbl->Release(ipIVPage);
- if ( ipIVPages )
- ipIVPages->lpVtbl->Release(ipIVPages);
- if ( ipIVDoc )
- ipIVDoc->lpVtbl->Release(ipIVDoc);
- if ( ipIVDocs )
- ipIVDocs->lpVtbl->Release(ipIVDocs);
- if ( ipIVApp )
- ipIVApp->lpVtbl->Release(ipIVApp);
-
- return 0;
- }
-
-
- /***********************************************************************
- *+ AboutDlgProc
- *
- */
-
- BOOL VAOCB AboutDlgProc(
- HWND hDlg,
- UINT msg,
- WPARAM wParam,
- LPARAM lParam)
- {
-
- switch (msg)
- {
- case WM_COMMAND:
- switch (wParam)
- {
- case IDOK:
- case IDCANCEL:
- EndDialog(hDlg, TRUE);
- return (TRUE);
- break;
- }
- }
-
- return (FALSE);
- }
-
-
- /***********************************************************************
- *+ ShowAboutDialog
- *
- * Displays the help about dialog.
- */
-
- void ShowAboutDialog(HINSTANCE hInstance)
- {
- FARPROC lpProcDlg = NULL;
-
- lpProcDlg = MakeProcInstance((FARPROC)AboutDlgProc, hInstance);
-
- DialogBox(hInstance, "ABOUTBOX", NULL, lpProcDlg);
-
- FreeProcInstance(lpProcDlg);
- };
-