home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / oleaut / lines / main.cpp < prev    next >
C/C++ Source or Header  |  1997-07-31  |  15KB  |  495 lines

  1. /*************************************************************************
  2. **
  3. **  This is a part of the Microsoft Source Code Samples.
  4. **
  5. **  Copyright (C) 1992-1997 Microsoft Corporation. All rights reserved.
  6. **
  7. **  This source code is only intended as a supplement to Microsoft Development
  8. **  Tools and/or WinHelp documentation.  See these sources for detailed
  9. **  information regarding the Microsoft samples programs.
  10. **
  11. **  OLE Automation Lines Object.
  12. **
  13. **  main.cpp
  14. **
  15. **  Written by Microsoft Product Support Services, Windows Developer Support
  16. **
  17. *************************************************************************/
  18. #include <windows.h>
  19. #include <windowsx.h>
  20. #ifdef WIN16   
  21.   #include <ole2.h>
  22.   #include <compobj.h>    
  23.   #include <dispatch.h> 
  24.   #include <variant.h>
  25.   #include <olenls.h>
  26.   #include <commdlg.h>  
  27. #endif  
  28. #include <initguid.h>
  29. #include "lines.h"        
  30.  
  31. // Globals  
  32. CApplication FAR* g_pApplication;
  33.  
  34. SCODE g_scodes[SCODE_COUNT] =                // Array of SCODEs for easy lookup
  35. {    LINES_E_UNEXPECTED,
  36.      LINES_E_OUTOFMEMORY,
  37.      LINES_E_INVALIDINDEX,
  38.      LINES_E_COLLECTIONFULL,
  39.      LINES_E_LINEFROMOTHERINSTANCE,
  40.      LINES_E_CANTADDENDPOINTS,
  41.      LINES_E_POINTFROMOTHERINSTANCE,
  42.      LINES_E_NOVISIBLEXCOORDINATE,
  43.      LINES_E_NOVISIBLEYCOORDINATE,
  44.      LINES_E_NOSTARTPOINT,
  45.      LINES_E_NOENDPOINT
  46. };
  47.  
  48. /*
  49.  * WinMain
  50.  *
  51.  * Purpose:
  52.  *  Main entry point of application. 
  53.  *
  54.  */
  55. int APIENTRY WinMain (HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR pCmdLine, int nCmdShow)
  56. {
  57.     MSG msg;
  58.     DWORD dwRegisterCF;     
  59.     DWORD dwRegisterActiveObject;
  60.  
  61. #ifdef WIN16
  62.    //  It is recommended that all 16 bit OLE applications set
  63.    //  their message queue size to 96. This improves the capacity
  64.    //  and performance of OLE's LRPC mechanism.
  65.    int cMsg = 96;                  // Recommend msg queue size for OLE
  66.    while (cMsg && !SetMessageQueue(cMsg))  // take largest size we can get.
  67.        cMsg -= 8;
  68.    if (!cMsg)
  69.        return -1;  // ERROR: we got no message queue       
  70. #endif
  71.    
  72.     if (!hinstPrev)
  73.        if (!InitApplication(hinst)) // Register window class        
  74.           return FALSE;
  75.     
  76.     if (!InitInstance(hinst))   // Initialize OLE and create Lines application object
  77.         return (FALSE);    
  78.     
  79.     // Determine if /Automation was specified in command line and register class
  80.     // factory and active object. Show window if application was started stand alone.
  81.     if (!ProcessCmdLine(pCmdLine, &dwRegisterCF, &dwRegisterActiveObject, nCmdShow))   
  82.     {
  83.        Uninitialize(dwRegisterCF, dwRegisterActiveObject);   
  84.        return (FALSE);    
  85.     }
  86.  
  87.     while (GetMessage(&msg, NULL, 0, 0))
  88.     {
  89.        TranslateMessage(&msg);
  90.        DispatchMessage(&msg);
  91.     }
  92.    
  93.     Uninitialize(dwRegisterCF, dwRegisterActiveObject);   
  94.     return (msg.wParam); 
  95. }
  96.  
  97. /*
  98.  * InitApplication
  99.  *
  100.  * Purpose:
  101.  *  Registers window class
  102.  *
  103.  * Parameters:
  104.  *  hinst       hInstance of application
  105.  *
  106.  * Return Value:
  107.  *  TRUE if initialization succeeded, FALSE otherwise.
  108.  */
  109. BOOL InitApplication (HINSTANCE hinst)
  110. {
  111.    WNDCLASS wc;
  112.    
  113.    wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
  114.    wc.lpfnWndProc = MainWndProc;
  115.    wc.cbClsExtra = 0;
  116.    wc.cbWndExtra = 0;
  117.    wc.hInstance = hinst;
  118.    wc.hIcon = LoadIcon(hinst, MAKEINTRESOURCE(IDI_ICON));
  119.    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  120.    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  121.    wc.lpszMenuName = TEXT("AppMenu");
  122.    wc.lpszClassName = TEXT("MainWndClass"); 
  123.      
  124.    return RegisterClass(&wc);        
  125. }
  126.  
  127. /*
  128.  * InitInstance
  129.  *
  130.  * Purpose:
  131.  *  Intializes OLE and creates Lines Application object
  132.  *
  133.  * Parameters:
  134.  *  hinst           hInstance of application
  135.  *
  136.  * Return Value:
  137.  *  TRUE if initialization succeeded, FALSE otherwise.
  138.  */
  139. BOOL InitInstance (HINSTANCE hinst)
  140. {  
  141.     HRESULT hr;
  142.     
  143.     // Intialize OLE
  144.     hr = OleInitialize(NULL);
  145.     if (FAILED(hr))
  146.        return FALSE; 
  147.     
  148.     // Create an instance of the Lines Application object. Object is
  149.     // created with refcount 0.
  150.     hr = CApplication::Create(hinst, &g_pApplication);       
  151.     if (FAILED(hr))
  152.         return FALSE;
  153.     return TRUE;          
  154. }
  155.  
  156. /*
  157.  * ProcessCmdLine
  158.  *
  159.  * Purpose:
  160.  *  Check if command line contains /Automation. If so, the class factory of the 
  161.  *  application object is registered.  If not, the application was started stand-alone and
  162.  *  so the window is shown. The application object is registered using RegisterActiveObject.
  163.  *
  164.  * Parameters:
  165.  *  pCmdLine       Command line passed to application
  166.  *  pdwRegisterCF   Returns id returned after class factory registration. Can be used to 
  167.  *                  revoke class factory registration. 
  168.  *  pdwRegisterActiveObject   Returns id returned after active object registration. Can be used to 
  169.  *                  revoke active object registration.   
  170.  *  nCmdShow        Specifies how window is to be shown if application was started stand alone.
  171.  *
  172.  * Return Value:
  173.  *    TRUE if OLE initialization succeeded, FALSE otherwise.
  174.  *
  175.  */
  176. BOOL ProcessCmdLine(LPSTR pCmdLine, LPDWORD pdwRegisterCF, LPDWORD pdwRegisterActiveObject, int nCmdShow)
  177. {
  178.    LPCLASSFACTORY pcf = NULL;
  179.    HRESULT hr;
  180.    
  181.    *pdwRegisterCF = 0;     
  182.    *pdwRegisterActiveObject = 0;
  183.    
  184.    // Expose class factory for application object if command line contains the 
  185.    // Automation switch       
  186.    if (_fstrstr(pCmdLine, "-Automation") != NULL
  187.        || _fstrstr(pCmdLine, "/Automation") != NULL)
  188.    {
  189.        pcf = new CApplicationCF;
  190.        if (!pcf)
  191.            goto error;  
  192.        pcf->AddRef();           
  193.        hr = CoRegisterClassObject(CLSID_Lines, pcf,
  194.                                      CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE,
  195.                                      pdwRegisterCF);
  196.        if (hr != NOERROR)
  197.            goto error;           
  198.        pcf->Release();
  199.    }  
  200.    else g_pApplication->ShowWindow(nCmdShow);    // Show window if started stand-alone       
  201.    
  202.    // Register Lines application object in the Running Object Table (ROT). This 
  203.    // allows controllers to connect to a running application object instead of creating
  204.    // a new instance. Use weak registration so that the ROT releases it's reference when 
  205.    // all external references are released. If strong registration is used, the ROT will not
  206.    // release it's reference until RevokeActiveObject is called and so will keep
  207.    // the object alive even after all external references have been released.
  208.    RegisterActiveObject(g_pApplication, CLSID_Lines, ACTIVEOBJECT_WEAK, pdwRegisterActiveObject);
  209.    return TRUE;           
  210.            
  211. error:
  212.     if (pcf)
  213.         pcf->Release();
  214.     return FALSE;
  215. }
  216.  
  217. /*
  218.  * Uninitialize
  219.  *
  220.  *  Purpose:
  221.  *   Revoke class factory and active object registration and uninitialize OLE.
  222.  *
  223.  * Parameters:
  224.  *  dwRegisterCF ID returned after class factory registration. 
  225.  *  dwRegisterActiveObject ID returned after active object registration.
  226.  *
  227.  */
  228. void Uninitialize(DWORD dwRegisterCF, DWORD dwRegisterActiveObject)
  229. {
  230.     if (dwRegisterCF != 0)
  231.         CoRevokeClassObject(dwRegisterCF);
  232.     if (dwRegisterActiveObject != 0)
  233.         RevokeActiveObject(dwRegisterActiveObject, NULL);   
  234.     OleUninitialize();
  235. }
  236.  
  237. /*
  238.  * MainWndProc
  239.  *
  240.  * Purpose:
  241.  *  Window procedure for main window
  242.  *
  243.  */
  244. LRESULT CALLBACK MainWndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  245. {     
  246.    switch (msg)
  247.    {           
  248.       case WM_PAINT:          
  249.           g_pApplication->Draw();            
  250.           break;
  251.       
  252.       case WM_SIZE:
  253.           g_pApplication->OnSize(LOWORD(lParam), HIWORD(lParam));        
  254.           break; 
  255.           
  256.       case WM_COMMAND:
  257.       {   
  258.           switch(GET_WM_COMMAND_ID(wParam,lParam))
  259.           {
  260.               case IDM_DRAWLINE:
  261.                   g_pApplication->CreateAndDrawLine();
  262.                   break;
  263.                   
  264.               case IDM_CLEAR:
  265.                   g_pApplication->ClearPane();              
  266.                   break;
  267.                   
  268.               case IDM_EXIT: 
  269.                   PostMessage(hwnd, WM_CLOSE, 0, 0L);
  270.                   break; 
  271.           }              
  272.       }
  273.       break;
  274.           
  275.       case WM_CLOSE: 
  276.          // Hide the window to release the refcount added by CoLockObjectExternal
  277.          // (See CLines::ShowWindow)
  278.          g_pApplication->m_bUserClosing = TRUE;
  279.          g_pApplication->ShowWindow(SW_HIDE); 
  280.          DestroyWindow(hwnd);
  281.          return 0L;
  282.       
  283.       case WM_DESTROY:            
  284.          PostQuitMessage(0);
  285.          break;
  286.       
  287.       default:                         
  288.          return DefWindowProc(hwnd, msg, wParam, lParam);
  289.    }
  290.    
  291.    return NULL;
  292.  
  293. /*
  294.  * DrawLineDialogFunc
  295.  *
  296.  * Purpose:
  297.  *  Dialog function of DrawLine dialog. Prompts user and returns information to draw a line.
  298.  *
  299.  */ 
  300. BOOL CALLBACK DrawLineDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  301. {
  302.    static LPLINEINFO plineinfo;      
  303.    BOOL b;  
  304.    CHOOSECOLOR cc;     
  305.    COLORREF clrCustom[16];
  306.    int n;
  307.    
  308.    switch (msg)
  309.    {
  310.       case WM_INITDIALOG:
  311.          plineinfo = (LPLINEINFO)lParam;   
  312.          // Initialize edit controls. Units are twips.
  313.          SetDlgItemText(hwndDlg, IDC_STARTPOINT_X, TEXT("4500"));
  314.          SetDlgItemText(hwndDlg, IDC_STARTPOINT_Y, TEXT("4500"));
  315.          SetDlgItemText(hwndDlg, IDC_ENDPOINT_X, TEXT("8000"));
  316.          SetDlgItemText(hwndDlg, IDC_ENDPOINT_Y, TEXT("8000"));
  317.          SetDlgItemText(hwndDlg, IDC_THICKNESS, TEXT("100"));
  318.          plineinfo->colorref = 0; 
  319.          return TRUE;
  320.  
  321.       case WM_COMMAND:
  322.          switch(GET_WM_COMMAND_ID(wParam,lParam))
  323.          {
  324.              case IDOK:
  325.                  plineinfo->ptStart.x = GetDlgItemInt(hwndDlg, IDC_STARTPOINT_X, &b, TRUE); 
  326.                  plineinfo->ptStart.y = GetDlgItemInt(hwndDlg, IDC_STARTPOINT_Y, &b, TRUE);
  327.                  plineinfo->ptEnd.x = GetDlgItemInt(hwndDlg, IDC_ENDPOINT_X, &b, TRUE);
  328.                  plineinfo->ptEnd.y = GetDlgItemInt(hwndDlg, IDC_ENDPOINT_Y, &b, TRUE);
  329.                  plineinfo->nThickness = GetDlgItemInt(hwndDlg, IDC_THICKNESS, &b, TRUE);        
  330.                  EndDialog(hwndDlg, IDOK);
  331.                  return TRUE;
  332.                  
  333.              case IDCANCEL:
  334.                  EndDialog(hwndDlg, IDCANCEL);
  335.                  return TRUE;
  336.                  
  337.              case IDC_CHOOSECOLOR:    
  338.                  memset(&cc, 0, sizeof(CHOOSECOLOR)); 
  339.                  cc.lStructSize = sizeof(CHOOSECOLOR); 
  340.                  cc.hwndOwner = hwndDlg;
  341.                  cc.rgbResult = RGB(0, 0, 0);
  342.                  cc.Flags = CC_RGBINIT;  
  343.                  for (n=0; n<16; n++)
  344.                     clrCustom[n] = RGB(255, 255, 255);
  345.                  cc.lpCustColors = clrCustom;
  346.                  if (ChooseColor(&cc))
  347.                      plineinfo->colorref = cc.rgbResult;                                                               
  348.          }
  349.          break;
  350.    }
  351.    return FALSE;
  352. }
  353.  
  354. /*
  355.  * LoadTypeInfo
  356.  *
  357.  *  Purpose:
  358.  *   Gets type information of an object's interface from type library.
  359.  *
  360.  * Parameters:
  361.  *  ppunkStdDispatch    Returns type information.
  362.  *  clsid               Interface id of object in type library. 
  363.  *
  364.  * Return Value:
  365.  *  HRESULT
  366.  *
  367.  */
  368. HRESULT LoadTypeInfo(ITypeInfo FAR* FAR* pptinfo, REFCLSID clsid)
  369. {                          
  370.     HRESULT hr;
  371.     LPTYPELIB ptlib = NULL;
  372.     LPTYPEINFO ptinfo = NULL;
  373.  
  374.     *pptinfo = NULL;     
  375.     
  376.     // Load Type Library. 
  377.     hr = LoadRegTypeLib(LIBID_Lines, 1, 0, 0x09, &ptlib);
  378.     if (FAILED(hr)) 
  379.     {   
  380.         // if it wasn't registered, try to load it from the path
  381.         // if this succeeds, it will have registered the type library for us
  382.         // for the next time.  
  383.         hr = LoadTypeLib(OLESTR("lines.tlb"), &ptlib); 
  384.         if(FAILED(hr))        
  385.             return hr;   
  386.     }
  387.     
  388.     // Get type information for interface of the object.      
  389.     hr = ptlib->GetTypeInfoOfGuid(clsid, &ptinfo);
  390.     if (FAILED(hr))  
  391.     { 
  392.         ptlib->Release();
  393.         return hr;
  394.     }   
  395.  
  396.     ptlib->Release();
  397.     *pptinfo = ptinfo;
  398.     return NOERROR;
  399. }
  400.  
  401. /*
  402.  * RaiseException
  403.  *
  404.  * Parameters:
  405.  *  nID                 Error number
  406.  *  rguid               GUID of interface that is raising the exception.
  407.  *
  408.  * Return Value:
  409.  *  HRESULT correspnding to the nID error number.
  410.  *
  411.  * Purpose:
  412.  *  Fills the EXCEPINFO structure. 
  413.  *  Sets ErrorInfo object for vtable-binding controllers.
  414.  *  For id-binding and late binding controllers DispInvoke
  415.  *  will return DISP_E_EXCEPTION and fill the EXCEPINFO parameter
  416.  *  with the error information set by SetErrorInfo.
  417.  *
  418.  */  
  419. HRESULT RaiseException(int nID, REFGUID rguid)
  420. {   
  421.     extern SCODE g_scodes[];
  422.     TCHAR szError[STR_LEN];   
  423.     ICreateErrorInfo *pcerrinfo;  
  424.     IErrorInfo *perrinfo;
  425.     HRESULT hr;
  426.     BSTR bstrDescription = NULL;
  427.     
  428.     if (LoadString(g_pApplication->m_hinst, nID, szError, sizeof(szError)))
  429.         bstrDescription = SysAllocString(TO_OLE_STRING(szError));    
  430.     
  431.     // Set ErrorInfo object so that vtable binding controller can get
  432.     // rich error information. If the controller is using IDispatch
  433.     // to access properties or methods, DispInvoke will fill the
  434.     // EXCEPINFO structure using the values specified in the ErrorInfo
  435.     // object and DispInvoke will return DISP_E_EXCEPTION. The property
  436.     // or method must return a failure SCODE for DispInvoke to do this.
  437.     hr = CreateErrorInfo(&pcerrinfo); 
  438.     if (SUCCEEDED(hr))
  439.     {
  440.        pcerrinfo->SetGUID(rguid);
  441.        pcerrinfo->SetSource(g_pApplication->m_bstrProgID);
  442.        if (bstrDescription)
  443.            pcerrinfo->SetDescription(bstrDescription);  
  444.        hr = pcerrinfo->QueryInterface(IID_IErrorInfo, (LPVOID FAR*) &perrinfo);
  445.        if (SUCCEEDED(hr))
  446.        {
  447.           SetErrorInfo(0, perrinfo);
  448.           perrinfo->Release();
  449.        }  
  450.        pcerrinfo->Release();
  451.     }  
  452.     
  453.     if (bstrDescription)
  454.         SysFreeString(bstrDescription);
  455.     return g_scodes[nID-1001];
  456.  
  457.  
  458.  
  459. /*
  460.  * Quick & Dirty ANSI/Unicode conversion routines. These routines use a static
  461.  * buffer of fixed size to hold the converted string. Consequently these
  462.  * routines are limited to strings of size STRCONVERT_MAXLEN. Also the same
  463.  * buffer is reused when the routine is called a second time. So make sure
  464.  * that the converted string is used before the conversion routine is called
  465.  * again
  466.  */
  467. #ifdef WIN32
  468.  
  469. #ifndef UNICODE
  470. char* ConvertToAnsi(OLECHAR FAR* szW)
  471. {
  472.   static char achA[STRCONVERT_MAXLEN]; 
  473.   
  474.   WideCharToMultiByte(CP_ACP, 0, szW, -1, achA, STRCONVERT_MAXLEN, NULL, NULL);  
  475.   return achA; 
  476.  
  477. OLECHAR* ConvertToUnicode(char FAR* szA)
  478. {
  479.   static OLECHAR achW[STRCONVERT_MAXLEN]; 
  480.  
  481.   MultiByteToWideChar(CP_ACP, 0, szA, -1, achW, STRCONVERT_MAXLEN);  
  482.   return achW; 
  483. }
  484. #endif
  485.  
  486. #endif      
  487.     
  488.  
  489.  
  490.    
  491.     
  492.