vc++学习笔记9-----修改程序外观,状态栏,工具栏
修个一个窗口的样式可以再函数BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs),中改变;
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) { if( !CFrameWnd::PreCreateWindow(cs) ) return FALSE; // TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs cs.cx=300;//修改窗体的高和款,显示 cs.cy=200; return TRUE; }
改变窗体名字
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) { if( !CFrameWnd::PreCreateWindow(cs) ) return FALSE; // TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs cs.style&=~FWS_ADDTOTITLE;//将此类型取反然后和style想与; //等价于直接对style赋值,cs.stytle=ws_overlappedwindow; cs.lpszName="我的测试"; return TRUE; }
SetWindowLong()窗口建立后,改变窗口属性;LONG SetWindowLong( HWND hWnd, int nIndex, LONG dwNewLong );修改时,在OnCreat函数中改变;
MFC中所有从CWnd派生的类都是窗口类,这些类中都有一个公有的成员变量保存了和这个对象相关的窗口的句柄,(m_hwnd);
SetWindowLong(m_hWnd,GWL_STYLE,WS_OVERLAPPEDWINDOW );//其中还有GetWindoLong()这个函数的问题;自己看
定义自己的窗口类,修改背景,图标等等;
定义属于自己的窗口类,在框架类中定义(MainFrame)因为只有框架类才有标题栏等等,但是修给背景色,和图标要在View类里面~
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) { if( !CFrameWnd::PreCreateWindow(cs) ) return FALSE; WNDCLASS wndcls; wndcls.cbClsExtra=0; wndcls.cbWndExtra=0; wndcls.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH); wndcls.hCursor=LoadCursor(NULL,IDC_HELP); wndcls.hIcon=LoadIcon(NULL,IDI_ERROR); wndcls.hInstance=AfxGetInstanceHandle();//返回当前应用程序句柄 wndcls.lpfnWndProc=::DefWindowProc;//默认的函数处理;加上::表示调用的是全局函数 wndcls.lpszClassName="我的测试窗口";//此处必须和下面的cs的类名保持一致;指示此类的标识 wndcls.lpszMenuName=NULL;//菜单的创建并不是创建窗口类确定的;是在initInsistance()将资源菜单传入 //pDocTemplate = new CSingleDocTemplate( /* IDR_MAINFRAME, RUNTIME_CLASS(CSytleDoc), RUNTIME_CLASS(CMainFrame), RUNTIME_CLASS(CSytleView)); */ wndcls.style=CS_VREDRAW|CS_HREDRAW;//是窗口类的style而不是窗口的类型; RegisterClass(&wndcls); cs.lpszClass="我的测试窗口"; return TRUE; }view类里面修改background和cursor;
BOOL CSytleView::PreCreateWindow(CREATESTRUCT& cs) { cs.lpszClass="我的测试窗口"; return CView::PreCreateWindow(cs); }
修给图标,背景的另一种实现:利用AfxRegisterWndClass()函数;
首先在Mainframe的PreCreateWindow()里面修给Icon
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
cs.lpszClass=AfxRegisterWndClass(CS_VREDRAW|CS_HREDRAW,0,0,LoadIcon(NULL,IDI_WARNING));
return TRUE;
}
其次在VIew里面修给background和cursor;
BOOL CSytleView::PreCreateWindow(CREATESTRUCT& cs) { cs.lpszClass=AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW,LoadCursor(NULL,IDC_CROSS),(HBRUSH)GetStockObject(DKGRAY_BRUSH),0); return CView::PreCreateWindow(cs); }
在已经创建好窗口时,修改窗口类型;利用全局API函数,DWORD GetClassLong( HWND hWnd, int nIndex );和DWORD GetClassLong( HWND hWnd, int nIndex );
SetClassLong( m_hWnd,GCL_HICON,(long)LoadIcon(NULL,IDI_WARNING) );//在onCreate函数里面添加
修改背景和光标的时候在View里面修改, 增加消息处理器对WM_CREATE响应;
====================================================================================================================================
动态改变窗口的ICON:
1、首先添加三个ICON;
2、然后在MainFrame里面的OnCreate函数加载这些图标;
m_hicons[0]=LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_ICON1));//AfxGetInstanceHandle()全局函数获得当前句柄 m_hicons[1]=LoadIcon(theApp.m_hInstance,MAKEINTRESOURCE(IDI_ICON2));//theApp是全局变量,单文档MFC生了一个sytleApp,指示当前这个应用程序 m_hicons[2]=LoadIcon(AfxGetApp()->m_hInstance,MAKEINTRESOURCE(IDI_ICON3));//afxGetApp函数返回当前应用程序指针; SetTimer(1,1000,NULL);//设定计时器,以规律改变图像 return 0; }
3、添加消息响应函数,响应WM_TIMER的消息
void CMainFrame::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default static int index=0;//如果不声明静态变量或者全局变量,index是局部变量随着timer到时,而被销毁,也就是inde一直为0,也就一直显示一个图片; SetClassLong(m_hWnd,GCL_HICON,(LONG)m_hicons[index]); //设置图标显示; index=++index%3;//将一个变量控制在一个取值范围之内,可以对该范围取模; CFrameWnd::OnTimer(nIDEvent); }
================================================================================================================================
创建自己的工具栏 toolbar
首先创建自己的toolbar资源
其次在MainFrame的oncreate函数里面建立自己的toolbar对象
if (!m_wndNewToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_RIGHT//创建自己的toolbar | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_wndNewToolBar.LoadToolBar(IDR_TOOLBAR1)) { TRACE0("Failed to create toolbar\n"); return -1; // fail to create } m_wndNewToolBar.EnableDocking(CBRS_ALIGN_ANY);//工具栏可以停靠主窗口; EnableDocking(CBRS_ALIGN_ANY);//主窗口可以被工具栏调控 DockControlBar(&m_wndNewToolBar);//将自己创建的工具栏停靠在主窗口另一个简单的函数来实现上面的功能ShowControlBar(&m_wndNewToolBar,!m_wndNewToolBar.IsWindowVisible(),TRUE);
void CMainFrame::OnViewNewtool() { ShowControlBar(&m_wndNewToolBar,!m_wndNewToolBar.IsWindowVisible(),TRUE);//利用此函数显示toolbar更加简单方便 }给菜单选项添加复选框,首先添加复选响应函数;onUpdate...
void CMainFrame::OnUpdateViewNewtool(CCmdUI* pCmdUI) { pCmdUI->SetCheck(m_wndNewToolBar.IsWindowVisible());//工具栏添加复选标记 如果IsWindowVisible()返回为真则设置为1 }
====================================================================================================================================状态栏的设置statusbar;
static UINT indicators[] =//指示器数组显示状态栏下面的状态显示,自己可以添加该数组,添加stringtable 串 { ID_SEPARATOR, // status line indicator ID_INDICATOR_CAPS, IDS_TIMER IDS_progress,//自己添加时钟和进度栏; ID_INDICATOR_NUM, ID_INDICATOR_SCRL, };
在Oncreate()函数里面添加对应状态栏信息,添加:
//添加时钟的消息响应; CTime t=CTime::GetCurrentTime();//获得当前时间,但是此时间 显示的时候是固定的不能够动态变化 CString str=t.Format("%h:%m:%s"); //CStatusBar::CommandToIndex()返回指定ID的索引 int index=m_wndStatusBar.CommandToIndex(IDS_TIMER); //CStatusBar::SetPaneText() 设置状态的内容,根据ID m_wndStatusBar.SetPaneText(index,str);
讲上面的函数优化,在设定statusbar 的时候,会产生不能完全显示的情况,因此要对statusbar扩充宽度;放在定时器里面响应 ontimer();
void CMainFrame::OnTimer(UINT nIDEvent) { CTime t=CTime::GetCurrentTime();//获得当前时间 CString str=t.Format("%H:%M:%S");//转为时间显示格式CTime::Format //CStatusBar::SetPaneInfo()可以设定panel的宽度,样式等等信息 CClientDC dc(this); CSize sz=dc.GetTextExtent(str);//获得当前欲显示的字符串的长度;高度等等 //CStatusBar::CommandToIndex()返回指定ID的索引 int ID=m_wndStatusBar.CommandToIndex(IDS_TIMER);//取得欲改变的ID m_wndStatusBar.SetPaneInfo(ID,IDS_TIMER,SBPS_NORMAL,sz.cx);//设定欲显示的宽度 //CStatusBar::SetPaneText() 设置状态的内容,根据ID m_wndStatusBar.SetPaneText(ID,str); CFrameWnd::OnTimer(nIDEvent); }===================================================================================================================================
对IDS_progress的进度栏的显示;
CProgeressCtrl::Create()函数;创建进度栏显示;首先在MainFrame里面创建对象m_progress;
然后在oncreate()创建进度栏;
m_progress.Create(WS_CHILD|WS_VISIBLE|PBS_VERTICAL,CRect(100,100,120,200),this,123);//创建进度栏 m_progress.SetPos(50);//创建状态栏位置;
在statusbar添加状态栏的显示:
获得状态栏的矩形区域作为进度栏的矩形区域显示;在oncreate函数创建完成之后,发送一个UM_CREATE消息,(备注:在此使用postMessage()让其排入消息队列,而不用sendMessage(),SendMessage直接把消息发给消息处理函数处理)然后捕捉此消息,建立状态显示框;
建立自己消息UM_PROGRESS
#define UM_PROGRESS WM_USER+1//WM_UEER 是系统定义的用户消息的界限建立消息响应函数(MainFrame)
afx_msg void OnProgress();建立消息映射
ON_MESSAGE(UM_PROGRESS,OnProgress)在OnCreate函数中发送消息
PostMessage(UM_PROGRESS);实现消息响应函数
void CMainFrame::OnProgress() { CRect rect; m_wndStatusBar.GetItemRect(2,&rect);//2是状态栏区域的ID m_progress.Create(WS_CHILD|WS_VISIBLE,rect,&m_wndStatusBar,123);//创建进度栏 m_progress.SetPos(50); }
此时创建的状态栏是固定的,如果窗口发生变化,状态栏的绝对位置并没有改变,因为必须在窗口重绘的时候重新获得satusbar的位置;
创建对WM_PAINT的消息响应函数;此时不postmessage()可以直接对WM_PAINT响应;
void CMainFrame::OnPaint()
{
CPaintDC dc(this); // device context for painting
CRect rect;
m_wndStatusBar.GetItemRect(2,&rect);//2是状态栏区域的大小
if (!m_progress.m_hWnd)//首先判断该进度栏是否被创建,已经创建的话,就不用在此创建,最简单的方法是判断其句柄
{
m_progress.Create(WS_CHILD|WS_VISIBLE,rect,&m_wndStatusBar,123);//创建进度栏
m_progress.SetPos(50);
}
else
m_progress.MoveWindow(rect);//窗口发生变化的时候,讲进度栏移动到矩形区域
}
在定时器OnTimer()函数里面添加让进度条逐渐增加的函数stepIt()m_progress.StepIt();在状态栏实时显示鼠标的位置:
首先添加一个消息响应函数 响应WM_MOUSEMOVE消息
void CSytleView::OnMouseMove(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CString str; str.Format("x=%d,y+%d",point.x,point.y); ((CMainFrame*)GetParent())->m_wndStatusBar.SetWindowText(str);//因为在view获得鼠标移动位置,然后在MainFrame里面显示所以获得框架指针 CView::OnMouseMove(nFlags, point); }
==================================================================================================================================
添加启动画面,利用VC自动的组件类就可以实现
点击“project”—>点击add to project --->点component and control ---->选择 visual c++ components ----》选择 splash windo 自动添加 启动图片