本文主要介绍:MFC中一些基础知识,包括文档类Doc和视图类View指针的获取,逻辑坐标与设备坐标及其转化和OnDraw函数。
一、获取Doc类和View类指针:
1.添加头文件:
#include "MainFrm.h" #include "C***Doc.h" //Doc类头文件要放在View类头文件前面 #include "C***View.h"
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坐标要为设备坐标
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函数 CRect ClientRect; //用Invalidte()刷新屏幕会闪 GetClientRect(&ClientRect); InvalidateRect(ClientRect); //或 Invalidte(); //或 UpdateWindow();