MAIN.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:15k
源码类别:

Windows编程

开发平台:

Visual C++

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