这两天一直在跟这东东较劲,今天终于有了点结果。
其实思路很简单:第一步找到Message的窗口句柄,第二步关掉它。
找句柄有若干的方法,这两天重点研究的是FindWindowEx() 和 GetLastActivePopup()。各有利弊。后述。
关窗口也有若干方法。可以发送WM_CLOSE/调用CloseWindow(), 发送WM_DESTROY/DestroyWindow(),PoseMessage(hWnd, WM_COMMAND, MAKEWPARAM(IDCANCEL,BN_CLICKED) , (LPARAM)::GetDlgItem( hWnd ,IDCANCEL ) )(发送点击button事件。根据Messagebox类型改变ID),以及EndDialog()实现。
CloseWindow()最不好用。因为它实际上只是将Messageox最小化了,并没有真正销毁。
DestroyWindo()虽然销毁了Messagebox,却没有重新激活其父窗口。在多窗口的时候会造成界面的混乱。
模拟点击Button比较万能,因为可以实现不同的逻辑效果,只是有点麻烦。
EndDialog最好用,能够安全地干掉Messagebox,并且模拟返回值(第二个参数)。
下面是查找句柄的两个例程:
一、使用GetLastActivePopup()。
前提条件:需要知道父窗口。
优点:简单明了。
缺陷:当焦点不在MessageBox上时无法将其关闭。
void DestroyMsg(HWND parent) { if (parent) { HWND hWnd = GetLastActivePopup( parent ) ; //查找激活的MessageBox if (hWnd) { EndDialog( hWnd, 0 ) ; } } }
二、使用FindWindowEx()。
前提条件:MessageBox的标题和内容
优点:可以找到任意MessageBox。
缺点:代码长,消耗资源大。
static BOOL CALLBACK EnumCommonProc( HWND hwnd, LPARAM lParam ) { stMsgFeature* pstMsg = (stMsgFeature*)lParam ; char szQuestionMsg[255] = { 0 } ; GetWindowText( hwnd , szQuestionMsg , 255 ) ; if ( ( strcmp( pstMsg->pszContent , szQuestionMsg ) == 0 ) ) { // found , and exit enum pstMsg->bFound = true ; return false ; } return true ; } bool IsMsgWnd ( HWND hWnd , char* pszContent ) { stMsgFeature stMsg ; stMsg.pszContent = pszContent ; stMsg.bFound = false ; EnumChildWindows( hWnd, EnumCommonProc, LPARAM(&stMsg)) ; return stMsg.bFound ; } void DestroyWnd(const char* pszCaption , const char* pszContent ) { HWND hJigCaption = FindWindowEx( NULL , // parent NULL , // child after NULL , // class pszCaption ) ; // caption while ( hJigCaption ) { if ( IsMsgWnd( hJigCaption , pszContent ) ) { break ; } // find next window hJigCaption = FindWindowEx( NULL , // parent hJigCaption , // child after NULL , // class pszCaption ) ; // caption } if (hJigCaption) { ::EndDialog( hJigCaption , 0 ) ; } }