这两个函数中的尺寸大小按逻辑单位计算。
SetScaleToFitSize设置视口尺寸为当前的窗口尺寸,这样,在没有滚动条时,逻辑视的内容被放大或者缩小到正好窗口大小。
SetScrollSizes设置窗口的映射模式,窗口尺寸,页和行尺寸。sizeDefualt被定义为(0,0)。
?
下面几个函数用来实现滚动或者得到滚动条相关的信息
void ScrollToPosition(POINT pt); // set upper left position void FillOutsideRect(CDC* pDC, CBrush* pBrush); void ResizeParentToFit(BOOL bShrinkOnly = TRUE);
CPoint GetScrollPosition() const; // upper corner of scrolling CSize GetTotalSize() const; // logical size
?
下面两个函数使用了设备坐标单位
CPoint GetDeviceScrollPosition() const;
void GetDeviceScrollSizes(int& nMapMode, SIZE& sizeTotal, SIZE& sizePage, SIZE& sizeLine) const;
?
覆盖的消息处理函数
处理WM_SIZE的OnSize; 处理WM_HSCROLL的OnHScroll; 处理WM_VSCROLL的OnVScroll;
?
覆盖的虚拟函数
CWnd的CalcWindowRect
CView的OnPrepareDC、OnScroll、OnScrollBy
?
用于DEBUG的Dump和AssertValid
这里,覆盖的消息处理函数和虚拟函数共同完成对滚动条、滚动消息的处理。
在CSrcollView的实现涉及到许多和Windows映射模式、坐标转换等相关的函数的使用。这里,不作具体讨论。
1. CFormView
CFormView派生于CSrcollView,本身没有增加新的函数,但覆盖了一些基类的虚拟函数,增加了几个成员变量(以下列出的不包含OLE处理)。 1. 增加的成员变量
LPCTSTR m_lpszTemplateName; CCreateContext* m_pCreateContext;
HWND m_hWndFocus; // last window to have focus
m_lpszTemplateName用来保存创建视图的对话框模板的名称,
_pCreateContext用来保存创建上下文,m_hWndFocus用来保存最近一次拥有焦点的控制窗口。在构造CFormView对象时,构造函数把有关信息保存到成员变量中,如下所示:
CFormView::CFormView(LPCTSTR lpszTemplateName) {
m_lpszTemplateName = lpszTemplateName; m_pCreateContext = NULL;
m_hWndFocus = NULL; // focus window is font }
2. 覆盖的虚拟函数
virtual void OnDraw(CDC* pDC); // MFC缺省处理空 virtual BOOL Create(LPCTSTR, LPCTSTR, DWORD, const RECT&, CWnd*, UINT, CCreateContext*); virtual BOOL PreTranslateMessage(MSG* pMsg); virtual void OnActivateView(BOOL, CView*, CView*); virtual void OnActivateFrame(UINT, CFrameWnd*);
创建基于对话框的视窗口,不同于创建普通视窗口(前者调用
CWnd::CreateEx,后者调用CWnd::CreateDlg),故需要覆盖Create虚拟函数。
覆盖PreTranslateMessage是为了过滤对话框消息,把一些消息让CFormView对象来处理。 3. 覆盖了两个消息处理函数:
afx_msg int OnCreate(LPCREATESTRUCT lpcs); afx_msg void OnSetFocus(CWnd* pOldWnd);
下面,分析几个函数作。Create函数解释了MFC如何使用一个对话框作为视的方法,PreTranslateMessage显示了CFormView不同于CDialog的实现。
1. CFormView的创建
设计CFormView的创建函数,必须考虑两个问题: 首先,CFormView是一个视,其创建函数必须是一个虚拟函数,原型必须和
CWnd::Create(LPSTR?pContext)函数一致,见图5-13视的创建。其次,CFormView使用了对话框创建函数和对话框“窗口类”来创建视,但必须作一些处理使得该窗口具备视的特征。 Create的实现如下:
BOOL CFormView::Create(LPCTSTR /*lpszClassName*/,
LPCTSTR /*lpszWindowName*/,
DWORD dwRequestedStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) {
ASSERT(pParentWnd != NULL);
ASSERT(m_lpszTemplateName != NULL);
m_pCreateContext = pContext; // save state for later OnCreate #ifdef _DEBUG
// dialog template must exist and be invisible with WS_CHILD set
if
(!_AfxCheckDialogTemplate(m_lpszTemplateName, TRUE)) {
ASSERT(FALSE); // invalid dialog template name PostNcDestroy(); // cleanup if Create fails too soon
return FALSE; }
#endif //_DEBUG
//若common control window类还没有注册,则注册 VERIFY(AfxDeferRegisterClass(AFX_WNDCOMMCTLS_REG));
// call PreCreateWindow to get prefered extended style
CREATESTRUCT cs; memset(&cs, 0, sizeof(CREATESTRUCT)); if (dwRequestedStyle == 0)
dwRequestedStyle = AFX_WS_DEFAULT_VIEW; cs.style = dwRequestedStyle; if (!PreCreateWindow(cs)) return FALSE;
//::CreateDialogIndirect间接被调用来创建一个无模式对话框
if (!CreateDlg(m_lpszTemplateName, pParentWnd)) return FALSE;
//创建对话框时,OnCreate被调用,m_pCreateContext的作用结束了 m_pCreateContext = NULL;
// we use the style from the template - but make sure that
// the WS_BORDER bit is correct
// the WS_BORDER bit will be whatever is in dwRequestedStyle
ModifyStyle(WS_BORDER|WS_CAPTION, cs.style & (WS_BORDER|WS_CAPTION));
ModifyStyleEx(WS_EX_CLIENTEDGE, cs.dwExStyle & WS_EX_CLIENTEDGE); SetDlgCtrlID(nID); CRect rectTemplate;
GetWindowRect(rectTemplate);
SetScrollSizes(MM_TEXT, rectTemplate.Size()); // initialize controls etc
if (!ExecuteDlgInit(m_lpszTemplateName)) return FALSE;
// force the size requested
SetWindowPos(NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,