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

Windows编程

开发平台:

Visual C++

  1. /*
  2.  * SQUARE.CPP
  3.  * Square Rendering/Calculation Automation Object Chapter 15
  4.  *
  5.  * An automation object that draws a square in various rotational
  6.  * states and provides access to it through IDispatch.
  7.  *
  8.  * This file contains all the code for this sample.
  9.  *
  10.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  11.  *
  12.  * Kraig Brockschmidt, Microsoft
  13.  * Internet  :  kraigb@microsoft.com
  14.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  15.  */
  16. #define INITGUIDS
  17. #include "square.h"
  18. ULONG       g_cObj=0;
  19. ULONG       g_cLock=0;
  20. HWND        g_hWnd=NULL;
  21. /*
  22.  * WinMain
  23.  *
  24.  * Purpose:
  25.  *  Main entry point of application.
  26.  */
  27. int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hInstPrev
  28.     , LPSTR pszCmdLine, int nCmdShow)
  29.     {
  30.     MSG         msg;
  31.     PCApp       pApp;
  32.     SETMESSAGEQUEUE;
  33.     pApp=new CApp(hInst, hInstPrev, pszCmdLine, nCmdShow);
  34.     if (NULL==pApp)
  35.         return -1;
  36.     if (pApp->Init())
  37.         {
  38.         while (GetMessage(&msg, NULL, 0,0 ))
  39.             {
  40.             TranslateMessage(&msg);
  41.             DispatchMessage(&msg);
  42.             }
  43.         }
  44.     delete pApp;
  45.     return msg.wParam;
  46.     }
  47. /*
  48.  * MainWndProc
  49.  *
  50.  * Purpose:
  51.  *  Standard window class procedure.
  52.  */
  53. LRESULT APIENTRY MainWndProc(HWND hWnd, UINT iMsg
  54.     , WPARAM wParam, LPARAM lParam)
  55.     {
  56.     switch (iMsg)
  57.         {
  58.         case WM_DESTROY:
  59.             PostQuitMessage(0);
  60.             break;
  61.         default:
  62.             return (DefWindowProc(hWnd, iMsg, wParam, lParam));
  63.         }
  64.     return 0L;
  65.     }
  66. /*
  67.  * ObjectDestroyed
  68.  *
  69.  * Purpose:
  70.  *  Function for the object to call when it gets destroyed.
  71.  *  We destroy the main window if the proper conditions are met
  72.  *  for shutdown.
  73.  */
  74. void ObjectDestroyed(void)
  75.     {
  76.     g_cObj--;
  77.     //No more objects and no locks, shut the app down.
  78.     if (0L==g_cObj && 0L==g_cLock && IsWindow(g_hWnd))
  79.         PostMessage(g_hWnd, WM_CLOSE, 0, 0L);
  80.     return;
  81.     }
  82. /*
  83.  * CApp::CApp
  84.  * CApp::~CApp
  85.  *
  86.  * Constructor Parameters:
  87.  *  hInst           HINSTANCE of the Application from WinMain
  88.  *  hInstPrev       HINSTANCE of a previous instance from WinMain
  89.  *  pszCmdLine      LPSTR of the command line.
  90.  *  nCmdShow        UINT specifying how to show the app window,
  91.  *                  from WinMain.
  92.  */
  93. CApp::CApp(HINSTANCE hInst, HINSTANCE hInstPrev
  94.     , LPSTR pszCmdLine, UINT nCmdShow)
  95.     {
  96.     //Initialize WinMain parameter holders.
  97.     m_hInst     =hInst;
  98.     m_hInstPrev =hInstPrev;
  99.     m_pszCmdLine=pszCmdLine;
  100.     m_nCmdShow  =nCmdShow;
  101.     m_dwRegCO=0;
  102.     m_pIClassFactory=NULL;
  103.     m_fInitialized=FALSE;
  104.     return;
  105.     }
  106. CApp::~CApp(void)
  107.     {
  108.     //Opposite of CoRegisterClassObject; class factory ref is now 1
  109.     if (0L!=m_dwRegCO)
  110.         CoRevokeClassObject(m_dwRegCO);
  111.     //The last Release, which frees the class factory.
  112.     if (NULL!=m_pIClassFactory)
  113.         m_pIClassFactory->Release();
  114.     if (m_fInitialized)
  115.         CoUninitialize();
  116.     return;
  117.     }
  118. /*
  119.  * CApp::Init
  120.  *
  121.  * Purpose:
  122.  *  Initializes an CApp object by registering window classes,
  123.  *  creating the main window, and doing anything else prone to
  124.  *  failure.  If this function fails the caller should guarantee
  125.  *  that the destructor is called.
  126.  *
  127.  * Return Value:
  128.  *  BOOL            TRUE if successful, FALSE otherwise.
  129.  */
  130. BOOL CApp::Init(void)
  131.     {
  132.     WNDCLASS    wc;
  133.     HRESULT     hr;
  134.     HWND        hWnd;
  135.     if (lstrcmpiA(m_pszCmdLine, "-Embedding"))
  136.         return FALSE;
  137.     CHECKVER_OLE;
  138.     if (FAILED(CoInitialize(NULL)))
  139.         return FALSE;
  140.     m_fInitialized=TRUE;
  141.     if (!m_hInstPrev)
  142.         {
  143.         wc.style          = CS_HREDRAW | CS_VREDRAW;
  144.         wc.lpfnWndProc    = MainWndProc;
  145.         wc.cbClsExtra     = 0;
  146.         wc.cbWndExtra     = 0;
  147.         wc.hInstance      = m_hInst;
  148.         wc.hIcon          = NULL;
  149.         wc.hCursor        = NULL;
  150.         wc.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);
  151.         wc.lpszMenuName   = NULL;
  152.         wc.lpszClassName  = TEXT("SphereSquare");
  153.         if (!RegisterClass(&wc))
  154.             return FALSE;
  155.         //Child window in which to draw
  156.         wc.lpfnWndProc    = SquareWndProc;
  157.         wc.cbWndExtra     = CBSQUAREWNDEXTRA;
  158.         wc.hCursor        = (HCURSOR)LoadCursor(NULL, IDC_ARROW);
  159.         wc.lpszClassName  = SZCLASSSQUARE;
  160.         if (!RegisterClass(&wc))
  161.             return FALSE;
  162.         }
  163.     //This window is never shown
  164.     hWnd=CreateWindow(TEXT("SphereSquare"), TEXT("SphereSquare")
  165.         , WS_OVERLAPPEDWINDOW, 100, 100, 400, 400
  166.         , NULL, NULL, m_hInst, NULL);
  167.     if (NULL==hWnd)
  168.         return FALSE;
  169.     g_hWnd=hWnd;
  170.     m_pIClassFactory=new CSquareClassFactory(hWnd, m_hInst);
  171.     if (NULL==m_pIClassFactory)
  172.         return FALSE;
  173.     m_pIClassFactory->AddRef();
  174.     hr=CoRegisterClassObject(CLSID_SphereSquare, m_pIClassFactory
  175.         , CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &m_dwRegCO);
  176.     if (FAILED(hr))
  177.         return FALSE;
  178.     return TRUE;
  179.     }
  180. //Class Factory implementation
  181. /*
  182.  * CSquareClassFactory::CSquareClassFactory
  183.  * CSquareClassFactory::~CSquareClassFactory
  184.  *
  185.  * Constructor Parameters:
  186.  *  hWnd            HWND of the application.
  187.  *  hInst           HINSTANCE to pass to objects we create.
  188.  */
  189. CSquareClassFactory::CSquareClassFactory(HWND hWnd
  190.     , HINSTANCE hInst)
  191.     {
  192.     m_cRef=0L;
  193.     m_hWnd=hWnd;
  194.     m_hInst=hInst;
  195.     return;
  196.     }
  197. CSquareClassFactory::~CSquareClassFactory(void)
  198.     {
  199.     return;
  200.     }
  201. /*
  202.  * CSquareClassFactory::QueryInterface
  203.  * CSquareClassFactory::AddRef
  204.  * CSquareClassFactory::Release
  205.  */
  206. STDMETHODIMP CSquareClassFactory::QueryInterface(REFIID riid
  207.     , PPVOID ppv)
  208.     {
  209.     *ppv=NULL;
  210.     if (IID_IUnknown==riid || IID_IClassFactory==riid)
  211.         *ppv=this;
  212.     if (NULL!=*ppv)
  213.         {
  214.         ((LPUNKNOWN)*ppv)->AddRef();
  215.         return NOERROR;
  216.         }
  217.     return ResultFromScode(E_NOINTERFACE);
  218.     }
  219. STDMETHODIMP_(ULONG) CSquareClassFactory::AddRef(void)
  220.     {
  221.     return ++m_cRef;
  222.     }
  223. STDMETHODIMP_(ULONG) CSquareClassFactory::Release(void)
  224.     {
  225.     if (0!=--m_cRef)
  226.         return m_cRef;
  227.     delete this;
  228.     return 0;
  229.     }
  230. /*
  231.  * CSquareClassFactory::CreateInstance
  232.  * CSquareClassFactory::LockServer
  233.  */
  234. STDMETHODIMP CSquareClassFactory::CreateInstance(LPUNKNOWN pUnkOuter
  235.     , REFIID riid, PPVOID ppvObj)
  236.     {
  237.     PCSquare    pObj;
  238.     HRESULT     hr;
  239.     *ppvObj=NULL;
  240.     if (NULL!=pUnkOuter)
  241.         return ResultFromScode(CLASS_E_NOAGGREGATION);
  242.     pObj=new CSquare();
  243.     g_cObj++;
  244.     hr=ResultFromScode(E_OUTOFMEMORY);
  245.     if (NULL!=pObj)
  246.         {
  247.         if (pObj->Init(m_hWnd, m_hInst))
  248.             {
  249.             hr=pObj->QueryInterface(riid, ppvObj);
  250.             }
  251.         }
  252.     if (FAILED(hr))
  253.         {
  254.         if (NULL!=pObj)
  255.             delete pObj;
  256.         ObjectDestroyed();
  257.         }
  258.     return hr;
  259.     }
  260. STDMETHODIMP CSquareClassFactory::LockServer(BOOL fLock)
  261.     {
  262.     if (fLock)
  263.         g_cLock++;
  264.     else
  265.         {
  266.         g_cLock--;
  267.         //Centralizes shutdown in ObjectDestroyed
  268.         g_cObj++;
  269.         ObjectDestroyed();
  270.         }
  271.     return NOERROR;
  272.     }
  273. //Object implementation
  274. /*
  275.  * CSquare::CSquare
  276.  * CSquare::~CSquare
  277.  */
  278. CSquare::CSquare(void)
  279.     {
  280.     m_cRef=0;
  281.     m_hWnd=NULL;
  282.     m_pITypeInfo=NULL;
  283.     m_pIUnkDisp=NULL;
  284.     m_cRadius=100.0;
  285.     m_dDeclin=0.0;
  286.     m_dTheta=0.0;
  287.     m_xOrg=(int)(1.5*m_cRadius);
  288.     m_yOrg=m_xOrg;
  289.     m_crBack=GetSysColor(COLOR_WINDOW);
  290.     m_crLinePos=RGB(255, 255, 0);
  291.     m_crLineNeg=RGB(255, 0, 0);
  292.     m_hPenPos=NULL;
  293.     m_hPenNeg=NULL;
  294.     m_cx=200;
  295.     m_cy=220;
  296.     m_xPos=100;
  297.     m_yPos=100;
  298.     return;
  299.     }
  300. CSquare::~CSquare(void)
  301.     {
  302.     ReleaseInterface(m_pITypeInfo);
  303.     ReleaseInterface(m_pIUnkDisp);
  304.     if (NULL!=m_hPenPos)
  305.         DeleteObject(m_hPenPos);
  306.     if (NULL!=m_hPenNeg)
  307.         DeleteObject(m_hPenNeg);
  308.     if (NULL!=m_hWnd)
  309.         DestroyWindow(m_hWnd);
  310.     return;
  311.     }
  312. /*
  313.  * CSquare::Init
  314.  *
  315.  * Purpose:
  316.  *  Creates the window in which we draw.
  317.  */
  318. BOOL CSquare::Init(HWND hWndOwner, HINSTANCE hInst)
  319.     {
  320.     ITypeLib       *pITypeLib;
  321.     HRESULT         hr;
  322.     //Create both default pens
  323.     CreatePens(TRUE, TRUE);
  324.     m_hWnd=CreateWindow(SZCLASSSQUARE, SZCLASSSQUARE
  325.         , WS_CAPTION | WS_POPUP, m_xPos, m_yPos, m_cx, m_cy
  326.         , hWndOwner, NULL, hInst, this);
  327.     if (NULL==m_hWnd)
  328.         return NULL;
  329.     if (FAILED(LoadRegTypeLib(LIBID_SphereSquareLibrary, 1, 0
  330.         , LANG_NEUTRAL, &pITypeLib)))
  331.         {
  332.         if (FAILED(LoadTypeLib(OLETEXT("SQUARE.TLB"), &pITypeLib)))
  333.             return FALSE;
  334.         }
  335.     hr=pITypeLib->GetTypeInfoOfGuid(IID_ISphereSquare, &m_pITypeInfo);
  336.     if (FAILED(hr))
  337.         {
  338.         pITypeLib->Release();
  339.         return FALSE;
  340.         }
  341.     hr=CreateStdDispatch((IUnknown *)this, (ISphereSquare *)this
  342.         , m_pITypeInfo, &m_pIUnkDisp);
  343.     pITypeLib->Release();
  344.     if (FAILED(hr))
  345.         return FALSE;
  346.     return TRUE;
  347.     }
  348. /*
  349.  * CSquare::CreatePens
  350.  *
  351.  * Purpose:
  352.  *  Creates one or both line color pens
  353.  *
  354.  * Parameters:
  355.  *  fPositive       BOOL instructing us to create positive line color.
  356.  *  fNegative       BOOL instructing us to create negative line color.
  357.  *
  358.  * Return Value:
  359.  *  None
  360.  */
  361. void CSquare::CreatePens(BOOL fPositive, BOOL fNegative)
  362.     {
  363.     if (fPositive)
  364.         {
  365.         if (NULL!=m_hPenPos)
  366.             DeleteObject(m_hPenPos);
  367.         m_hPenPos=CreatePen(PS_SOLID, 1, m_crLinePos);
  368.         if (NULL==m_hPenPos)
  369.             m_hPenPos=(HPEN)GetStockObject(BLACK_PEN);
  370.         }
  371.     if (fNegative)
  372.         {
  373.         if (NULL!=m_hPenNeg)
  374.             DeleteObject(m_hPenNeg);
  375.         m_hPenNeg=CreatePen(PS_SOLID, 1, m_crLineNeg);
  376.         if (NULL==m_hPenNeg)
  377.             m_hPenNeg=(HPEN)GetStockObject(BLACK_PEN);
  378.         }
  379.     return;
  380.     }
  381. /*
  382.  * CSquare::Draw
  383.  *
  384.  * Purpose:
  385.  *  Draws the image of a square rotated according to m_dDeclin
  386.  *  and m_dTheta with an edge length of m_cRadius.
  387.  *
  388.  * Parameters:
  389.  *  hDC             HDC on which to draw.
  390.  *
  391.  * Return Value;
  392.  *  None
  393.  */
  394. void CSquare::Draw(HDC hDC)
  395.     {
  396.     POINT           pt[5];
  397.     int             x, y;
  398.     double          rad;
  399.     RECT            rc;
  400.     HGDIOBJ         hGDI;
  401.     SetBkColor(hDC, m_crBack);
  402.     //Erase the background
  403.     SetRect(&rc, 0, 0, m_xOrg*2, m_yOrg*2);
  404.     ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
  405.     rad=cos(m_dDeclin);
  406.     x=(int)(m_cRadius*cos(m_dTheta));
  407.     y=(int)(m_cRadius*rad*sin(m_dTheta));
  408.     SETPOINT(pt[0], m_xOrg+x, m_yOrg+y);
  409.     SETPOINT(pt[2], m_xOrg-x, m_yOrg-y);
  410.     x=(int)(m_cRadius*cos(m_dTheta+PI/2));
  411.     y=(int)(m_cRadius*rad*sin(m_dTheta+PI/2));
  412.     SETPOINT(pt[3], m_xOrg+x, m_yOrg+y);
  413.     SETPOINT(pt[1], m_xOrg-x, m_yOrg-y);
  414.     pt[4]=pt[0];
  415.     /*
  416.      * Set the line color according to which side of the square
  417.      * is facing out of the screen.  We'll draw the positive
  418.      * z lines a yellow (default), the negative face red
  419.      * (default).  Both colors can be changed by the controller.
  420.      *
  421.      * To determine which side is out, we only have to look at
  422.      * the rad value which is cos(m_dDeclin).  If positive, then
  423.      * we're in the positive range.
  424.      */
  425.     hGDI=SelectObject(hDC, (rad > 0) ? m_hPenPos : m_hPenNeg);
  426.     Polyline(hDC, pt, sizeof(pt)/sizeof(POINT));
  427.     SelectObject(hDC, GetStockObject(WHITE_PEN));
  428.     MoveToEx(hDC, m_xOrg, m_yOrg, NULL);
  429.     LineTo(hDC, pt[0].x, pt[0].y);
  430.     SelectObject(hDC, hGDI);
  431.     return;
  432.     }
  433. /*
  434.  * SquareWndProc
  435.  *
  436.  * Purpose:
  437.  *  Window procedure for the Square window.
  438.  */
  439. LRESULT APIENTRY SquareWndProc(HWND hWnd, UINT iMsg, WPARAM wParam
  440.     , LPARAM lParam)
  441.     {
  442.     PCSquare    pcp;
  443.     PAINTSTRUCT         ps;
  444.     HDC                 hDC;
  445.     RECT                rc;
  446.     pcp=(PCSquare)GetWindowLong(hWnd, SQWL_STRUCTURE);
  447.     switch (iMsg)
  448.         {
  449.         case WM_CREATE:
  450.             pcp=(PCSquare)((LPCREATESTRUCT)lParam)
  451.                 ->lpCreateParams;
  452.             SetWindowLong(hWnd, SQWL_STRUCTURE, (LONG)pcp);
  453.             break;
  454.         case WM_ERASEBKGND:
  455.             hDC=(HDC)wParam;
  456.             SetBkColor(hDC, pcp->m_crBack);
  457.             GetClientRect(hWnd, &rc);
  458.             ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
  459.             break;
  460.         case WM_PAINT:
  461.             hDC=BeginPaint(hWnd, &ps);
  462.             pcp->Draw(hDC);
  463.             EndPaint(hWnd, &ps);
  464.             break;
  465.         case WM_CLOSE:
  466.             /*
  467.              * Eat this or Alt+F4 can destroy the window, even
  468.              * though we don't have a system menu.
  469.              */
  470.             break;
  471.         default:
  472.             return DefWindowProc(hWnd, iMsg, wParam, lParam);
  473.         }
  474.     return 0L;
  475.     }
  476. /*
  477.  * CSquare::QueryInterface
  478.  * CSquare::AddRef
  479.  * CSquare::Release
  480.  *
  481.  * Purpose:
  482.  *  IUnknown members for CSquare object.
  483.  */
  484. STDMETHODIMP CSquare::QueryInterface(REFIID riid, PPVOID ppv)
  485.     {
  486.     *ppv=NULL;
  487.     if (IID_IUnknown==riid || IID_ISphereSquare==riid)
  488.         *ppv=this;
  489.     if (IID_IDispatch==riid || DIID_DISphereSquare==riid)
  490.         return m_pIUnkDisp->QueryInterface(IID_IDispatch, ppv);
  491.     if (NULL!=*ppv)
  492.         {
  493.         ((IUnknown *)*ppv)->AddRef();
  494.         return NOERROR;
  495.         }
  496.     return ResultFromScode(E_NOINTERFACE);
  497.     }
  498. STDMETHODIMP_(ULONG) CSquare::AddRef(void)
  499.     {
  500.     return ++m_cRef;
  501.     }
  502. STDMETHODIMP_(ULONG) CSquare::Release(void)
  503.     {
  504.     if (0L!=--m_cRef)
  505.         return m_cRef;
  506.     ObjectDestroyed();
  507.     delete this;
  508.     return 0L;
  509.     }
  510. //ISphereSquare members
  511. STDMETHODIMP_(double) CSquare::get_Radius(void)
  512.     {
  513.     return m_cRadius;
  514.     }
  515. STDMETHODIMP_(void) CSquare::put_Radius(double cRadius)
  516.     {
  517.     //Only use positive radii.
  518.     if (cRadius > 0.0)
  519.         m_cRadius=cRadius;
  520.     //We'll be lazy and not throw exceptions.
  521.     return;
  522.     }
  523. STDMETHODIMP_(double) CSquare::get_Theta(void)
  524.     {
  525.     return m_dTheta;
  526.     }
  527. STDMETHODIMP_(void) CSquare::put_Theta(double dTheta)
  528.     {
  529.     //Anything is valid when you do trig
  530.     m_dTheta=dTheta;
  531.     return;
  532.     }
  533. STDMETHODIMP_(double) CSquare::get_Declination(void)
  534.     {
  535.     return m_dDeclin;
  536.     }
  537. STDMETHODIMP_(void) CSquare::put_Declination(double dDeclin)
  538.     {
  539.     m_dDeclin=dDeclin;
  540.     return;
  541.     }
  542. STDMETHODIMP_(long) CSquare::get_BackColor(void)
  543.     {
  544.     return m_crBack;
  545.     }
  546. STDMETHODIMP_(void) CSquare::put_BackColor(long crBack)
  547.     {
  548.     m_crBack=crBack;
  549.     return;
  550.     }
  551. STDMETHODIMP_(long) CSquare::get_LineColorPositive(void)
  552.     {
  553.     return m_crLinePos;
  554.     }
  555. STDMETHODIMP_(void) CSquare::put_LineColorPositive(long crLinePos)
  556.     {
  557.     m_crLinePos=crLinePos;
  558.     return;
  559.     }
  560. STDMETHODIMP_(long) CSquare::get_LineColorNegative(void)
  561.     {
  562.     return m_crLineNeg;
  563.     }
  564. STDMETHODIMP_(void) CSquare::put_LineColorNegative(long crLineNeg)
  565.     {
  566.     m_crLineNeg=crLineNeg;
  567.     return;
  568.     }
  569. STDMETHODIMP_(void) CSquare::Draw(void)
  570.     {
  571.     InvalidateRect(m_hWnd, NULL, FALSE);
  572.     UpdateWindow(m_hWnd);
  573.     return;
  574.     }
  575. STDMETHODIMP_(void) CSquare::SetCenterPoint(int cx, int cy)
  576.     {
  577.     //No validation...we're deing lazy
  578.     m_xOrg=cx;
  579.     m_yOrg=cy;
  580.     return;
  581.     }
  582. STDMETHODIMP_(void) CSquare::ShowWindow(int nCmdShow)
  583.     {
  584.     ::ShowWindow(m_hWnd, nCmdShow);
  585.     UpdateWindow(m_hWnd);
  586.     return;
  587.     }
  588. STDMETHODIMP_(void) CSquare::SetWindowPosition(int xPos, int yPos)
  589.     {
  590.     m_xPos=xPos;
  591.     m_yPos=yPos;
  592.     SetWindowPos(m_hWnd, NULL, m_xPos, m_yPos, 0, 0
  593.         , SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
  594.     return;
  595.     }
  596. STDMETHODIMP_(void) CSquare::SetWindowSize(int cx, int cy)
  597.     {
  598.     m_cx=cx;
  599.     m_cy=cy;
  600.     SetWindowPos(m_hWnd, NULL, 0, 0, m_cx, m_cy
  601.         , SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  602.     return;
  603.     }