精华区 [关闭][返回]

当前位置:网易精华区>>讨论区精华>>编程开发>>C/C++>>WINDOWS界面设计>>MFC的窗口管理客户区的方法(2)

主题:MFC的窗口管理客户区的方法(2)
发信人: girlrong()
整理人: supermario(1999-11-18 07:37:04), 站内信件

                        ID的分配

    可以看到,每个子窗口都有个id,同一个父窗口的子窗口的id不能重复。mf
c的一些现成的控件子窗口都有预定义的id:

     id名                id值      意义

AFX_IDW_TOOLBAR         0xE800  // 主窗口的工具栏的id
AFX_IDW_STATUS_BAR      0xE801  // 状态栏的id
AFX_IDW_PREVIEW_BAR     0xE802  // PrintPreview Dialog Bar
AFX_IDW_RESIZE_BAR      0xE803  // OLE in-place resize bar
AFX_IDW_REBAR           0xE804  // COMCTL32 "rebar" Bar
AFX_IDW_DIALOGBAR       0xE805  // CDialogBar

还有象单文档程序的视图窗口,多文档程序的那个MDIClient窗口,分隔条窗口,
他们的id值介于下面两个id值之间:

AFX_IDW_PANE_FIRST      0xE900  //
AFX_IDW_PANE_LAST       0xE9FF


    你要给你自己的子窗口分配id的话,别和上面的重复了。一般如果用IDE的菜
单view/resource symbols项来加入自己的id的话,是不会重复的。有关id,还可
以看看msdn里的TN020文章,那是专讲id的。



                        实例分析

1。CFrameWnd类是如何调用RepositionBars函数的
    前面介绍了RepositionBars的各个参数和意义,现在看看CFrameWnd类是如何
调用这个函数的,从中可以学习RepositionBars函数的使用方法。
    CFrameWnd类及其派生类生成的窗口的客户区内可以有工具栏,状态条和视图
窗口等子窗口。当父窗口的尺寸发生变化时,这些子窗口的各自的位置和大小比
例关系保持不变,这就需要父窗口一旦在它自己的尺寸发生变化时就调用Reposi
tionBars函数。CFrameWnd类是集中在函数RecalcLayout里调用RepositionBars函
数的。该类保证了在窗口尺寸发生变化时函数RecalcLayout都被调用,从而Repo
sitionBars函数也能被及时调用,确保了各个子窗口都能及时调整自己的位置和
大小。
    RecalcLayout是个虚函数。该函数的功能就是在主框架的客户区内提供一个
初始的可用区域,并把这个区域放在一个CRect类型的变量里。该函数大致是这样
的:
void CFrameWnd::RecalcLayout(BOOL bNotify)
{
    if (m_bInRecalcLayout)
         return;//这大概是在防止该函数重入
    m_bInRecalcLayout = TRUE;
....
....
....
....
    if (GetStyle() & FWS_SNAPTOBARS)
    {
        CRect rect(0, 0, 32767, 32767);
        RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposQuery,
              &rect, &rect, FALSE);
        RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposExtra,
              &m_rectBorder, &rect, TRUE);
        CalcWindowRect(&rect);
        SetWindowPos(NULL, 0, 0, rect.Width(), rect.Height(),
            SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER);
    }
    else
        RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposExtra, &m_r
ectBorder);
    m_bInRecalcLayout = FALSE;
}
    可以看出,mfc认为这个函数是不能重入的。在编制自己的RecalcLayout()函
数时也得用同样的方法来防止重入。
    后面的if语句检查框架窗口是否具有风格FWS_SNAPTOBARS,这个风格用在什
么时候呢?我是这样认为的:通常都是在主框架窗口的尺寸改变时,子窗口在响
应WM_SIZEPARENT消息时调整自己的尺寸以便跟上框架窗口的尺寸变化。有这样的
情况:父窗口的客户区内的子窗口的数目是动态变化的,而且这些子窗口互相不
能重叠,他们的尺寸由于某种原因不好改变。那么当子窗口的数目发生增减时,
如不调整父窗口自己的尺寸,就会导致客户区留下空白或新增加的子窗口没有多
余空间安排。FWS_SNAPTOBARS风格就是用在这种情况下,使父窗口能调整自己的
大小以便容纳子窗口。看这个分支里的语句,似乎是这样的。
    一般都不会有FWS_SNAPTOBARS风格的,所以一般是执行else分支。在这个分
支里简单地调用RepositionBars去重排所有的子窗口,它的参数lpRectClient 使
用默认的NULL值,意思就是初始可用区域是父窗口的整个客户区。
    可以在自己的派生类里编写自己的RecalcLayout函数,以便用自己的方法调
用RepositionBars函数。要注意的是在CFrameWnd类的窗口刚被创建时RecalcLay
out函数也被调用,此时可能某些用户自己加的子窗口还未被创建出来,所以在这
个函数内如果要引用某个用户自己加的子窗口的句柄的话必须先用::IsWindow()
函数判断一下该窗口句柄是否可用。否则的话就会出现非法操作了。


                        实战演练
    
    由于精力有限,只提供一个实战例子:将视图,工具栏和状态栏赶到右边
    我们要生成这样的界面:视图窗口,工具栏和状态条统统在右边,左边是个
自己加的窗口。

第一步:启动AppWizard生成一个单文档程序,全部使用默认设置。
第二步:在CMainFrame类里增加一个成员 CWnd m_mywnd。
第三步:在CMainFrame::OnCreate()函数里增加这几行:
    m_mywnd.CreateEx
    (
        WS_EX_CLIENTEDGE,
        AfxRegisterWndClass
       (
            CS_HREDRAW|CS_VREDRAW,
            ::LoadCursor(NULL,IDC_ARROW),
            ::CreateSolidBrush(RGB(190,190,190))
        ),
       "",
       WS_VISIBLE|WS_CHILD,
       CRect(0,0,0,0),
       this,
       IDC_MYPANE //用IDE的菜单view/resource symbols项加入的id。
    );
第四步:启动ClassView,在CMainFrame里加上虚函数RecalcLayout(),函数体这
样写:

void CMainFrame::RecalcLayout(BOOL bNotify)
{
    if (m_bInRecalcLayout)
        return;
    m_bInRecalcLayout = TRUE;

    //rect1是新加的窗口将占据的区域
    //rect2就是提供给工具栏,状态条和视图窗口的初始可用区域。
    CRect rect1,rect2;
    GetClientRect(&rect1);
    rect1.right=rect1.right/3;
    GetClientRect(&rect2);
    rect2.left=rect2.right/3;

    if(::IsWindow(m_mywnd.m_hWnd)) //这句是不能少的
        m_mywnd.MoveWindow(&rect1);
    RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposExtra, CRect(0,
0,0,0),&rect2);
    m_bInRecalcLayout = FALSE;
}

第五步:用IDE的菜单view/resource symbols项加入一个id:IDC_MYPANE。
第六步:编译并运行程序。

    好了,在主框架窗口的左边多了一个灰色的窗口,它占主窗口客户区的三分
之一。工具栏,状态条和视图都被赶到右边三分之二的地方去了。

--
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.103.243.56]

[关闭][返回]