分享
 
 
 

开始VC之路--创建窗体

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

第一讲用Create()方法新建一个窗体应用程序

一般来讲,大多数Windows应用程序的界面都是由一个或数个窗体构成。

而VC++中提供了丰富的类库,用于创建Windows窗体应用程序。

我们一般可以通过CFreameWnd类中的Create()方法来创建一个窗体,Create()

函数的定义如下:

BOOL Create(LPCTSTR lpszClassName,

LPCTSTR lpszWindowName,

DWORD dwStyle = WS_OVERLAPPEDWINDOW,

const RECT& rect = rectDefault,

CWnd* pParentWnd = NULL, // != NULL for popups

LPCTSTR lpszMenuName = NULL,

DWORD dwExStyle = 0,

CCreateContext* pContext = NULL);

这是一个虚函数①,第一个参数lpszClassName是一个窗体类名字符串的指针

(一个WNDCLASS②结构体)。此类名可以是任意的由全局函数AfxRegisterWndClass

注册过的预定义控件类名。如果为空,则使用CWnd类的默认属性。第二个参数

lpszWindowName是作为窗体标题的字符串指针。

第三个参数dwStyle是宏定义的窗体类型,具体定义如下:

WS_BORDER 创建一个有边框的窗体。

WS_CAPTION 创建一个有标题栏的窗体(隐含了WS_BORDER). 不能和WS_DLGFRAME

一起使用.

WS_CHILD 创建一个子窗体。不能和WS_POPUP一起使用。

WS_CLIPCHILDREN 不包括在父窗体中被子窗体占用的区域。用于创建父窗体。

WS_CLIPSIBLINGS 使子窗体彼此别住;就是当一个指定的子窗体接收到一个

paint消息时,WS_CLIPSIBLINGS类型将别住所有重叠的子窗

体超过区域的部分一起更新,(如果没有使用WS_CLIPSIBLINGS

并且子窗体重叠,当你在一个子窗体的客户区绘图时,可能

会绘图到邻近的子窗体的客户区。)只与WS_CHILD一起使用。

WS_DISABLED 创建一个初始不可用的窗体。

WS_DLGFRAME 创建一个有双边但无标题的窗体。

WS_GROUP 指定一个用户可以用方向键从一个控件移到另一个控件的控

件组的第一个控件。All controls defined with the WS_GROUP

style FALSE after the first control belong to the same

group. The next control with the WS_GROUP style starts

the next group (that is, one group ends where the next

begins).

WS_HSCROLL 创建一个带水平滚动条的窗体。

WS_MAXIMIZE 创建一个最大尺寸的窗体。

WS_MAXIMIZEBOX 创建一个有最大化按扭的窗体。

WS_MINIMIZE 创建一个初始最小化的窗体。只与WS_OVERLAPPED一起使用。

WS_MINIMIZEBOX 创建一个有最小化按扭的窗体。

WS_OVERLAPPED 创建一个重叠窗体。一个重叠窗体一般有标题和边框。

WS_OVERLAPPEDWINDOW 创建一个和WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU,

WS_THICKFRAME, WS_MINIMIZEBOX, and WS_MAXIMIZEBOX一

使用的重叠窗体。

WS_POPUP 创建一个弹出式窗体。不能和WS_CHILD一起使用。

WS_POPUPWINDOW 创建一个和WS_BORDER, WS_POPUP, and WS_SYSMENU一起使

用的弹出式窗体。WS_CAPTION必须和WS_POPUPWINDOW组合使

用才能让控件菜单可见。

WS_SYSMENU 创建一个在标题栏有控件菜单框的窗体。只能和有标题栏的

窗体一起使用。

WS_TABSTOP 指定任意数量控件中的一个可以由用户使用TAB键移动到的

控件。TAB键使用户移动到由WS_TABSTOP指定的下一个控件。

WS_THICKFRAME 创建一个有厚边框的Window,使其可以改变大小。

WS_VISIBLE 创建一个初始可见的窗体。

WS_VSCROLL 创建一个有垂直滚动条的窗体。

由于上表中常量可以进行组合,用按位或运算,所以常量名的值被定义为类似于

0x00C00000L的32位16进制数型式。例如进行WS_SYSMENU|WS_MINIMIZEBOX运算时即

0x00080000L|0x00020000L。数字前面的0x是16位数的标识符,L表示32位,上式的演

算式可表示如下:

=

00000000000010000000000000000000

(|) 00000000000000100000000000000000

------------------------------------------

00000000000010100000000000000000 = 0X000A0000L = 655360;

当你用十进制数655360替代WS_SYSMENU|WS_MINIMIZEBOX作为实参时,你会看到相

同的结果。

第四个参数rect是一个RECT结构体的对象,用于指定窗体的尺寸和位置。RECT结

构体的定义如下:

typedef struct tagRECT

{

LONG left;

LONG top;

LONG right;

LONG bottom;

} RECT, *PRECT, NEAR *NPRECT, FAR *LPRECT;

我们可以利用从tagRECT结构体派生出的CRect类的构造函数来初始化一个RECT结构

体。CRect的一个重载构造函数定义如下:

// from left, top, right, and bottom

CRect(int l, int t, int r, int b);

第五个参数pParentWnd用于指定父窗体,这是一个指向CWnd类对象的指针。第六

个参数nID用于指定作为子窗体的窗体ID。最后一个参数是关于创建内容的指针,已

被默认为NULL,不用理会。

注释:

①虚函数的作用:如果没有把需要在派生类中重载的同名

基类函数定义为虚函数,则当用基类定义的指针指向派生类对象的地址时(赋

值兼容规则),通过此指针调用的该同名函数是在基类中定义的;反之如果定

义的虚函数,则通过指针调用的该同名函数是在指针指向的对象中定义的。

第二讲Create()方法的应用

下面是一个用CFrameWnd类的Create()函数创建一个窗体的例子:

/////////////////////////////////////////////

#include <afxwin.h>

class CMyWnd:public CFrameWnd

{

public:

CMyWnd()

{

Create(AfxRegisterWndClass(CS_DBLCLKS,0,HBRUSH(COLOR_WINDOWFRAME),AfxGetApp()->LoadStandardIcon(IDI_APPLICATION)),__T("Creamdog"),WS_SYSMENU,CRect(100, 100, 500, 500),this,NULL);

ShowWindow(SW_SHOWNORMAL);

};

};

class CMyApp:public CWinApp

{

public:

virtual BOOL InitInstance()

{

m_pMainWnd=new CMyWnd;

return TRUE;

};

};

CMyApp myApp;

/////////////////////////////////////////

首先从其类CFrame中派生出CMyWnd类,并定义构造函数,用于生成一个新窗体。

在构造函数中是使用Creat()函数创建窗体的,其中系统全局函数AfxRegisterWndClass()

用于注册一个窗体类,该函数的具体定义如下:

LPCTSTR AFXAPI AfxRegisterWndClass(UINT nClassStyle,HCURSOR hCursor = 0, HBRUSH hbrBackground = 0, HICON hIcon = 0);

第一个参数nClassStyle指定了窗体类的类型,如果为NULL则所有参数都使用

默认值。具体默认值为:

nClassStyle=CS_DBLCLKS;//响应双击事件

hCursor=IDC_ARROW;//标准箭头

hbrBackground=Null;//不更新背景

hIcon=IDI_APPLICATION;//Windows徽标(在WinXP中为小窗口)

由于用默认值时窗体不会更新,一般函数的四个参数需要人为指定,第一个参数

设为为CS_DBLCLKS即可。CS_DBLCLKS是窗体类型的一个宏定义,下表列出了所有窗体

类型的宏定义。

CS_BYTEALIGNCLIENT 在字节边界(在X方向)上对齐窗体的客户区。此类型将影

响到在窗体显示时它的宽度和它的水平位置。

CS_BYTEALIGNWINDOW 在字节边界(在X方向)上对齐窗体。此类型将影响到在窗

体显示时它的宽度和它的水平位置。

CS_CLASSDC 分配一个设备环境并被类中的所有窗体共享。由于窗体类

被处理特化,它是可以适用于一个应用程序的若干线程创

建一个相同类的窗体。它同样适用于多个线程试图同时使

用相同的设备环境。当此种情况发生时,系统只允许一个

线程去成功的它的绘图操作。

CS_DBLCLKS 当指针在属于此类的窗体内部,并且用户双击鼠标时,将

会发送一个双击消息到窗体程序。

CS_GLOBALCLASS 指定此窗体类是一个应用程序全局类。应用程序全局类是

由一个在进程中对所有模块有效的exe或ddl注册的一个窗

体类。

CS_HREDRAW 如果窗体被移动或尺寸调整器改变了客户区的大小,重绘

全部的窗体。

CS_NOCLOSE 关闭按扭不可用。

CS_OWNDC 为此类中的每一个窗体分配唯一的设备环境。

CS_PARENTDC 设置子窗体中剪下的矩形到父窗体中,以使子窗全可以在父

窗体上绘图。一个具有CS_PARENTDC属性控制的窗体从设备

环境的系统缓存中接收到一个规则的设备环境。它不把父窗

体的设备环境或设备环境设置给予子窗体。指定CS_PARENTDC

以提高应用程序的性能。

CS_SAVEBITS 保存被此类的一个窗体摭住的屏幕图象的一部分为位图。当

窗体被移动,系统使用保存过的位图去恢复屏幕图象,包括

其它被摭住的窗体。因此如果被位图使用内存没有被释放,

并且其它的屏幕动作没有使储存的图像无效。系统不会发送

WM_PAINT消息到被摭盖的窗体。

这种类型对在其它屏幕动作发生时被暂时显示小窗体(如菜

单或对话框)很有用。这种类型增加了显示窗体所需的时间,

因为系统必须先分配内存去存储位图。

CS_VREDRAW 如果窗体被移动或尺寸调整器改变了客户区的高度,重绘

全部的窗体。

上表中的宏定义值是类似于0x0080的16位16进制数,因此它们之间可以用按位

或 | 符号进行组合,原理前面以经介绍过了。

第二个参数hCursor为鼠标指针的句柄,但由于在窗体打开事件发生时,光标就

会被重绘为箭头,因此在注册窗体类时对此进行设置意义不大,设为0即可。如果需

要定义光标,首先应关闭数标重绘,方法是:重载窗体类基类的OnSetCursor()函数,

让其返回TRUE值,这样当重绘时调用OnSetCursor()函就不起作用了。可以用下面的

语句进行设置。

SetCursor(AfxGetMainWnd()->LoadStandardCursor(IDC_IBEAM));

其中::SetCursor()是全局函数,用来设置整个例程的光标参数是宏定义光标句

柄。AfxGetMainWnd()是一个系统函数,它返回当前主窗体的句柄。而CWinApp的

LoadStandardCursor()成员函数用来读取一个系统指针,每一种系统指针的具体宏

定义如下:

IDC_APPSTARTING 带小沙漏的标准箭头

IDC_ARROW 标准箭头

IDC_CROSS 十字光标(用于定位)

IDC_HAND Windows 2000:手型

IDC_HELP 带问号的箭头

IDC_IBEAM I型标

IDC_ICON Obsolete for applications marked version 4.0 or later.

IDC_NO 禁止符号

IDC_SIZE Obsolete for applications marked version 4.0 or later. Use IDC_SIZEALL.

IDC_SIZEALL 十字箭头

IDC_SIZENESW 指向东北和西南的双向箭头

IDC_SIZENS 指向南和北的双向箭头

IDC_SIZENWSE 指向西北和东南的双向箭头

IDC_SIZEWE 指向东西的双向箭头

IDC_UPARROW 上箭头

IDC_WAIT 沙漏

上表中宏定义值为类似于MAKEINTRESOURCE(32649)的函数,MAKEINTRESOURCE()的

定义如下:

#define MAKEINTRESOURCEW(i) (LPWSTR)((DWORD)((WORD)(i))) //UNICODE

#define MAKEINTRESOURCE MAKEINTRESOURCEW

将其还原为容易理解的C代码:

char *(unsigned long(unsigned short(32649))

至于为什么系统要将其倒来倒去,是为了在重载函数中和一般的整形实参相区

别(本人估计)。另外,如果想要使用自定义图标或指针文件,则牵扯到实例资源

分配的问题,将在以后进行说明。

第三个参数hbrBackground,指定窗体背景的画笔资源,应该指定一个,否则

背景将不会更新。此参数可使用系统颜色,定义如下:

COLOR_SCROLLBAR 0

COLOR_BACKGROUND 1

COLOR_ACTIVECAPTION 2

COLOR_INACTIVECAPTION 3

COLOR_MENU 4

COLOR_WINDOW 5

COLOR_WINDOWFRAME 6

COLOR_MENUTEXT 7

COLOR_WINDOWTEXT 8

COLOR_CAPTIONTEXT 9

COLOR_ACTIVEBORDER 10

COLOR_INACTIVEBORDER 11

COLOR_APPWORKSPACE 12

COLOR_HIGHLIGHT 13

COLOR_HIGHLIGHTTEXT 14

COLOR_BTNFACE 15

COLOR_BTNSHADOW 16

COLOR_GRAYTEXT 17

COLOR_BTNTEXT 18

COLOR_INACTIVECAPTIONTEXT 19

COLOR_BTNHIGHLIGHT 20

第四个参数为程序图标的标识符,为0时是默认的Windows徽标。与光标同样,

需要自定义图标时,添加设置图标的语句,例如:

AfxGetMainWnd()->SetIcon(AfxGetApp()->LoadStandardIcon(IDI_EXCLAMATION),FALSE);

与设置光标不同的是,设置光标的函数是全局函数,而设置图标的函数是

CWinApp类的成员函数(因为图标只在窗体内有效),故在函数调用之前需要用系

统函数AfxGetMainWnd()来获取当前主窗体的句柄,再用CWinApp的LoadStandardIcon()

成员函数来读取系统图标并返回一个图标的句柄,最后CFrameWnd类的SetIcon()

成员函数将窗体的图标设置为刚才返回的图标句柄。

回到刚才的Create()语句,第一个参数用的是刚才注册的类名。第二个参数中

用到了强制类型转换(__T),这个数据类型不对字符串做任何的改变,只是起到规

范化编程的做用。第三个参数是前面提过的窗体类型,WS_SYSMENU是使窗体具有最

大化、最小化、关闭三个按扭。第四个参数使窗体在所给出的位置和尺寸上打开。

第五个参数this的意义是此窗体为父窗体。第六个参数表示无子窗体。

ShowWindow()故名思意,即显示窗体。其参数nCmdShow是确定窗体被怎样显示。

它必须是下面宏定义中的一个:

SW_HIDE 0 隐藏此窗体并激活其它窗体。

SW_MAXIMIZE 3 激活并显示此窗体为最大化。

SW_MINIMIZE 6 最小化指定的窗体并激活下一个在Z顺序中位

于顶层的窗体。

SW_RESTORE 9 激活并显示此窗体。如果此窗体已被最大化或

最小化,系统将恢复此窗体至原尺寸和原位置。

一个应用程序应该在恢复一个最小化窗体时指

定这个标记。

SW_SHOW 5 在当前尺寸和位置上激活并显示此窗体。

SW_SHOWMAXIMIZED 3 同SW_MAXIMIZE

SW_SHOWMINIMIZED 2 激活并显示此窗体为最小化。

SW_SHOWMINNOACTIVE 7 显示此窗体为最小化。这个值类似于SW_SHOWMINIMIZED,

除非窗体未被激活。

SW_SHOWNA 8 在最近一次的尺寸和位置显示此窗体,这个值

类似于SW_SHOWNORMAL,除非窗体未被激活。

SW_SHOWNOACTIVATE 4 在当前的尺寸和位置显示此窗体。这个值类似于SW_SHOW,

除非窗体未被激活。

SW_SHOWNORMAL 1 激活并显示一个窗体。如果此窗体已被最大化

或最小化,系统将恢复此窗体至原尺寸和原位置。

一个应用程序应该在第一次打开这个窗体时指定

这个标记。

有关窗体框架的定义就结束了,下面是由CWinApp基类派生出的类CMyApp,在

类定义中对基类中的虚成员函数InitInstance()进行了重载,关于虚函数的有关概

念前面以经提过了。在开始说明此函数内部的语句时首先需要对CWinApp的数据成员

m_pMainWnd进行说明。

m_pMainWnd数据成员被用于储存一个指向你的线程中主窗体对向的指针。当涉

及到m_pMainWnd的窗体被关闭时,MFC库将自动的终止你的线程。如果此线程为你的

应用程序中的主线程,应用程序也将同样被终止。如果此数据成员为NULL,当终止

此线程时,为了应用程序的CWinApp对象的主窗体也将常常被终止。m_pMainWnd是

CWnd类指针的一个公有变量。

一般来讲,当你重载InitInstance()函数时设置此变量。在一个工作线程中,

此数据成员的值是从它的父线程中继承来的。

正如上面所说,例子中在重载InitInstance()函数时对此变量进行了赋值,让

它指向一个新的框架窗体类对象,而这个对象是由刚才定义的派生类CMyWnd实例化

出来的。下来返回一个真值,表示初始化实例成功。

最后,用CMyApp类实例化出一个对象,名子随意。系统将对前面定义的类和函

进行构造,这样就完成了一个简单窗体的创建。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有