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 written
m_bLeftDown=0;
m_pSelection = NULL; // initialize selection
m_bActive=1;
CSize sizeTotal;
// TODO: calculate the total size of this view
CSize 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类的成员函数
DPtoLP和
LPtoDP
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_LBUTTONDOWN, WM_LBUTTONUP),所有的非GDI函数和少数GDI函数(如GetDeviceCaps函数)和
SetViewportExtEx、SetViewportOrgEx
GetMessage、GetCursorPos、GetWindowRect、WindowFromPoint、SetBrushOrg、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 objects
InvalidateRect(rect, FALSE);
}