SetModifiedFlag(); }
long CToppCtrl::Add(LPCTSTR strItem) {
// TODO: Add your dispatch handler code here long l = m_saItems.Add(strItem); InvalidateControl(); return l;
return m_saItems.Add(strItem); return 0; }
void CToppCtrl::SetItem(long nItem, LPCTSTR lpszNewValue) {
// TODO: Add your property handler here
if(nItem >= 0 && nItem < m_saItems.GetSize()){ m_saItems[nItem] = lpszNewValue; }
InvalidateControl(); SetModifiedFlag(); }
3.调整属性页中的几个函数,使它们还原为用第9步所讲的方法来调用,为什么要这样做,很简单,也是为了要调用到 InvlidateControl()。
第10步中所讲的方法都是直接访问内部成员变量了,如果一定要这么做的话,还得在属性页中访问成员变量之后,再调用一下COleControl的InvalidateControl()了,这感觉上就有些乱了。
BOOL CToppPropPage::AddItem(LPCTSTR lpszItem) {
USES_CONVERSION;
COleDispatchDriver PropDispDriver; BOOL bResult = FALSE; ULONG nObjects = 0;
LPDISPATCH* ppDisp = GetObjectArray(&nObjects); for (ULONG i = 0; i < nObjects; i++) {
DISPID dwDispID;
LPCOLESTR lpOleStr = T2COLE(\
if (SUCCEEDED(ppDisp->GetIDsOfNames(IID_NULL, (LPOLESTR*)&lpOleStr, 1, 0, &dwDispID))) {
PropDispDriver.AttachDispatch(ppDisp, FALSE); BYTE rgbParams[] = VTS_BSTR; long lret = 0;
PropDispDriver.InvokeHelper(dwDispID, DISPATCH_METHOD, VT_I4, &lret, rgbParams,
lpszItem);
PropDispDriver.DetachDispatch(); bResult = TRUE; } }
return bResult; }
CString CToppPropPage::GetItem(long lItem) {
CString str = _T(\ USES_CONVERSION;
COleDispatchDriver PropDispDriver; ULONG nObjects = 0;
LPDISPATCH* ppDisp = GetObjectArray(&nObjects); for (ULONG i = 0; i < nObjects; i++) {
DISPID dwDispID;
LPCOLESTR lpOleStr = T2COLE(\
if (SUCCEEDED(ppDisp->GetIDsOfNames(IID_NULL, (LPOLESTR*)&lpOleStr, 1, 0, &dwDispID))) {
PropDispDriver.AttachDispatch(ppDisp, FALSE); BYTE rgbParams[] = VTS_I4;
PropDispDriver.InvokeHelper(dwDispID, DISPATCH_PROPERTYGET, VT_BSTR, &str, rgbParams, lItem);
PropDispDriver.DetachDispatch(); } }
return str; }
COLORREF CToppPropPage::GetColor() {
long l = 0;
GetPropText(\ COLORREF cr = RGB(0, 0, 0);
::OleTranslateColor((OLE_COLOR)l, NULL, &cr); return cr; }
void CToppPropPage::SetColor(COLORREF cr) {
SetPropText(\}
long CToppPropPage::GetCount() {
long lcount = 0;
GetPropText(\ return lcount; }
4.增加一个Remove方法,免得字符串越加越多了:) void CToppCtrl::Remove(long lItem) {
// TODO: Add your dispatch handler code here m_saItems.RemoveAt(lItem); InvalidateControl(); }
5.在属性页中,增加一个按钮(\删除项目\,添加一函数void RemoveItem(long lItem)和按钮处理函数
void CToppPropPage::RemoveItem(long lItem) {
USES_CONVERSION;
COleDispatchDriver PropDispDriver; ULONG nObjects = 0;
LPDISPATCH* ppDisp = GetObjectArray(&nObjects); for (ULONG i = 0; i < nObjects; i++) {
DISPID dwDispID;
LPCOLESTR lpOleStr = T2COLE(\
if (SUCCEEDED(ppDisp->GetIDsOfNames(IID_NULL, (LPOLESTR*)&lpOleStr, 1, 0, &dwDispID))) {
PropDispDriver.AttachDispatch(ppDisp, FALSE); BYTE rgbParams[] = VTS_I4; long lret = 0;
PropDispDriver.InvokeHelper(dwDispID, DISPATCH_METHOD, VT_EMPTY, &lret, rgbParams, lItem);
PropDispDriver.DetachDispatch(); } } }
void CToppPropPage::OnButtonRemoveitem() {
// TODO: Add your control notification handler code here int n = m_list.GetCurSel(); if(n >= 0){
RemoveItem(n); }
long lcount = GetCount(); m_list.ResetContent(); for(int i=0; i m_list.AddString(GetItem(i)); } } 编译一下,运行,就可以发现在属性页中的任何修改都能影响到控件的显示,可惜的是控件重新打开时还是空白一片,显然还需要持久化的支持。 那么现在我们就切入正题,添加持久化。 1.增加函数BOOL PX_Items(CPropExchange* pPX),用来持久化m_saItems 这里要注意的是 BOOL PX_Blob( CPropExchange* pPX, LPCTSTR pszPropName, HGLOBAL& hBlob, HGLOBAL hBlobDefault = NULL ); 函数中的hBlob内存块的开关必须是一个DWORD类型的长度,表示后面实际数据的字节数。 BOOL CToppCtrl::PX_Items(CPropExchange *pPX) { if(!pPX->IsLoading()) { DWORD cbGuess = 5000;//分配足够大的内存空间来存放你要保存的信息 HANDLE hMem = GlobalAlloc(GPTR, cbGuess); if(hMem != NULL) { BYTE* pMem = (BYTE*)hMem; //任何能够保存在文件中的信息,都能保存在控件的持久化中 CSharedFile file; //pMem必须以一个DWORD带头,表示接下来的数据块的字节数 file.Attach(pMem + sizeof(DWORD), cbGuess-sizeof(DWORD)); CArchive ar(&file, CArchive::store); int n = m_saItems.GetSize(); ar << n; for(int i=0; i CString str = m_saItems; ar << str; } ar.Close(); *(DWORD*)pMem = file.GetLength(); file.Close(); PX_Blob(pPX, _T(\ GlobalFree(hMem); hMem = NULL; } else{ return FALSE;
相关推荐: