MFC CScrollView中的设备坐标和逻辑坐标转换

来源:互联网 发布:tensorflow 语义分析 编辑:程序博客网 时间:2024/06/11 02:20
CView派生类的说明
  • CEdit View 实现像便签多行正文编辑器的视图
  • CFormView 使用对话框控件模板资源来定义用户应用程序接口的滚动视图
  • CListView 支持重点在列表控件的文档/视图结构的视图
  • CRecordView 显示对话框控件中的数据库记录的视图
  • CRichEditView 支持重点在金莲能编辑控件的文档/视图结构的视图
  • CScrollView 提供支持自动化滚动的视图
  • CTreeView 支持重点在树控件的文档/视力结构的视图

这些增强的视类,都可以作为应用程序视图类的基类。

例如用CScrollView作为应用程序视图类的基类,那么在Class View窗口中就会看到,应用程序视图类中含有一个成员函数
OnInitialUpdate.它是一个虚函数.它在生成视图对象且与文档结合时,被程序框架调用一次,因此这是初始化滚动条参数的地方.
其原型为:
void SetScrollSizes(int nMapMode, SIZE sizeTotal, const SIZE& sizePage = sizeDefault, const SIZE& sizeLine = sizeDefault)(    int nMapMode, //映射模式,一般为MM_TEXT     SIZE sizeTotal, //文档尺寸    const SIZE& sizePage=sizeDefault, //每滚动一页的尺寸    const SIZE& sizeLine=sizeDefault); //每滚动一行的尺寸
在6_3的基础上
void CRVView::OnInitialUpdate(){CScrollView::OnInitialUpdate();// TODO: remove this code when final selection model code is writtenm_bLeftDown=0;m_pSelection = NULL;    // initialize selectionm_bActive=1;CSize sizeTotal;// TODO: calculate the total size of this viewCSize size = GetDocument()->GetSize();CClientDC dc(NULL);size.cx = MulDiv(size.cx, dc.GetDeviceCaps(LOGPIXELSX), 100);size.cy = MulDiv(size.cy, dc.GetDeviceCaps(LOGPIXELSY), 100);int a=size.cx;int b=size.cy;SetScrollSizes(MM_TEXT, size);//size设置滚动式图总的尺寸m_View=this;}
如果按上面的方法编写处理滚动条的代码,还是会出现一些问题的.因为使用滚动条后,窗口已经向右发生移动,从而使文档的坐标原点与视图的原点实际已不再重合了.但是由于视图类不能对此变化进行自动修正.

解决方法:在绘图时就需要把视图的坐标转换为文档的坐标,而在显示文档数据时则需把文档的坐标再转换为视类的坐标,可以用DC类的成员函数DPtoLPLPtoDP
void DPtoLP( LPPOINT lpPoints, int nCount = 1 ) const;void DPtoLP( LPRECT lpRect ) const;void DPtoLP( LPSIZE lpSize ) const;//和void LPtoDP( LPPOINT lpPoints, int nCount = 1 ) const;void LPtoDP( LPRECT lpRect ) const;void LPtoDP( LPSIZE lpSize ) const;
其中函数DPtoLP能把设备坐标(视图坐标)转换为逻辑坐标(文档坐标)
而LPtoDP则相反
把6_4的OnLButtoDown()和OnUpdate()的代码做如下修改. 
void CMy6_4View::OnLButtonDown(UINT nFlags, CPoint point) {// TODO: Add your message handler code here and/or call default    CClientDC dc(this); //获得视图的DC    OnPrepareDC(& dc); //这是一个和坐标映射相关的函数    dc.DPtoLP(& point); //在绘图之前把鼠标位置传票转换为逻辑坐标.    pObj->DoOut(point);    //绘图函数};

windows对所有的消息(如WM_SIZE,WM_MOUSEMOVE,WM_LBUTTONDOWNWM_LBUTTONUP,所有的非GDI函数和少数GDI函数(如GetDeviceCaps函数)和SetViewportExtExSetViewportOrgExGetMessageGetCursorPosGetWindowRectWindowFromPointSetBrushOrg、InvalidateRect永远使用设备坐标。对大部分的GDI函数(如Ellipse,Rectangle等)、SetWindowExtEx使用逻辑坐标
void CRVView::InvalObj(CDrawObj *pObj){CRect rect = pObj->m_position;DocToClient(rect);if (m_bActive && IsSelected(pObj)){rect.left -= 4;rect.top -= 5;rect.right += 5;rect.bottom += 4;}rect.InflateRect(1, 1); // handles CDrawOleObj objectsInvalidateRect(rect, FALSE);}

0 0
原创粉丝点击