MFC窗口
- 格式:wps
- 大小:41.50 KB
- 文档页数:12
1.创建MFC对话框工程
2.布置界面
3.创建类。
4.设计类的方法和属性。
5.更改控件ID
6.添加按钮处理函数。
7.编写按钮处理函数。
练习:
实现一个日期计算器程序,基于MFC对话框。
要求;
1.设计一个C++类CDater, 该类实现两个功能:
功能一:计算指定日期是一年中的第几天。
如2011 年1 月31日是2011年的第31天。
功能二:计算某年的某天是几月几日。
如2011年的第32天是2011年2月1日。
2.在对话框中设计两个按钮和若干个编辑框,以及若干静态文本框,要求调用CDater类的函数。
按钮一:把用户输入的年月日转化为第多少天。
按钮二:把用户输入的第多少天转化为几月几日。
MFC(Microsoft Foundation Class)是微软公司开发的用于Windows评台的C++类库,用于简化Windows应用程序的开发。
在MFC中,关闭当前多文档的子窗口可以通过以下步骤实现:1. 获取当前活动的文档视图需要获取到当前处于活动状态的文档视图,可以通过以下代码实现:```cppCWnd* pActiveWnd = AfxGetM本人nWnd(); CMDIChildWnd* pChild = (CMDIChildWnd*)pActiveWnd; CView* pView = pChild->GetActiveView();```2. 关闭子窗口有了当前活动的文档视图之后,可以通过以下代码关闭子窗口:```cpppChild->MDIDestroy();```在这段代码中,`MDIDestroy` 函数用于关闭当前子窗口。
3. 整合关闭子窗口的代码将以上两个步骤整合在一起,完整的代码如下所示:```cppCWnd* pActiveWnd = AfxGetM本人nWnd(); CMDIChildWnd* pChild = (CMDIChildWnd*)pActiveWnd; CView* pView = pChild->GetActiveView();pChild->MDIDestroy();```这样,就可以在MFC中关闭当前多文档的子窗口了。
以上代码基于MFC类库,在多文档程序框架下实现了关闭当前子窗口的功能。
在实际开发中,可以根据具体的需求和程序结构进行适当的修改和扩展。
总结起来,关闭当前多文档的子窗口在MFC中实现并不复杂,通过获取当前活动的文档视图并调用相应的函数即可完成这一操作。
希望本文对MFC开发者能有所帮助。
初步思考:续写部分将围绕MFC中关闭子窗口的方法展开,涉及到MFC开发中更广泛的内容,包括MFC文档视图架构、消息处理机制等。
MFC浮动窗⼝使⽤⽅法和注意事项使⽤VS2008+SP1创建悬浮窗⼝的步骤:1. 创建悬浮窗⼝类每⼀个悬浮窗⼝都是⼀个CDockablePane的派⽣类的对象, 因此要为每⼀个悬浮窗⼝创建⼀个新类1.1 添加类通过菜单Project->Add Class...或者在类视图中⼯程名字处右键选择Add->Class...添加类选择MFC Class, 点Add按钮进⼊下⼀步Class name处写⼊新类的名字, 这⾥⽤CDock, 选择Base class为CDockablePane按Finish按钮, 添加类完成.1.2 添加消息处理函数⼀般⾄少要处理两个消息, ⼀个是WM_CREATE, ⼀个是WM_SIZE, 具体步骤为:(1) 头⽂件中添加函数声明(函数名及参数不可写错)protected:afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);afx_msg void OnSize(UINT nType, int cx, int cy);(2) cpp⽂件中添加消息映射BEGIN_MESSAGE_MAP(CDock, CDockablePane)ON_WM_CREATE()ON_WM_SIZE()END_MESSAGE_MAP()这⾥BEGIN_MESSAGE_MAP和END_MESSAGE_MAP宏都是⾃动⽣成的, 只需要添加中间两⾏代码即可(3) 添加函数实现部分int CDock::OnCreate(LPCREATESTRUCT lpCreateStruct){if (CDockablePane::OnCreate(lpCreateStruct) == -1)return -1;// 在这⼉创建控件return 0;}void CDock::OnSize(UINT nType, int cx, int cy){CDockablePane::OnSize(nType, cx, cy);// 这⼉添加代码}1.3 添加控件现在创建的CDock类中由于没有任何控件, 因此如果现在创建该类的对象并显⽰, 该区域中由于全是垃圾数据, 故可能该窗⼝显⽰时为花屏. 如果程序运⾏期间出现类似花屏的问题, ⼤概会有⼏种可能性: 1. 没有创建控件 2. 已创建控件, 但控件位置不对或未覆盖整个的dockablePane 3. 控件虽然占据整个区域, 但不能⾃动刷新这⾥以添加⼀个listBox为例:(1) 在类的头⽂件中添加控件对象, 代码为:protected:CListBox _listBox;(2) 在OnCreate()中添加创建控件窗⼝的代码:这⾥必须要注意, 需要先调⽤基类的函数OnCreate()int CDock1::OnCreate(LPCREATESTRUCT lpCreateStruct){if (CDockablePane::OnCreate(lpCreateStruct) == -1)return -1;// 在这⼉创建控件// nID为该控件的ID, 可以⾃⾏设置, 如果对ID不感兴趣, 也可以选择传递0让系统做处理if (!_listBox.Create(WS_CHILD | WS_VISIBLE, CRect(0, 0, 0, 0), this, nID)){TRACE0("创建listbox失败");return -1;}return 0;}(3) 在OnSize中设置各个控件的位置这⾥要注意的是, 需要将控件布满整个窗⼝. 这⾥只有⼀个listBox, 故可以直接⽤listBox覆盖窗⼝.同理, 必须要先调⽤基类函数CDockablePane::OnSize(nType, cx, cy)void CDock::OnSize(UINT nType, int cx, int cy){CDockablePane::OnSize(nType, cx, cy);// 这⼉添加代码if (GetSafeHwnd() == NULL){return;}if (_listBox.GetSafeHwnd() != NULL){CRect rectClient;GetClientRect(rectClient);_listBox.SetWindowPos(NULL, rectClient.left, rectClient.top, rectClient.Width(), rectClient.Height(), SWP_NOACTIVATE | SWP_NOZORDER);}}2. 在程序中添加悬浮窗⼝对象上⾯⼀步只是给⼯程添加了⼀个悬浮窗⼝类, 但并没⽣成该类的实例. 这⾥创建该实例(在CMainFrame类中)2.1 在主框架类声明中添加对象, 代码为:protected:CDock m_wndDock;2.2 创建dockablePane的窗⼝, 在主框架的OnCreate()函数中(注: 这⾥我建议在OnCreate函数中⾃动⽣成代码EnableAutoHidePanes(CBRS_ALIGN_ANY)的后⾯添加)int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct){...EnableAutoHidePanes(CBRS_ALIGN_ANY);// 利⽤这⾥的CBRS_RIGHT来设置最初的窗⼝停靠的位置, 可以的取值是// CBRS_NOALIGN, CBRS_LEFT, CBRS_TOP, CBRS_RIGHT, CBRS_BOTTOMDWORD style = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBRS_RIGHT |CBRS_FLOAT_MULTI;if (!wndDock1.Create(// 该dock窗⼝的标题(如果可以有的话...)_T("Dock1"),// 该dock窗⼝的parent, 设置为thisthis,// 窗⼝的⼤⼩, 注意是"悬浮"的情况下的⼤⼩, 处于dock状态时⼤⼩与该值⽆关CRect(0, 0, 200, 200),// 该dock窗⼝是否有标题, 如果为FALSE, 则第⼀个字符串参数显⽰不出来TRUE,// 该dock窗⼝的ID值. 注意: 如果希望dock窗⼝的状态可以保存在注册表中(这样下次启动程序时仍保持该状态), 则该值必须的唯⼀的nID,//style)){return FALSE;}...}2.3去掉CDockablePane的Close按钮?⽅法⼀:在继承CDockablePane的类中重写CanBeClosed()⽅法:virtual BOOL CanBeClosed() const; ... BOOL COutputWnd::CanBeClosed() const { return FALSE;}⽅法⼆:if (!m_wndView.Create(strFileView, this, CRect(0, 0, 250, 200), TRUE, ID_VIEW_VIEW,WS_CHILD | WS_VISIBLE | CBRS_LEFT | CBRS_HIDE_INPLACE | WS_CAPTION, AFX_CBRS_REGULAR_TABS, AFX_CBRS_RESIZE))在Create的时候后⾯加上这样的参数设置AFX_CBRS_REGULAR_TABS, AFX_CBRS_RESIZE 就不会有那个关闭按钮了2.4显⽰隐藏CDockablePanem_wndFileView.ShowPane(TRUE,FALSE,TRUE);//显⽰m_wndFileView.ShowPane(FALSE,FALSE,TRUE);//隐藏2.5 给悬浮窗⼝添加icon, 暂时省略.3. 设置窗⼝悬浮⽅式, 令窗⼝悬浮3.1 设置窗⼝悬浮位置这部分代码也应该在MainFrame类的OnCreate函数中, ⽽且紧跟创建悬浮窗⼝的后⾯.设置悬浮位置只需要调⽤CDockablePane::EnableDocking即可m_wndDock.EnableDocking(CBRS_ALIGN_ANY);其中, 参数可以是CBRS_ALIGN_TOP, CBRS_ALIGN_RIGHT, CBRS_ALIGN_BOTTOM, CBRS_ALIGN_ANY3.2 令窗⼝悬浮欲使⼀个CDockablePane对象悬浮, 只需要调⽤框架类的DockPane函数即可:DockPane(&m_wndDock);但是若有另外⼀个悬浮窗⼝的对象需要和m_wndDock在⼀起显⽰, 构成⼀个组(就像VS的资源视⼒和类视图), 那么第⼆个悬浮窗⼝需要使⽤CDockablePane类的AttchToTabWnd函数, 代码如下:DockPane(&m_wndDock);CDockablePane *pTabbedBar = NULL;m_wndDock2.AttachToTabWnd(&m_wndDock, DM_SHOW, FALSE, &pTabbedBar);CDockablePane 使⽤这个是转载的int m_nshowCurrent;m_nshowCurrent=theApp.GetProfileInt(_T("Workspace//Pane-377"),_T("IsFloating"),0); //在构造函数中⾸先派⽣两个⼦类,源码就不⽤写出来了,占篇幅,在MainFrm⾥申明如:CCurrentDockablePane m_wndCurrentDockablePane;CHistoryDockablePane m_wndHistoryDockablePane;CDockablePane* m_pTabbedBar;然后在OnCreate()⾥⾯:CString strHistoryDockablePane;CString strCurrentView;strCurrentView.LoadString(IDS_Current_VIEW);strHistoryDockablePane.LoadString(IDS_History_VIEW);if (!m_wndHistoryDockablePane.Create(strHistoryDockablePane, this, CRect(0, 0, 200, 200),TRUE, ID_VIEW_HistoryDockablePane, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI)){TRACE0("Failed to create Class View window/n");return FALSE; // failed to create}if (!m_wndCurrentDockablePane.Create(strCurrentView, this, CRect(0, 0, 200, 200),TRUE, ID_VIEW_CurrentView, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBRS_LEFT|CBRS_FLOAT_MULTI)){TRACE0("Failed to create File View window/n");return FALSE; // failed to create}再给她们添加图标:HICON hHistoryDockablePaneIcon = (HICON) ::LoadImage(::AfxGetResourceHandle(),MAKEINTRESOURCE(bHiColorIcons ? IDI_history : IDI_history), IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON),::GetSystemMetrics(SM_CYSMICON), 0);m_wndHistoryDockablePane.SetIcon(hHistoryDockablePaneIcon, FALSE);HICON hCurrentViewIcon = (HICON) ::LoadImage(::AfxGetResourceHandle(),MAKEINTRESOURCE(bHiColorIcons ? IDI_Currrently : IDI_Currrently), IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON),::GetSystemMetrics(SM_CYSMICON), 0);m_wndCurrentDockablePane.SetIcon(hCurrentViewIcon, FALSE);m_wndHistoryDockablePane.EnableDocking(CBRS_ALIGN_ANY);m_wndCurrentDockablePane.EnableDocking(CBRS_ALIGN_ANY);DockPane(&m_wndHistoryDockablePane);DockPane(&m_wndCurrentDockablePane);m_pTabbedBar = NULL;m_wndCurrentDockablePane.AttachToTabWnd(&m_wndHistoryDockablePane, DM_SHOW, FALSE, &m_pTabbedBar);相关显⽰代码就这样的了.后来⽼⼤说关闭需要修改⼯具栏⾥的显⽰状态,即去掉对勾.在⼯具栏⾥控制他们的显⽰和隐藏简单啊,就是⽤m_wndCurrentDockablePane.ShowPane(TRUE,FALSE,TRUE);可是关闭再去修改⼯具栏想了半天,以为要重载CDockablePane的Close()消息,⼜尝试了他的很多消息,都不对.跟踪进去才知道是调⽤MainFrm来关闭的.⾥⾯有pMainfrm.onCloseDockingPane(this);好了,我就重载这个⽅法.BOOL CMainFrame::OnCloseDockingPane( CDockablePane* pWnd ){CWnd * pfWnd = pWnd->GetFocus();if (*pfWnd == m_wndCurrentDockablePane){m_nshowCurrent = 0;}else if(*pfWnd == m_wndHistoryDockablePane){m_nshowHistory = 0;}return TRUE;}这样⼯具栏⾥⾯的信息就更新了.呵呵,⾼兴的太早了,才做了⼀半,当两个⾯板拆开,即处于浮动状态时关闭根本就不调⽤这⾥.⼜郁闷了半天,还是⽼⼤⽜逼,说那种情况是OnCloseMiniFrame,于是有如下重载:BOOL CMainFrame::OnCloseMiniFrame( CPaneFrameWnd* pWnd ){CWnd *ptWnd = pWnd->GetWindow( GW_CHILD );if (*ptWnd ==m_wndCurrentDockablePane){m_nshowCurrent = 0;}else if (*ptWnd == m_wndHistoryDockablePane){m_nshowHistory = 0;}return TRUE;}//写注册表,在析构函数中theApp.WriteProfileInt(_T("Workspace//Pane-377"),_T("IsFloating"),m_nshowCurrent);。
转载MFC中封装很多常用的控件,把类名也给封装了,没有提供明显的接口出来,用win api 写窗口程序,第一步就是注册窗口类此时类名和标题名是一起注册的,所以能把标题很好地让用户来设定,类名也应该是很简单的,可惜的是MFC没有这样做,原因也许是window name可以不停的改,而类名不能。
窗口的类名是有Create来确定的,要在Create前,给窗口选择一个已经注册的窗口类名,作为参数窗口Create就ok了,CWnd的Create最终还是到了CreateEx中来,看看CreateEx 就会清楚许多BOOL CWnd::CreateEx(DWord dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, LPVOID lpParam /* = NULL */){ return CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, pParentWnd->GetSafeHwnd(), (HMENU)(UINT_PTR)nID, lpParam);}BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam){ ASSERT(lpszClassName == NULL || AfxIsValidString(lpszClassName)|| AfxIsValidAtom(lpszClassName)); ENSURE_ARG(lpszWindowName == NULL || AfxIsValidString(lpszWindowName)); // allow modification of several common create parameters CREA TESTRUCT cs; cs.dwExStyle = dwExStyle; cs.lpszClass = lpszClassName; cs.lpszName = lpszWindowName; cs.style = dwStyle; cs.x = x; cs.y = y; cs.cx = nWidth; cs.cy = nHeight; cs.hwndParent = hWndParent; cs.hMenu = nIDorHMenu; cs.hInstance = AfxGetInstanceHandle(); cs.lpCreateParams = lpParam; if (!PReCreateWindow(cs)) { PostNcDestroy(); returnFALSE; } AfxHookWindowCreate(this); HWND hWnd = ::AfxCtxCreateWindowEx(cs.dwExStyle, cs.lpszClass, cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy, cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);#ifdef _DEBUG if (hWnd == NULL) { TRACE(traceAppMsg, 0, "Warning: Window creation failed: GetLastError returns 0x%8.8Xn", GetLastError()); }#endif if (!AfxUnhookWindowCreate()) PostNcDestroy(); // cleanup if CreateWindowEx fails too soon if (hWnd == NULL) return FALSE; ASSERT(hWnd == m_hWnd); // should have been set in send msg hook return TRUE;}可以看到最后到了::AfxCtxCreateWindowEx,可以很容易地知道这里调用了CreateWindowEx 来创建一个窗口在前面有一个PreCreateWindow(cs),而cs经过PreCreateWindow处理后,交给::AfxCtxCreateWindowEx处理::AfxCtxCreateWindowEx在中转给CreateWindowEx,cs.lpszClass就是类名,可以清楚了AfxCtxCreateWindowEx的用心良苦我们可以重载的PreCreateWindow,来修改类名,如下的代码:// TODO: 在此添加专用代码和/或调用基类//VERIFY(AfxDeferRegisterClass(AFX_WND_REG)); //AfxEndDeferRegisterClass(AF X_WND_REG); //cs.lpszClass = AfxRegisterWndClass(NULL); WNDCLASS wndcls; memset(&wndcls, 0, sizeof(WNDCLASS)); // start with NULL // defaults wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; //you can specify your own window procedure wndcls.lpfnWndProc = ::DefWindowProc; wndcls.hInstance = AfxGetInstanceHandle(); wndcls.hIcon = NULL; // or load a different icon wndcls.hCursor =NULL; wndcls.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); wndcls.lpszMenuName = NULL; // Specify your own class name for using FindWindow later wndcls.lpszClassName = _T("MyNewClass"); // Register the new class and exit if it fails if(!AfxRegisterClass(&wndcls)) { TRACE("Class Registration Failedn"); return FALSE; } cs.lpszClass = wndcls.lpszClassName; return TRUE; //return CWnd::PreCreateWindow(cs);其实就是为了把一个已经注册的类名字符串传给CreateWindowEx,从上面代码中的注释中来看,我还用了一种让系统来生成className的方法AfxRegisterWndClass。
在MFC中,窗口的重绘通常是通过重载窗口类的OnPaint函数来实现的。
OnPaint函数是一个回调函数,当窗口需要重绘时,MFC会自动调用该函数。
以下是一个示例,展示了如何在MFC中使用OnPaint函数来处理窗口的重绘:
cpp
class CMyWindow : public CWnd
{
public:
afx_msg void OnPaint();
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(CMyWindow, CWnd)
ON_WM_PAINT()
END_MESSAGE_MAP()
void CMyWindow::OnPaint()
{
CPaintDC dc(this); // 创建设备上下文
// 在这里进行绘制操作
// 例如,使用dc对象的绘图函数来绘制图形、文本等
// 最后,调用父类的OnPaint函数
CWnd::OnPaint();
}
在上述示例中,CMyWindow是一个自定义的窗口类,继承自CWnd。
通过重载OnPaint 函数,并在函数内部进行绘制操作,可以实现窗口的重绘。
需要注意的是,为了使窗口类能够接收到WM_PAINT消息并调用OnPaint函数,需要在消息映射中添加ON_WM_PAINT()宏。
以上是MFC中处理窗口重绘的一种常见方式,你可以根据自己的需求和具体情况来进行调整和扩展。
MFChierarchy chart(类库列表)MFC与Win321 win32:函数,使用API一步一步搭建应用程序。
(常使用FileView操作)2 MFC编程:实现仍然调用API函数,但是是用类封装API函数,使用向导自动生成应用程序框架。
(常使用ClassView操作)2.1需要掌握的技能2.1.1断点调试2.1.2堆栈调用的查看MFC课程内容1 MFC:MFC的六大机制,文档式架构,常用的MFC类,(10--12)。
2 COM(组件对象模型):COM的原理和应用(6)。
3 ADO/Socket:MFC访问数据库以及一些简单的网络编程。
MFC应用程序编程1 MFC的历史:92(VC1)98(VC6)……………………….2 MFC库基础:2.1 MFC库,微软基础类库。
封装了Windows应用程序编程的各种API以及相关机制的C++类库3 类库的相关头文件件★afx-application framework(应用程序框架x)3.1<stdafx.h>-不是类库头文件,是项目的头文件,称为VC下编译的预编译头文件,用来提高编译速度的。
(*.pch)(头文件是不参加编译的但是他参与生成*.pch)3.2<afxwin.h>-几乎包含了各种常用的MFC有文件3.3 <afxext.h>-提供扩展窗口类的支持(创建工具栏,状态栏等………)MFC应用程序的类型1 支持MFC的控制台应用程序(控制台的第四个选项)1.1 多了一个CWinApp(应用程序类,封装类应用程序启动过沉重所涉及到得相关信息)的全局对象(必须有,而且只能有一个)1.2主函数中多了一个AfxWinInit函数,初始化MFC库中的相关信息2 MFC库程序2.1 MFC支持的静态库2.2 MFC支持的动态库2.2.1 MFC规则库(shared MFC DLL)-可以被各种应用程序调用(非MFC程序,没有MFC类也可以调用)★还是有一个CWinApp派生的CMFC_DLLApp类对象2.2.2 MFC扩展库(using shared MFC DLL)-只能被MFC库所编写的应用程序所调用(对原有的MFC类扩展)★DllMain主函数只能被MFC程序调用3 MFC应用程序-----(注意看父类,子类名字可能不一样)3.1单文档视图应用程序★CWinApp 应用程序类★CAboutDlg(对话框-生成关于窗口-和框架没有任何关系)★CMainFrame(父类是:CFrameWnd)(应用程序主框架窗口类-生成应用程序的主框架-负责各个对象的协调工作)★CDocument(它是父类)(文档类-看不到的很重要-管理数据)★CView(它是父类)(视图类-显示数据并和用户进行交互)★CSingleDocApp(父类是CWinApp)-(使用前面的3个类来创建对象)3.2多文档视图架构★CWinApp 应用程序类★CAboutDlg(对话框-生成关于窗口-和框架没有任何关系)★CView(它是父类)(视图类-显示数据并和用户进行交互)★CDocument(它是父类)(文档类-看不到的很重要-管理数据)★CMDIChildWnd(子框架窗口类,父类)★CMDIFrameWnd(主框架窗口类,父类)我们看到的子窗体其实是★CView和★CMDIChildWnd叠加的3.3基于对话框的应用程序★CWinApp 应用程序类★CDialog(对话框窗口类)★★m_pMainWnd保存主窗口地址DoModal 显示对话框MFC相关类的说明1继承自CObject1.1 CObject类:绝大多数MFC类的父类,提供了MFC库的一些机制1 new/delete操作符,定义了与构造函数相关的内存分配函数2 assert和dump调试,堆调试的支持★3 运行时类信息-属于哪个类,还有类的层次结构★4 动态创建★5 序列化1.2 CWinThread: 线程类。
mfc窗口创建过程
MFC窗口的创建过程包括以下几个步骤:
1. 定义窗口类:首先需要定义一个派生自CWnd类的窗口类,该类是窗口的实例。
可以在应用程序的头文件中声明该类,并在源文件中实现其成员函数。
2. 注册窗口类:在应用程序的初始化阶段,需要调用AfxRegisterClass函数来注册窗口类,该函数会将窗口类的信息添加到注册表中。
3. 创建窗口:在初始化阶段,还需要创建窗口实例。
可以通过调用Create函数来创建一个新的窗口。
在调用Create函数之前,需要设置一些窗口的属性,如标题、大小、样式等。
4. 响应消息:窗口创建后,会进入一个消息循环。
在消息循环中,窗口会不断接收和处理消息。
可以通过覆盖窗口类的OnXXX函数来响应不同的消息,如OnPaint函数来处理窗口绘制消息。
5. 显示窗口:当窗口创建并响应消息后,需要调用ShowWindow 函数来显示窗口。
可以通过传入SW_SHOW参数来显示窗口。
以上就是MFC窗口的创建过程,通过这些步骤可以创建和管理窗口的实例,并实现窗口的功能。
如何使⽤visualstudio2019创建简单的MFC窗⼝(使⽤C++)本⽂介绍了如何使⽤visual studio2019创建简单的MFC窗⼝(使⽤C++)```cpp使⽤visual studio 2019 创建过程请参考Bili的上⼀篇⽂章⬇⬇→!使⽤visual studio 2019 创建简单的MFC窗⼝「使⽤底层的C语⾔」#include<windows.h> //底层实现窗⼝的头⽂件//6.处理窗⼝过程//CALLBACK 代表_stdcall 参数的传递顺序:从右到左依次⼊栈,并且函数返回前清空堆栈LRESULT CALLBACK WindowProc(HWND hand, //消息所属窗⼝句柄UINT uMsg, //具体消息名称 WM_XXXX消息名WPARAM wParam, //键盘附加消息LPARAM lParam) { //⿏标附加消息switch (uMsg){case WM_CLOSE://所有以XXXXWindow为结尾的⽅法,都不会进⼊到消息队列中,⽽是直接执⾏DestroyWindow(hand);//发送另⼀个消息WM_DESTROYbreak;case WM_DESTROY:PostQuitMessage(0);break;case WM_LBUTTONDOWN://⿏标左键按下{int xPos = LOWORD(lParam);int yPos = HIWORD(lParam);char buf[1024];wsprintf(buf, TEXT("x = %d,y = %d"),xPos,yPos);MessageBox(hand, buf, TEXT("按下⿏标左键"), MB_OK);break;}case WM_KEYDOWN: //键盘{MessageBox(hand, TEXT("键盘"), TEXT("按下键盘"), MB_OK);break;}case WM_PAINT: //画图{PAINTSTRUCT ps; //画图结构体HDC hdc = BeginPaint(hand, &ps);TextOut(hdc, 100, 100,TEXT("hello"), strlen("hello"));EndPaint(hand, &ps);break;}default:break;}//返回值⽤默认处理⽅式return DefWindowProc(hand, uMsg, wParam, lParam);}/*程序⼊⼝函数_In_ HINSTANCE hInstance,//应⽤程序实例句柄_In_opt_ HINSTANCE hPrevInstance,//上⼀个应⽤程序句柄,在WIN32环境下⼀般为NULL,不起作⽤了_In_ LPSTR lpCmdLine,//char * argv[]_In_ int nShowCmd//显⽰命令最⼤化、最⼩化、正常WINAPI 代表_stdcall 参数的传递顺序:从右到左依次⼊栈,并且函数返回前清空堆栈*/int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd ) {/*1.设计窗⼝2.注册窗⼝3.创建窗⼝4.显⽰和更新5.通过循环取消息6.处理消息(窗⼝过程)*///1.设计窗⼝WNDCLASS wc;wc.cbClsExtra = 0; //类的额外的内存wc.cbWndExtra = 0; //窗⼝额外的内存wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //设置背景wc.hCursor = LoadCursor(NULL, IDC_HAND); //设置光标,如果第⼀个参数为null,代表使⽤系统提供的光标wc.hIcon = LoadIcon(NULL, IDI_ERROR); //图标,如果第⼀个参数为null,代表使⽤系统提供的图标wc.hInstance = hInstance; //应⽤程序的实例句柄,传⼊winmain的形参即可wc.lpfnWndProc = WindowProc; //回调函数窗⼝过程wc.lpszClassName = TEXT("WIN"); //指定窗⼝名称wc.lpszMenuName = NULL; //菜单名称wc.style = 0; //显⽰风格,0代表默认//2.注册窗⼝RegisterClass(&wc);//3.创建窗⼝/*lpszClassName,//类名lpWindowName, //标题名dwStyle, //风格 WC_OVERLAPPEDWINDOWx, //坐标 CW_USERDEFAULTy, //坐标nWidth, //宽nHeight, //⾼hWndParent, //⽗窗⼝ nullhMenu, //菜单 nullhInstance, //实例句柄lpParam //附加值⿏标附加值*/HWND hwnd = CreateWindow(wc.lpszClassName, TEXT("WINDOWS"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); //4.显⽰和更新ShowWindow(hwnd, SW_SHOWNORMAL);UpdateWindow(hwnd);/*HWND hwnd; //主窗⼝句柄UINT message; //具体消息名称WPARAM wParam; //附加消息键盘消息LPARAM lParam; //附加消息⿏标消息DWORD time; //消息产⽣时间POINT pt;*/ //附加消息⿏标消息 x,y//5.通过循环取消息MSG msg;/*_Out_ LPMSG lpMsg, //消息_In_opt_ HWND hWnd, //捕获窗⼝填null表⽰捕获所有窗⼝_In_ UINT wMsgFilterMin, //最⼤和最⼩的过滤消息⼀般填0_In_ UINT wMsgFilterMax);*/while (GetMessage(&msg, NULL, 0, 0)){/*if (GetMessage(&msg, NULL, 0, 0) == FALSE) {break;}*///翻译消息TranslateMessage(&msg);//不是false//分发消息DispatchMessage(&msg);}return 0;}划重点:项⽬->属性->常规->⾼级->将MFC的使⽤设置为在“共享dll中使⽤mfc”头⽂件mfc.h#include <afxwin.h>//mfc头⽂件class MyApp:public CWinApp{public:virtual BOOL InitInstance();};class MyFrame :public CFrameWnd {//窗⼝框架类public:MyFrame();//声明宏提⽰消息映射机制DECLARE_MESSAGE_MAP();afx_msg void OnLButtonDown(UINT,CPoint);afx_msg void OnChar(UINT,UINT,UINT);afx_msg void OnPaint();};源⽂件mfc.cpp#include “mfc.h”MyApp app;BOOL MyApp::InitInstance() {//创建窗⼝MyFrame* frame = new MyFrame;//显⽰和更新frame->ShowWindow(SW_SHOWNORMAL);frame->UpdateWindow();m_pMainWnd = frame;//保存指向应⽤程序的主窗⼝的指针return TRUE;//返回正常初始化}//分界宏BEGIN_MESSAGE_MAP(MyFrame, CFrameWnd)ON_WM_LBUTTONDOWN()//⿏标左键按下ON_WM_CHAR()ON_WM_PAINT()END_MESSAGE_MAP()MyFrame::MyFrame(){Create(NULL,TEXT(“windows”));}void MyFrame::OnLButtonDown(UINT, CPoint point){//TCHAR buf[1024];//wsprintf(buf, TEXT(“x = %d,y = %d”), point.x, point.y);//MessageBox(buf);CString str;str.Format(TEXT(“x = %d,y = %d”),point.x,point.y);MessageBox(str);}void MyFrame::OnChar(UINT key, UINT, UINT){CString str;str.Format(TEXT(“按下了%c键”),key);MessageBox(str);}void MyFrame::OnPaint(){CPaintDC dc(this);dc.TextOutW(100,100,TEXT(“为了部落”));dc.Ellipse(10,10,100,100);}到此这篇关于如何使⽤visual studio2019创建简单的MFC窗⼝(使⽤C++)的⽂章就介绍到这了,更多相关vs2019创建MFC窗⼝内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章希望⼤家以后多多⽀持!。
1.WS_BORDER = 0x00800000创建一个带边框的窗口。
2.WS_CAPTION = 0x00C00000必须和WS_BORDER风格配合,但不能与WS_DLGFRAME风格一起使用。
指示窗口包含标题要部分。
(创建一个有标题框的窗口(包括WS_BODER风格))。
3.WS_CHILD = 0x40000000创建一个子窗口。
这个风格不能与WS_POPUP风格合用。
(说明窗口为子窗口,不能应用于弹出式窗口风格(WS_POPUP))4.WS_CHILDWINDOW与WS_CHILD相同。
5.WS_CLIPCHILDREN = 0x02000000当在父窗口内绘图时,排除子窗口区域。
在创建父窗口时使用这个风格。
(绘制父窗口时,不绘制子窗口的裁剪区域。
使用在建立父窗口时)6.WS_CLIPSIBLINGS = 0x04000000排除子窗口之间的相对区域,也就是,当一个特定的窗口接收到WM_PAINT 消息时,WS_CLIPSIBLINGS 风格将所有层叠窗口排除在绘图之外,只重绘指定的子窗口。
如果未指定WS_CLIPSIBLINGS风格,并且子窗口是层叠的,则在重绘子窗口的客户区时,就会重绘邻近的子窗口。
(剪裁相关的子窗口,这意味着,当一个特定的子窗口接收到重绘消息时,WS_CLIPSIBLINGS风格将在子窗口要重画的区域中去掉与其它子窗口重叠的部分。
(如果没有指定WS_CLIPSIBLINGS风格,并且子窗口有重叠,当你在一个子窗口的客户区绘图时,它可能会画在相邻的子窗口的客户区中。
)只与WS_CHILD风格一起使用)7.WS_DISABLED = 0x08000000创建一个初始状态为禁止的子窗口。
一个禁止状态的窗口不能接受来自用户的输入信息。
8.WS_DLGFRAME = 0x00400000创建一个带对话框边框风格的窗口。
这种风格的窗口不能带标题条。
(创建一个窗口,具有双重边界,但是没有标题条)9.WS_GROUP = 0x00020000指定一组控制的第一个控制。
MFC的窗⼝句柄1.窗⼝、控件的指针和句柄的相互转化1)指针转化为句柄在MFC应⽤程序中⾸先要获得窗⼝的指针,然后将其转化为句柄 CWnd* pWnd; HANDLE hWnd = pWnd->GetSafeHwnd();2)句柄转化为指针在MFC应⽤程序中⾸先获得对话框控件的句柄,然后获得其指针HANDLE hWnd;GetDlgItem(IDC_xxx,&hWnd);CWnd * pWnd = FromHandle(hWnd);获得程序窗⼝指针的办法:a.获得主框架窗⼝指针(任何时候都可以⽤,只要是MFC程序中):CWnd* pWnd = AfxGetMainWnd();b.获得对话框中控件指针:CWnd* pWnd = GetDlgItem(IDC_xxx);c.获得对话框中某控件的句柄:HANDLE GetDlgItem(m_hDLG,m_nID_DlgItem);d.获得GDI对象的句柄:HANDLE m_hGDIObj = m_pGDIObj->GetSafeHanle();2. 如何获取应⽤程序的实例句柄?AfxGetInstanceHandle()应⽤程序的实例句柄保存在CWinAppIm_hInstance 中,可以这么调⽤ AfxGetInstancdHandle获得句柄;Example: HANDLE hInstance=AfxGetInstanceHandle();3. 如何通过代码获得应⽤程序主窗⼝的指针?AfxGetMainWnd GetSafeHwnd() AfxGetAppName() AfxGetThread主窗⼝的指针保存在CWinThread::m_pMainWnd中,调⽤ AfxGetMainWnd实现。
【例】 AfxGetMainWnd() ->ShowWindow(SW_SHOWMAXMIZED); //使程序最⼤化.【例】此例的主窗⼝是对话框,下⾯的代码是在另外⼀个CFileTreeCtrl 类(⼦窗)中相关函数实现在主对话框(主窗)中的⼏个静态⽂本框(⼦窗)中显⽰路径:CWnd* m_pCWnd= AfxGetMainWnd(); //得到主窗⼝指针,通过主窗指针访问其他⼦窗资源//⽅法⼀m_pCWnd->SetDlgItemText(IDC_STATIC_path,"CWnd* "+m_sCurPath); //在主窗中的⼦窗(ID:IDC_STATIC_path)中显⽰字符串m_pCWnd->SetDlgItemText(IDC_STATIC_who,"路径显⽰由FileTreeCtrl类完成:");//⽅法⼆m_pCWnd->SendMessage(STN_CLICKED); //向主窗⼝发送⼀个消息,显⽰任务由主窗完成。
MFC(Microsoft Foundation Class)是一种用于Windows应用程序开发的C++框架。
在MFC中,使用Create函数可以创建窗口。
但是有时候会出现创建窗口时返回的句柄为空的情况。
下面我们来分析一下这个问题,以及可能的解决方法。
一、问题描述在使用MFC中的Create函数创建窗口时,有时候会遇到返回的句柄为空的情况。
这种情况通常会导致窗口无法正常显示或者无法响应用户操作,给程序的运行和用户体验带来影响。
二、可能的原因1. 调用顺序问题在使用MFC的Create函数创建窗口时,可能存在一些调用顺序上的问题,导致返回的句柄为空。
比如在调用Create函数之前没有正确设置好窗口类的属性,或者在Create函数之后立即进行了一些操作,这些情况都有可能导致句柄为空的问题。
2. 窗口类注册问题窗口类的注册是窗口创建的重要步骤,如果在注册窗口类时出现了错误,就有可能导致Create函数返回的句柄为空。
比如窗口类的属性设置不正确、窗口过程函数指定错误等。
3. 窗口样式问题在调用Create函数创建窗口时,指定的窗口样式可能会影响到句柄的返回。
如果指定的样式不正确,就有可能导致句柄为空的问题。
4. 其他原因除了上述几种可能的原因外,还有一些其他一些可能性,比如内存不足、系统环境问题等。
三、解决方法针对上述可能的原因,可以采取以下一些解决方法:1. 细致分析代码首先需要仔细分析代码,确保调用顺序正确、窗口类注册正确、窗口样式设置正确等。
通过仔细分析代码,查找可能存在的问题点。
2. 检查窗口类注册代码检查窗口类注册的代码,确保窗口类的属性设置正确、窗口过程函数指定正确等。
如果发现问题,及时进行修改。
3. 调试程序可以通过调试工具对程序进行调试,观察在调用Create函数时的情况,以便发现问题所在。
4. 测试环境在不同的系统环境下进行测试,以确定是否是系统环境问题导致的句柄为空的情况。
5. 寻求帮助如果以上方法都无法解决问题,可以寻求相关领域的专家或者论坛上的朋友进行求助,也许可以得到一些新的思路和解决方法。
1.WS_EX_ACCEPTFILES = 0x00000010指明了一个已创建视窗具有拖拽文件功能(指定以该风格创建的窗口接受一个拖拽文件)2.WS_EX_APPWINDOW = 0x00040000强制一个可见的顶级视窗到工具栏上(当窗口可见时,将一个顶层窗口放置到任务条上)3.WS_EX_CLIENTEDGE = 0x00000200使一个视窗具有凹陷边框(指定窗口有一个带阴影的边界)4.WS_EX_COMPOSITED = 0x02000000Windows XP:将一个窗体的所有子窗口使用双缓冲按照从低到高方式绘制出来,参阅remark项.如果这个视窗已经使用经典样式中的下列值CS_OWNDC , CS_CLASSDC,WS_EX_CONTEXTHELP.此参数将不能使用.这个样式的视窗在标题栏上有一个问号,当拥护点击着个问号,鼠标变成一个问号,如果用户然后点击一个子窗口,子窗就会收到一条WM_HELP消息.子窗口将把这个消息传递给他的父进程,这个父进程将用HELP_WM_HELP命令调用WinHelp函数.这个帮助程序常常弹出一个典型的包含其子窗口的帮助的窗口本参数不能和WS_MAXIMIZEBOX ,WS_MINIMIZEBOX一起使用.5.WS_EX_CONTEXTHELP = 0x00000400在窗口的标题条包含一个问号标志。
当用户点击了问号时,鼠标光标变为一个问号的指针、如果点击了一个子窗口,则子窗口接收到WM_HELP消息。
子窗口应该将这个消息传递给父窗口过程,父窗口再通过HELP_WM_HELP命令调用WinHelp函数。
这个Help应用程序显示一个包含子窗口帮助信息的弹出式窗口。
WS_EX_CONTEXTHELP不能与WS_MAXIMIZEBOX和WS_MINIMIZEBOX同时使用。
6.WS_EX_CONTROLPARENT = 0x00010000这个窗体本身包含了参与对话框导航的子窗口.如果使用了这个参数,对话框管理器进入这个窗体的子窗口,当执行导航操作时,比如按住TAB键,方向键.(允许用户使用Tab键在窗口的子窗口间搜索)7.WS_EX_DLGMODALFRAME = 0x00000001创建一个具有双边框的窗口,这个窗口可以通过使用WS_CAPTION样式被创建成具有一个标题栏的窗口.(创建一个带双边的窗口;该窗口可以在dwStyle 中指定WS_CAPTION风格来创建一个标题栏。
mfc子窗口调用父窗口方法1.前言在MFC程序设计中,经常需要子窗口调用父窗口的方法。
这通常是因为子窗口需要操作父窗口中的数据或者控制父窗口中的界面。
本文将介绍在MFC程序中如何实现子窗口调用父窗口的方法,并提供几个实例。
2.使用消息传递机制在MFC中,子窗口和父窗口之间可以通过消息传递机制实现相互通信。
具体地说,子窗口可以向父窗口发送消息,父窗口可以接收子窗口发送的消息,并根据消息内容来执行相应的方法。
MFC提供了许多消息类型,例如WM_COMMAND、WM_NOTIFY、WM_PAINT等。
如果需要在子窗口和父窗口之间传递自定义消息,可以通过自定义消息类型来实现。
以下是一个使用消息传递机制实现子窗口调用父窗口方法的示例://在子窗口类中添加如下代码:define WM_CHILD_TO_PARENT(WM_USER+1)//自定义消息类型void CChildDlg::OnButton1(){//向父窗口发送消息GetParent()->SendMessage(WM_CHILD_TO_PARENT,0,0);}//在父窗口类中添加如下代码:afx_msg LRESULT CParentDlg::OnChildToParent(WPARAM wParam, LPARAM lParam){//执行父窗口方法//...return0;}BEGIN_MESSAGE_MAP(CParentDlg,CDialog)ON_MESSAGE(WM_CHILD_TO_PARENT,OnChildToParent)END_MESSAGE_MAP()在上述示例中,子窗口类CChildDlg中的OnButton1方法向父窗口发送了一个自定义消息类型WM_CHILD_TO_PARENT。
父窗口类CParentDlg重载了消息映射函数OnChildToParent,并在其中执行相应的方法。
通过这种方式,子窗口就可以调用父窗口的方法了。
MFC子窗口和父窗口(SetParent, SetOwner)一、概念和区别在windows系统中,每个窗口对象都对应有一个数据结构,形成一个list链表。
系统的窗口管理器通过这个list来获取窗口信息和管理每个窗口。
这个数据结构中有四个数据用来构建list,即child、sibling、parent、owner四个域。
所以我们可以看到,窗口之间的关系有两种:owner-owned 关系和parent-child关系。
前者称之为拥有/被拥有关系,后者称之为父/子关系。
在这篇文字中,我把owner窗口称之所有者窗口。
换句话说,一个窗口在有一个父窗口(parent)的同时,还可能被不同的窗口拥有(owner),也可以有自己的子窗口(child)。
在MFC 的CWnd类中,所有者窗口保存在m_hWndOwner成员变量中,父窗口则保存在m_hParent中,但是这两个值并不一定和窗口对象数据结构中的值相对应。
窗口之间的关系,决定了窗口的外在表现。
比如显示、销毁等。
如果一个窗口数据的owner域非NULL,则它和该窗口建立了owner-owned 关系,拥有关系决定了:(1)被拥有的窗口永远显示在拥有它的那个窗口的前面;(2)当所有者窗口最小化的时候,它所拥有的窗口都会被隐藏;(3)当所有者窗口被销毁的时候,它所拥有的窗口都会被销毁。
需要注意的是,隐藏所有者窗口并不会影响它所拥有的窗口的可见状态。
比如:如果窗口A 拥有窗口B,窗口B拥有窗口C,则当窗口A最小化的时候,窗口B被隐藏,但是窗口C还是可见。
如果一个窗口的parent域非NULL,则它和该窗口之间就建立了parent-child关系。
父子决定了:(1)窗口在屏幕上面的显示位置。
父窗口提供了用来定位子窗口的坐标系统,一个子窗口只能显示在它的父窗口的客户区中,之外的部分将被裁减。
这个裁减法则决定了如果父窗口不可见,则子窗口肯定不可见。
如果父窗口移动到了屏幕之外,子窗口也一样。
mfc直线和多边形矩形窗口裁剪算法MFC直线和多边形矩形窗口裁剪算法是一种在MFC框架下用于裁剪直线和多边形的算法。
该算法可以确保在绘制图形时,图形的边界不会超出指定的矩形窗口范围。
这种裁剪算法是为了确保图形的可视性和美观性,以及提高程序的性能。
在MFC框架中,绘制图形一般是通过在窗口的OnPaint函数中完成的。
在OnPaint函数中,我们可以获取绘图设备上下文(device context,简称DC),并在DC上进行绘图操作。
为了实现裁剪效果,我们需要在绘图之前对要绘制的图形进行裁剪,确保图形不会超出指定的窗口范围。
对于直线的裁剪,我们可以使用Cohen-Sutherland裁剪算法。
该算法是一种基于线段的区域编码(region encoding)算法,用于裁剪位于矩形窗口外部的线段。
算法的基本思路是判断直线的两个端点是否在窗口的内部,如果都在内部,则直接绘制该直线;如果都在外部,则直接丢弃该直线;如果一个在内部,一个在外部,则通过计算交点并选择正确的端点来裁剪直线。
对于多边形的裁剪,我们可以使用Sutherland-Hodgman裁剪算法。
该算法是一种基于点的裁剪算法,用于裁剪位于矩形窗口外部的多边形。
算法的基本思路是将多边形分割为若干条边和端点,然后根据边与窗口的关系进行裁剪。
具体步骤包括:将多边形的各个顶点与窗口的边界进行比较,并根据顶点在内部和外部的情况确定裁剪结果;根据边界与窗口的关系确定新的裁剪结果,并将结果作为下一次裁剪的输入。
在MFC中实现直线和多边形的裁剪算法,可以按照以下步骤进行:1.获取绘图设备上下文(DC)。
2.设置裁剪区域为窗口矩形范围。
3.使用Cohen-Sutherland算法进行直线裁剪,对于每条需要绘制的直线,判断其裁剪结果并进行绘制。
4.使用Sutherland-Hodgman算法进行多边形裁剪,对于每个需要绘制的多边形,判断其裁剪结果并进行绘制。
5.释放绘图设备上下文。
MFC中关闭窗口的几种办法+MFC中MessageBox的用法MFC中关闭窗口的几种办法:退出程序用AfxGetMainWnd()->SendMessage(WM_CLOSE);关闭当前窗口用DestroyWindow( );关闭模式对话框用EndDialog(0);MFC中MessageBox的用法消息框是个很常用的控件,属性比较多,本文列出了它的一些常用方法,及指出了它的一些应用场合。
1.MessageBox("这是一个最简单的消息框!");2.MessageBox("这是一个有标题的消息框!","标题");3.MessageBox("这是一个确定取消的消息框!","标题", MB_OKCANCEL );4.MessageBox("这是一个警告的消息框!","标题", MB_ICONEXCLAMA TION );5.MessageBox("这是一个两种属性的消息框!","标题", MB_ICONEXCLAMA TION|MB_OKCANCEL );6.if(MessageBox("一种常用的应用","标题",MB_ICONEXCLAMA TION|MB_OKCANCEL)==IDCANCEL)return;附其它常用属性系统默认图标,可在消息框上显示X错误MB_ICONHAND, MB_ICONSTOP, and MB_ICONERROR询问MB_ICONQUESTION!警告MB_ICONEXCLAMA TION and MB_ICONWARNINGi信息MB_ICONASTERISK and MB_ICONINFORMA TION按钮的形式MB_OK 默认MB_OKCANCEL 确定取消MB_YESNO 是否MB_YESNOCANCEL 是否取消返回值IDCANCEL 取消被选IDNO 否被选IDOK 确定被选IDYES 是被选MFC 文本框用法//获得EDITCEdit* pBoxOne;pBoxOne = (CEdit*) GetDlgItem(IDC_EDIT1);//付值pBoxOne->SetWindowText( _T"FOO" );//取值CString str;pBoxOne->GetWindowText(str);GetDlgItem(IDC_EDIT1)->SetWindowText( _T"FOO" );也可以//取值CString str;GetDlgItem(IDC_EDIT1)->GetWindowText(str);EditControl是在MFC对话框中最频繁的使用的控件之一VC++2005提供EditControl的属性和控件事件操作简单方便1只允许输入数字如果设置EditControl中只能输入数字,在VC6.0中需要编写一个派生类来达到目的,而在VC++2005下只需要在属性对话框中将Number的属性值设为True就可以了.2获取EditControl的内容两种方法第一种,利用MFC应用程序向导生成一个基于对话框的应用程序,从资源视图中选择该Dialog窗体,利用右侧的工具箱,向Dialog内添加一个EditControl项,声明控件变量的类别为V alue,变量类型为CString,变量名为m_sEdit_Content. CString m_sEdit_Content;CString s;UpdateData(true);s=m_sEdit_Content.GetString();MessageBox(s,_T("获取编辑框的内容"),MB_OK);s.ReleaseBuffer();这样就取得了编辑框的内容UpdateData(true);这句代码很重要,它的作用是将输入的数据装入EditControl对应的变量m_sEdit_Content中.由于MFC应用程序向导默认是使用Unicode库,所以MessageBox中的字符串需要用_T(),否则会出现const char[]转换LPCTSTR错误,如果不使用Unicode库就不需要_T().第二种方法声明控件变量的类别为Control,变量类型为CEdit,变量名为m_Edit_Content.代码如下(Unicode)CString s;s.GetBufferSetLength(1024);m_Edit_Content.GetWindowTextW(s.GetBuffer(),s.GetLength());MessageBox(s,_T("获取文本框的内容"),MB_OK);s.ReleaseBuffer();如果不是Unicode下获取编辑框内容的函数就是GetWindowTextA3将EditControl中的内容转化为整数在限制编辑框只能数字之后,要将字符串转化为整数声明控件变量的类别为V alue,变量类型为CString,变量名为m_sEdit_Content.CString s;UpdateData(true);s=m_sEdit_Content.GetString();int n=_tstoi(s);s.ReleaseBuffer();n就是所需要的整数在VC2005下字符串转换成整数需要_tstoi这个函数4限制编辑框的输入长度声明控件变量的类别为Control,变量类型为CEdit,变量名为m_Edit_Content.在对话框初始化的地方写m_Edit_Content.SetLimitText(1);编辑框就只能输入一个字符了.教你如何用WORD文档(2012-06-27 192246)转载▼标签:杂谈1. 问:WORD 里边怎样设置每页不同的页眉?如何使不同的章节显示的页眉不同?答:分节,每节可以设置不同的页眉。
1、建立MFC文件,工程名定义为“qiehuan03”,选择对话框形式。
在主对话框添加按钮控件。
2、在上图左侧“Dialog”右键单击,选择“插入”->“Dialog”->“新建”。
3、选中该新建对话框,右键->“ClassWizard”->“Create a new class”,为类取名为“CSHOWSTATE_DLG”。
4、打开“qiehuan03.cpp”、“qiehuan03Dlg.cpp”、“qiehuan03Dlg.h”,添加头文件“#include"SHOWSTATE_DLG.h"”5、在“qiehuan03Dlg.h”文件中增加语句“CSHOWSTATE_DLG *dlg”。
6、在“qiehuan03Dlg.cpp”文件中添加语句“dlg=new CSHOWSTATE_DLG”。
7、在“qiehuan03Dlg.cpp”文件的OnButton()下添加代码:if(dlg->GetSafeHwnd()==0){dlg->Create(IDD_SHOW_DIALOG);}dlg->ShowWindow(SW_SHOW);编译执行。
教你如何用WORD文档(2012-06-27 192246)转载▼标签:杂谈1. 问:WORD 里边怎样设置每页不同的页眉?如何使不同的章节显示的页眉不同?答:分节,每节可以设置不同的页眉。
文件――页面设置――版式――页眉和页脚――首页不同。
2. 问:请问word 中怎样让每一章用不同的页眉?怎么我现在只能用一个页眉,一改就全部改了?答:在插入分隔符里,选插入分节符,可以选连续的那个,然后下一页改页眉前,按一下“同前”钮,再做的改动就不影响前面的了。
简言之,分节符使得它们独立了。
这个工具栏上的“同前”按钮就显示在工具栏上,不过是图标的形式,把光标移到上面就显示出”同前“两个字来。
3. 问:如何合并两个WORD 文档,不同的页眉需要先写两个文件,然后合并,如何做?答:页眉设置中,选择奇偶页不同与前不同等选项。
MFC窗口的创建过程详细解析作者:关于MFC的窗口创建过程一直感觉比较神秘,那么我们来看下MFC中的窗口创建到底是一个什么过程(窗口创建前的窗口类准备就直接忽略了,与标准Win32窗口类准备大同小异)。
MFC中窗口创建主要涉及三个重要的函数,分别是CWnd::CreateEx(或者CWnd::Create)、AfxHookWindowCreate、AfxCbtFilterHook函数,首先是大概介绍下MFC 的窗口创建过程,当CWnd::CreateEx被调用时,CWnd::CreateEx在调用API函数::CreateWindowEx创建窗口前会通过调用AfxHookWindowCreate安装一个名为_AfxCbtFilterHook的线程钩子,并将需要创建的窗口的CWnd指针保存到线程状态结构中,在API函数::CreateWindowEx真正创建窗口前AfxCbtFilterHook会被调用,AfxCbtFilterHook 会执行子类化操作,把要创建的窗口的窗口过程子类化为线程状态结构中的窗口过程(AfxGetModuleState()->m_pfnAfxWndProc),即MFC的标准窗口过程,这样MFC的窗口(CWnd及其派生类)都可以通过消息映射机制接收和响应包括从创建开始的各种各样的消息。
(关于AfxCbtFilterHook可以参考MSDN中关于SetWindowsHookEx的解释。
)1. CWnd::CreateExBOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,LPCTSTR lpszWindowName, DWORD dwStyle,int x, int y, int nWidth, int nHeight,HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam){// allow modification of several common create parameters准备一个结构给PreCreateWindow函数使用,这样就允许应用程序在创建窗口前修改窗口创建参数,比如给cs.lpszClass重新指定一个窗口类给CreateWindow函数。
CREATESTRUCT cs;cs.dwExStyle = dwExStyle;cs.lpszClass = lpszClassName;cs.lpszName = lpszWindowName;cs.style = dwStyle;cs.x = x;cs.y = y;cs.cx = nWidth;cs.cy = nHeight;cs.hwndParent = hWndParent;cs.hMenu = nIDorHMenu;cs.hInstance = AfxGetInstanceHandle();cs.lpCreateParams = lpParam;//允许应用程序修改窗口创建的参数。
if (!PreCreateWindow(cs)){PostNcDestroy();return FALSE;}Hook窗口的创建过程:主要是给当前现成安装一个名为_AfxCbtFilterHook的线程钩子,并讲需要创建的窗口的CWnd指针保存到线程状态结构(_AFX_THREAD_STATE)中。
AfxHookWindowCreate(this);开始创建窗口,在该函数正真开始创建窗口之前,AfxCbtFilterHook会被调用,AfxCbtFilterHook会执行子类化操作,把要创建的窗口的窗口过程子类化为线程状态结构中的窗口过程(AfxGetModuleState()->m_pfnAfxWndProc),这样MFC的窗口(CWnd及其派生类)都可以接收和响应包括从创建开始的各种各样的消息HWND hWnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass,cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);#ifdef _DEBUGif (hWnd == NULL){TRACE1("Warning: Window creation failed: GetLastError returns 0x%8.8X\n",GetLastError());}#endif解除创建窗口的Hookif (!AfxUnhookWindowCreate())PostNcDestroy(); // cleanup if CreateWindowEx fails too soonif (hWnd == NULL)return FALSE;ASSERT(hWnd == m_hWnd); // should have been set in send msg hookreturn TRUE;}2.AfxHookWindowCreateAfxHookWindowCreate主要是Hook窗口的创建过程:主要是给当前现成安装一个名为_AfxCbtFilterHook的线程钩子,并讲需要创建的窗口的CWnd指针保存到线程状态结构void AFXAPI AfxHookWindowCreate(CWnd* pWnd)//获取线程状态_AFX_THREAD_STA TE* pThreadState = _afxThreadState.GetData();//如果线程状态里的m_pWndInit成员与pWnd相等表明给窗口正在创建中,直接返回if (pThreadState->m_pWndInit == pWnd)return;if (pThreadState->m_hHookOldCbtFilter == NULL){给本线程安装一个名为AfxCbtFilterHook的钩子,AfxCbtFilterHook会在::CreateWindowEx 真正开始创建窗口前被调用,更多信息请参考MSDN关于SetWindowsHookEx的解释。
pThreadState->m_hHookOldCbtFilter = ::SetWindowsHookEx(WH_CBT,_AfxCbtFilterHook, NULL, ::GetCurrentThreadId());if (pThreadState->m_hHookOldCbtFilter == NULL)AfxThrowMemoryException();}ASSERT(pThreadState->m_hHookOldCbtFilter != NULL);ASSERT(pWnd != NULL);ASSERT(pWnd->m_hWnd == NULL); // only do onceASSERT(pThreadState->m_pWndInit == NULL); // hook not already in progress把需要Hook创建的窗口指针保存到线程状态中,AfxCbtFilterHook被调用时会用到。
pThreadState->m_pWndInit = pWnd;}3. AfxCbtFilterHookAfxCbtFilterHook会执行子类化操作,把要创建的窗口的窗口过程子类化为线程状态结构中的窗口过程(AfxGetModuleState()->m_pfnAfxWndProc),即MFC的标准窗口过程,这样MFC 的窗口(CWnd及其派生类)都可以接收和响应包括从创建开始的各种各样的消息LRESULT CALLBACK_AfxCbtFilterHook(int code, WPARAM wParam, LPARAM lParam){_AFX_THREAD_STA TE* pThreadState = _afxThreadState.GetData();if (code != HCBT_CREATEWND){// wait for HCBT_CREATEWND just pass others on...return CallNextHookEx(pThreadState->m_hHookOldCbtFilter, code, wParam, lParam);}ASSERT(lParam != NULL);LPCREATESTRUCT lpcs = ((LPCBT_CREATEWND)lParam)->lpcs;ASSERT(lpcs != NULL);//获取要创建的窗口CWnd* pWndInit = pThreadState->m_pWndInit;BOOL bContextIsDLL = afxContextIsDLL;if (pWndInit != NULL || (!(lpcs->style & WS_CHILD) && !bContextIsDLL)){// Note: special check to avoid subclassing the IME windowif (_afxDBCS){// check for cheap CS_IME style first...if (GetClassLong((HWND)wParam, GCL_STYLE) & CS_IME)goto lCallNextHook;//获取窗口类// get class name of the window that is being createdLPCTSTR pszClassName;TCHAR szClassName[_countof("ime")+1];if (HIWORD(lpcs->lpszClass)){pszClassName = lpcs->lpszClass;}else{szClassName[0] = '\0';GlobalGetAtomName((ATOM)lpcs->lpszClass, szClassName, _countof(szClassName));pszClassName = szClassName;}// a little more expensive to test this way, but necessary...if (lstrcmpi(pszClassName, _T("ime")) == 0)goto lCallNextHook;}ASSERT(wParam != NULL); // should be non-NULL HWND//获取即将创建的窗口句柄HWND hWnd = (HWND)wParam;WNDPROC oldWndProc;if (pWndInit != NULL){#ifdef _AFXDLLAFX_MANAGE_STATE(pWndInit->m_pModuleState);#endif//确保窗口句柄未与窗口(CWnd)关联// the window should not be in the permanent map at this time ASSERT(CWnd::FromHandlePermanent(hWnd) == NULL);//使窗口句柄与窗口(CWnd)关联,// connect the HWND to pWndInit...pWndInit->Attach(hWnd);//CWnd子类可以重载这个函数以在子类化进行前做一些处理// allow other subclassing to occur firstpWndInit->PreSubclassWindow();//获取窗口的原始窗口过程,该窗口过程保存在CWnd:: m_pfnSuper里,用CWnd::GetSuperWndProcAddr()函数可以获取,该函数为虚函数,可以重载把原来的窗口过程替换。