Visual c++ 向派生CView类发送Message/PostMessage不适用于MFC应用程序
我正在为传统的基于MFC的应用程序(MFC应用程序)构建一个测试应用程序(testApp)。我试图通过在MFC应用程序之间传递消息来模拟鼠标点击。我能够成功地从MFC应用程序菜单中打开对话框。然而,当我试图在MFC-app的视图上模拟鼠标点击时,它似乎不起作用 我的主要问题是,在尝试使用SendMessage、PostMessage函数与CView的派生类通信时,是否存在已知的限制?还要注意,我正在重用ON_COMMAND()处理程序来处理我的消息,因为我的目标是使用相同的处理程序,该处理程序通过我的TestApp单击菜单选项来调用。有关我尝试的内容和我遇到的错误的更多详细信息: 尝试1。 TestApp: ::向MFC应用程序的CMInframe发送消息,要求其使用所需输入调出CView。-->这很有效 MFCApp: CMInframe:使用下面描述的方法检索CView(CDesignView)的派生类及其HWND句柄的ptr: 使用的代码粘贴在下面:Visual c++ 向派生CView类发送Message/PostMessage不适用于MFC应用程序,visual-c++,mfc,sendmessage,cview,Visual C++,Mfc,Sendmessage,Cview,我正在为传统的基于MFC的应用程序(MFC应用程序)构建一个测试应用程序(testApp)。我试图通过在MFC应用程序之间传递消息来模拟鼠标点击。我能够成功地从MFC应用程序菜单中打开对话框。然而,当我试图在MFC-app的视图上模拟鼠标点击时,它似乎不起作用 我的主要问题是,在尝试使用SendMessage、PostMessage函数与CView的派生类通信时,是否存在已知的限制?还要注意,我正在重用ON_COMMAND()处理程序来处理我的消息,因为我的目标是使用相同的处理程序,该处理程序通
CMDIChildWnd * pChild = MDIGetActive();
if ( !pChild )
return -1;
CView *pView = pChild->GetActiveView();
if (!pView) {
MessageBox(_T("Could not get a handle to the design"), _T("Test2 Error"), MB_OK);
return -1;
}
// Fail if view is of wrong kind
if ( !pView->IsKindOf( RUNTIME_CLASS(CDesignView) ) ) {
MessageBox(_T("View obtained is not of type DesignView"), _T("Test2 Error"), MB_OK);
return -1;
}
CDesignView* designView = (CDesignView*)pView ;
HWND view_hWnd = designView->m_hWnd ;
if (!view_hWnd) {
MessageBox(_T("designView handle could not be obtained"), _T("Test2 Error"), MB_OK);
return -1;
}
------------------->此时,代码的view_hWnd和designView具有非空值。但是,当我将这些用于SendMessage时,它会失败:
designView->PostMessageW(ID\u DESIGN\u xxx,NULL,NULL)
-->这不起作用,即应用程序中没有更改,就好像从未发送过mesg一样。从未调用ID\u DESIGN\u xxx处理程序。
处理程序在CDesignView消息映射中声明如下:
ON_命令(ID_设计_xxx,OnXXX)
(注意:我正在重新使用MFCApp已经用于CDesignView上与此函数对应的菜单选项的处理程序,因为目标是测试它)
-------------------->当我将其替换为直接调用处理程序时,如下所示:
设计视图->OnStarOrder()
然而,这不是我想要的行为,因为它涉及将太多的视图处理程序公开为公共的,并且还破坏了一个紧密模拟实际使用模型的测试应用程序的目的
------------------->为了进一步调试,我还尝试调用本机WM_xxx消息,如下所示
designView->PostMessageW(WM_CLOSE,NULL,NULL)
此检查中出现异常失败:IsKindOf(运行时)类(CView)断言失败
尝试2
我还试图让TestApp将消息发送到MFCApp CDesignView,而不是它自己的大型机,而不是像上面所描述的那样。因此,我使用ON_COPY消息将CDerivedView句柄视图从上述代码传递给TestApp。然后TestApp执行::SendMessage(view_hWnd,WM_CLOSE,NULL,NULL)。得到了相同的错误。
这种方法试图排除CDesignView在发送消息时不是活动窗口的可能性。在这种情况下,在让TestApp发送消息之前,我手动单击MFCApp的CView
这些似乎都不起作用。您提供的任何建议都会有很大帮助。提前感谢!关于您的主要问题“尝试使用SendMessage、PostMessage函数与CView派生类通信是否存在已知限制”,答案是否定的。函数
SendMessage()
和PostMessage()
是标准的Win32 API函数,用于向定义了窗口句柄的任何窗口提供消息
一点MFC的背景知识
大多数包装窗口的MFC类都是从某个点CWnd
派生而来的。CWnd
类用于包装Windows窗口和与窗口一起使用的Win32 API。因此,许多采用窗口句柄的Win32 API函数都有类似的CWnd
类方法
如果您查看CView
的声明,您可以看到它是从CWnd
派生的,该声明将这两个函数的一个版本作为方法。但是CWnd
的方法与Win32 API版本具有不同的接口,因为它们消除了作为第一个参数的窗口句柄
CWnd
类声明如下所示
LRESULT-CWnd::SendMessage(UINT-message,WPARAM-WPARAM=0,LPARAM-LPARAM=0);
该方法在CWnd
类中的实现可能大致如下:
LRESULT CWnd::SendMessage(UINT message, WPARAM wParam, LPARAM lParam)
{
return ::SendMessage (m_hWnd, message, wParam, lParam);
}
其中m_-hWnd
在CWnd
类中定义为hWnd m_-hWnd;
,是CWnd
类正在包装的窗口句柄
什么是消息映射
在MFC窗口类文件中,例如对于从CView
派生的类,将有一组源代码行,类似于:
BEGIN_MESSAGE_MAP(CPCSampleApp, CWinApp)
//{{AFX_MSG_MAP(CPCSampleApp)
ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
ON_COMMAND(ID_APP_EXIT, OnAppExit)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
这是在包含文件中定义的一组预处理器宏,允许创建MFC消息映射
BEGIN\u MESSAGE\u MAP
宏如下所示:
#define BEGIN_MESSAGE_MAP(theClass, baseClass) \
PTM_WARNING_DISABLE \
const AFX_MSGMAP* theClass::GetMessageMap() const \
{ return GetThisMessageMap(); } \
const AFX_MSGMAP* PASCAL theClass::GetThisMessageMap() \
{ \
typedef theClass ThisClass; \
typedef baseClass TheBaseClass; \
static const AFX_MSGMAP_ENTRY _messageEntries[] = \
{
#define END_MESSAGE_MAP() \
{0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } \
}; \
static const AFX_MSGMAP messageMap = \
{ &TheBaseClass::GetThisMessageMap, &_messageEntries[0] }; \
return &messageMap; \
} \
PTM_WARNING_RESTORE
#define ON_COMMAND(id, memberFxn) \
{ WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)id, AfxSigCmd_v, \
static_cast<AFX_PMSG> (memberFxn) },
// ON_COMMAND(id, OnBar) is the same as
// ON_CONTROL(0, id, OnBar) or ON_BN_CLICKED(0, id, OnBar)
#define ON_NOTIFY_EX(wNotifyCode, id, memberFxn) \
{ WM_NOTIFY, (WORD)(int)wNotifyCode, (WORD)id, (WORD)id, AfxSigNotify_EX, \
(AFX_PMSG) \
(static_cast< BOOL (AFX_MSG_CALL CCmdTarget::*)(UINT, NMHDR*, LRESULT*) > \
(memberFxn)) },
BOOL CPCSampleView::OnToolTipText( UINT id, NMHDR * pNMHDR, LRESULT * pResult )
#define ON_NOTIFY(wNotifyCode, id, memberFxn) \
{ WM_NOTIFY, (WORD)(int)wNotifyCode, (WORD)id, (WORD)id, AfxSigNotify_v, \
(AFX_PMSG) \
(static_cast< void (AFX_MSG_CALL CCmdTarget::*)(NMHDR*, LRESULT*) > \
(memberFxn)) },
它正在创建一组函数以及一个数组,以将各种消息映射条目存储到其中
END\u MESSAGE\u MAP
宏提供消息映射项数组的结尾,如下所示:
#define BEGIN_MESSAGE_MAP(theClass, baseClass) \
PTM_WARNING_DISABLE \
const AFX_MSGMAP* theClass::GetMessageMap() const \
{ return GetThisMessageMap(); } \
const AFX_MSGMAP* PASCAL theClass::GetThisMessageMap() \
{ \
typedef theClass ThisClass; \
typedef baseClass TheBaseClass; \
static const AFX_MSGMAP_ENTRY _messageEntries[] = \
{
#define END_MESSAGE_MAP() \
{0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } \
}; \
static const AFX_MSGMAP messageMap = \
{ &TheBaseClass::GetThisMessageMap, &_messageEntries[0] }; \
return &messageMap; \
} \
PTM_WARNING_RESTORE
#define ON_COMMAND(id, memberFxn) \
{ WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)id, AfxSigCmd_v, \
static_cast<AFX_PMSG> (memberFxn) },
// ON_COMMAND(id, OnBar) is the same as
// ON_CONTROL(0, id, OnBar) or ON_BN_CLICKED(0, id, OnBar)
#define ON_NOTIFY_EX(wNotifyCode, id, memberFxn) \
{ WM_NOTIFY, (WORD)(int)wNotifyCode, (WORD)id, (WORD)id, AfxSigNotify_EX, \
(AFX_PMSG) \
(static_cast< BOOL (AFX_MSG_CALL CCmdTarget::*)(UINT, NMHDR*, LRESULT*) > \
(memberFxn)) },
BOOL CPCSampleView::OnToolTipText( UINT id, NMHDR * pNMHDR, LRESULT * pResult )
#define ON_NOTIFY(wNotifyCode, id, memberFxn) \
{ WM_NOTIFY, (WORD)(int)wNotifyCode, (WORD)id, (WORD)id, AfxSigNotify_v, \
(AFX_PMSG) \
(static_cast< void (AFX_MSG_CALL CCmdTarget::*)(NMHDR*, LRESULT*) > \
(memberFxn)) },
实际数组元素是一个struct AFX\u MSGMAP\u条目
,如下所示:
struct AFX_MSGMAP_ENTRY
{
UINT nMessage; // windows message
UINT nCode; // control code or WM_NOTIFY code
UINT nID; // control ID (or 0 for windows messages)
UINT nLastID; // used for entries specifying a range of control id's
UINT_PTR nSig; // signature type (action) or pointer to message #
AFX_PMSG pfn; // routine to call (or special value)
};
MFC的引擎盖下是一系列查找函数,这些函数获取一条Windows消息,然后迭代消息映射数组中声明的Windows消息列表,以查看是否存在匹配项
如果它找到了Windows消息id和相应的wParam
值的匹配项,那么它将通过函数指针调用该函数,该函数指针提供了用于匹配消息映射项的接口规范的适当参数
包含数组项源的ON_命令
宏如下所示:
#define BEGIN_MESSAGE_MAP(theClass, baseClass) \
PTM_WARNING_DISABLE \
const AFX_MSGMAP* theClass::GetMessageMap() const \
{ return GetThisMessageMap(); } \
const AFX_MSGMAP* PASCAL theClass::GetThisMessageMap() \
{ \
typedef theClass ThisClass; \
typedef baseClass TheBaseClass; \
static const AFX_MSGMAP_ENTRY _messageEntries[] = \
{
#define END_MESSAGE_MAP() \
{0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } \
}; \
static const AFX_MSGMAP messageMap = \
{ &TheBaseClass::GetThisMessageMap, &_messageEntries[0] }; \
return &messageMap; \
} \
PTM_WARNING_RESTORE
#define ON_COMMAND(id, memberFxn) \
{ WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)id, AfxSigCmd_v, \
static_cast<AFX_PMSG> (memberFxn) },
// ON_COMMAND(id, OnBar) is the same as
// ON_CONTROL(0, id, OnBar) or ON_BN_CLICKED(0, id, OnBar)
#define ON_NOTIFY_EX(wNotifyCode, id, memberFxn) \
{ WM_NOTIFY, (WORD)(int)wNotifyCode, (WORD)id, (WORD)id, AfxSigNotify_EX, \
(AFX_PMSG) \
(static_cast< BOOL (AFX_MSG_CALL CCmdTarget::*)(UINT, NMHDR*, LRESULT*) > \
(memberFxn)) },
BOOL CPCSampleView::OnToolTipText( UINT id, NMHDR * pNMHDR, LRESULT * pResult )
#define ON_NOTIFY(wNotifyCode, id, memberFxn) \
{ WM_NOTIFY, (WORD)(int)wNotifyCode, (WORD)id, (WORD)id, AfxSigNotify_v, \
(AFX_PMSG) \
(static_cast< void (AFX_MSG_CALL CCmdTarget::*)(NMHDR*, LRESULT*) > \
(memberFxn)) },
或者,您可以将Win32 API用于:
::SendMessage (viewObject->m_hWnd, WM_COMMAND, ID_DESIGN_xxx, 0);
另一个例子:ON\u NOTIFY\u EX
另一个不同的消息映射宏是th