• 2004-06-18

    大头随笔(三)

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://www.blogbus.com/dreamhead-logs/227671.html

    起因

    一个同学发过封急信来让我帮忙看看代码哪出了问题。义不容辞!

    问题是这样的:

    他要用CSplitterWnd做个切分窗口,很简单的那种,左边一个,右边一个。他告诉我,他创建的是一个单文档工程,没有选择document/view支持。(看好问题了!)

    代码也比较简单。改写CMainFrame的OnCreateClient函数(这是一个虚函数):
      BOOL ret = m_wndSplitter.CreateStatic(this,1,2);
      ret |= m_wndSplitter.CreateView(0, 0,
                                      RUNTIME_CLASS(CMyTreeView),
                                      CSize(100,100), pContext);
      ret |= m_wndSplitter.CreateView(0,1,
                                      RUNTIME_CLASS(CRightView),
                                      CSize(400,400) , pContext);
      return ret;

    其中m_wndSplitter是自己添的CSplitterWnd类型变量,CMyTreeView和 CRightView分别对应着一个FormView。

    毛病在哪呢?

    挺好的程序,运行起来,窗口的下半部分一片白,连可爱的工具栏都不见了。不用说,肯定是有问题了。:)

    经过

    解决问题的关键在于找到问题所在。(小声说一下,我已经有好长时间没用VC了,加上原来就是半吊子,所以现在很多东西我都不会了。)

    第一步,我先要找到一般切分窗口是如何做的。到哪找?上网搜。google实在太可爱了,敲个CSplitterWnd进去,搜简体中文的网页(像这种用的比较广泛的东西,中文资料一定不少,加上只是需要做一下简单的了解,没有必要找英文的),一下搜出一堆来。挑出几篇文章来,照着试一下。

    中间不顺利过程,省略N字。

    终于顺利的写出一个切分窗口的程序。满以为可以轻松搞定同学的问题,所以,顺便准备了一大堆教育他的句子。

    把他的程序拿过来一看,我立刻傻眼了。同我完成的试验程序相比,他的程序写的几乎没有任何问题,稍加整理就可以看出来,二者在逻辑上应该是完全相同的。也就是说,我了解到的东西还不足以解决他的问题。奇怪的是,我的程序运行的很好啊!

    找出刚才的文章,和他的问题细细比较一下。原来,大部分讲CSplitterWnd的文章都是基于document/view支持的,我做的试验程序也是,可这位兄弟的问题是在没有document/view支持的情况下如何做?(看看前面的问题^_^)换句话说,我忙活了半天,只是帮着自己学会了CSplitterWnd是如何使用,真正的问题,我还没贴边呢?

    怎么办?接着搜!

    这次傻了,用google搜出来的还是那些东西。上CSDN搜,我可不愿意发个帖子去问一个别人可能早已问过的问题。结果呢?似乎大家商量好了一样,几乎所有问题都是一样的,都是在问怎么切。根本没人关注在没有document/view使用CSplitterWnd切分窗口的问题。发个帖子问?我着不起那个急,况且这种问题估计一般很难有人注意到(否则早有人问了)。

    突然冒出一种叫天天不应,叫地地不灵的感觉。没办法,没人可靠,只能靠自己了。

    为了确认问题真的是与document/view支持有关,我试着做了一个没有document/view支持的程序,看看是否能使结果重现。果然,同样的问题果然出现了。

    要找出问题究竟出在哪里,我就得把这些东西和自己掌握的东西联系到一起。

    看过《深入浅出MFC》之后,我觉得MFC程序的运转流程对我来说,不再是什么神奇的东西,那几个基本的虚函数在哪调用,我心里也大概有个数。这个程序中,真正把新代码加入到MFC整个的框架中的,只是那个OnCreateClient。不过,这个包含所有切分窗口动作的OnCreateClient究竟是哪里调用,我还不清楚(《深入浅出MFC》中没介绍)。这好办,祭起debug法宝,单步走一遍。

    在OnCreateClient里面设下断点,一步一步走下去,最终发现它在CMainFrame的OnCreate中出来。在OnCreate开篇有这么一句。
      if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
        return -1;

    OnCreateClient就是在这个CFrameWnd::OnCreate()中调用的。现在函数的执行位置定下来,我就可以把它很好同我掌握的东西联系起来了。

    另外的线索是document/view支持的区别。

    想想,有没有document/view支持的程序有什么区别;想想,《深入浅出MFC》中怎么讲的。结果呢?什么也没想出来。掌握得不是非常扎实的东西,一到用的时候,肯定是有问题。天啊!

    结局

    只有瞎猜了!

    又运行了几遍有问题的程序,突然注意到工具条正常显示出来(原来也一样,只是没有太注意),于是,突然想起,会不会和工具条初始化有关(标准的瞎猜!)?工具条的初始化是在CMainFrame的OnCreate中,哎?刚好是和CFrameWnd::OnCreate()在同一个函数中。根据程序代码显示,工具条的初始化是在CFrameWnd::OnCreate()后面完成的。会不会是CFrameWnd::OnCreate()先进行了,而导致程序出的问题啊?

    我实在不愿意这么想,因为这里的代码是利用MFC AppWizard自动生成的,也就是说,如果确实有问题的话,那就是VC自动生成代码的错。不过,不这么想也不成,实在是走投无路了。没办法,瞎猫只能试着找下死耗子了。我把CFrameWnd::OnCreate()那句剪切到这个函数的最后,return 0之前。

    编译、运行、祈祷……

    OK!问题搞定了。

    我感觉天空一下子亮了起来(虽然当时是晚上)。多美妙的感觉啊!我相信,就是这种感觉使得许多人为了编程如痴如狂,我就是其中一个。^_^

    尾声

    把问题的解决办法告诉给那位同学,他很高兴的说了许多让我也高兴的马屁话,最后一句是,有document/view支持就可以啊?我不知道啊,早知道我就用有document/view

    我晕……

    分享到:

    历史上的今天:

    Hello, Modernizr 2011-06-18
    苍天作弄 2008-06-18
    引用地址: