• MFC DLL如何响应PreTranslateMessage消息


    最近项目中使用到MFC,由于工程是DLL的,在使用ToolTip时碰到非模态对话框无法显示的问题。查了一番资料,发现原因是由于:虽然MFC Regular DLL派生了CWinApp类,并有一个theApp全局对象。但它不包含CWinApp::Run机制,主消息由exe负责接收、分发,导致DLL的PreTranslateMessage不生效。参考资料:https://www.cnblogs.com/hanford/p/6177904.html 第2.5 PreTranslateMessage小节。该文中提到使DLL调用PreTranslateMessage的方法,但对于NX二次开发来说无法实现,毕竟主exe是已经封装好的。又经过一阵搜索,发现钩子函数可以解决,具体方法如下:

    第一步:在App类中定义钩子和对话框变量

    class CTestApp : public CWinApp
    {
    public:
        CTestApp();
        CTestDlg* m_dlg;
        HHOOK m_hHook;

    第二步:构造函数中初始化成员变量

    CTestApp::CTestApp():m_hHook(NULL),m_dlg(NULL)
    {
        // TODO: 在此处添加构造代码,
        // 将所有重要的初始化放置在 InitInstance 中
    }

    第三步:定义钩子函数

    加粗部分千万不能省掉,需要判断消息是否属于该对话框,否则可能导致界面卡死

    class CTestApp : public CWinApp
    {
    public:
        CTestApp();
        CTestDlg* m_dlg;
        HHOOK m_hHook;
    // 重写
    public:
        virtual BOOL InitInstance();
    
        DECLARE_MESSAGE_MAP()
        virtual int ExitInstance();
        static LRESULT CALLBACK GetMessageProc(int nCode, WPARAM wParam, LPARAM lParam);
    };
    LRESULT CALLBACK CTestApp::GetMessageProc(int nCode, WPARAM wParam, LPARAM lParam)
    {
        AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
        LPMSG lpMsg = (LPMSG)lParam;
        if( (AfxGetApp()->PreTranslateMessage(lpMsg)) && (lpMsg->hwnd == theApp.m_dlg->m_hWnd))
        {        
            theApp.m_dlg->PreTranslateMessage(lpMsg);    
        }
        return CallNextHookEx(theApp.m_hHook, nCode, wParam, lParam);
    }

    第四步:安装钩子

    BOOL CTestApp::InitInstance()
    {
        BOOL bInit = CWinApp::InitInstance();
    
        if (bInit)
        {
            // TODO: Add your own module initialization code here.
            m_hHook = ::SetWindowsHookEx(
                WH_GETMESSAGE,
                GetMessageProc,
                AfxGetInstanceHandle(),
                GetCurrentThreadId());
    
            return CWinApp::InitInstance();    
        }
    
        return bInit;
    }

     第五步:卸载钩子

    int CTestApp::ExitInstance()
    {
        // TODO: 在此添加专用代码和/或调用基类
        UnhookWindowsHookEx((HHOOK)m_hHook);
        return CWinApp::ExitInstance();
    }

    第六步:创建非模态对话框

    static UF_MB_cb_status_t  test(
        UF_MB_widget_t             widget,
        UF_MB_data_t               client_data,
        UF_MB_activated_button_p_t call_button )
    {
        if (UF_initialize() != 0) 
            return UF_MB_CB_ERROR;
    
        AFX_MANAGE_STATE(AfxGetStaticModuleState());
        
        if (theApp.m_dlg == NULL)
        {
            theApp.m_dlg = new CTestDlg();
            theApp.m_dlg->Create(CTestDlg::IDD);
        }
        
        theApp.m_dlg->ShowWindow(SW_NORMAL);
        UF_terminate();   
        return UF_MB_CB_CANCEL;
    }

    大功告成!测试:

    作者:快雪
    本文版权归作者所有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。
  • 相关阅读:
    Android网络编程要学的东西与Http协议学习
    数据存储与访问之——初见SQLite数据库
    ViewPager基础入门
    调用android方法,出现版本太低解决方法
    Android Studio 代码自动提示无效
    策略模式
    C#通过SendARP()获取WinCE设备的Mac网卡物理地址
    简单理解和使用 C# 委托与事件
    Oracle SQL developer客户端 如何连接已经安装完毕的Oracle服务器端
    源码分析之Map(二)HashCode详解
  • 原文地址:https://www.cnblogs.com/kuaixue/p/13722921.html
Copyright © 2020-2023  润新知