windows程序设计:第三章:窗口与消息

本文是我学习《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的中文注释如下:

windows程序设计:第三章:窗口与消息_第1张图片

在窗口过程里用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);


实际上,任何Windows程序的机构都和本章例子大体类似,没有人会真正记住这种框架的所有细节。通常Windows程序员都是将已有的程序代码复制到新程序中,再加以修改。

你可能感兴趣的:(windows程序设计:第三章:窗口与消息)