在对话框中绘制滚动视窗总结

1.思路的产生

起初是想在一个Dialog内加载一幅图片,而这幅图片又较大,使用Dialog需要手动加滚动条,似乎比较麻烦(没有深入探究,如果大家有较方便的办法,请留言)。而CScrollView是一个自动带滚动条的窗体,于是在Dialog内嵌入一个CScrollView的想法就产生了。

 

2.实现过程。

         关于CScrollViewDialog内的位置,大概有两种办法确定,一种是通过获取CDialog的位置做相对变换。第二种是先在Dialog内用工具箱添加一个静态文本框控件,而这个控件的位置和大小就调整为CScrollView准备放的位置。这样就能通过较直观的方式设置CScrollView的位置了。下面就以第二种方法为例,解析一下重点代码。

 

//CCreateViewDlg 即为放置CScrollView的CDialog类的衍生类

//CMyView为CScrollView的衍生类

BOOL CCreateViewDlg::OnInitDialog()  

{

      CDialog::OnInitDialog();

 

      // TODO: 在此添加额外的初始化

      UINT TargetCtrlID =IDC_STATIC_VIEW;    //这个控件ID就是静态文本框的ID

      CWnd *pWnd = this->GetDlgItem(IDC_STATIC_VIEW);

      CRect RectTargetCtrl;

      pWnd->GetWindowRect(&RectTargetCtrl);

      this->ScreenToClient(RectTargetCtrl);

      m_pView = (CMyView*)RUNTIME_CLASS(CMyView)->CreateObject();

      m_pView->Create(NULL,NULL,AFX_WS_DEFAULT_VIEW|WS_VSCROLL|WS_HSCROLL,RectTargetCtrl,this,TargetCtrlID);

      m_pView->MyInit();   //对象初始化函数(自定义的)

      return TRUE; // return TRUE unless you set the focus to a control

      //异常: OCX属性页应返回FALSE

}


 

注意:

1.为什么使用m_pView = (CMyView*)RUNTIME_CLASS(CMyView)->CreateObject();

而不是使用new呢,这是因为CScrollView的构造函数是保护类的,不允许直接构造。

 

 

2.为什么我会在上面写一个MyInit()的初始化函数呢?

起初,我不是这样写的,我是将MyInit()里面的初始化内容放到了CMyView类的OnInitUpdate()函数中,结果我发现总是出现各种断言错误。最后发现,系统就根本没有调用OnInitUpdate()函数。结果我就查询了msdn。是这样描述的“Called by the framework after the view is first attached to the document, but before the view is initially displayed.”就是(该函数)在视图第一次绑定到文档后调用的,而不是在初始显示之前(调用)。(个人翻译,如果有错误请留言)。其实msdn说清楚了,Dialog类是不关联文档的,那么在Dialog类上建立的View也就不会关联文档,所以就不会调用OnInitUpdate()。

解决办法有两种:第一种,在Dialog中建立一套框架程序,将View与Doc绑定。

                      第二种,不使用OnInitUpdate()函数,

我就是按照第二种方法做的,个人认为第一种方法太复杂,没有多大用处。有人会问如果不调用在使用View时不调用OnInitUpdate()函数的父类会不会出错,这个问题我也时犹豫不决,毕竟OninitUpdate函数时View的初始化函数。但是目前我按第二种方法是没有问题的。

如此就将CScrollView创建了。

下面为滚动条的处理:

根据msdn对CScollView的描述“You must call either SetScrollSizes orSetScaleToFitSize before the scroll view is usable”。在ScrollView可用之前必须调用SetScrollSizes orSetScaleToFitSize SetScrollSizes()函数作用就是设置视图逻辑尺寸、映射模式、滚动条大小。其实这时SetScollSizes就可以放在之前说明的MyInit()或者是CMyView的构造函数里。

CMyView::CMyView()

{

      

      CSize sizeTotal(6000, 5000);// 20 by 30 cm

      CSize sizePage(sizeTotal.cx / 20, sizeTotal.cy / 20);

      CSize sizeLine(sizeTotal.cx / 500, sizeTotal.cy / 500);

      SetScrollSizes(MM_LOENGLISH, sizeTotal, sizePage, sizeLine);  m_pdcMemory =new CDC;

      m_pBitmap = new CBitmap;

}


此时CScollView对象基本就算创建完成了,可以调试运行了,此时显示的为一个对话框内部有带滚动条的View。如图

这时还有一点瑕疵,当鼠标点击View时,会出现断言错误ASSERT(pParentFrame   ==   pDesktopWnd   ||   pDesktopWnd->IsChild(pParentFrame))

我想这应该也是找不到父框架导致的。于是通过调试发现问题出现在OnMouseActivate相应函数中。

原函数

int CMyView::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message)

{

      // TODO:在此添加消息处理程序代码和/或调用默认值

 

      return CScrollView::OnMouseActivate(pDesktopWnd, nHitTest, message);

}


改为

int CMyView::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message)

{

      // TODO:在此添加消息处理程序代码和/或调用默认值

 

      return CWnd::OnMouseActivate(pDesktopWnd, nHitTest, message);

}


问题解决。

接下来也算个验证,就是在ScrollView内填充了一幅图。

关键代码:

void CMyView::MyInit(void)

{

      BITMAP bm;

      if (m_pdcMemory->GetSafeHdc() == NULL)

      {

           CClientDC dc(this);

           OnPrepareDC(&dc);// necessary

           m_pBitmap->LoadBitmap(IDB_BITMAP1);

           m_pdcMemory->CreateCompatibleDC(&dc);

           m_pdcMemory->SelectObject(m_pBitmap);

           m_pBitmap->GetObject(sizeof(bm), &bm);

           m_sizeSource.cx = bm.bmWidth;

           m_sizeSource.cy = bm.bmHeight;

           m_sizeDest = m_sizeSource;

           dc.DPtoLP(&m_sizeDest);

      }

}

 

void CMyView::OnDraw(CDC* pDC)

{

 

      CDocument* pDoc = GetDocument();

      // TODO:在此添加绘制代码

      pDC->SetStretchBltMode(COLORONCOLOR);

      if(m_pdcMemory->GetSafeHdc() == NULL)

      {

           return ;

      }

      pDC->StretchBlt(0, -0, m_sizeSource.cx, -m_sizeSource.cy,

                      m_pdcMemory, 0, 0,

                      m_sizeSource.cx, m_sizeSource.cy, SRCCOPY);

}


 

结果

 

到此结束.

源码下载http://dl.dbank.com/c0x1xa09dh

(网盘)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值