ActiveX控件的MFC设计之旅 联系客服

发布时间 : 星期四 文章ActiveX控件的MFC设计之旅更新完毕开始阅读0008256ca98271fe910ef902

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;