本文是我学习《windows程序设计》(第5版)的笔记,方便以后查阅。如果被您看到并且对您有用的话,那再好不过了。本文不涉及具体的讲解,详细的讲解请看《windows程序设计》(第5版)这本书,它才是经典之作!
本章主要讲创建一个Windows窗口,按先后顺序有以下几个步骤:
———————在WinMain函数里——————————
窗口类的注册
窗口的创建
窗口的显示
消息循环
————————在WndProc函数里—————————
消息过程
消息的处理
代码如下:
#include <windows.h>
#include <mmsystem.h> // 加上,不然PlaySound函数无法使用
#pragma comment(lib, "WINMM.LIB") // 加上,不然PlaySound函数无法使用
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("HelloWin") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;//类风格
wndclass.lpfnWndProc = WndProc ;//设定窗口类的窗口过程
wndclass.cbClsExtra = 0 ;//预留额外空间
wndclass.cbWndExtra = 0 ;//预留额外空间
wndclass.hInstance = hInstance ;//实例句柄
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;//加载光标
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;//加载鼠标光标
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;//获取一个图形对象
wndclass.lpszMenuName = NULL ;//指定窗口类菜单
wndclass.lpszClassName = szAppName ;//赋给窗口类一个名称
if (!RegisterClass (&wndclass))//注册窗口类
return -1 ;
hwnd = CreateWindow (szAppName, // window class name
TEXT ("The Hello Program"), // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL) ; // creation parameters
ShowWindow (hwnd, iCmdShow) ;//显示窗口
UpdateWindow (hwnd) ;//指示窗口对自身进行重绘
while (GetMessage (&msg, NULL, 0, 0))//从消息队列获取消息
{
TranslateMessage (&msg) ;//翻译一些键盘消息
DispatchMessage (&msg) ;//将消息发送给窗口过程
}
return msg.wParam ;
}
//窗口过程
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc ;
PAINTSTRUCT ps ;
RECT rect ;
switch (message)
{
case WM_CREATE:
PlaySound (TEXT ("HelloWin.wav"), NULL, SND_FILENAME | SND_ASYNC) ;
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;//表明窗口绘制开始
GetClientRect (hwnd, &rect) ;//获取客户区尺寸
DrawText (hdc, TEXT ("Hello, Windows 98!"), -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
EndPaint (hwnd, &ps) ;//窗口绘制结束
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;//将“退出”消息插入消息队列
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;//执行默认的消息处理
}
类风格主要有以下几种:
CS_BYTEALIGNCLIENT: 在字节边界上(在x方向上)定位窗口的用户区域的位置
CS_BYTEALIGNWINDOW: 在字节边界上(在x方向上)定位窗口的位置
CS_CLASSDC: 该窗口类的所有窗口实例都共享一个窗口类DC
CS_DBLCLKS: 允许向窗口发送双击鼠标键的消息
CS_GLOBALCLASS: 当调用CreateWindow 或 CreateWindowEx 函数来创建窗口时允许它的hInstance参数和注册窗口类时传递给RegisterClass 的 hInstance参数不同。如果不指定该风格,则这两个 hInstance 必须相同。
CS_HREDRAW: 当水平长度改变或移动窗口时,重画整个窗口
CS_NOCLOSE: 禁止系统菜单的关闭选项
CS_OWNDC: 给予每个窗口实例它本身的DC。注意,尽管这样是很方便,但它必须慎重使用,因为每个DC大约要占800个字节的内存。
CS_PARENTDC: 将子窗口的裁剪区域设置到父窗口的DC中去,这样子窗口便可以在父窗口上绘制自身。注意,这是子窗口还是从系统缓存中获取DC,而不是使用父窗口的DC。使用该风格可以提高系统性能。
CS_SAVEBITS: 以位图形式保存被该窗口遮挡的屏幕部分,这样当给窗口移动以后,系统便可以用该保存的位图恢复屏幕移动的相应部分,从而系统不用向被该窗口遮挡的窗口发送 WM_PAINT 消息。该特性对于菜单类型的窗口比较合适,因为它通常是简短的显示一下之后便消失。设置该特性将增加显示该窗口的时间,因为它通常要先分配保存位图的内存。
CS_VREDRAW: 当垂直长度改变或移动窗口时,重画整个窗口
注册窗口类的代码如下:
if (!RegisterClass(&wndclass))//注册窗口类
{
MessageBox(NULL,TEXT("This programrequires Windows NT!"),
szAppName,MB_ICONERROR);
return0;
}
这里由于作者写书时间是1998年,当时还是windows98呢。今天我们直接写成下面的形式即可:
if (!RegisterClass(&wndclass))//注册窗口类
return-1;
CreateWindow的中文注释如下:
在窗口过程里用DefWindowProc()函数来对所有窗口过程没有处理的消息进行默认处理非常重要,否则其他的正常行为将无法进行。
想要用PlaySound()播放声音,必须包含以下两行代码:
#include <mmsystem.h>// 加上,不然PlaySound函数无法使用
#pragma comment( lib, "WINMM.LIB") // 加上,不然 PlaySound 函数无法使用
PlaySound函数还可以按下面的方法使用,第一个参数是ID名,我们需要把我们要播放的声音文件(.wav格式)添加到资源里,然后,把它的ID命名为你想的名字即可(PlaySound函数的第一个参数就用你定义的ID名)
PlaySound((LPCTSTR)IDR_ALARM,AfxGetInstanceHandle(), SND_RESOURCE | SND_ASYNC);