2007年12月5日星期三

MFC中窗体的控制

1、在CMainFrame的PreCreateWindow(CREATESTRUCT& cs)函数中,加入:
cs.cx=300;
cs.cy=400;
即可控制窗体初始化时的大小。

2、加入这段代码可以设置一个没有“最小化”按钮和“最大化”按钮,也没有大小可调边框的主框架窗口。此窗口最初在屏幕上居中。
cs.style = WS_OVERLAPPED | WS_SYSMENU | WS_BORDER;
// Size the window to 1/3 screen size and center it
cs.cy = ::GetSystemMetrics(SM_CYSCREEN) / 3;
cs.cx = ::GetSystemMetrics(SM_CXSCREEN) / 3;
cs.y = cs.cy;// ((cs.cy * 3) - cs.cy) / 2;
cs.x = cs.cx;//((cs.cx * 3) - cs.cx) / 2;

3、如果要在创建窗体前设置标题,需加入一下两行:
cs.style &= ~FWS_ADDTOTITLE; //如果style中已经有WS_OVERLAPPED,如上例,就已经包含了~FWS_ADDTOTITLE项;
cs.lpszName = "http://www.icafe8.net";

4、如果在窗体创建时改变窗体的一些属性,可以用SetWindowLong()函数,如:
SetWindowLong(m_hWnd,GWL_STYLE, GetWindowLong(m_hWnd,GWL_STYLE) & ~WS_MAXIMIZEBOX); //先获取窗体的类型,然后禁用最大化按钮。

5、创建一个窗体:
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="limeng's window";
wndcls.lpszMenuName=NULL;
wndcls.style=CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wndcls); //将窗体注册到类
cs.lpszClass="limeng's window"; //这里的名字必须和上面创建的wndcls类的名字相同
return TRUE;
}
注意:上面的代码只写在MainFrame中,必须在View窗体中增加最后一行,否则将无法看到效果,因为View窗体始终覆盖在Main窗体之上。

6、如果觉得上面的方法太烦,我们可以通过AfxRegisterWndClass函数简单的改变一个窗体的样式:
可以在MainFrame的PreCreateWindow中加入:
cs.lpszClass=AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,0,0,LoadIcon(NULL,IDI_WARNING)); //因为在框架中设置鼠标和底色是无法体现的,所以设置为0。
在View的PreCreateWindow中加入:
cs.lpszClass=AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW, LoadCursor(NULL,IDC_HELP),(HBRUSH)GetStockObject(DKGRAY_BRUSH), 0);//而在View窗体中,图表设置又是无效的,所以为0

7、有意思的的是,如果在Main和View的PreCreateWindow中用默认的参数注册窗口:
cs.lpszClass=AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW);
结果,鼠标是默认的箭头鼠标,图标为window默认的波浪图标,但是窗口因为是空的画刷,所以你可以看到一个透明的窗口,但是你拖动窗体时,窗体不会重绘,所以能保持刚才的背景图画,除非窗体被重画的动作发生,如最小化,或别的窗体在此窗体的顶部停留。

8、这里我们可以通过SetClassLong对窗体的单个属性进行设置。
在main框架函数的OnCreate函数中写入:
SetClassLong(m_hWnd,GCL_HICON,(LONG)LoadIcon(NULL,IDI_WARNING));//设置窗体的图标为IDI_ERROR
右键点View窗体类,增加一个WM_CREATE消息相应函数,在View窗体的OnCreate函数中写入:
SetClassLong(m_hWnd,GCL_HBRBACKGROUND,(LONG)GetStockObject(DKGRAY_BRUSH));//设置背景为灰色
SetClassLong(m_hWnd,GCL_HCURSOR,(LONG)LoadCursor(NULL,IDC_HELP));//设置鼠标为help类型
便可以得到如6中相同的效果。

9、接下来我们试着设计一个程序,让他在3个图标中每秒切换一个。
首先我们在插入资源中,导入3张.ico的图片,资源ID号分别为IDI_ICON1,IDI_ICON2,IDI_ICON3。然后在MainFrame中添加一个数组成员变量:
private:
HICON m_hIcons[3];
在MainFrame的OnCreate函数中,将icon加载进来:
m_hIcons[0]=LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_ICON1)); /*方法一,通过全局函数直接获得当前实例的句柄,然后直接将图标的ID号转换为资源名称。*/
m_hIcons [1]=LoadIcon(theApp.m_hInstance,MAKEINTRESOURCE(IDI_ICON2)); /*方法二,利用 CWinApp派生的App类中。注意要在函数前面申明引用外部变量extern CStyleApp theApp。*/
m_hIcons[2]=LoadIcon(AfxGetApp()->m_hInstance,MAKEINTRESOURCE(IDI_ICON3)); /*方法三,通过获得应用程序的成员变量。*/
SetTimer(1,1000,NULL); //设置一个每1秒钟触发一次的OnTimer事件
在MainFrame中增加一个OnTimer的Windows消息相应函数:
static int index=0; //注意用静态变量,否则会被每次调用OnTimer事件时初始化为0。
SetClassLong(m_hWnd,GCL_HICON,(LONG)m_hIcons[index]);
index=++index%3; //取模,让index限定在0-2之间。

没有评论: