MFC第二十八天 WM_SIZE应用,CFrameWnd类LoadFrame的方法,PreCreateWindow窗口预处理,Frame-view窗口视图

文章目录

  • WM_SIZE应用
    • 通过WM_SIZE消息实现窗口布局管理
    • 通过控件属性实现窗口布局管理
  • CFrameWnd类
    • CFrameWnd类简介
    • OnCreate和OnCreateClient的方法
    • 注册时的要素与窗口设置
    • PreCreateWindow创建窗口的预处理函数
  • 附录
    • 预处理函数的结构体
    • CFrameWnd::LoadFrame与CreateFrame

WM_SIZE应用

通过WM_SIZE消息实现窗口布局管理

// CApp 消息处理程序
BOOL CAboutDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();
	CRect rect, rc;
	GetClientRect(rect);
	m_ok.GetWindowRect(rc); //这个取得屏幕 全屏的坐标
	ScreenToClient(rc); // 转化为同一坐标系
	m_cxMargin = rect.right - rc.right;
	m_cyMargin = rect.bottom - rc.bottom;
	
	return TRUE;  
}
void CAboutDlg::OnSize(UINT nType, int cx, int cy)
{
	CDialogEx::OnSize(nType, cx, cy);
	
	if (m_ok)
	{
		CRect rect;
		m_ok.GetWindowRect(rect);
		int x = cx - m_cxMargin - rect.Width();
		int y = cy - m_cyMargin - rect.Height();
		m_ok.SetWindowPos(NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
	}
}

通过控件属性实现窗口布局管理

点击相应控件的属性,对其进行动态布局的设置,选择两者,窗口再次进行拉伸就会进行改变。

MFC第二十八天 WM_SIZE应用,CFrameWnd类LoadFrame的方法,PreCreateWindow窗口预处理,Frame-view窗口视图_第1张图片

CFrameWnd类

CFrameWnd类简介

a)CFrameWnd类偏爱WM_CREATE,因为所有的内部窗口都是代码创建的。
而不像对话框是拖入的。
b)CFrameWnd::rectDefault管理层叠
static const CRect rectDefault;
c)LoadFrame内部包含CreateFrame,同时执行注册以及加载快捷键等(参见附录)

class CFrameWnd : public CWnd
{
	DECLARE_DYNCREATE(CFrameWnd)

// Constructors
public:
	static AFX_DATA const CRect rectDefault;
	CFrameWnd();

	BOOL LoadAccelTable(LPCTSTR lpszResourceName);
//创建框架
	virtual BOOL Create(LPCTSTR lpszClassName,
				LPCTSTR lpszWindowName,
				DWORD dwStyle = WS_OVERLAPPEDWINDOW,
				const RECT& rect = rectDefault,
				CWnd* pParentWnd = NULL,        // != NULL for popups
				LPCTSTR lpszMenuName = NULL,
				DWORD dwExStyle = 0,
				CCreateContext* pContext = NULL);
// 加载框架 - load frame and associated resources
	virtual BOOL LoadFrame(UINT nIDResource,
				DWORD dwDefaultStyle = WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE,
				CWnd* pParentWnd = NULL,
				CCreateContext* pContext = NULL);

// 创建中央视图 helper for view creation
	CWnd* CreateView(CCreateContext* pContext, UINT nID = AFX_IDW_PANE_FIRST);

// 第十三章文档架构时获取激活文档
	virtual CDocument* GetActiveDocument();
//多文档架构获取激活视图 Active child view maintenance
	CView* GetActiveView() const;           // active view or NULL
	void SetActiveView(CView* pViewNew, BOOL bNotify = TRUE);
		// active view or NULL, bNotify == FALSE if focus should not be set

	// 多文档架构的让某个子框架激活,Active frame (for frames within frames -- MDI)
	virtual CFrameWnd* GetActiveFrame();

	// For customizing the default messages on the status bar
	virtual void GetMessageString(UINT nID, CString& rMessage) const;

	BOOL m_bAutoMenuEnable;
		// TRUE => menu items without handlers will be disabled

	BOOL IsTracking();
// Operations
	virtual void RecalcLayout(BOOL bNotify = TRUE); //核心排版
	virtual void ActivateFrame(int nCmdShow = -1);
	void InitialUpdateFrame(CDocument* pDoc, BOOL bMakeVisible);
	void SetTitle(LPCTSTR lpszTitle);
	CString GetTitle() const;
	
	virtual UINT GetTrackingID() { return m_nIDTracking; }
	// set/get menu bar visibility style
	virtual void SetMenuBarVisibility(DWORD dwStyle);
	virtual DWORD GetMenuBarVisibility() const;
	// set/get menu bar visibility state
	virtual BOOL SetMenuBarState(DWORD dwState);
	virtual DWORD GetMenuBarState() const;
	BOOL GetMenuBarInfo(LONG idObject, LONG idItem, PMENUBARINFO pmbi) const;
protected:
	virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext);

	friend class CWinApp;
};

OnCreate和OnCreateClient的方法

为啥对话框CDialog类不偏爱WM_CREATE消息?
a)对话框类使用WM_INITDIALOG消息或者虚函数来初始化;
b)WM_CREATE消息对于对话框也是有效的,为什么对话框很少用这 个消息呢?
c)对话框程序需要初始化控件,WM_CREATE是主窗口刚刚创建好,控件还没有。
d)所以它偏爱OnInitDialog虚函数,控件都被创建好之后方便初始化那些控件。

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
		return -1;

	static CMenu menu;  //临时对象生命周期不够需要加static
	menu.LoadMenu(IDR_MAINFRAME);
	SetMenu(&menu);

	CCreateContext cc;
	cc.m_pNewViewClass = RUNTIME_CLASS(CMainView);
	CreateView(&cc);
}
#include "CTestBtn.h"
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) 
//创建客户区的主区视图
{
	CCreateContext cc;
//	cc.m_pNewViewClass = RUNTIME_CLASS(CTestBtn);
	cc.m_pNewViewClass = RUNTIME_CLASS(CMainView);
	m_pMainView = (CMainView*)CreateView(&cc, AFX_IDW_PANE_FIRST);
	 //AFX_IDW_PANE_FIRST在中间区域自动缩放
	return m_pMainView!=NULL;
}
int CTestBtn::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CButton::OnCreate(lpCreateStruct) == -1)
		return -1;

	SetWindowText(_T("按钮?"));
	return 0;
}

BOOL CTestBtn::PreCreateWindow(CREATESTRUCT& cs)  //视图就是CreateView
{
	cs.lpszClass = _T("BUTTON");

	return CButton::PreCreateWindow(cs);
}

注册时的要素与窗口设置

a)例如:注册时你指定灰色背景,窗口生成后可以在WM_ERASEBKGND消息中改成别的颜色。
b)其他包括图标(SetIcon),光标WM_SETCURSOR消息中改,以及菜单(SetMenu)。
c)例如:但凡Create一个Edit注册时的要素都会默认呈现,比如光标的形状,背景是白色。
d)但是后面都是可以改的,比如你想把某个edit改为绿底红字的。(WM_CTLCOLOR)

BOOL CMainFrame::OnEraseBkgnd(CDC* pDC)
{  
	CRect rect;
	GetClientRect(rect);
	pDC->FillSolidRect(rect, 0xffee00); //可指定其他的颜色 注册可以该 默认的实施  按照注册来实施
	
	return TRUE;
	//你注册的灰色是由return CFrameWnd::OnEraseBkgnd(pDC);来实施的
	//return CFrameWnd::OnEraseBkgnd(pdc)  改为return TRUE 则没有注册的颜色
}

PreCreateWindow创建窗口的预处理函数

创建窗口的预处理函数:virtual BOOL PreCreateWindow(CREATESTRUCT& cs);  

a)预处理核心的一个工作就是注册窗口规格,包括光标,图标以及背景颜色等;
b)预处理函数的结构体中包含,位置、高宽以及菜单,style和dwExStyle
c)为什么LoadFrame中使用注册,而CreateFrame根本没注册都好使?
那就是因为窗口预处理中执行注册,可以说即使从CWnd类派生你只要做预处理就不用RegisterClass

//预处理核心的一个工作就是注册窗口规格,包括光标,图标以及背景颜色等
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs){
	if( !CFrameWnd::PreCreateWindow(cs) )
		return FALSE;
	//  CREATESTRUCT cs 来修改窗口类或样式
	/*cs.x = 100;
	cs.y = 100;
	cs.cx = 200;
	cs.cy = 300;*/ //没有这几行的代码的话 默认是重叠的 有了的话不会重叠
//	cs.style |= WS_THICKFRAME; //拖动大小开关
//	cs.hMenu = ::LoadMenu(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME));
	cs.dwExStyle &= ~WS_EX_CLIENTEDGE;
	cs.lpszClass = AfxRegisterWndClass(0);
	return TRUE;
}

附录

预处理函数的结构体

typedef struct tagCREATESTRUCTW {
    LPVOID      lpCreateParams;
    HINSTANCE   hInstance;
    HMENU       hMenu;
    HWND        hwndParent;
    int         cy;
    int         cx;
    int         y;
    int         x;
    LONG        style;
    LPCWSTR     lpszName;//标题
    LPCWSTR     lpszClass;//类型名
    DWORD       dwExStyle;//扩展风格
} CREATESTRUCTW, *LPCREATESTRUCTW;

CFrameWnd::LoadFrame与CreateFrame

BOOL CFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle,
	CWnd* pParentWnd, CCreateContext* pContext)
{

	CString strFullString;
	if (strFullString.LoadString(nIDResource))
		AfxExtractSubString(m_strTitle, strFullString, 0);    // first sub-string

	VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));

	// attempt to create the window
	LPCTSTR lpszClass = GetIconWndClass(dwDefaultStyle, nIDResource);
	CString strTitle = m_strTitle;
	if (!Create(lpszClass, strTitle, dwDefaultStyle, rectDefault, 
	  pParentWnd, ATL_MAKEINTRESOURCE(nIDResource), 0L, pContext))
	{
		return FALSE;   // will self destruct on failure normally
	}

	// save the default menu handle
	ASSERT(m_hWnd != NULL);
	m_hMenuDefault = m_dwMenuBarState == AFX_MBS_VISIBLE ? ::GetMenu(m_hWnd) : m_hMenu;

	// load accelerator resource
	LoadAccelTable(ATL_MAKEINTRESOURCE(nIDResource));

	if (pContext == NULL)   // send initial update
		SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE);

	return TRUE;
}

你可能感兴趣的:(MFC开发,mfc,c++)