home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / ctlnownd.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-16  |  11.3 KB  |  470 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12.  
  13. #ifdef AFXCTL_CORE1_SEG
  14. #pragma code_seg(AFXCTL_CORE1_SEG)
  15. #endif
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. #define new DEBUG_NEW
  23.  
  24. /////////////////////////////////////////////////////////////////////////////
  25. // CWindowlessDC - used by COleControl::GetDC and COleControl::ReleaseDC
  26.  
  27. class CWindowlessDC : public CDC
  28. {
  29.     DECLARE_DYNAMIC(CWindowlessDC)
  30. public:
  31.     CWindowlessDC(HDC hDC, CPoint& pointOrigin);
  32.     HDC Detach();
  33. protected:
  34.     CPoint m_pointOrigin;
  35. };
  36.  
  37. IMPLEMENT_DYNAMIC(CWindowlessDC, CDC)
  38.  
  39. CWindowlessDC::CWindowlessDC(HDC hDC, CPoint& pointOrigin)
  40. {
  41.     m_hDC = m_hAttribDC = hDC;
  42.     m_pointOrigin =  GetViewportOrg();
  43.     SetViewportOrg(m_pointOrigin + pointOrigin);
  44. }
  45.  
  46. HDC CWindowlessDC::Detach()
  47. {
  48.     SetViewportOrg(m_pointOrigin);
  49.     HDC hDC = m_hDC;
  50.     m_hDC = m_hAttribDC = NULL;
  51.     return hDC;
  52. }
  53.  
  54. /////////////////////////////////////////////////////////////////////////////
  55. // Overridables used with the various windowless interfaces
  56.  
  57. void COleControl::GetClientOffset(long* pdxOffset, long* pdyOffset) const
  58. {
  59.     int nOffset = (m_sBorderStyle == 1) + (2 * (m_sAppearance == 1));
  60.  
  61.     if (nOffset > 0)
  62.     {
  63.         *pdxOffset = nOffset * GetSystemMetrics(SM_CXBORDER);
  64.         *pdyOffset = nOffset * GetSystemMetrics(SM_CYBORDER);
  65.     }
  66.     else
  67.     {
  68.         *pdxOffset = *pdyOffset = 0;
  69.     }
  70. }
  71.  
  72. UINT COleControl::ParentToClient(LPCRECT lprcBounds, LPPOINT pPoint,
  73.     BOOL bHitTest) const
  74. {
  75.     long dxOffset;
  76.     long dyOffset;
  77.     GetClientOffset(&dxOffset, &dyOffset);
  78.  
  79.     UINT nHitTest = HTNOWHERE;
  80.  
  81.     if (bHitTest && ::PtInRect(lprcBounds, *pPoint))
  82.     {
  83.         if (dxOffset > 0)
  84.         {
  85.             CRect rectClient(lprcBounds);
  86.             rectClient.InflateRect(-dxOffset, -dyOffset);
  87.             nHitTest = rectClient.PtInRect(*pPoint) ? HTCLIENT : HTBORDER;
  88.         }
  89.         else
  90.         {
  91.             nHitTest = HTCLIENT;
  92.         }
  93.     }
  94.  
  95.     pPoint->x -= lprcBounds->left + dxOffset;
  96.     pPoint->y -= lprcBounds->top  + dyOffset;
  97.  
  98.     return nHitTest;
  99. }
  100.  
  101. void COleControl::ClientToParent(LPCRECT lprcBounds, LPPOINT pPoint) const
  102. {
  103.     long dxOffset;
  104.     long dyOffset;
  105.     GetClientOffset(&dxOffset, &dyOffset);
  106.     pPoint->x += lprcBounds->left + dxOffset;
  107.     pPoint->y += lprcBounds->top  + dyOffset;
  108. }
  109.  
  110. /////////////////////////////////////////////////////////////////////////////
  111. // Overridables for IPointerInactive methods
  112.  
  113. DWORD COleControl::GetActivationPolicy()
  114. {
  115.     return 0;
  116. }
  117.  
  118. BOOL COleControl::OnInactiveSetCursor(LPCRECT lprcBounds, long x, long y,
  119.     DWORD dwMouseMsg, BOOL bSetAlways)
  120. {
  121.     CPoint point(x, y);
  122.     UINT nHitTest = ParentToClient(lprcBounds, &point, TRUE);
  123.  
  124.     LRESULT lResult = 0;
  125.     OnWndMsg(WM_SETCURSOR, nHitTest, dwMouseMsg, &lResult);
  126.  
  127.     if (bSetAlways && ! lResult)
  128.         ::SetCursor(::LoadCursor(NULL, IDC_ARROW));
  129.  
  130.     return bSetAlways || lResult;
  131. }
  132.  
  133. void COleControl::OnInactiveMouseMove(LPCRECT lprcBounds, long x, long y,
  134.     DWORD dwKeyState)
  135. {
  136.     CPoint point(x, y);
  137.     ParentToClient(lprcBounds, &point);
  138.     OnWndMsg(WM_MOUSEMOVE, dwKeyState, MAKELONG(point.x, point.y), NULL);
  139. }
  140.  
  141. /////////////////////////////////////////////////////////////////////////////
  142. // COleControl::XPointerInactive
  143.  
  144. STDMETHODIMP_(ULONG) COleControl::XPointerInactive::AddRef()
  145. {
  146.     METHOD_PROLOGUE_EX_(COleControl, PointerInactive)
  147.     return (ULONG)pThis->ExternalAddRef();
  148. }
  149.  
  150. STDMETHODIMP_(ULONG) COleControl::XPointerInactive::Release()
  151. {
  152.     METHOD_PROLOGUE_EX_(COleControl, PointerInactive)
  153.     return (ULONG)pThis->ExternalRelease();
  154. }
  155.  
  156. STDMETHODIMP COleControl::XPointerInactive::QueryInterface(
  157.     REFIID iid, LPVOID* ppvObj)
  158. {
  159.     METHOD_PROLOGUE_EX_(COleControl, PointerInactive)
  160.     return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
  161. }
  162.  
  163. STDMETHODIMP COleControl::XPointerInactive::GetActivationPolicy(
  164.    DWORD* pdwPolicy)
  165. {
  166.     METHOD_PROLOGUE_EX_(COleControl, PointerInactive)
  167.     *pdwPolicy = pThis->GetActivationPolicy();
  168.     return S_OK;
  169. }
  170.  
  171. STDMETHODIMP COleControl::XPointerInactive::OnInactiveSetCursor(
  172.     LPCRECT lprcBounds, long x, long y, DWORD dwMouseMsg, BOOL bSetAlways)
  173. {
  174.     METHOD_PROLOGUE_EX_(COleControl, PointerInactive)
  175.     return pThis->OnInactiveSetCursor(lprcBounds, x, y, dwMouseMsg, bSetAlways) ?
  176.         S_OK : S_FALSE;
  177. }
  178.  
  179. STDMETHODIMP COleControl::XPointerInactive::OnInactiveMouseMove(
  180.     LPCRECT lprcBounds, long x, long y, DWORD dwKeyState)
  181. {
  182.     METHOD_PROLOGUE_EX_(COleControl, PointerInactive)
  183.     pThis->OnInactiveMouseMove(lprcBounds, x, y, dwKeyState);
  184.     return S_OK;
  185. }
  186.  
  187. /////////////////////////////////////////////////////////////////////////////
  188. // Overridables for IOleInPlaceObjectWindowless methods
  189.  
  190. BOOL COleControl::OnWindowlessMessage(UINT msg, WPARAM wParam, LPARAM lParam,
  191.     LRESULT* plResult)
  192. {
  193.     if ((msg >= WM_MOUSEFIRST && msg <= WM_MOUSELAST) || (msg == WM_CONTEXTMENU))
  194.     {
  195.         CPoint point(LOWORD(lParam), HIWORD(lParam));
  196.         ParentToClient(m_rcPos, &point, FALSE);
  197.         lParam = MAKELONG(point.x, point.y);
  198.     }
  199.  
  200.     return OnWndMsg(msg, wParam, lParam, plResult);
  201. }
  202.  
  203. IDropTarget* COleControl::GetWindowlessDropTarget()
  204. {
  205.     return NULL;
  206. }
  207.  
  208. /////////////////////////////////////////////////////////////////////////////
  209. // COleControl::XOleInPlaceObject (IOleInPlaceObjectWindowless methods)
  210.  
  211. STDMETHODIMP COleControl::XOleInPlaceObject::OnWindowMessage(UINT msg,
  212.     WPARAM wParam, LPARAM lParam, LRESULT* plResult)
  213. {
  214.     METHOD_PROLOGUE_EX_(COleControl, OleInPlaceObject)
  215.     return pThis->OnWindowlessMessage(msg, wParam, lParam, plResult) ?
  216.         S_OK : S_FALSE;
  217. }
  218.  
  219. STDMETHODIMP COleControl::XOleInPlaceObject::GetDropTarget(
  220.     IDropTarget** ppDropTarget)
  221. {
  222.     METHOD_PROLOGUE_EX_(COleControl, OleInPlaceObject)
  223.  
  224.     *ppDropTarget = pThis->GetWindowlessDropTarget();
  225.     return (*ppDropTarget != NULL) ? S_OK : E_NOTIMPL;
  226. }
  227.  
  228. /////////////////////////////////////////////////////////////////////////////
  229. // Cover functions for IOleInPlaceSiteWindowless methods
  230.  
  231. CWnd* COleControl::SetCapture()
  232. {
  233.     ASSERT((m_hWnd != NULL) || (m_bInPlaceSiteWndless && m_bInPlaceActive));
  234.  
  235.     if (m_bInPlaceSiteWndless && m_bInPlaceActive)
  236.     {
  237.         CWnd* pWndPrev = GetCapture();
  238.         m_pInPlaceSiteWndless->SetCapture(TRUE);
  239.         return pWndPrev;
  240.     }
  241.     else
  242.     {
  243.         return CWnd::SetCapture();
  244.     }
  245. }
  246.  
  247. BOOL COleControl::ReleaseCapture()
  248. {
  249.     ASSERT((m_hWnd != NULL) || (m_bInPlaceSiteWndless && m_bInPlaceActive));
  250.  
  251.     if (m_bInPlaceSiteWndless && m_bInPlaceActive)
  252.         return (m_pInPlaceSiteWndless->SetCapture(FALSE) == S_OK);
  253.     else
  254.         return ::ReleaseCapture();
  255. }
  256.  
  257. CWnd* COleControl::GetCapture()
  258. {
  259.     ASSERT((m_hWnd != NULL) || (m_bInPlaceSiteWndless && m_bInPlaceActive));
  260.  
  261.     if (m_bInPlaceSiteWndless && m_bInPlaceActive)
  262.     {
  263.         return (m_pInPlaceSiteWndless->GetCapture() == S_OK) ?
  264.             this : NULL;
  265.     }
  266.     else
  267.     {
  268.         return CWnd::GetCapture();
  269.     }
  270. }
  271.  
  272. CWnd* COleControl::SetFocus()
  273. {
  274.     ASSERT((m_hWnd != NULL) || (m_bInPlaceSiteWndless && m_bInPlaceActive));
  275.  
  276.     if (m_bInPlaceSiteWndless && m_bInPlaceActive)
  277.     {
  278.         CWnd* pWndPrev = GetFocus();
  279.         m_pInPlaceSiteWndless->SetFocus(TRUE);
  280.         return pWndPrev;
  281.     }
  282.     else
  283.     {
  284.         return CWnd::SetFocus();
  285.     }
  286. }
  287.  
  288. CWnd* COleControl::GetFocus()
  289. {
  290.     ASSERT((m_hWnd != NULL) || (m_bInPlaceSiteWndless && m_bInPlaceActive));
  291.  
  292.     if (m_bInPlaceSiteWndless && m_bInPlaceActive)
  293.     {
  294.         return (m_pInPlaceSiteWndless->GetFocus() == S_OK) ?
  295.             this : NULL;
  296.     }
  297.     else
  298.     {
  299.         return CWnd::GetFocus();
  300.     }
  301. }
  302.  
  303. CDC* COleControl::GetDC(LPCRECT lprcRect, DWORD dwFlags)
  304. {
  305.     ASSERT((m_hWnd != NULL) || (m_bInPlaceSiteWndless && m_bInPlaceActive));
  306.  
  307.     if (m_bInPlaceSiteWndless && m_bInPlaceActive)
  308.     {
  309.         CPoint point(0, 0);
  310.         ClientToParent(m_rcPos, &point);
  311.         CRect rect;
  312.         if (lprcRect != NULL)
  313.         {
  314.             rect.CopyRect(lprcRect);
  315.             rect.OffsetRect(point);
  316.             lprcRect = ▭
  317.         }
  318.  
  319.         HDC hDC;
  320.         if (FAILED(m_pInPlaceSiteWndless->GetDC(lprcRect, dwFlags, &hDC)))
  321.             return NULL;
  322.  
  323.         CDC* pDC = NULL;
  324.         TRY
  325.         {
  326.             pDC = new CWindowlessDC(hDC, point);
  327.         }
  328.         CATCH_ALL(e)
  329.         {
  330.             m_pInPlaceSiteWndless->ReleaseDC(hDC);
  331.         }
  332.         END_CATCH_ALL
  333.  
  334.         return pDC;
  335.     }
  336.     else
  337.     {
  338.         // NOTE: can only use non-default values for these parameters when
  339.         // activated windowless.
  340.         ASSERT(lprcRect == NULL);
  341.         ASSERT(dwFlags == OLEDC_PAINTBKGND);
  342.         return CWnd::GetDC();
  343.     }
  344. }
  345.  
  346. BOOL COleControl::ReleaseDC(CDC* pDC)
  347. {
  348.     ASSERT((m_hWnd != NULL) || (m_bInPlaceSiteWndless && m_bInPlaceActive));
  349.  
  350.     if (m_bInPlaceSiteWndless && m_bInPlaceActive)
  351.     {
  352.         CWindowlessDC* pWindowlessDC = DYNAMIC_DOWNCAST(CWindowlessDC, pDC);
  353.         ASSERT(pWindowlessDC != NULL);
  354.         HDC hDC = pWindowlessDC->Detach();
  355.         delete pWindowlessDC;
  356.         return m_pInPlaceSiteWndless->ReleaseDC(hDC);
  357.     }
  358.     else
  359.     {
  360.         return CWnd::ReleaseDC(pDC);
  361.     }
  362. }
  363.  
  364. void COleControl::InvalidateRgn(CRgn* pRgn, BOOL bErase)
  365. {
  366.     ASSERT((m_hWnd != NULL) || (m_bInPlaceSiteWndless && m_bInPlaceActive));
  367.  
  368.     if (m_bInPlaceSiteWndless && m_bInPlaceActive)
  369.     {
  370.         CRgn rgn;
  371.         if (pRgn != NULL)
  372.         {
  373.             CPoint point(0, 0);
  374.             ClientToParent(m_rcPos, &point);
  375.             rgn.CopyRgn(pRgn);
  376.             rgn.OffsetRgn(point);
  377.         }
  378.         m_pInPlaceSiteWndless->InvalidateRgn(rgn, bErase);
  379.     }
  380.     else
  381.     {
  382.         CWnd::InvalidateRgn(pRgn, bErase);
  383.     }
  384. }
  385.  
  386. void COleControl::ScrollWindow(int xAmount, int yAmount, LPCRECT lpRect,
  387.     LPCRECT lpClipRect)
  388. {
  389.     ASSERT((m_hWnd != NULL) || (m_bInPlaceSiteWndless && m_bInPlaceActive));
  390.  
  391.     if (m_bInPlaceSiteWndless && m_bInPlaceActive)
  392.     {
  393.         if (lpRect != NULL || lpClipRect != NULL)
  394.         {
  395.             CPoint point(0, 0);
  396.             ClientToParent(m_rcPos, &point);
  397.             CRect rect;
  398.             CRect rectClip;
  399.             if (lpRect != NULL)
  400.             {
  401.                 rect.CopyRect(lpRect);
  402.                 rect.OffsetRect(point);
  403.                 lpRect = ▭
  404.             }
  405.             if (lpClipRect != NULL)
  406.             {
  407.                 rectClip.CopyRect(lpClipRect);
  408.                 rectClip.OffsetRect(point);
  409.                 lpClipRect = &rectClip;
  410.             }
  411.         }
  412.  
  413.         m_pInPlaceSiteWndless->ScrollRect(xAmount, yAmount, lpRect, lpClipRect);
  414.     }
  415.     else
  416.     {
  417.         CWnd::ScrollWindow(xAmount, yAmount, lpRect, lpClipRect);
  418.     }
  419. }
  420.  
  421. BOOL COleControl::ClipCaretRect(LPRECT lpRect)
  422. {
  423.     BOOL bNotEmpty = FALSE;
  424.  
  425.     if (m_bInPlaceSiteWndless && m_bInPlaceActive)
  426.     {
  427.         CPoint point(0, 0);
  428.         ClientToParent(m_rcPos, &point);
  429.         CRect rect(lpRect);
  430.         rect.OffsetRect(point);
  431.         bNotEmpty = (m_pInPlaceSiteWndless->AdjustRect(rect) == S_OK);
  432.         rect.OffsetRect(-point.x, -point.y);
  433.     }
  434.  
  435.     return bNotEmpty;
  436. }
  437.  
  438. /////////////////////////////////////////////////////////////////////////////
  439. // Helper functions for windowless controls
  440.  
  441. void COleControl::GetClientRect(LPRECT lpRect) const
  442. {
  443.     ASSERT((m_hWnd != NULL) || (m_bInPlaceSiteWndless && m_bInPlaceActive));
  444.  
  445.     if (m_bInPlaceSiteWndless && m_bInPlaceActive)
  446.     {
  447.         long dxOffset;
  448.         long dyOffset;
  449.         GetClientOffset(&dxOffset, &dyOffset);
  450.         ::CopyRect(lpRect, m_rcPos);
  451.         ::InflateRect(lpRect, -dxOffset, -dyOffset);
  452.  
  453. #ifdef _DEBUG
  454.         CPoint point(0, 0);
  455.         ClientToParent(m_rcPos, &point);
  456.         ASSERT(point.x == lpRect->left && point.y == lpRect->top);
  457. #endif
  458.  
  459.         ::OffsetRect(lpRect, -lpRect->left, -lpRect->top);
  460.     }
  461.     else if (m_hWnd != NULL)
  462.     {
  463.         CWnd::GetClientRect(lpRect);
  464.     }
  465.     else
  466.     {
  467.         ::SetRectEmpty(lpRect);
  468.     }
  469. }
  470.