Visual c++ 向派生CView类发送Message/PostMessage不适用于MFC应用程序

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()处理程序来处理我的消息,因为我的目标是使用相同的处理程序,该处理程序通

我正在为传统的基于MFC的应用程序(MFC应用程序)构建一个测试应用程序(testApp)。我试图通过在MFC应用程序之间传递消息来模拟鼠标点击。我能够成功地从MFC应用程序菜单中打开对话框。然而,当我试图在MFC-app的视图上模拟鼠标点击时,它似乎不起作用

我的主要问题是,在尝试使用SendMessage、PostMessage函数与CView的派生类通信时,是否存在已知的限制?还要注意,我正在重用ON_COMMAND()处理程序来处理我的消息,因为我的目标是使用相同的处理程序,该处理程序通过我的TestApp单击菜单选项来调用。有关我尝试的内容和我遇到的错误的更多详细信息:

尝试1。 TestApp: ::向MFC应用程序的CMInframe发送消息,要求其使用所需输入调出CView。-->这很有效

MFCApp: CMInframe:使用下面描述的方法检索CView(CDesignView)的派生类及其HWND句柄的ptr: 使用的代码粘贴在下面:

  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