VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

有编程疑问吗?还请到提问专区发帖提问!
搜索
查看: 666|回复: 2

[求助] MFC机制问题咨询,谢谢!

[复制链接]
04_avatar_middle
online_vip yanghbao 发表于 2017-8-18 00:19:35 | 显示全部楼层 |阅读模式
@Syc     请教几个关于MFC机制的问题,谢谢!
    新建一个对话框MFC项目,在消息响应函数OnCreate中添加如下代码:if (IsWindow(m_hWnd)){MessageBox(_T("Yes"));}        else MessageBox(_T("No"));

    从入口函数(_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
        _In_ LPTSTR lpCmdLine, int nCmdShow))开始追踪,在wincore.cpp文件中发现在对话框创建之前创建了一个勾子,创建函数为: pThreadState->m_hHookOldCbtFilter = ::SetWindowsHookEx(WH_CBT,_AfxCbtFilterHook, NULL,::GetCurrentThreadId());,继续往下追踪,在dlgcore.cpp中执行到这条语句:hWnd = ::CreateDialogIndirect(hInst, lpDialogTemplate,pParentWnd->GetSafeHwnd(), AfxDlgProc);问题来了:1、对话框窗口为啥不是CreateWindowEx创建的呢? 全局函数::CreateDialogIndirect 的内部是不是通过CreateWindowEx创建窗口的呢? 2、在::CreateDialogIndirect返回之前,OnCreate 函数中的MessageBox(_T("Yes"));执行了。问题是:WM_CREATE 消息是不是在对话框创建之前就已经发出去了(所以OnCreate才得到响应了)?假如窗口在创建之前就已经发出去了,响应WM_ONCREATE消息的时候窗口还没有创建,为什么IsWindow(m_hWnd)执行的结果是true呢?既然窗口没有创建,m_hWnd为什么又是一个窗口句柄呢? 3、在窗口创建之前通过如下代码(从dlgcore.cpp中原样复制)的正数第二行创建了一个勾子,是不是又通过如下代码倒数第二的AfxUnhookWindowCreate()卸载的呢?这个勾子生存期这么短是不是就是为了拦截窗口创建之前发生的WM_ONCREATE等等消息的呢? 谢谢!

// create modeless dialog
                AfxHookWindowCreate(this);
                hWnd = ::CreateDialogIndirect(hInst, lpDialogTemplate,
                        pParentWnd->GetSafeHwnd(), AfxDlgProc);
#ifdef _DEBUG
                dwError = ::GetLastError();
#endif
        }
        CATCH_ALL(e)
        {
                DELETE_EXCEPTION(e);
                m_nModalResult = -1;
        }
        END_CATCH_ALL

        /* This is a bit tricky.  At this point, 1 of 3 things has happened:
         * 1) ::CreateDialogIndirect() created successfully and hWnd != NULL.
         * 2) ::CreateDialogIndirect() did create a window and then send the appropiate
         *    creation messages (ie. WM_CREATE).  However, the user handled WM_CREATE and
         *    returned -1.  This causes windows to send WM_DESTROY and WM_NCDESTROY to the
         *    newly created window.  Since WM_NCDESTROY has been sent, the destructor of this
         *    CWnd object has been called.  And ::CreateDialogIndirect() returns NULL.
         * 3) ::CreateDialogIndirect() did NOT create the window (ie. due to error in template)
         *    and returns NULL.
         *
         * (Note: In 3, this object is still valid; whereas in 2, this object has been deleted).
         *
         * Adding to the complexity, this function needs to do 2 memory clean up (call
         * pOccManager->PostCreateDialog() and delete occDialogInfo) if the destructor of
         * this object hasn't been called.  If the destructor has been called, the clean up is done
         * in the destructor.
         *
         * We can use the return valid of AfxUnhookWindowCreate() to differentiate between 2 and 3.
         *  - If AfxUnhookWindowCreate() returns true and hWnd==NULL, this means that (2) has happened
         *    and we don't have to clean up anything. (Cleanup should be done in the destructor).
         *  - If AfxUnhookWindowCreate() returns false and hWnd== NULL, this means that (3) has happened
         *    and we need to call PostNcDestroy().
         *
         * Note: hWnd != NULL implies that AfxUnhookWindowCreate() return TRUE.
         *
         * Note2: From this point on, don't access any member variables without checking hWnd.  If
         *        hWnd == NULL, the object has been destroyed already.
         */

#ifndef _AFX_NO_OCC_SUPPORT
        if (pOccManager != NULL)
        {
                if (hWnd != NULL)
                {
                        pOccManager->PostCreateDialog(&occDialogInfo);
                        SetOccDialogInfo(NULL);
                }
        }
#endif //!_AFX_NO_OCC_SUPPORT

        if (!AfxUnhookWindowCreate())
                PostNcDestroy();        // cleanup if Create fails too soon




上一篇:请问一下win32编程时函数前有双冒号和没有双冒号的区别?
下一篇:请教一个小问题,谢谢!

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你已经在论坛发帖求助,并且从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友?可以给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

01_avatar_middle
online_admins admin 发表于 2017-8-18 01:08:46 | 显示全部楼层
1、CreateDialogIndirect 内部实际上就是调用 CreateWindowEx 来创建窗口的,CreateDialogIndirect 对 CreateWindowEx 又包了一层,可以直接使用对话框模版来创建对话框窗口,

Remarks

The CreateDialogIndirect macro uses the CreateWindowEx function to create the dialog box. CreateDialogIndirect then sends a WM_INITDIALOG message to the dialog box procedure.

详情见:https://msdn.microsoft.com/en-us ... 45436(v=vs.85).aspx

2、咱们来看看关于 WM_CREATE 这个消息的MSDN解释:
Sent when an application requests that a window be created by calling the CreateWindowEx or CreateWindow function. (The message is sent before the function returns.) The window procedure of the new window receives this message after the window is created, but before the window becomes visible.

看到了吧,我用的谷歌翻译,翻译过来的解释就是:
当应用程序请求通过调用CreateWindowEx或CreateWindow函数创建一个窗口时发送。 (该消息在函数返回之前发送。)新窗口的窗口过程在创建窗口后,但在窗口变为可见之前收到此消息。

重点看这句:a window be created by calling the CreateWindowEx or CreateWindow function
注意,是 be created,所以表明当这个消息被发送的时候说明窗口已经被创建完成了。所以 MessageBox(_T("Yes")); 执行了。

3、楼主可以看下钩子函数 _AfxCbtFilterHook 的源码,貌似还做了其他一些工作,专门为MFC的窗口服务的。

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你已经在论坛发帖求助,并且从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友?可以给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复 支持 反对

使用道具 举报

04_avatar_middle
ico_lz  楼主| yanghbao 发表于 2017-8-18 01:38:07 | 显示全部楼层
好的,这下就明白了,非常感谢,一直在追踪、调试,竟然没想到要去仔细阅读一下MSDN,不好意思...MFC机制问题咨询,谢谢!

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你已经在论坛发帖求助,并且从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友?可以给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号tongdun|网站地图wx_jqr

GMT+8, 2018-12-11 02:55

Powered by Discuz! X3.4

© 2009-2018 cctry.com

快速回复 返回顶部 返回列表