给视图添加控件

本文介绍了如何在MFC的视图类CScrollView中添加控件,特别是在对话框和SDI程序中。通过创建CScrollView的派生类并处理WM_PAINT和WM_SIZE消息,实现滚动条的自动管理。详细步骤包括创建视图对象、在OnInitDialog中初始化、处理WM_SIZE消息以调整视图大小,以及在SDI程序中添加视图到对话框的方法。
摘要由CSDN通过智能技术生成

在MFC中,CView及其派生类将显示及其相关的操作做的很好,比如在程序中
如果我们的视图类继承CScrollView了那么我们不用写任何代码该视图就能够
具有滚动的响应机制,能够自动根据设置的滚动范围和窗口实际大小确定是
否显示滚动条(水平或者竖直的),CEditViewCRichEditView等也提供了
相应的在不同实用范围内的一些基本操作处理。

    通常在程序中,我们需要处理并且显示一些数据,将显示部分如果放到视图中
的话,我们将可以忽略大部分的窗口交互的细节,将注意力关注在数据的显示
上。

    本文是在处理如下的情况中提出的:在数据采集和分析的时候,常常需要观看很
多的数据。我们不可能在程序的主界面上显示。我们需要一个弹出窗口来显示,
可以随时的关闭之,也就是说这样的窗口应该动态的生成,数量不定(这样限制
了我们使用切分视图的选择)。对于这些弹出窗口,我们可以自己写一个CWnd
派生类,自然这是完全可以的,但是这样要求你可能处理滚动等等的一些列消息(我
曾经在一个显示图像灰度直方图、以及二值图像投影等中遇到过要求这样显示的
情况,当时就是自己从CWnd派生了一个类来显示数据,由于图像比较大,一屏显
示不完整,所以要给窗口加滚动条,这样在处理这些消息上花费了我大量的时间,
而真正显示数据的代码却很少)。因此我也在一直想使用MFC已经封装的非常好的
CView类及其派生类来显示数据。由于我主要用到的就是CScrollView,因此我也
以它为列来讲述怎么用视图。


基于对话框和SDI结构的实现上有不同细节, 必须分开了说:

 
1、如果你的程序是一个基于对话框的程序的话(指的是如利用MFC向导生成的对话
框程序之类),那么事情就很简单:
   首先,很自然的在Insert/New Class中插入一个类,选择CScrollView做基类
假设你自己的视图类命名为CMyScrollView。
   在对话框(不论是主界面的对话框还是新弹出的对话框,都一样)的OnInitDialog
中加上如下的代码:
    
 CRect rectWndClient;
 GetClientRect(&rectWndClient);

 CRuntimeClass *pViewRuntimeClass=RUNTIME_CLASS(CMyScrollView);

 CMyScrollView *pView=(CMyScrollView*)pViewRuntimeClass->CreateObject();
 pView->Create(NULL,NULL,WS_VISIBLE|WS_CHILD,
                          rectWndClient,
                           this,123,NULL);
  pView->OnInitialUpdate();
    
    说明:
          1)、由于CView及其派生类的构造函数是保护成员,所以采用RuntimeClass方式来构造
      对对象, 
          2)、在Create函数中第一个参数必须有WS_CHILD属性,表明视图是一个子窗口
          3)、第四个参数rectWndClient可以视情况,改变,因为你可能只想在对话框的某个区域
      创建视图。
          4)、第五个参数表明把对话框作为视图的父窗口。
          5)、第六个参数是视图的ID可以任意指定一个整数
      
      在创建之后,如果不掉用OnInitialUpdate的话会有错误,这是因为CScrollView类有个保护成员
     m_nMapMode,它在CScrollView的构造函数中被置为 0,如下
     m_nMapMode = MM_NONE;//在VIEWSCRL.CPP的115行,MM_NONE是宏, 定义为0
     
     下面是错误的分析原因:
      通常窗口是在响应WM_PAINT的时候绘制客户区。所有的视图都派生自CView,他们的的WM_PAINT响应函数如下
           
   void CView::OnPaint() //在VIEWCORE.CPP 176行
  {
   // standard paint routine
   CPaintDC dc(this);
   OnPrepareDC(&dc);
   OnDraw(&dc);
  }
  
       可见,在绘图之前虚函数OnPrepareDC会被调用,在CScroolView中重写了这个虚函数,这个虚函数的
       开头部分如下
       
       ASSERT_VALID(pDC);
       
       #ifdef _DEBUG
   if (m_nMapMode == MM_NONE)
   {
    TRACE0("Error: must call SetScrollSizes() or SetScaleToFitSize()");
    TRACE0(" before painting scroll view. ");
    ASSERT(FALSE);
    return;
   }
   #endif //_DEBUG
   
   可见如果m_nMapMode是0(在构造函数中被默认置为0)的话将在调试程序的时候错误
   所以通常应该在调用OnInitialUpdate的时候(注意:OnInitialUpdate被声明为CView的public成员函数,但是用MFC向导产生自己派生类的OnInitialUpdate函数的时候被声明成了protect,你可以将它改成public,然后调用OnInitialUpdate来初始化自己的视图,或者在构造函数中设置m_nMapMode为自己想要的映射模式)初始化一些东西,并且设置m_nMapMode的正确值,m_nMapMode的一个典型值就是 MM_TEXT(关于映射模式可以看有关文章或者书详细介绍)。
   
   
   上面讲述了如何在对话框中创建视图和相关函数调用的原因。 有一点要讲的是如果你的对话框加上了
   最大化按钮的话,你可能想要在最大话对话框的时候让视图也跟着变化,所以你要处理对话框的
   WM_SIZE消息。在其中你依据当前对话框的实际大小来调整视图大小。这样你就需要视图的指针
   因此你可能的程序应该是这样的
   
   // 在对话框头文件中,声明一个指向你的视图的指针
   CMyScrollView     * m_pView;
   // 在构造函数中将指针赋值NULL
   m_pView = NULL;
        
  //在OnInitDialog创建视图
        
 CRect rectWndClient;
  GetClientRect(&rectWndClient);
 
  CRuntimeClass *pViewRuntimeClass=RUNTIME_CLASS(CMyScrollView);
 
  m_pView=(CMyScrollView*)pViewRuntimeClass->CreateObject();
  m_pView->Create(NULL,NULL,WS_VISIBLE|WS_CHILD,
                               rectWndClient,
                               this,123,NULL);
  m_pView->OnInitialUpdat();
  // 在OnSize中改变视图大小
 if  (m_pView) //注意在第一次调用OnSi

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值