标签:
如果希望在应用程序窗口创建之前修改它的大小、标题和风格,应该在CMainFrame类的PreCreateWindow成员函数进行。该函数有个类型是CREATESTRUCT结构的参数,如果在修改了这个参数中的成员变量的值,那么这种改变会反映到MFC底层代码中,当MFC底层代码调用CreateWindowEx函数去创建窗口时,它就会使用改变后的参数值去创建这个窗口。
1)更改窗口大小
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT&cs) { if( !CFrameWnd::PreCreateWindow(cs) ) return FALSE; //TODO: 在此处通过修改 // CREATESTRUCT cs 来修改窗口类或样式 cs.cx = 400; cs.cy = 200; return TRUE; }
2)更改应用程序标题
框架的默认窗口样式是WS_OVERLAPPEDWINDOW和FWS_ADDTOTITLE样式的组合。其中FWS_ADDTOTITLE是MFC特定的一种样式,指示框架将文档标题添加到窗口标题上。因此,如果想让窗口显示自己的标题,只需将窗口的FWS_ADDTOTITLE样式去掉即可。设置窗口标题的代码之前加上:
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT&cs) { if( !CFrameWnd::PreCreateWindow(cs) ) return FALSE; //TODO: 在此处通过修改 // CREATESTRUCT cs 来修改窗口类或样式 cs.cx = 400; cs.cy = 200; cs.style = cs.style & ~FWS_ADDTOTITLE; // cs.style = WS_OVERLAPPEDWINDOW; cs.lpszName = "标题"; return TRUE; }
在应用程序窗口创建之后修改它的风格属性,可在CMainFrame类的OnCreate函数中调用SetWindowLong函数实现。
SetWindowLong(HWND hWnd, int nIndex, LONGdwNewLong)
该函数的作用是改变制定窗口的属性(包括设置新的窗口风格、设置新的窗口过程、设置新的应用程序实例局柄等)。要改变窗口的风格,则将该函数的第二个参数指定为GWL_STYLE,然后由第三个参数指定新的窗口风格。
如果是在已有类型的基础上进行修改的话,那么可以利用GetWindowLong这个函数获得这个窗口的现有类型,然后修改。例如:
SetWindowLong(m_hWnd, GWL_STYLE, GetWindowLong(m_hWnd, GWL_STYLE) & ~WS_MAXIMIZEBOX);
在应用程序窗口创建之后修改标题,可在CMainFrame类的OnCreate函数中调用SetWindowText函数实现。
在应用程序窗口创建之后修改大小,可在CMainFrame类的OnCreate函数中调用SetWindowPos函数实现。
之前对于窗口的大小、标题和风格是在创建窗口时设定的。而光标、图标和背景是在设计窗口类时指定的。窗口类的设计与注册是由MFC底层代码自动完成的,我们不可能、也不应该去修改MFC底层代码。但是我们可以编写自己的窗口类注册,然后让随后的窗口按照我们编写的窗口类去创建。
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT&cs) { if( !CFrameWnd::PreCreateWindow(cs) ) return FALSE; … WNDCLASSMyWnd; MyWnd.cbClsExtra = NULL;MyWnd.cbWndExtra = NULL; MyWnd.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); MyWnd.hCursor = LoadCursor(NULL, IDC_CROSS); MyWnd.hIcon = LoadIcon(NULL, IDI_WARNING); MyWnd.hInstance = AfxGetInstanceHandle(); MyWnd.lpfnWndProc = ::DefWindowProc; MyWnd.lpszClassName = "Hello"; MyWnd.lpszMenuName = NULL; MyWnd.style = CS_HREDRAW | CS_VREDRAW; RegisterClass(&MyWnd); cs.lpszClass = "hello"; return TRUE; }
上述代码的运行结果是:仅仅是程序的标题栏图标发生了改变,但窗口的背景和光标没有改变。原因是:视类窗口覆盖在主窗口上面,我们看到的窗口实际上是视类窗口,而上述代码修改的是框架类窗口的背景和光标。应用程序的图标属于框架窗口,因此上述程序运行后,图标发生了改变。
结论:在MFC中,如果要修改应用程序窗口的图标,则应该框架类中进行,因为框架窗口才有标题栏;如果要修改程序窗口的背景和光标,则应该在视类中进行。解决方法:在视类的PreCreateWindow函数中添加代码: cs.lpszClass= "hello";。
同时MFC为我们提供了一个全局函数AfxRegisterWndClass()。
LPCTSTR AFXAPI AfxRegisterWndClass(UINTnClassStyle, HCRSOR hCursor = 0, HBRUSH hbrBackground = 0, HICON hIcon = 0);
要在应用程序窗口创建之后修改它的光标、图标和背景,可在OnCreate函数中调用SetClassLong函数实现。DWORD SetClassLong(HWNDhWnd, int nIndex, LONG dwNewLong)
该函数的作用是:重新设置指定窗口所属窗口类的WNDCLASS结构体中指定数据成员的属性(包括设置新的窗口背景画刷、光标、图标和窗口类样式)。
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; … SetClassLong(m_hWnd,GCL_HICON, (LONG)LoadIcon(NULL, IDI_WARNING)); return 0; } int CMyMFCAppView::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CView::OnCreate(lpCreateStruct) == -1) return -1; … //7.2.2 在窗口创建之后更改光标、标题栏图标、窗口背景 SetClassLong(m_hWnd, GCL_HBRBACKGROUND, (LONG)GetStockObject(BLACK_BRUSH)); SetClassLong(m_hWnd, GCL_HCURSOR, (LONG)LoadCursor(NULL, IDC_CROSS)); return 0; }
添加IDI_ICON1-4资源,气候在框架类定义一个图标句柄成员变量,添加数组时,类型设置为HICON [4]方能设置成功。在视类添加一下代码。
m_hIcons[0] = ::LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_ICON1)); m_hIcons[1] = ::LoadIcon(theApp.m_hInstance,MAKEINTRESOURCE(IDI_ICON2)); m_hIcons[2] = ::LoadIcon(AfxGetApp()->m_hInstance,MAKEINTRESOURCE(IDI_ICON3)); m_hIcons[3] = AfxGetApp()->LoadIcon(IDI_ICON4);
其中LoadIcon第一个参数,加载第一幅时,AfxGetInstanceHandle可以获取应用程序当前句柄。第二个参数,通过MAKEINTRESOURSE宏将ID转换为相应的资源表示符字符串。第二幅应用theApp的获取应用程序的CWinApp对象,其数据成员m_hInstance得到实例句柄。但是App文件中已经定义了一个theApp全局变量,所以在框架类OnCreate函数前extern CMyMFCApp theApp。第三幅加载,用AfxGetApp全局函数实现。
在框架类OnCreate函数添加SetTime函数,没1000ms触发一次定时器消息。
SetTimer(1, 1000, NULL);
在框架类添加定时器消息(WM_TIMER)的响应函数,并在响应函数调用SetClassLong函数改变应用程序窗口图标。
void CMainFrame::OnTimer(UINT_PTR nIDEvent) { //TODO: 在此添加消息处理程序代码和/或调用默认值 static int index = 1; SetClassLong(m_hWnd, GCL_HICON, (LONG)m_hIcons[index]); index = ++index % 4; CFrameWnd::OnTimer(nIDEvent); CFrameWnd::OnTimer(nIDEvent); }
因为程序每次发送定时器消息都会调用OnTimer函数,所以把index定义为静态(分配在栈中)。
在资源的toolbar中在IDR_MAINFRAME的最右边添加一个按钮IDM_TEST。并在菜单栏【帮助】下添加一个同ID的按钮,Caption设置为Test。添加一个命令响应函数OnTestShow。可以将T按钮享有拖动一点,此时帮助与T按钮有一定空隙。想要删除只需del。
void CMainFrame::OnTestShow() { //TODO: 在此添加命令处理程序代码 MessageBox("Teston toolbar"); }
Step1:创建工具栏资源;
Step2:构造CToolBar对象;主框架添加私有变量
Step3:调用Create或CreateEx函数创建Window工具栏(工具栏也是窗口)
Step4:调用LoadToolBar函数加载工具栏资源。
在TOOLBAR添加新资源,在框架类加加一个CToolBar类型的成员变量,调用create函数创建工具栏,与CToolBar相关联,可以在框架类的OnCreate函数实现。添加一下代码。
<span style="white-space:pre"> </span>if (!m_newToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_newToolBar.LoadToolBar(IDR_TOOLBAR1)) { TRACE0("Failed to create toolbar\n"); return-1; // fail to create } m_newToolBar.EnableDocking(CBRS_ALIGN_ANY); DockControlBar(&m_newToolBar);
CreateEx函数创建工具栏,并与工具栏对象:m_newToolBar关联,停靠位置设置为CBRS_RIGHT。调用LoadToolBar加载资源。调用EnableDocking函数允许工具栏停靠客户区任意位置。最后调用DockControlBar函数,让工具栏停靠在主框架窗口上。
在【视图】自此阿达您下载添加一个菜单项。ID属性为IDM_VIEW_NEWTOOLBAR,Caption为“新的工具栏”。接着添加命令响应函数。在响应函数中,实现先前新建的工具栏的显示与隐藏。可以调用ShowWindow函数。之后需要调整他们的位置,调用RecalcLayout函数。限制或隐藏后再次调用框架类DockControlBar函数。让工具栏停靠在主框架窗口上,使用DockControlBar函数。
void CMainFrame::OnViewNewtoolbar() { //TODO: 在此添加命令处理程序代码 if (m_newToolBar.IsWindowVisible()) m_newToolBar.ShowWindow(SW_HIDE); else m_newToolBar.ShowWindow(SW_SHOW); RecalcLayout(); DockControlBar(&m_newToolBar); }
如何让新建的工具栏舍在原先显示位置显示。需要调用ShowControlBar函数。
下面,添加复选编辑。为此为菜单项添加一个UPDATE_COMMAND_UI函数。内部添加代码。
void CMainFrame::OnUpdateViewNewtoolbar(CCmdUI *pCmdUI) { //TODO: 在此添加命令更新用户界面处理程序代码 // 添加复选框 pCmdUI->SetCheck(m_newToolBar.IsWindowVisible()); }
状态栏分为两部分:提示行与指示器。左边最长的部分为提示行,通常用于显示菜单项或工具按钮的提示信息。右边由若干窗格组成的部分为状态栏指示器,通常用来显示大小写键、数字锁定键等信息。
框架程序专门提供了一个indicators数组来管理提示行与指示器。如果要修改状态栏的外观,则只需在indicators数组中添加或减少相应的字符串资源ID即可。
① 在资源编辑器中新增字符串资源ID:
ID_TIMER 时钟
② 将新的字符串资源ID添加到indicators数组中
③ 获取系统当前时间(加在CMainFrame的OnCreate函数的后部)
CTime t = CTime::GetCurrentTime(); CString str = t.Format("%H:%M:%S");
④ 将字符串显示到状态栏的窗格上,调用CStatusBar类的成员函数SetPaneText。如果不知道窗格的索引,可以调用CStatusBar类的成员函数CommandToIndex获得。m_wndStatusBar.CommandToIndex(ID_TIMER)
m_wndStatusBar.SetPaneText(1, str);⑤ 调整窗格大小
CStatusBar类的成员函数:SetPaneInfo,该函数可以为指定的窗格设置新的ID、样式和宽度。
CClientDC dc(this); CSize sz = dc.GetTextExtent(str); m_wndStatusBar.SetPaneInfo(1, ID_TIMER, SBPS_NORMAL,sz.cx);
⑥ 在OnTimer中添加相关代码。
方法一:调用SetWindowText函数设置状态栏提示行文本
需添加头文件并把m_wndStatusBar改为公有
CString str; str.Format("x=%d, y=%d", point.x, point.y); ((CMainFrame*)GetParent())->m_wndStatusBar.SetWindowText(str);
方法二:利用CFrameWnd类的成员函数SetMessageText实现,该函数的作用是在状态栏的提示行中设置文本。
((CMainFrame*)GetParent())->SetMessageText(str);
方法三:利用CFrameWnd类的成员函数GetMessageBar可以返回状态栏对象的指针,这样也不用再访问CMainFrame类的保护成员变量:m_wndStatusBar。
((CMainFrame*)GetParent())->GetMessageBar()->SetWindowText(str);
在提示行中显位图(借助位图按钮的方法)
在框架类添加CBitmapButton m_bmp变量。
CRect rc(100, 4, 120, 20); if (!m_bmp.Create("", WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, rc, &m_wndStatusBar, 0)) return FALSE; if (!m_bmp.LoadBitmaps(IDB_BITMAP1, NULL, NULL, NULL)) return FALSE;
单击[Project \ Add to Project \Components and controls…],在弹出的组件和控件库对话框中双击“Visual C++ Components”目录,在该目录下找到Splashscreen组件。
替换splsh.bmp位图文件可替换启动界面;
更改SetTimer(1, 2000, NULL)可设定启动画面的停留时间。
1)新建一个ID_BITMAP3的位图资源。
2)现在项目下新建一个类CSplashWnd,基类为CWnd;
3)在该类下添加一个protected型的变量CBitmap m_bitmap
4)添加一个Create函数加载位图,创建窗口;
public: BOOL Create(); BOOL CSplashWnd::Create() { if (!m_bitmap.LoadBitmap(IDB_BITMAP3)) return false; BITMAP bm; m_bitmap.GetBitmap(&bm); return CreateEx(0, AfxRegisterWndClass(0,AfxGetApp()->LoadStandardCursor(IDC_ARROW)), NULL, WS_POPUP | WS_VISIBLE, 0,0, bm.bmWidth, bm.bmHeight, NULL, NULL); }
5)显示窗口发送WM_PAINT消息,映射此消息;
void CSplashWnd::OnPaint() { CPaintDC dc(this); // device context for painting // TODO: 在此处添加消息处理程序代码 // 不为绘图消息调用 CWnd::OnPaint() CDC dcimage; if (!dcimage.CreateCompatibleDC(&dc)) return; BITMAP bm; m_bitmap.GetBitmap(&bm); CBitmap* pOldBitmap = dcimage.SelectObject(&m_bitmap); dc.BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &dcimage, 0, 0, SRCCOPY); dcimage.SelectObject(pOldBitmap); }
6)在App类中包含新类的头文件后,在InitInstance()函数中添加以下代码:
CSplashWnd *pSplashWindow = new CSplashWnd;//创建对象 pSplashWindow->Create(); pSplashWindow->CenterWindow(); pSplashWindow->ShowWindow(SW_SHOW); //显示窗口 pSplashWindow->UpdateWindow(); Sleep(2000); //表示启动画面持续时间 pSplashWindow->DestroyWindow(); //销毁启动画面 delete pSplashWindow; //删除
标签:
原文地址:http://blog.csdn.net/ling_xiao007/article/details/51721441