原文:http://blog.sina.com.cn/s/blog_413115f7010006fi.html
以上的标识符可以在WINUSER.H中找到。函数返回代表该图标对象的句柄。
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
LoadCursor()函数加载一个预先定义的光标,并返回该项光标的句柄。该项句柄被赋给WNDCLASS结构的hCursor域。当鼠标经过"基于此窗口类创建的窗口"时,它变成一个小箭头。不过因为之前的光标也是小箭头,所以我们看不出光标的变化。下面是预定义的鼠标指针标识符:
IDC_APPSTARTING 标准箭头及小沙漏
IDC_ARROW 标准箭头
IDC_CROSS 十字交叉
IDC_HAND (Windows2000)手形
IDC_HELP 箭头和问号
IDC_IBEAM 文本I形
IDC_ICON 空图标
IDC_NO 斜杠圈
IDC_SIZE 四向箭头
IDC_SIZEALL 四向箭头
IDC_SIZENESW 指向东北和西南的双向箭头
IDC_SIZENS 指向南北的双向箭头
IDC_SIZENWSE 指向西北和东南的双向箭头
IDC_SIZEWE 指向东西的双向箭头
IDC_UPARROW 垂直箭头
IDC_WAIT 沙漏
您可以把语句中的IDC_ARROW换成别的,然后再编译运行一次。当您把鼠标移到窗口上面时会看到不同的结果。试一试啊!!你可以先试一试IDC_CROSS。
wndclass.hCursor = LoadCursor(NULL, IDC_CROSS);
然后编译运行一次。把鼠标移到窗口对象上面,看看鼠标有什么变化?鼠标是不是变成十字形了?之前的LoadIcon()也是同样道理,您可以试着换一下第二个参数。看看有什么变化。
wndclass.hbrBackground = GetStockObject(WHITE_BRUSH);
设定基于此窗口类创建的窗口对象的背景颜色。hbr代表“handle to a brush(刷子句柄)”。刷子是图形学上的术语。指用来填充一个区域的着色像素模式。Windows有几个标准刷子,也称为备用(stock)刷子。上面所示的GetStockObject()调用将返回一个白色刷子的句柄。窗口客户区将完全为白色。这是一种及其普遍的做法。
wndclass.lpszMenuName = NULL;
指定窗口类菜单。HelloWin没有菜单,所以这项为NULL。
wndclass.lpszClassName = szAppName;
给这个窗口类取名字。以后就用这个名字认它了。
if (!RegisterClass (&wndclass))//为程序窗口注册窗口类
{
}
创建一个窗口首先需要注册一个窗口类。RegisterClass()的功能是注册窗口类。但是注册窗口类并不是每次都能成功。所以应该有一个查错机制。
RegisterClass()注册失败后会返回0。所以当窗口类注册失败后if为真,接着执行MessageBox()。执行MessageBox()的结果是显示一个消息框,并显示"This program requires Windows NT!"。然后退出整个程序。这段英文的大概意思是说"本程序需要Windows NT的支持!"。如果您使用的是Windows98,当您运行附书光盘中的HelloWin.exe时可能有机会看到这个消息框。我的是Win2k,所以看不到啊。出现这个消息框表明注册窗口类失败。
窗口类定义了窗口的一般特征,可以使用同一窗口类创建许多不同的窗口。调用CreateWindow()创建窗口时指定有关窗口的更详细的信息。
为什么一个窗口的所有特征不能被一步到位指定呢?实际上以这种方式分开这些风格信息是非常方便的。例如,所有的按钮窗口都可以基于同样的窗口类来创建。与这个窗口类相关的窗口过程位于Windows内部。所有的按钮都是以同样的方式工作的。但是每一个按钮都有不同的尺寸,不同的屏幕位置,以及不同的文本串。这些不同的特征是CreateWindow()定义的一部分,而不是窗口类定义的。
hwnd = CreateWindow (szAppName, // 指定一个窗口类,基于该窗口类创建窗口
我们要关注的是第三个参数WS_OVERLAPPEDWINDOW
WINUSER.H中对WS_OVERLAPPDWINDOW定义如下。
#define WS_OVERLAPPDWINDOW (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX)
您想搞清楚这一长串到底是什么东东吗?很…很…很Easy!这是定义该窗口对象的风格。从上面的语句里可以看出第三行的真正的内容是:
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX
问题是书上没有说明上面六个WS_XXXX都是干什么用的,所以只能由我们自己想办法。
请将第三个参数WS_OVERLAPPDWINDOW换成:
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX
接下来要做的就是把六个WS_XXXX一个一个地去掉,每去掉一次就重新编译一次,看看窗口会变成什么样子。首先去掉WS_SYSMENU,也就是说第三个参数变成了:
WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX
然后编译一次,您会Lucky地看到您的HelloWin.exe已经是面目全非了,窗口右上角的三个按钮不见了,左上角的小图标也不见了,用鼠标右击标题栏时不会出现系统菜单。由此我们已经知道WS_SYSMENU的含义了。接下来让我们看看WS_MINIMIZEBOX,WS_MAXIMIZEBOX是干什么用的,改成如下所示后,再编译
WS_OVERLAPPED |WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
您会High地看到右上角只有一个按钮了,最大化,最小化两个按钮消失于时间和空间的尽头……以此类推,您可以一个一个的试。
第四,第五个参数分别是窗口对象在屏幕上的x,y坐标,准确地说是窗口对象的左上角的坐标。
第六,第七个参数分别是窗口对象的宽度和高度。
第八个参数父窗口句柄。您不知道父窗口是什么东东?好,请打开记事本程序,按CTRL+O,会发现出现一个窗口,这个窗口总是在记事本上面,这个窗口是记事本的子窗口,而记事本就是父窗口。OK?还不知道?………………HelloWin没有父窗口,也就没有子窗口。所以这一项选的是NULL。
HelloWin没有菜单,所以第九项也是NULL。
第十项,书上写的是,hInstance是程序的实例句柄,也就是说这个句柄代表的是程序自身。同时它也是WinMain()的参数之一。
第十一项,窗口对象的参数指针句柄。看到这么长的名字是不是头晕了?我不知道具体含义sorry......
CreateWindow()返回被创建的窗口的句柄,该句柄被存放在变量hwnd中。Windows中的每个窗口都有一个句柄,程序用句柄来引用窗口。许多Windows函数都需要使用hwnd作为参数,这样,Windows才能知道函数是针对哪个窗口的。如果一个程序创建了许多窗口,则每个窗口都有一个句柄。窗口句柄是Windows程序处理的最重要的句柄之一。
就这样,CreateWindows()调用返回后窗口已经创建完毕。Windows已经分配了一块内存,用来保存在创建窗口过程中设置的全部信息。
但是我们仍然无法在屏幕上看到窗口。还需要两个函数显示窗口。一个是:
ShowWindow(hwnd, iCmdShow);
hwnd是刚刚用CreateWindow()创建的窗口对象的句柄。我们要好好看一看第二个参数。这也是WinMain()的第四个参数,int类型。那么,这是干什么用的呢?Come on Baby!
第二个参数有三个常量可供选择。
SW_SHOWNORMAL
这些都是干什么用的???跟上次一样,改代码!请把
ShowWindow(hwnd, iCmdShow);
改成
ShowWindow(hwnd, SW_SHOWMAXIMIZED) 或是 ShowWindow(hwnd, SW_SHOWMINNOACTIVE)
运行一次您就Know了。虽然名字是ShowWindow(),但是我们还是不能Show到HelloWin生成的窗口。因为我们需要重新画屏幕,也就是刷新。
UpdateWindow(hwnd);
while (GetMessage (&msg, NULL, 0, 0))
{
}
Windows为当前运行的每个程序维护一个消息队列。这一点很重要。当您点击鼠标左右键的时候会发生消息,当您点了某个按钮的时候也会发生消息。总之,不管您干什么,都会产生消息。这些消息会进入消息队列中。GetMessage()负责从消息队列中取出消息。
TranslateMessage()在按键时系统产生虚拟键消息(VK_TAB等等)。在接收虚拟键代码时该函数将相应的WM_CHAR代码发送到应用程序消息队列中。具体的意思嘛我不懂啊。不过这个东东暂时好像不是很重要。
DispatchMessage()从应用程序的消息循环中发送消息至相应的窗口过程。
消息有入队与不入队之分。入队消息按照顺序一个一个送到窗口过程,就像排队买票一样。不入队消息的优先级是比较高的,可以直接发送给窗口过程。就好像领导不用排队买电影票一样。while循环处理的都是入队的消息。