📄 ctlppg.cpp
字号:
if ((lstrcmpi(szClassName, _T("button")) == 0) &&
_AfxIsRadioButton(hWndCtl))
{
// Special case for radio buttons:
// mark first button in group
while ((hWndCtl != NULL) &&
!(GetWindowLong(hWndCtl, GWL_STYLE) & WS_GROUP))
{
hWndCtl = ::GetWindow(hWndCtl, GW_HWNDPREV);
}
// First button in group must have WS_GROUP style,
// and must be a radio button.
ASSERT(hWndCtl != NULL);
ASSERT(_AfxIsRadioButton(hWndCtl));
// Mark first radio button as dirty
if (hWndCtl != NULL)
nID = ::GetWindowLong(hWndCtl, GWL_ID);
}
// Control has been modified
m_bDirty = TRUE;
SetControlStatus(nID, TRUE);
flags = PROPPAGESTATUS_DIRTY;
break;
}
}
if (m_bDirty)
{
for (int iNotify=0; iNotify < _countof(_afxUpdateList); iNotify++)
{
if (lstrcmpi(_afxUpdateList[iNotify].szClassName, szClassName)==0 &&
_afxUpdateList[iNotify].wNotifyCode == wNotifyCode &&
GetControlStatus(nID))
{
flags |= PROPPAGESTATUS_VALIDATE;
}
}
}
}
}
if (flags != 0)
{
ASSERT(m_pPageSite != NULL);
m_pPageSite->OnStatusChange(flags);
}
return bSuccess;
}
void COlePropertyPage::IgnoreApply(UINT nID)
{
m_IDArray.Add(nID);
}
BOOL COlePropertyPage::GetControlStatus(UINT nID)
{
for (int nControl = 0; nControl < m_nControls; nControl++)
if (m_pStatus[nControl].nID == nID)
return m_pStatus[nControl].bDirty;
// If we couldn't find the control - assume it is dirty
return TRUE;
}
BOOL COlePropertyPage::SetControlStatus(UINT nID, BOOL bDirty)
{
for (int nControl = 0; nControl < m_nControls; nControl++)
if (m_pStatus[nControl].nID == nID)
{
m_pStatus[nControl].bDirty = bDirty;
return TRUE;
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////////////
// Function Templates using the Preprocessor
// [This should be replaced with C++ Templates when the 16 bit compiler allows]
#define DEFINE_GET_SET_PROP(ctype,casttype,vttype) \
BOOL COlePropertyPage::SetPropText(LPCTSTR pszPropName, ctype& data ) \
{ \
USES_CONVERSION;\
COleDispatchDriver PropDispDriver; \
BOOL bResult = FALSE; \
for (ULONG i = 0; i < m_nObjects; i++) \
{ \
DISPID dwDispID; \
LPCOLESTR lpOleStr = T2COLE(pszPropName);\
if (SUCCEEDED(m_ppDisp[i]->GetIDsOfNames(IID_NULL, (LPOLESTR*)&lpOleStr, 1, 0, &dwDispID))) \
{ \
PropDispDriver.AttachDispatch(m_ppDisp[i], FALSE); \
PropDispDriver.SetProperty(dwDispID, vttype, (casttype)data ); \
PropDispDriver.DetachDispatch(); \
bResult = TRUE; \
} \
} \
return bResult; \
} \
BOOL COlePropertyPage::GetPropText(LPCTSTR pszPropName, ctype *data ) \
{ \
USES_CONVERSION;\
COleDispatchDriver PropDispDriver; \
BOOL bSuccess = FALSE; \
for (ULONG i = 0; i < m_nObjects; i++) \
{ \
DISPID dwDispID; \
LPCOLESTR lpOleStr = T2COLE(pszPropName);\
if (SUCCEEDED(m_ppDisp[i]->GetIDsOfNames(IID_NULL, (LPOLESTR*)&lpOleStr, 1, 0, &dwDispID))) \
{ \
ctype dataTemp; \
static ctype fill; \
PropDispDriver.AttachDispatch(m_ppDisp[i], FALSE); \
PropDispDriver.GetProperty(dwDispID, vttype, &dataTemp); \
PropDispDriver.DetachDispatch(); \
if (i == 0) *data = dataTemp; \
if (*data != dataTemp) *data = fill; \
bSuccess = TRUE; \
} \
} \
return bSuccess; \
}
/////////////////////////////////////////////////////////////////////////////
// DDP_ property get/set helpers
DEFINE_GET_SET_PROP( BYTE, BYTE, VT_UI1 );
DEFINE_GET_SET_PROP( short, short, VT_I2 );
DEFINE_GET_SET_PROP( int, int, VT_I4 );
DEFINE_GET_SET_PROP( UINT, UINT, VT_I4 );
DEFINE_GET_SET_PROP( long, long, VT_I4 );
DEFINE_GET_SET_PROP( DWORD, DWORD, VT_I4 );
DEFINE_GET_SET_PROP( float, float, VT_R4 );
DEFINE_GET_SET_PROP( double, double, VT_R8 );
DEFINE_GET_SET_PROP( CString, LPCTSTR, VT_BSTR );
BOOL COlePropertyPage::SetPropCheck(LPCTSTR pszPropName, int Value)
{
USES_CONVERSION;
COleDispatchDriver PropDispDriver;
BOOL bResult = FALSE;
BOOL bValue;
if (Value == 1)
bValue = TRUE;
else
bValue = FALSE; // default to off
// Set the properties for all the objects
for (ULONG i = 0; i < m_nObjects; i++)
{
DISPID dwDispID;
// Get the Dispatch ID for the property and if successful set the value of the property
LPCOLESTR lpOleStr = T2COLE(pszPropName);
if (SUCCEEDED(m_ppDisp[i]->GetIDsOfNames(IID_NULL, (LPOLESTR*)&lpOleStr, 1, 0, &dwDispID)))
{
// Set property
PropDispDriver.AttachDispatch(m_ppDisp[i], FALSE);
PropDispDriver.SetProperty(dwDispID, VT_BOOL, bValue);
PropDispDriver.DetachDispatch();
bResult = TRUE;
}
}
return bResult;
}
BOOL COlePropertyPage::GetPropCheck(LPCTSTR pszPropName, int* pValue)
{
USES_CONVERSION;
COleDispatchDriver PropDispDriver;
BOOL bSuccess = FALSE;
// Check the property values for all the objects
for (ULONG i = 0; i < m_nObjects; i++)
{
DISPID dwDispID;
// Get the Dispatch ID for the property and if successful get the value of the property
LPCOLESTR lpOleStr = T2COLE(pszPropName);
if (SUCCEEDED(m_ppDisp[i]->GetIDsOfNames(IID_NULL, (LPOLESTR*)&lpOleStr, 1, 0, &dwDispID)))
{
// Get property
BOOL bTemp = FALSE;
int tempValue;
PropDispDriver.AttachDispatch(m_ppDisp[i], FALSE);
PropDispDriver.GetProperty(dwDispID, VT_BOOL, &bTemp);
PropDispDriver.DetachDispatch();
// Convert boolean value to check box equivalent
if (bTemp)
tempValue = 1;
else
tempValue = 0;
// Handle special case for first object
if (i == 0)
*pValue = tempValue;
// If the current check value is not the same as the one just retrieved then
// set the current check value to the indeterminate state.
if (tempValue != *pValue)
*pValue = 2;
bSuccess = TRUE;
}
}
return bSuccess;
}
BOOL COlePropertyPage::SetPropRadio(LPCTSTR pszPropName, int Value)
{
USES_CONVERSION;
COleDispatchDriver PropDispDriver;
BOOL bSuccess = FALSE;
// Set the properties for all the objects
for (ULONG i = 0; i < m_nObjects; i++)
{
DISPID dwDispID;
// Get the Dispatch ID for the property and if successful set the value of the property
LPCOLESTR lpOleStr = T2COLE(pszPropName);
if (SUCCEEDED(m_ppDisp[i]->GetIDsOfNames(IID_NULL, (LPOLESTR*)&lpOleStr, 1, 0, &dwDispID)))
{
short nTemp = (short)Value;
// Set property
PropDispDriver.AttachDispatch(m_ppDisp[i], FALSE);
PropDispDriver.SetProperty(dwDispID, VT_I2, nTemp);
PropDispDriver.DetachDispatch();
bSuccess = TRUE;
}
}
return bSuccess;
}
BOOL COlePropertyPage::GetPropRadio(LPCTSTR pszPropName, int* pValue)
{
USES_CONVERSION;
COleDispatchDriver PropDispDriver;
BOOL bSuccess = FALSE;
// Check the property values for all the objects
for (ULONG i = 0; i < m_nObjects; i++)
{
DISPID dwDispID;
// Get the Dispatch ID for the property and if successful get the value of the property
LPCOLESTR lpOleStr = T2COLE(pszPropName);
if (SUCCEEDED(m_ppDisp[i]->GetIDsOfNames(IID_NULL, (LPOLESTR*)&lpOleStr, 1, 0, &dwDispID)))
{
short nTemp;
// Get property
PropDispDriver.AttachDispatch(m_ppDisp[i], FALSE);
PropDispDriver.GetProperty(dwDispID, VT_I2, &nTemp);
PropDispDriver.DetachDispatch();
// Handle special case for first object
if (i == 0)
*pValue = nTemp;
// Compare the current radio value with the one just retrieved then
// if they are different then set the radio value to -1, so that no
// radio buttons will be checked.
if (nTemp != *pValue)
*pValue = -1;
bSuccess = TRUE;
}
}
return bSuccess;
}
BOOL COlePropertyPage::SetPropIndex(LPCTSTR pszPropName, int Value)
{
return SetPropRadio(pszPropName, Value);
}
BOOL COlePropertyPage::GetPropIndex(LPCTSTR pszPropName, int* pValue)
{
return GetPropRadio(pszPropName, pValue);
}
/////////////////////////////////////////////////////////////////////////////
// DDP_Begin data exchange routines (Should be C++ templated someday!)
#define DEFINE_DDP_(group,ctype,vtype,bEditCtrl) \
void AFXAPI DDP_End##group(CDataExchange* pDX, int, \
ctype *member, LPCTSTR pszPropName ) \
{ \
COlePropertyPage* propDialog = STATIC_DOWNCAST(COlePropertyPage, pDX->m_pDlgWnd); \
if (pDX->m_bSaveAndValidate) \
propDialog->SetProp##group(pszPropName, *member ); \
} \
void AFXAPI DDP_##group(CDataExchange* pDX, int nCtrlId, \
ctype &member, LPCTSTR pszPropName ) \
{ \
ASSERT(AfxIsValidString(pszPropName)); \
COlePropertyPage* propDialog = STATIC_DOWNCAST(COlePropertyPage, pDX->m_pDlgWnd); \
if (pDX->m_bSaveAndValidate) /*Are we Saving?*/ \
{ \
if (propDialog->GetControlStatus(nCtrlId)) /*Is Control Dirty?*/ \
{ \
void (AFXAPI *pfv)(CDataExchange*,int,ctype*,LPCTSTR) = \
DDP_End##group; \
AFX_DDPDATA *pDDP = new AFX_DDPDATA( (void *)pfv, nCtrlId, bEditCtrl, \
(void*)&member, (UINT)vtype, \
pszPropName ); \
propDialog->m_arrayDDP.Add(pDDP); \
} \
} \
else /* Loading data from properties! */ \
{ \
propDialog->GetProp##group(pszPropName, &member); \
propDialog->SetControlStatus(nCtrlId,FALSE); \
} \
}
/////////////////////////////////////////////////////////////////////////////
// DDP Functions (Pseudo Template Generation)
DEFINE_DDP_(Text,BYTE,VT_UI1,TRUE);
DEFINE_DDP_(Text,short,VT_I2,TRUE);
DEFINE_DDP_(Text,int,VT_I4,TRUE);
DEFINE_DDP_(Text,UINT,VT_UI4,TRUE);
DEFINE_DDP_(Text,long,VT_I4,TRUE);
DEFINE_DDP_(Text,DWORD,VT_UI4,TRUE);
DEFINE_DDP_(Text,float,VT_R4,TRUE);
DEFINE_DDP_(Text,double,VT_R8,TRUE);
DEFINE_DDP_(Text,CString,VT_BSTR,TRUE);
DEFINE_DDP_(Check,BOOL,VT_I4,FALSE);
DEFINE_DDP_(Radio,int,VT_I4,FALSE);
//////////////////////////////////////////////////////////////////////////////
// DDP Deferred Property Write Handler
void AFXAPI DDP_PostProcessing(CDataExchange*pDX)
{
if (pDX->m_bSaveAndValidate)
{
CPtrArray &arrayDDP =
((COlePropertyPage *)pDX->m_pDlgWnd)->m_arrayDDP;
AFX_DDPDATA *pDDP = NULL;
int cDDP = arrayDDP.GetSize();
for (int i = 0 ; i < cDDP; i++)
{
pDDP = (AFX_DDPDATA*)arrayDDP[i];
TRY
{
if (pDDP->m_bEditCtrl)
pDX->PrepareEditCtrl(pDDP->m_nCtrlId);
else
pDX->PrepareCtrl(pDDP->m_nCtrlId);
switch( pDDP->m_nType )
{
case VT_I1:
{
typedef void (AFXAPI *PFV)(CDataExchange *, int,
char *, LPCTSTR );
(*(PFV)pDDP->m_lpHandler)(pDX, pDDP->m_nCtrlId,
(char *)pDDP->m_lpMember,
pDDP->m_lpszOleName );
break;
}
case VT_UI1:
{
typedef void (AFXAPI *PFV)(CDataExchange *, int,
BYTE *, LPCTSTR );
(*(PFV)pDDP->m_lpHandler)(pDX, pDDP->m_nCtrlId,
(BYTE *)pDDP->m_lpMember,
pDDP->m_lpszOleName );
break;
}
case VT_I2:
{
typedef void (AFXAPI *PFV)(CDataExchange *, int,
short *, LPCTSTR );
(*(PFV)pDDP->m_lpHandler)(pDX, pDDP->m_nCtrlId,
(short *)pDDP->m_lpMember,
pDDP->m_lpszOleName );
break;
}
case VT_UI2:
{
typedef void (AFXAPI *PFV)(CDataExchange *, int,
WORD *, LPCTSTR );
(*(PFV)pDDP->m_lpHandler)(pDX, pDDP->m_nCtrlId,
(WORD *)pDDP->m_lpMember,
pDDP->m_lpszOleName );
break;
}
case VT_I4:
{
typedef void (AFXAPI *PFV)(CDataExchange *, int,
long *, LPCTSTR );
(*(PFV)pDDP->m_lpHandler)(pDX, pDDP->m_nCtrlId,
(long *)pDDP->m_lpMember,
pDDP->m_lpszOleName );
break;
}
case VT_UI4:
{
typedef void (AFXAPI *PFV)(CDataExchange *, int,
DWORD *, LPCTSTR );
(*(PFV)pDDP->m_lpHandler)(pDX, pDDP->m_nCtrlId,
(DWORD *)pDDP->m_lpMember,
pDDP->m_lpszOleName);
break;
}
case VT_R4:
{
typedef void (AFXAPI *PFV)(CDataExchange *, int,
float *, LPCTSTR );
(*(PFV)pDDP->m_lpHandler)(pDX, pDDP->m_nCtrlId,
(float *)pDDP->m_lpMember,
pDDP->m_lpszOleName);
break;
}
case VT_R8:
{
typedef void (AFXAPI *PFV)(CDataExchange *, int,
double *, LPCTSTR );
(*(PFV)pDDP->m_lpHandler)(pDX, pDDP->m_nCtrlId,
(double *)pDDP->m_lpMember,
pDDP->m_lpszOleName );
break;
}
case VT_BSTR:
{
typedef void (AFXAPI *PFV)(CDataExchange *, int,
CString *, LPCTSTR );
(*(PFV)pDDP->m_lpHandler)(pDX, pDDP->m_nCtrlId,
(CString *)pDDP->m_lpMember,
pDDP->m_lpszOleName );
break;
}
default:
// Unknown Data Type!
ASSERT(FALSE);
break;
}
}
CATCH(COleDispatchException, e)
{
// Dleanup before pDX->Fail() throws exception.
_AfxCleanupDDPs(arrayDDP);
// Display message box for dispatch exceptions.
COlePropertyPage* pPropPage = (COlePropertyPage*)pDX->m_pDlgWnd;
pPropPage->MessageBox((LPCTSTR)e->m_strDescription, NULL,
MB_ICONEXCLAMATION | MB_OK);
DELETE_EXCEPTION(e);
pDX->Fail();
}
AND_CATCH_ALL(e)
{
// Ignore other exceptions.
DELETE_EXCEPTION(e);
}
END_CATCH_ALL
}
_AfxCleanupDDPs(arrayDDP);
}
}
/////////////////////////////////////////////////////////////////////////////
// Force any extra compiler-generated code into AFX_INIT_SEG
#ifdef AFX_INIT_SEG
#pragma code_seg(AFX_INIT_SEG)
#endif
IMPLEMENT_DYNAMIC(COlePropertyPage, CDialog)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -