第十一课: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();
评论