mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
469 lines
11 KiB
469 lines
11 KiB
// This is a part of the Microsoft Foundation Classes C++ library.
|
|
// Copyright (C) 1992-1995 Microsoft Corporation
|
|
// All rights reserved.
|
|
//
|
|
// This source code is only intended as a supplement to the
|
|
// Microsoft Foundation Classes Reference and related
|
|
// electronic documentation provided with the library.
|
|
// See these sources for detailed information regarding the
|
|
// Microsoft Foundation Classes product.
|
|
|
|
#include "stdafx.h"
|
|
|
|
#ifdef AFXCTL_CORE1_SEG
|
|
#pragma code_seg(AFXCTL_CORE1_SEG)
|
|
#endif
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
#define new DEBUG_NEW
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CWindowlessDC - used by COleControl::GetDC and COleControl::ReleaseDC
|
|
|
|
class CWindowlessDC : public CDC
|
|
{
|
|
DECLARE_DYNAMIC(CWindowlessDC)
|
|
public:
|
|
CWindowlessDC(HDC hDC, CPoint& pointOrigin);
|
|
HDC Detach();
|
|
protected:
|
|
CPoint m_pointOrigin;
|
|
};
|
|
|
|
IMPLEMENT_DYNAMIC(CWindowlessDC, CDC)
|
|
|
|
CWindowlessDC::CWindowlessDC(HDC hDC, CPoint& pointOrigin)
|
|
{
|
|
m_hDC = m_hAttribDC = hDC;
|
|
m_pointOrigin = GetViewportOrg();
|
|
SetViewportOrg(m_pointOrigin + pointOrigin);
|
|
}
|
|
|
|
HDC CWindowlessDC::Detach()
|
|
{
|
|
SetViewportOrg(m_pointOrigin);
|
|
HDC hDC = m_hDC;
|
|
m_hDC = m_hAttribDC = NULL;
|
|
return hDC;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Overridables used with the various windowless interfaces
|
|
|
|
void COleControl::GetClientOffset(long* pdxOffset, long* pdyOffset) const
|
|
{
|
|
int nOffset = (m_sBorderStyle == 1) + (2 * (m_sAppearance == 1));
|
|
|
|
if (nOffset > 0)
|
|
{
|
|
*pdxOffset = nOffset * GetSystemMetrics(SM_CXBORDER);
|
|
*pdyOffset = nOffset * GetSystemMetrics(SM_CYBORDER);
|
|
}
|
|
else
|
|
{
|
|
*pdxOffset = *pdyOffset = 0;
|
|
}
|
|
}
|
|
|
|
UINT COleControl::ParentToClient(LPCRECT lprcBounds, LPPOINT pPoint,
|
|
BOOL bHitTest) const
|
|
{
|
|
long dxOffset;
|
|
long dyOffset;
|
|
GetClientOffset(&dxOffset, &dyOffset);
|
|
|
|
UINT nHitTest = HTNOWHERE;
|
|
|
|
if (bHitTest && ::PtInRect(lprcBounds, *pPoint))
|
|
{
|
|
if (dxOffset > 0)
|
|
{
|
|
CRect rectClient(lprcBounds);
|
|
rectClient.InflateRect(-dxOffset, -dyOffset);
|
|
nHitTest = rectClient.PtInRect(*pPoint) ? HTCLIENT : HTBORDER;
|
|
}
|
|
else
|
|
{
|
|
nHitTest = HTCLIENT;
|
|
}
|
|
}
|
|
|
|
pPoint->x -= lprcBounds->left + dxOffset;
|
|
pPoint->y -= lprcBounds->top + dyOffset;
|
|
|
|
return nHitTest;
|
|
}
|
|
|
|
void COleControl::ClientToParent(LPCRECT lprcBounds, LPPOINT pPoint) const
|
|
{
|
|
long dxOffset;
|
|
long dyOffset;
|
|
GetClientOffset(&dxOffset, &dyOffset);
|
|
pPoint->x += lprcBounds->left + dxOffset;
|
|
pPoint->y += lprcBounds->top + dyOffset;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Overridables for IPointerInactive methods
|
|
|
|
DWORD COleControl::GetActivationPolicy()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
BOOL COleControl::OnInactiveSetCursor(LPCRECT lprcBounds, long x, long y,
|
|
DWORD dwMouseMsg, BOOL bSetAlways)
|
|
{
|
|
CPoint point(x, y);
|
|
UINT nHitTest = ParentToClient(lprcBounds, &point, TRUE);
|
|
|
|
LRESULT lResult = 0;
|
|
OnWndMsg(WM_SETCURSOR, nHitTest, dwMouseMsg, &lResult);
|
|
|
|
if (bSetAlways && ! lResult)
|
|
::SetCursor(::LoadCursor(NULL, IDC_ARROW));
|
|
|
|
return bSetAlways || lResult;
|
|
}
|
|
|
|
void COleControl::OnInactiveMouseMove(LPCRECT lprcBounds, long x, long y,
|
|
DWORD dwKeyState)
|
|
{
|
|
CPoint point(x, y);
|
|
ParentToClient(lprcBounds, &point);
|
|
OnWndMsg(WM_MOUSEMOVE, dwKeyState, MAKELONG(point.x, point.y), NULL);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COleControl::XPointerInactive
|
|
|
|
STDMETHODIMP_(ULONG) COleControl::XPointerInactive::AddRef()
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleControl, PointerInactive)
|
|
return (ULONG)pThis->ExternalAddRef();
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) COleControl::XPointerInactive::Release()
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleControl, PointerInactive)
|
|
return (ULONG)pThis->ExternalRelease();
|
|
}
|
|
|
|
STDMETHODIMP COleControl::XPointerInactive::QueryInterface(
|
|
REFIID iid, LPVOID* ppvObj)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleControl, PointerInactive)
|
|
return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
|
|
}
|
|
|
|
STDMETHODIMP COleControl::XPointerInactive::GetActivationPolicy(
|
|
DWORD* pdwPolicy)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleControl, PointerInactive)
|
|
*pdwPolicy = pThis->GetActivationPolicy();
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP COleControl::XPointerInactive::OnInactiveSetCursor(
|
|
LPCRECT lprcBounds, long x, long y, DWORD dwMouseMsg, BOOL bSetAlways)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleControl, PointerInactive)
|
|
return pThis->OnInactiveSetCursor(lprcBounds, x, y, dwMouseMsg, bSetAlways) ?
|
|
S_OK : S_FALSE;
|
|
}
|
|
|
|
STDMETHODIMP COleControl::XPointerInactive::OnInactiveMouseMove(
|
|
LPCRECT lprcBounds, long x, long y, DWORD dwKeyState)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleControl, PointerInactive)
|
|
pThis->OnInactiveMouseMove(lprcBounds, x, y, dwKeyState);
|
|
return S_OK;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Overridables for IOleInPlaceObjectWindowless methods
|
|
|
|
BOOL COleControl::OnWindowlessMessage(UINT msg, WPARAM wParam, LPARAM lParam,
|
|
LRESULT* plResult)
|
|
{
|
|
if ((msg >= WM_MOUSEFIRST && msg <= WM_MOUSELAST) || (msg == WM_CONTEXTMENU))
|
|
{
|
|
CPoint point(LOWORD(lParam), HIWORD(lParam));
|
|
ParentToClient(m_rcPos, &point, FALSE);
|
|
lParam = MAKELONG(point.x, point.y);
|
|
}
|
|
|
|
return OnWndMsg(msg, wParam, lParam, plResult);
|
|
}
|
|
|
|
IDropTarget* COleControl::GetWindowlessDropTarget()
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COleControl::XOleInPlaceObject (IOleInPlaceObjectWindowless methods)
|
|
|
|
STDMETHODIMP COleControl::XOleInPlaceObject::OnWindowMessage(UINT msg,
|
|
WPARAM wParam, LPARAM lParam, LRESULT* plResult)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleControl, OleInPlaceObject)
|
|
return pThis->OnWindowlessMessage(msg, wParam, lParam, plResult) ?
|
|
S_OK : S_FALSE;
|
|
}
|
|
|
|
STDMETHODIMP COleControl::XOleInPlaceObject::GetDropTarget(
|
|
IDropTarget** ppDropTarget)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleControl, OleInPlaceObject)
|
|
|
|
*ppDropTarget = pThis->GetWindowlessDropTarget();
|
|
return (*ppDropTarget != NULL) ? S_OK : E_NOTIMPL;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Cover functions for IOleInPlaceSiteWindowless methods
|
|
|
|
CWnd* COleControl::SetCapture()
|
|
{
|
|
ASSERT((m_hWnd != NULL) || (m_bInPlaceSiteWndless && m_bInPlaceActive));
|
|
|
|
if (m_bInPlaceSiteWndless && m_bInPlaceActive)
|
|
{
|
|
CWnd* pWndPrev = GetCapture();
|
|
m_pInPlaceSiteWndless->SetCapture(TRUE);
|
|
return pWndPrev;
|
|
}
|
|
else
|
|
{
|
|
return CWnd::SetCapture();
|
|
}
|
|
}
|
|
|
|
BOOL COleControl::ReleaseCapture()
|
|
{
|
|
ASSERT((m_hWnd != NULL) || (m_bInPlaceSiteWndless && m_bInPlaceActive));
|
|
|
|
if (m_bInPlaceSiteWndless && m_bInPlaceActive)
|
|
return (m_pInPlaceSiteWndless->SetCapture(FALSE) == S_OK);
|
|
else
|
|
return ::ReleaseCapture();
|
|
}
|
|
|
|
CWnd* COleControl::GetCapture()
|
|
{
|
|
ASSERT((m_hWnd != NULL) || (m_bInPlaceSiteWndless && m_bInPlaceActive));
|
|
|
|
if (m_bInPlaceSiteWndless && m_bInPlaceActive)
|
|
{
|
|
return (m_pInPlaceSiteWndless->GetCapture() == S_OK) ?
|
|
this : NULL;
|
|
}
|
|
else
|
|
{
|
|
return CWnd::GetCapture();
|
|
}
|
|
}
|
|
|
|
CWnd* COleControl::SetFocus()
|
|
{
|
|
ASSERT((m_hWnd != NULL) || (m_bInPlaceSiteWndless && m_bInPlaceActive));
|
|
|
|
if (m_bInPlaceSiteWndless && m_bInPlaceActive)
|
|
{
|
|
CWnd* pWndPrev = GetFocus();
|
|
m_pInPlaceSiteWndless->SetFocus(TRUE);
|
|
return pWndPrev;
|
|
}
|
|
else
|
|
{
|
|
return CWnd::SetFocus();
|
|
}
|
|
}
|
|
|
|
CWnd* COleControl::GetFocus()
|
|
{
|
|
ASSERT((m_hWnd != NULL) || (m_bInPlaceSiteWndless && m_bInPlaceActive));
|
|
|
|
if (m_bInPlaceSiteWndless && m_bInPlaceActive)
|
|
{
|
|
return (m_pInPlaceSiteWndless->GetFocus() == S_OK) ?
|
|
this : NULL;
|
|
}
|
|
else
|
|
{
|
|
return CWnd::GetFocus();
|
|
}
|
|
}
|
|
|
|
CDC* COleControl::GetDC(LPCRECT lprcRect, DWORD dwFlags)
|
|
{
|
|
ASSERT((m_hWnd != NULL) || (m_bInPlaceSiteWndless && m_bInPlaceActive));
|
|
|
|
if (m_bInPlaceSiteWndless && m_bInPlaceActive)
|
|
{
|
|
CPoint point(0, 0);
|
|
ClientToParent(m_rcPos, &point);
|
|
CRect rect;
|
|
if (lprcRect != NULL)
|
|
{
|
|
rect.CopyRect(lprcRect);
|
|
rect.OffsetRect(point);
|
|
lprcRect = ▭
|
|
}
|
|
|
|
HDC hDC;
|
|
if (FAILED(m_pInPlaceSiteWndless->GetDC(lprcRect, dwFlags, &hDC)))
|
|
return NULL;
|
|
|
|
CDC* pDC = NULL;
|
|
TRY
|
|
{
|
|
pDC = new CWindowlessDC(hDC, point);
|
|
}
|
|
CATCH_ALL(e)
|
|
{
|
|
m_pInPlaceSiteWndless->ReleaseDC(hDC);
|
|
}
|
|
END_CATCH_ALL
|
|
|
|
return pDC;
|
|
}
|
|
else
|
|
{
|
|
// NOTE: can only use non-default values for these parameters when
|
|
// activated windowless.
|
|
ASSERT(lprcRect == NULL);
|
|
ASSERT(dwFlags == OLEDC_PAINTBKGND);
|
|
return CWnd::GetDC();
|
|
}
|
|
}
|
|
|
|
BOOL COleControl::ReleaseDC(CDC* pDC)
|
|
{
|
|
ASSERT((m_hWnd != NULL) || (m_bInPlaceSiteWndless && m_bInPlaceActive));
|
|
|
|
if (m_bInPlaceSiteWndless && m_bInPlaceActive)
|
|
{
|
|
CWindowlessDC* pWindowlessDC = DYNAMIC_DOWNCAST(CWindowlessDC, pDC);
|
|
ASSERT(pWindowlessDC != NULL);
|
|
HDC hDC = pWindowlessDC->Detach();
|
|
delete pWindowlessDC;
|
|
return m_pInPlaceSiteWndless->ReleaseDC(hDC);
|
|
}
|
|
else
|
|
{
|
|
return CWnd::ReleaseDC(pDC);
|
|
}
|
|
}
|
|
|
|
void COleControl::InvalidateRgn(CRgn* pRgn, BOOL bErase)
|
|
{
|
|
ASSERT((m_hWnd != NULL) || (m_bInPlaceSiteWndless && m_bInPlaceActive));
|
|
|
|
if (m_bInPlaceSiteWndless && m_bInPlaceActive)
|
|
{
|
|
CRgn rgn;
|
|
if (pRgn != NULL)
|
|
{
|
|
CPoint point(0, 0);
|
|
ClientToParent(m_rcPos, &point);
|
|
rgn.CopyRgn(pRgn);
|
|
rgn.OffsetRgn(point);
|
|
}
|
|
m_pInPlaceSiteWndless->InvalidateRgn(rgn, bErase);
|
|
}
|
|
else
|
|
{
|
|
CWnd::InvalidateRgn(pRgn, bErase);
|
|
}
|
|
}
|
|
|
|
void COleControl::ScrollWindow(int xAmount, int yAmount, LPCRECT lpRect,
|
|
LPCRECT lpClipRect)
|
|
{
|
|
ASSERT((m_hWnd != NULL) || (m_bInPlaceSiteWndless && m_bInPlaceActive));
|
|
|
|
if (m_bInPlaceSiteWndless && m_bInPlaceActive)
|
|
{
|
|
if (lpRect != NULL || lpClipRect != NULL)
|
|
{
|
|
CPoint point(0, 0);
|
|
ClientToParent(m_rcPos, &point);
|
|
CRect rect;
|
|
CRect rectClip;
|
|
if (lpRect != NULL)
|
|
{
|
|
rect.CopyRect(lpRect);
|
|
rect.OffsetRect(point);
|
|
lpRect = ▭
|
|
}
|
|
if (lpClipRect != NULL)
|
|
{
|
|
rectClip.CopyRect(lpClipRect);
|
|
rectClip.OffsetRect(point);
|
|
lpClipRect = &rectClip;
|
|
}
|
|
}
|
|
|
|
m_pInPlaceSiteWndless->ScrollRect(xAmount, yAmount, lpRect, lpClipRect);
|
|
}
|
|
else
|
|
{
|
|
CWnd::ScrollWindow(xAmount, yAmount, lpRect, lpClipRect);
|
|
}
|
|
}
|
|
|
|
BOOL COleControl::ClipCaretRect(LPRECT lpRect)
|
|
{
|
|
BOOL bNotEmpty = FALSE;
|
|
|
|
if (m_bInPlaceSiteWndless && m_bInPlaceActive)
|
|
{
|
|
CPoint point(0, 0);
|
|
ClientToParent(m_rcPos, &point);
|
|
CRect rect(lpRect);
|
|
rect.OffsetRect(point);
|
|
bNotEmpty = (m_pInPlaceSiteWndless->AdjustRect(rect) == S_OK);
|
|
rect.OffsetRect(-point.x, -point.y);
|
|
}
|
|
|
|
return bNotEmpty;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Helper functions for windowless controls
|
|
|
|
void COleControl::GetClientRect(LPRECT lpRect) const
|
|
{
|
|
ASSERT((m_hWnd != NULL) || (m_bInPlaceSiteWndless && m_bInPlaceActive));
|
|
|
|
if (m_bInPlaceSiteWndless && m_bInPlaceActive)
|
|
{
|
|
long dxOffset;
|
|
long dyOffset;
|
|
GetClientOffset(&dxOffset, &dyOffset);
|
|
::CopyRect(lpRect, m_rcPos);
|
|
::InflateRect(lpRect, -dxOffset, -dyOffset);
|
|
|
|
#ifdef _DEBUG
|
|
CPoint point(0, 0);
|
|
ClientToParent(m_rcPos, &point);
|
|
ASSERT(point.x == lpRect->left && point.y == lpRect->top);
|
|
#endif
|
|
|
|
::OffsetRect(lpRect, -lpRect->left, -lpRect->top);
|
|
}
|
|
else if (m_hWnd != NULL)
|
|
{
|
|
CWnd::GetClientRect(lpRect);
|
|
}
|
|
else
|
|
{
|
|
::SetRectEmpty(lpRect);
|
|
}
|
|
}
|