第十一课:Windows样式 一、首先回忆一下WinMain一课中的创建一个窗口的几个步骤。 二、首先回忆一下MFC一课中程序执行的顺序。 三、修改Windows样式: 1. 在CMainFrame::PreCreateWindow中修改: 在窗口产生之前,会调用它的成员函数PreCreateWindow,此时窗口还没有产生,相当于一栋大楼修建之前,在它的设计图纸上修改它的式样,然后按照修改后的图纸去修建大楼。 a. 直接修改CREATESTRUCT:(让最大化按钮不可用) cs.style &= ~WS_MAXIMIZEBOX; //去掉窗口的最大化按钮 b. 重新注册WNDCLASS:(修改窗口的图标及背景) 对于窗口的图标、背景等,不能直接修改。需要重新注册WNDCLASS。我们以修改图标为例,在资源面板中添加一个图标,其ID为IDI_ICON1: i. 用AfxRegisterWndClass函数: cs.lpszClass=::AfxRegisterWndClass(NULL,NULL,NULL, AfxGetApp()->LoadIcon(IDI_ICON1)); ii. 重新填写WNDCLASS WNDCLASS wndClass; wndClass.style=CS_HREDRAW; wndClass.lpfnWndProc=(WNDPROC)::DefWindowProc; wndClass.cbClsExtra=0; wndClass.cbWndExtra=0; wndClass.hInstance=::AfxGetInstanceHandle(); wndClass.hIcon=LoadIcon(::AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_ICON1)); wndClass.hCursor=LoadCursor(NULL,IDC_NO); LOGBRUSH lgbr; lgbr.lbStyle=BS_SOLID; lgbr.lbColor=RGB(255,255,0); lgbr.lbHatch=HS_CROSS; wndClass.hbrBackground=CreateBrushIndirect(&lgbr); wndClass.lpszMenuName=NULL; wndClass.lpszClassName="It315"; RegisterClass(&wndClass); cs.lpszClass="It315"; 此时会发现窗口的图标改变了,但背景和光标没有变。应将此段代码拷入CXxxView::PreCreateWindow中。 iii. 利用GetClassInfo函数: WNDCLASS wndclass; ::GetClassInfo(AfxGetInstanceHandle(),cs.lpszClass,&wndclass); wndclass.hIcon=::LoadIcon(::AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_ICON1)); wndclass.lpszClassName="It315"; ::RegisterClass(&wndclass); cs.lpszClass="It315"; 2. 在窗口产生以后修改: 在CMainFrame::OnCreate中 a. 去掉最大化按钮: SetWindowLong(m_hWnd,GWL_STYLE, ::GetWindowLong(m_hWnd,GWL_STYLE) & ~WS_MAXIMIZEBOX); b. 修改图标: SetClassLong(m_hWnd,GCL_HICON,(long)AfxGetApp()->LoadIcon(IDI_ICON1)) 3. 制作动画图标: a. 在资源面板中添加三个图标,其ID为IDI_ICON1,IDI_ICON2, IDI_ICON3。 b. 定义一个成员变量 ,用于装入三个图标的句柄: HICON m_hIcon[3]; c. CMainFrame的构造函数中装入三个图标的句柄: m_hIcon[0]=AfxGetApp()->LoadIcon(IDI_ICON1); m_hIcon[1]=AfxGetApp()->LoadIcon(IDI_ICON2); m_hIcon[2]=AfxGetApp()->LoadIcon(IDI_ICON3); d. 在CMainFrame::OnCreate中设置定时器: SetTimer(1,200,NULL); e. 加入WM_TIMER的消息响应函数OnTimer,在其中加入代码: static i=0; SetClassLong(m_hWnd,GCL_HICON,(LONG)m_hIcon[i]); i=++i%3; 四、贴图: 在资源面板中装入一幅位图,其ID为IDB_BITMAP1,在CXxxView::OnDraw中贴图。 贴图必须以如下步骤进行: 1. 产生一个兼容DC: CDC dccompatible; dccompatible.CreateCompatibleDC(pDC); 2. 装入位图: CBitmap bmp; bmp.LoadBitmap(IDB_BITMAP1); 3. 将位图选入兼容DC: dccompatible.SelectObject(&bmp); 4. 将兼容DC上的内容拷入当前DC上: CRect rect; GetClientRect(&rect); pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dccompatible,0,0,SRCCOPY); 说明: 1. BitBlt会按1:1的比例将位图拷入,如果想在CxxxView上显示整个位图,可以用StretchBlt函数: BITMAP bitmap; bmp.GetBitmap(&bitmap); pDC->StretchBlt(0,0,rect.Width(),rect.Height(), &dccompatible,0,0, bitmap.bmWidth,bitmap.bmHeight,SRCCOPY); 2. 系统在发出WM_PAINT消息之前,会发出WM_EARSEBKGND消息,去执行真正的刷新背景的操作,可将以上代码剪贴到WM_EARSEBKGND消息的响应函数OnEraseBkgnd中去。然后将原来的return CView::OnEraseBkgnd(pDC);改为return true; 五、操作状态栏: 1. 在状态栏显示鼠标坐标: 在 CxxxView中加入WM_MOUSEMOVE的响应函数OnMouseMove,加入代码: CString str; str.Format("X=%d,Y=%d",point.x,point.y); ((CMainFrame*)GetParent())->m_wndStatusBar.SetWindowText(str); 此种方法要将CMainFrame中的m_wndStatusBar改为public类型,再在CxxxView的执行文件中加入#include "MainFrm.h"。它破坏了CMainFrame的封装性,不建议使用。改用下面的方法: ((CFrameWnd*)GetParent())->SetMessageText(str); 或者 (CFrameWnd*)AfxGetApp()->m_pMainWnd)->GetMessageBar()->SetWindowText(str); 2. 加入自定义状态栏,显示系统时间: a. 在资源面板中加入一个字符串资源,其ID为IDS_TIME。 b. 将IDS_TIME加入CMainFrame中控制状态栏的数组static UINT indicators[]中,IDS_TIME在数组中的序号决定自定义状态栏的位置。 c. 在CMainFrame::OnCreate中设置定时器和自定义状态栏的大小: SetTimer(2,1000,NULL); CTime tm=CTime::GetCurrentTime(); CString str=tm.Format("%H:%M:%S"); CClientDC dc(this); CSize sz=dc.GetTextExtent(str); m_wndStatusBar.SetPaneInfo(2,111,SBPS_POPOUT,sz.cx); m_wndStatusBar.SetPaneText(2,str); d. 在OnTimer中加入代码: if(2==nIDEvent) { CTime tm=CTime::GetCurrentTime(); CString str=tm.Format("%H:%M:%S"); m_wndStatusBar.SetPaneText(2,str); } else ………… 3. 在状态栏中加入进度条: a. CmainFrame中定义成员变量,用于产生进度条: CProgressCtrl m_ctrlProg; b. 在资源面板中加入一个字符串资源,其ID为IDS_PROGRESS。 c. 将IDS_ PROGRESS加入CMainFrame中控制状态栏的数组static UINT indicators[]。 d. 在CMainFrame中加入WM_PAINT的响应函数CMainFrame::OnPaint() CRect rect; m_wndStatusBar.GetItemRect(2,&rect); if(m_ctrlProg.m_hWnd) { m_ctrlProg.SetWindowPos(NULL,rect.left,rect.top, rect.Width(),rect.Height(),SWP_NOZORDER); } else m_ctrlProg.Create(WS_CHILD|WS_VISIBLE,rect,&m_wndStatusBar,111); e. 在OnTimer中加入触发进度条的代码: m_ctrlProg.StepIt();

评论