文章目录
- 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);}
}
通过控件属性实现窗口布局管理
点击相应控件的属性,对其进行动态布局的设置,选择两者,窗口再次进行拉伸就会进行改变。
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 popupsLPCTSTR lpszMenuName = NULL,DWORD dwExStyle = 0,CCreateContext* pContext = NULL);
// 加载框架 - load frame and associated resourcesvirtual BOOL LoadFrame(UINT nIDResource,DWORD dwDefaultStyle = WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE,CWnd* pParentWnd = NULL,CCreateContext* pContext = NULL);// 创建中央视图 helper for view creationCWnd* CreateView(CCreateContext* pContext, UINT nID = AFX_IDW_PANE_FIRST);// 第十三章文档架构时获取激活文档virtual CDocument* GetActiveDocument();
//多文档架构获取激活视图 Active child view maintenanceCView* GetActiveView() const; // active view or NULLvoid 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 barvirtual void GetMessageString(UINT nID, CString& rMessage) const;BOOL m_bAutoMenuEnable;// TRUE => menu items without handlers will be disabledBOOL IsTracking();
// Operationsvirtual 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 stylevirtual void SetMenuBarVisibility(DWORD dwStyle);virtual DWORD GetMenuBarVisibility() const;// set/get menu bar visibility statevirtual 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; //临时对象生命周期不够需要加staticmenu.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-stringVERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));// attempt to create the windowLPCTSTR 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 handleASSERT(m_hWnd != NULL);m_hMenuDefault = m_dwMenuBarState == AFX_MBS_VISIBLE ? ::GetMenu(m_hWnd) : m_hMenu;// load accelerator resourceLoadAccelTable(ATL_MAKEINTRESOURCE(nIDResource));if (pContext == NULL) // send initial updateSendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE);return TRUE;
}