本文是我学习《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);