MFC基础知识(一)——文档视图类指针获取、逻辑与设备坐标以及OnDraw

本文主要介绍:MFC中一些基础知识,包括文档类Doc和视图类View指针的获取,逻辑坐标与设备坐标及其转化和OnDraw函数。

一、获取Doc类和View类指针:

1.添加头文件:

#include "MainFrm.h"
#include "C***Doc.h" //Doc类头文件要放在View类头文件前面
#include "C***View.h"

2.单文档中获取:

CMainFrame*   pFrame=(CMainFrame*)AfxGetMainWnd();   
C***Doc *pDoc = (C***Doc*)pFrame->GetActiveDocument(); //获取文档类
C***View* pView = (C***View*)pFrame->GetActiveView(); //获取视图类
//或
CMainFrame*  pFrame=(CMaimFrame*)AfxGetApp()->m_pMainWnd;  
C***Doc *pDoc = (C***Doc*)pFrame->GetActiveDocument(); //获取文档类
C***View* pView = (C***View*)pFrame->GetActiveView(); //获取视图类<pre name="code" class="cpp">

 3.多问档中获取: 
 

//获得文档类指针
 CMDIFrameWnd *pFrame = (CMDIFrameWnd*)AfxGetApp()->m_pMainWnd;
 CMDIChildWnd *pChild = CMDIChildWnd *)pFrame->GetActiveFrame();
 C***Doc *pDoc = (C***Doc *)pChild->GetActiveDocument();
 
 //或
 C***Doc* pDoc = (C***Doc*)((CMainFrame *)AfxGetMainWnd())->GetActiveFrame()->GetActiveDocument();
 
 //获取视图类指针
 CMDIFrameWnd *pFrame = (CMDIFrameWnd*)AfxGetApp()->m_pMainWnd;
 CMDIChildWnd *pChild = CMDIChildWnd *)pFrame->GetActiveFrame();
 C***View *pView = (C***View*)pChild->GetActiveView();
 
 //或
 C***View* pView = (C***View*)((CMainFrame *)AfxGetMainWnd())->GetActiveFrame()->GetActiveView(); 
注:在View类中,可以直接回去Doc类: C***Doc *pDoc = GetDocument();

二、设备坐标与逻辑坐标及其转化

1.逻辑坐标与设备坐标的区别:

如果MFC没有滚动条的话,两者是相等的,当视图类为CScrollView,滚动条有偏移时,两者不等:

设备坐标:即是屏幕坐标,左上角为(0,0),消息函数OnLButtonDown(UINT nFlags, CPoint point)和OnMouseMove(UINT nFlags, CPoint point)函数中的point指的都是设备坐标,无论滚动条偏移与否,左上角都是(0,0)。

逻辑坐标:即独立于设备,与设备大小无关,它原点坐标(0,0)是文档的起点,当滚动条下拉时,文档会下移,逻辑坐标的原点(0,0)会随着文档起点而上移。

所以逻辑坐标(LPoint)与设备坐标(DPoint)有以下关系:

假设:滚动条当前滑动位置为:ScollPoint,则:

LPoint.x = DPoint.x + ScollPoint.x;

LPoint.y = DPoint.y + ScollPoint.y;

即:逻辑坐标 = 设备坐标 + 滚动条位置坐标。

2.逻辑坐标与设备坐标的转化:

<1>MFC中有相应的转化函数:

CDC *pDC = GetDC();
OnPrepareDC(pDC);//该函数属于view类,转化前必须调用该函数,否则不能转化
pDC->DPtoLP(&point); //设备坐标转逻辑坐标,转化的结果仍未point
pDC->LPtoDP(&point); //逻辑坐标转设备坐标,转化的结果仍未point
ReleaseDC(pDC);
<2>获取滚动条位置转化:

获取滚动条位置坐标,然后按照上式转化:

//重载两个与滑动条有关的函数
BOOL CRoadExtractionSysView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) 
{
	// TODO: Add your message handler code here and/or call default
	ScrollPos = GetScrollPosition();	
//	return CScrollView::OnMouseWheel(nFlags, zDelta, pt);
	return 0;
}

BOOL CRoadExtractionSysView::OnScroll(UINT nScrollCode, UINT nPos, BOOL bDoScroll) 
{
	// TODO: Add your specialized code here and/or call the base class	
	ScrollPos = GetScrollPosition();	
	return CScrollView::OnScroll(nScrollCode, nPos, bDoScroll);
}

三、CDC类与CClientDC类绘图参数坐标的不同

CRect ClientRect; 
GetClientRect(&ClientRect); //获取客户区大小
GetClientRect获取的窗口客户区的大小,窗口客户区为窗口中除标题栏、菜单栏之外的地方

CClientDC类是CDC类的派生类, 在调用绘图函数时,它们的参数坐标有所不同:

CDC *pDC = GetDC();
pDC->MoveTo(point); //point坐标要为逻辑坐标

CClientDC dc;
dc.MoveTo(point); //point坐标要为设备坐标

根据逻辑坐标和设备坐标的关系可知:如果没有滚动条或滚动条没有偏移时,逻辑坐标等于设备坐标,它们绘制的图不会有区别,当滚动条有偏移时,同样的point绘制的图将会不同,以MoveTo为例:

                                                   CDC类                                        CClientDC

以逻辑坐标为参考               point点处                                        point + ScollPoint点处

以设备坐标为参考               point - ScollPoint 点处                 point点处

画图时,一般是以当前客户区为参考的,所以CDC类,虽然参数为逻辑坐标,但绘图时自动减去滚动条偏移,所以拖得动滚动条时,所画的图形也会虽滚动条移动而移动;

而CClientDC类,相对于客户区,仍为point,不会随滚动条的移动而移动。

例如:point = (200,200),当滚动条没有偏移时,两类都是MoveTo到(200,200),当前滚动条为 ScollPoint (50,50),CDC类会MoveTo到(150,150),CClientDC类会MoveTo移动到(200,200)。

四、OnDraw函数的触发条件与手动触发

//以下函数不会触发OnDraw函数
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);

拉动滚动条时,会自动调用OnDraw.

//编程触发OnDraw函数
CRect ClientRect; //用Invalidte()刷新屏幕会闪
GetClientRect(&ClientRect);
InvalidateRect(ClientRect);

//或
Invalidte();

//或
UpdateWindow();


你可能感兴趣的:(onDraw,逻辑坐标,设备坐标,文档类,视图类)