VC++编程常见问题解答十九 问:RegisterWindowMessage中的BroadcastSystemMessage如何处理? 我想用BroadcastSystemMessage来在两个进程之间通讯,我从一个进程发送了一个 用 RegisterWindowMessage注册过的消息,但在目的进程中却没有收到该消息. 答:我认为你应该在两个进程的最高级窗口中都注册该消息.请看下例: static UINT sBroadcastCommand = ::RegisterWindowMessage( _T("BroadcastCommand")); BEGIN_MESSAGE_MAP( Gui_Top_Level_MainFrame, Gui_MainFrame ) ON_REGISTERED_MESSAGE( sBroadcastCommand, onBroadcastCommand ) END_MESSAGE_MAP() LRESULT Gui_MainFrame :: onBroadcastCommand( UINT aMsg, LPARAM lParam ) { your code... } 然后发送进行应该包含: While the sending process would contain: static UINT sBroadcastCommand = ::RegisterWindowMessage( _T("BroadcastCommand")); void Someclass :: someMethod( void ) { ::PostMessage( (HWND)HWND_BROADCAST,sBroadcastCommand, 0,yourMessageId ); } 问:CListCtrl中选择变化时如何获得通知? 我在Report View中使用了一个CListCtrl(自绘制类型),我想知道什么时候选择项 发生了改变. 答:在选择项变化时,可以使用按钮有效或失效,按如下操作: 加入LVN_ITEMCHANGED消息处理. void CYourClassNameHere::OnItemchangedEventList(NMHDR* pNMHDR, LRESULT* pResult) { NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; *pResult = 0; if (pNMListView->uChanged == LVIF_STATE) { if (pNMListView->uNewState) GetDlgItem(IDC_DELETE)->EnableWindow(TRUE); else GetDlgItem(IDC_DELETE)->EnableWindow(FALSE); } } 问:如何向ATL-COM对象传送一个数组? 我想创建一个函数来向ATL-COM对象传送数组. 答:如下代码的方法用于ACTIVEX中,可能对ATL-COM也有启发吧. CoInitialize(NULL); CLSID m_clsid; USES_CONVERSION; ::CLSIDFromString(T2OLE("ROUNDANALOG.RoundAnlgAARCtrl.1"), &m_clsid); IDispatch FAR* pObj = (IDispatch FAR*)NULL; CString str = "UpdateControl"; BSTR bstr = str.AllocSysString(); HRESULT hr = CoCreateInstance(m_clsid, NULL, CLSCTX_ALL, IID_IDispatch, (void**)&pObj); SafeArrayAccessData(psa, (void**)&bstrArray); bstrArray[0] = str.AllocSysString(); bstrArray[1] = str.AllocSysString(); SafeArrayUnaccessData(psa); VARIANTARG* pvars = new VARIANTARG[1]; VariantInit(&pvars[0]); pvars[0].vt = VT_ARRAY|VT_BYREF|VT_BSTR; pvars[0].pparray = &psa; DISPID dispid; hr = pObj->GetIDsOfNames(IID_NULL, &bstr, 1,LOCALE_USER_DEFAULT, &dispid); DISPPARAMS disp = {pvars, &dispid, 1,1}; hr = pObj->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT,DISPATCH_PROPERTYPUT,&disp,NULL, NULL, NULL); delete[] pvars; pObj->Release(); CoUninitialize(); 在你的控制中建立如下函数: void CRoundAnlgAARCtrl::SaveFunc(const VARIANT FAR& var) { // TODO: Add your dispatch handler code here ASSERT(var.vt == VT_ARRAY | VT_BYREF | VT_BSTR); SAFEARRAY* psa = *var.pparray; } 问:如何选择CTreeCtrl中的节点文本进行编辑? 在向CTreeCtrl中加入一项后,有什么方法可以编辑该节点的文本呢? 答:首先设置你的CcompTreeCtrl具有TVS_EDITLABELS属性.在设计时用控件属性 来设置 在运行时用GetStyle()/SetStyle()成员函数来设置.然后请看下述代码: HTREEITEM CCompTreeCtrl::AddSet() { static int setCnt =3D 1; HTREEITEM hItem; CString csSet; //create text for new note: New Set 1, New Set 2 ... csSet.Format( _T( "New Set %d" ), setCnt++ ); hItem =3D InsertItem( csSet, IMG_CLOSEDFOLDER, IMG_CLOSEDFOLDER ); if( hItem !=3D NULL ) EditLabel( hItem ); return hItem; }