📄 ctlcore.cpp
字号:
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1998 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
#define _afxTrackingMenu (AfxGetThreadState()->m_hTrackingMenu)
/////////////////////////////////////////////////////////////////////////////
// Special WM_PAINT message handler that includes the HDC
#define ON_WM_PAINT_SPECIAL() \
{ WM_PAINT, 0, 0, 0, AfxSig_vD, \
(AFX_PMSG)(AFX_PMSGW)(void (AFX_MSG_CALL CWnd::*)(CDC*))&OnPaint },
/////////////////////////////////////////////////////////////////////////////
// Window to serve as "parking space" for not-yet-activated subclassed controls
AFX_MODULE_STATE* AFXAPI _AfxGetOleModuleState();
AFX_STATIC HWND AFXAPI _AfxGetParkingWindow()
{
_AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
ASSERT(pThreadState != NULL);
if (pThreadState->m_pWndPark == NULL)
{
AFX_MANAGE_STATE(_AfxGetOleModuleState());
CWnd* pWndTmp = NULL;
TRY
{
#ifdef _DEBUG
HWND hWndActive = ::GetActiveWindow();
#endif
pWndTmp = new CParkingWnd;
ASSERT(pWndTmp->m_hWnd != NULL);
#ifdef _DEBUG
ASSERT(hWndActive == ::GetActiveWindow());
#endif
}
CATCH_ALL(e)
{
if (pWndTmp)
delete pWndTmp;
pWndTmp = NULL;
}
END_CATCH_ALL
pThreadState->m_pWndPark = pWndTmp;
}
return pThreadState->m_pWndPark->GetSafeHwnd();
}
AFX_STATIC void AFXAPI _AfxReleaseParkingWindow()
{
_AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
ASSERT(pThreadState != NULL);
ASSERT(pThreadState->m_nCtrlRef == 0);
if (pThreadState->m_pWndPark != NULL)
{
AFX_MANAGE_STATE(_AfxGetOleModuleState());
ASSERT(pThreadState->m_pWndPark->m_hWnd != NULL);
ASSERT(::GetWindow(pThreadState->m_pWndPark->m_hWnd, GW_CHILD) == NULL);
HWND hWnd = pThreadState->m_pWndPark->Detach();
::SetWindowLong(hWnd, GWL_WNDPROC, (long)DefWindowProc);
::DestroyWindow(hWnd);
delete pThreadState->m_pWndPark;
pThreadState->m_pWndPark = NULL;
}
}
/////////////////////////////////////////////////////////////////////////////
// COleControl interface map
BEGIN_INTERFACE_MAP(COleControl, CCmdTarget)
INTERFACE_PART(COleControl, IID_IQuickActivate, QuickActivate)
INTERFACE_PART(COleControl, IID_IOleObject, OleObject)
INTERFACE_PART(COleControl, IID_IViewObjectEx, ViewObject)
INTERFACE_PART(COleControl, IID_IPersistMemory, PersistMemory)
INTERFACE_PART(COleControl, IID_IPersistStreamInit, PersistStreamInit)
INTERFACE_PART(COleControl, IID_IProvideClassInfo2, ProvideClassInfo)
INTERFACE_PART(COleControl, IID_IConnectionPointContainer, ConnPtContainer)
INTERFACE_PART(COleControl, IID_IOleControl, OleControl)
INTERFACE_PART(COleControl, IID_IOleInPlaceObject, OleInPlaceObject)
INTERFACE_PART(COleControl, IID_IOleInPlaceObjectWindowless, OleInPlaceObject)
INTERFACE_PART(COleControl, IID_IOleInPlaceActiveObject, OleInPlaceActiveObject)
INTERFACE_PART(COleControl, IID_IDispatch, Dispatch)
INTERFACE_PART(COleControl, IID_IOleCache, OleCache)
INTERFACE_PART(COleControl, IID_IViewObject, ViewObject)
INTERFACE_PART(COleControl, IID_IViewObject2, ViewObject)
INTERFACE_PART(COleControl, IID_IDataObject, DataObject)
INTERFACE_PART(COleControl, IID_IPersistPropertyBag, PersistPropertyBag)
INTERFACE_PART(COleControl, IID_ISpecifyPropertyPages, SpecifyPropertyPages)
INTERFACE_PART(COleControl, IID_IPerPropertyBrowsing, PerPropertyBrowsing)
INTERFACE_PART(COleControl, IID_IProvideClassInfo, ProvideClassInfo)
INTERFACE_PART(COleControl, IID_IPersist, PersistStorage)
INTERFACE_PART(COleControl, IID_IPersistStorage, PersistStorage)
END_INTERFACE_MAP()
/////////////////////////////////////////////////////////////////////////////
// COleControl event map
const AFX_EVENTMAP COleControl::eventMap = { NULL, NULL };
/////////////////////////////////////////////////////////////////////////////
// COleControl message map
BEGIN_MESSAGE_MAP(COleControl, CWnd)
ON_WM_PAINT_SPECIAL()
//{{AFX_MSG_MAP(COleControl)
ON_WM_ERASEBKGND()
ON_WM_NCCREATE()
ON_WM_NCCALCSIZE()
ON_WM_SIZE()
ON_WM_MOVE()
ON_WM_SHOWWINDOW()
ON_WM_CREATE()
ON_MESSAGE(WM_SETTEXT, OnSetText)
ON_WM_NCPAINT()
ON_WM_DESTROY()
ON_WM_ENTERIDLE()
ON_WM_KILLFOCUS()
ON_WM_SETFOCUS()
ON_MESSAGE(OCM_CTLCOLORBTN, OnOcmCtlColorBtn)
ON_MESSAGE(OCM_CTLCOLORDLG, OnOcmCtlColorDlg)
ON_MESSAGE(OCM_CTLCOLOREDIT, OnOcmCtlColorEdit)
ON_MESSAGE(OCM_CTLCOLORLISTBOX, OnOcmCtlColorListBox)
ON_MESSAGE(OCM_CTLCOLORMSGBOX, OnOcmCtlColorMsgBox)
ON_MESSAGE(OCM_CTLCOLORSCROLLBAR, OnOcmCtlColorScrollBar)
ON_MESSAGE(OCM_CTLCOLORSTATIC, OnOcmCtlColorStatic)
ON_WM_MOUSEMOVE()
ON_WM_NCHITTEST()
ON_WM_MOUSEACTIVATE()
ON_WM_NCLBUTTONDOWN()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_LBUTTONDBLCLK()
ON_WM_MBUTTONDOWN()
ON_WM_MBUTTONUP()
ON_WM_MBUTTONDBLCLK()
ON_WM_RBUTTONDOWN()
ON_WM_RBUTTONUP()
ON_WM_RBUTTONDBLCLK()
ON_WM_KEYDOWN()
ON_WM_KEYUP()
ON_WM_CHAR()
ON_WM_SYSKEYDOWN()
ON_WM_SYSKEYUP()
ON_WM_INITMENUPOPUP()
ON_WM_MENUSELECT()
ON_WM_CANCELMODE()
ON_WM_SETCURSOR()
ON_WM_GETDLGCODE()
ON_MESSAGE(WM_SETMESSAGESTRING, OnSetMessageString)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// COleControl implementation
COleControl::COleControl() :
#ifdef _AFXDLL
m_font(&m_xFontNotification)
#else
m_font(NULL)
#endif
{
// add to parking window reference count
_AFX_THREAD_STATE* pState = AfxGetThreadState();
ASSERT(pState != NULL);
++pState->m_nCtrlRef;
m_bFinalReleaseCalled = FALSE;
m_bChangingExtent = FALSE;
m_bUIDead = FALSE;
m_pReflect = NULL;
m_pRectTracker = NULL;
m_pClientSite = NULL;
m_pOleAdviseHolder = NULL;
m_pDataAdviseHolder = NULL;
m_pInPlaceSite = NULL;
m_pInPlaceFrame = NULL;
m_pInPlaceDoc = NULL;
m_pControlSite = NULL;
m_pDefIUnknown = NULL;
m_pDefIPersistStorage = NULL;
m_pDefIViewObject = NULL;
m_pDefIOleCache = NULL;
m_pAdviseInfo = NULL;
m_pUIActiveInfo = NULL;
m_nIDTracking = 0;
m_nIDLastMessage = 0;
m_bAutoMenuEnable = TRUE; // auto enable on by default
m_bInPlaceActive = FALSE;
m_bUIActive = FALSE;
m_bPendingUIActivation = FALSE;
#ifdef _AFXDLL
m_bOpen = FALSE;
m_pWndOpenFrame = NULL;
#endif
m_bInitialized = FALSE;
m_dwVersionLoaded = 0;
m_bModified = TRUE;
m_iButtonState = 0;
m_iDblClkState = 0;
m_sBorderStyle = 0;
m_sAppearance = 0;
m_bEnabled = TRUE;
m_lReadyState = READYSTATE_COMPLETE;
m_hFontPrev = NULL;
m_cEventsFrozen = 0;
m_bConvertVBX = FALSE;
m_pSimpleFrameSite = NULL;
m_bSimpleFrame = FALSE;
m_ptOffset.x = 0;
m_ptOffset.y = 0;
m_bNoRedraw = FALSE;
m_bInPlaceSiteEx = FALSE;
m_bInPlaceSiteWndless = FALSE;
m_bOptimizedDraw = FALSE;
m_bDataPathPropertiesLoaded = TRUE;
SetInitialSize(100, 50);
// Wire up aggregation support
EnableAggregation();
// Wire up IDispatch support
EnableAutomation();
// Wire up connection map support
EnableConnections();
m_pDataSource = NULL;
AfxOleLockApp();
}
COleControl::~COleControl()
{
if (m_pDataSource != NULL)
delete m_pDataSource;
if (m_pReflect != NULL)
m_pReflect->DestroyWindow();
#ifdef _AFXDLL
if (m_pWndOpenFrame != NULL)
m_pWndOpenFrame->DestroyWindow();
#endif
ReleaseCaches();
if (m_hWnd != NULL)
DestroyWindow();
// release parking window if reference count is now zero
_AFX_THREAD_STATE* pState = AfxGetThreadState();
ASSERT(pState != NULL);
if (pState->m_nCtrlRef == 0 || --pState->m_nCtrlRef == 0)
_AfxReleaseParkingWindow();
AfxOleUnlockApp();
}
void COleControl::ReleaseCaches()
{
RELEASE(m_pClientSite);
RELEASE(m_pOleAdviseHolder);
RELEASE(m_pDataAdviseHolder);
RELEASE(m_pInPlaceSite);
RELEASE(m_pInPlaceFrame);
RELEASE(m_pInPlaceDoc);
RELEASE(m_pControlSite);
RELEASE(m_pSimpleFrameSite);
LPUNKNOWN pUnk = GetControllingUnknown();
InterlockedIncrement(&m_dwRef); // Keep ref count from going to zero again.
if (m_pDefIPersistStorage != NULL)
{
pUnk->AddRef();
RELEASE(m_pDefIPersistStorage);
}
if (m_pDefIViewObject != NULL)
{
pUnk->AddRef();
RELEASE(m_pDefIViewObject);
}
if (m_pDefIOleCache != NULL)
{
pUnk->AddRef();
RELEASE(m_pDefIOleCache);
}
if (m_pAdviseInfo != NULL)
{
RELEASE(m_pAdviseInfo->m_pAdvSink);
delete m_pAdviseInfo;
m_pAdviseInfo = NULL;
}
RELEASE(m_pDefIUnknown);
InterlockedDecrement(&m_dwRef);
}
void COleControl::OnFinalRelease()
{
if (!m_bFinalReleaseCalled)
{
m_bFinalReleaseCalled = TRUE;
ReleaseCaches();
if (m_hWnd != NULL)
DestroyWindow();
CCmdTarget::OnFinalRelease();
}
}
LPUNKNOWN COleControl::GetInterfaceHook(const void* piid)
{
ASSERT_POINTER(piid, IID);
if (m_piidPrimary != NULL && _AfxIsEqualGUID(*m_piidPrimary, *(IID*)piid))
{
return GetInterface((void*)&IID_IDispatch);
}
if (_AfxIsEqualGUID(IID_IPointerInactive, *(IID*)piid) &&
(GetControlFlags() & pointerInactive))
{
return &m_xPointerInactive;
}
return NULL;
}
void COleControl::SetInitialSize(int cx, int cy)
{
SIZEL szlPixels;
SIZEL szlHimetric;
szlPixels.cx = cx;
szlPixels.cy = cy;
_AfxXformSizeInPixelsToHimetric(NULL, &szlPixels, &szlHimetric);
m_cxExtent = szlHimetric.cx;
m_cyExtent = szlHimetric.cy;
}
BOOL COleControl::GetDispatchIID(IID* pIID)
{
if (m_piidPrimary != NULL)
*pIID = *m_piidPrimary;
return (m_piidPrimary != NULL);
}
void COleControl::InitializeIIDs(const IID* piidPrimary, const IID* piidEvents)
{
m_piidPrimary = piidPrimary;
m_piidEvents = piidEvents;
EnableTypeLib();
// Initialize the masks for stock events and properties.
InitStockEventMask();
InitStockPropMask();
#ifdef _DEBUG
// Verify that the type library contains all the correct information.
// If any of the following assertions fail, carefully check the IDs
// in the control's .CPP file against those in its .ODL file.
LPTYPEINFO pTypeInfo;
HRESULT hr;
CLSID clsid;
GetClassID(&clsid);
if (SUCCEEDED(hr = GetTypeInfoOfGuid(0, clsid, &pTypeInfo)))
RELEASE(pTypeInfo);
ASSERT(SUCCEEDED(hr)); // Class ID may be corrupted
if (SUCCEEDED(hr = GetTypeInfoOfGuid(0, *m_piidPrimary, &pTypeInfo)))
RELEASE(pTypeInfo);
ASSERT(SUCCEEDED(hr)); // Primary dispatch interface ID may be corrupted
if (SUCCEEDED(hr = GetTypeInfoOfGuid(0, *m_piidEvents, &pTypeInfo)))
RELEASE(pTypeInfo);
ASSERT(SUCCEEDED(hr)); // Event dispatch interface ID may be corrupted
#endif
}
#ifdef _DEBUG
void COleControl::AssertValid() const
{
CWnd::AssertValid();
}
void AFXAPI _AfxDumpGuid(CDumpContext& dc, const GUID* pGuid)
{
USES_CONVERSION;
if (pGuid == NULL)
{
dc << "(NULL)";
return;
}
OLECHAR szGuid[40];
::StringFromGUID2(*pGuid, szGuid, 40);
dc << OLE2CT(szGuid);
}
void AFXAPI _AfxDumpHex(CDumpContext& dc, DWORD dw)
{
TCHAR szHex[10];
wsprintf(szHex, _T("0x%08lx"), dw);
dc << szHex;
}
void COleControl::Dump(CDumpContext& dc) const
{
CWnd::Dump(dc);
#ifdef _AFXDLL
dc << "\nm_pModuleState = " << m_pModuleState;
#endif
dc << "\nm_piidPrimary = ";
_AfxDumpGuid(dc, m_piidPrimary);
dc << "\nm_piidEvents = ";
_AfxDumpGuid(dc, m_piidEvents);
dc << "\nm_dwVersionLoaded = ";
_AfxDumpHex(dc, m_dwVersionLoaded);
dc << "\nm_cEventsFrozen = " << m_cEventsFrozen;
dc << "\nm_rcPos = " << m_rcPos;
dc << "\nm_cxExtent = " << m_cxExtent;
dc << "\nm_cyExtent = " << m_cyExtent;
dc << "\nm_bFinalReleaseCalled = " << m_bFinalReleaseCalled;
dc << "\nm_bModified = " << m_bModified;
dc << "\nm_bCountOnAmbients = " << m_bCountOnAmbients;
dc << "\nm_iButtonState = " << m_iButtonState;
dc << "\nm_iDblClkState = " << m_iDblClkState;
dc << "\nm_bInPlaceActive = " << m_bInPlaceActive;
dc << "\nm_bUIActive = " << m_bUIActive;
dc << "\nm_bPendingUIActivation = " << m_bPendingUIActivation;
#ifdef _AFXDLL
dc << "\nm_bOpen = " << m_bOpen;
#endif
dc << "\nm_bChangingExtent = " << m_bChangingExtent;
dc << "\nm_bConvertVBX = " << m_bConvertVBX;
dc << "\nm_bSimpleFrame = " << m_bSimpleFrame;
dc << "\nm_bUIDead = " << m_bUIDead;
}
#endif // _DEBUG
/////////////////////////////////////////////////////////////////////////////
// _AfxFillPSOnStack (WINBUG)
//
// Windows has a bug in the WM_PAINT code for the Button control. If the
// paint is a sub-classed paint, and if the display driver is a Win3.0
// display driver, then Windows calls IsRectEmpty, passing in the rectangle
// from the paint structure. Since it was a sub-classed paint, and
// BeginPaint was not called, the rectangle struct passed to IsRectEmpty is
// uninitialized. If IsRectEmpty returned True, then the control was not
// painted. To work around the bug, we call FillPSOnStack before calling
// windows with the WM_PAINT. This routine fills a buffer on the stack
// 0x80 bytes of consecutive values from 0 to 0x7f. That way, if the
// rectangle falls anywhere within this buffer range, and the stack has not
// been modified by other means, then IsRectEmpty will return FALSE, so that
// the control will Paint.
#define WORDBUFSIZE 0x40
void AFXAPI _AfxFillPSOnStack()
{
// Stack hack needed on Win32s
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -