MFC学习之模式对话框设计

               

   从昨天晚上就开始学习MFC的模式对话框设计,模式对话框在我以前学习WINDOWS API编程的时候就接触过---后来学习32位汇编也接触过。

  先来看一下用API怎样来创建对话框。首先的有对话框资源,得到对话框资源名IDC_MYDLG,然后在程序里得有个对话框过程处理函数----不是消息函数,最后执行DialogBox,执行到此函数时,只有等到对话框关闭EndDialog后,该函数才会返回在对函数EndDialog的调用中的nResult参数,然后我们要做的就是在对话框过程处理函数中处理各种我们可以处理的消息!----以前看过资料,说是这个处理函数不能处理WM_PAINTWM_DESTROY,WM_CREATE消息,经我实验,该函数接受到了WM_PAINTWM_DESTROY消息,但是没有接收到 WM_CREATE 消息。

  那MFC是怎么样来创建的呢?我用wiszard生成了一个默认的基于对话框的工程,打开原代码,仔细看,昨天研究MFC大体执行过程的时候已经看过了,现在看还是很熟悉的~~

  看看那个 Wiszard默认生成的代码流程:进入InitInstance-à定义对话框类对象-à调用该对象的DoModal方法-à处理该方法的返回值--àInitInstance返回,很有可能关键地方就在于DoModal~~如果有MFC原代码就好了~~不知道偶看得懂没~~

  上网一查~~ 晕~结果还真的有MFC原代码,而且还就在SRC目录下面~~那天我还正在奇怪那里面的文件是干什么的呢~~

  ~看看文件~~呵呵~DLGCORE比较可疑~~打开一看~~DoModal真在里面~~看看去~

    看了看DoModal函数,有点迷茫,但是我现在不需要去仔细看它,我只需要发现它的执行流程。对,里面会装载对话框资源,然后会调用Cdialog的另一些成员函数来创建窗口,那么那个对话框资源从哪里来引用呢?HOHO~~忽略了~~在我们的程序里,CMyDialogCDialog派生,在创建CMyDialog对象时,CMyDialog构造函数还调用了Cdialog的构造函数,注意,它传递了CMyDialog中的枚举类型IDD,该类型就包含了对话框资源名----YEAH~那执行流程是什么呢?从那个直接使用SDK做的对话框程序可以看出:当执行到创建对话框的函数(实际上是宏)DialogBox时,程序就会等到对话框关闭才继续执行~

  DoModal里有创建对话框的代码,那么在我们程序里调用DoModal 后,我们的程序就应该不在继续执行了吧~~这个时候程序的交互就会通过那个对话框消息的处理函数了~~~~Cdialog中找到一个AfxDlgProc函数,它就是作为那个在创建对话框时传递的函数(指针)。但是在我们的程序里可以通过消息映射机制来处理消息----当有消息时,相应的消息处理函数就会被调用,于是可以推想:在Cdialog类里的AfxDlgProc必然要调用其派生类的相应函数---这就涉及到:消息映射机制是如何实现的?还有,在CMyDialog里好象并没有映射WM_INITDIALOG消息,那程序又是如何来调用派生类CMyDialog中的OnInitDialog函数的?还有,如果当调用DoModal后程序阻塞,那当对话框结束时,程序就会继续执行InitInstance后的代码啊?但是我在那后面放置的代码好象并没有执行---我在那后面放置了弹出消息框的代码,程序执行时没有出现消息框~~~ ~~疑惑~~~

 于是到网上翻文章~~以下是我翻到的文章的部分节选:

 

MFC下,所有的窗口类都使用了同一个窗口过程,CDialog也不例外。CDialog对象在创建Windows对话框时,采用了类似于CWnd的创建函数过程,采用子类化的手段将Windows提供给对话框的窗口过程取代为AfxWndProc或者AfxBaseWndProc,同时提供了对话框过程AfxDlgProc。

AfxDlgProc处理WM_INITDIALOG消息时调用虚拟函数OnInitDialog,给程序员一个机会处理对话框的初始化。(难道CMyDialog里的重载的OnInitDialog就是由它调用的?)

  AfxWndProc是所有的MFC窗口类使用的窗口过程,它取代了模式对话框原来的窗口过程(Windows提供),(采用子类化技术~)

DoModal的实现可以看出:

它首先Disable对话框窗口的父窗口;然后使用::CreateIndrectDialog创建对话框窗口,使用子类化的方法用AfxWndProc(或者AfxBaseProc)替换了原来的窗口过程,并把原来的窗口过程保存在CWnd的成员变量m_pfnSuper中。原来的窗口过程就是::DialogBox等创建对话框窗口时指定的,是Windows内部提供的对话框“窗口类”的窗口过程。

OnInitDialog的MFC缺省实现主要完成三件事情:

调用ExecInitDialog初始化对话框中的控制;调用UpdateData初始化对话框控制中的数据;确定是否显示帮助按钮。所以,程序员覆盖该函数时,一定要调用基类的实现。

MFC采用子类化的方法取代了对话框的窗口过程,实现了12.1节描述的模式对话框窗口的一些特性,原来SDK下对话框过程要处理的东西大部分转移给MFC窗口过程处理,如处理控制窗口的控制通知消息等。如果不能处理或者必须借助于原来的窗口过程的,则通过缺省处理函数Default传递给原来的窗口过程处理,如同这里对WM_INITDIALOG的处理一样。

DoModal的实现可以看出,DoModal调用CreateDlgIndirect创建的是无模式对话框,CDialog调用了RunModalLoop来实现模式窗口的消息循环。RunModalLoopCWnd的成员函数。

  再看看DoModal的另一分描述:

  DoModal负责对模态话框的创建和撤销。在创建对话框时,DoModal的任务包括载入对话框模板资源、调用OnInitDialog初始化对话框和将对话框显示在屏幕上。完成对话框的创建后,DoModal启动一个消息循环,以响应用户的输入。由于该消息循环截获了几乎所有的输入消息,使主消息循环收不到对对话框的输入,致使用户只能与模态对话框进行交互,而其它用户界面对象收不到输入信息。

  弄了半天,还是不怎么清楚---偶是不是太深入了?刚刚学习MFC,可能没有这个必要这样追根溯源吧~~不过我真的觉得面对着MFC这个黑箱~~心里就是压抑不住的好奇~~

  总结一下:大致过程就是:告诉CDialog对话框资源名--->调用DoModal--->创建对话框-->MFC接管WINDOWS的对话框管理器--->初始化,产生WM_INITDIALOG消息,调用AfxDlgProc-->调用CDialog派生类的OnInitDialog,返回后--->此时已经进入消息循环--->产生消息,调用CDialog相应的消息处理函数,如果在其派生类中被重载,就调用其重载的函数--~~END

  恩~~还是不怎么清楚~~汗~~深入下去就觉得难了~~

  其实我现在还不需要这个样子,毕竟不可能别人都是这样一开始就想完全深入到MFC中,把MFC看个透彻的~~其实偶也不想这样,呵呵,完全是好奇心驱使,不知不觉就这样了~~

  在用对话框时,咳,其实MFC已经把我们需要的告诉我们了。要初始化一些数据了,重载OnInitDialog,对话框出现后,最主要的也就是处理各种各样的消息---要用什么消息,那就添加消息映射~~这不就得了~?汗~~

           

猜你喜欢

转载自blog.csdn.net/qq_44906504/article/details/89279903