HelloWin详解

(注意:遇到程序在弄懂之后一定要自己去敲,一定要自己去敲,一定要自己去敲)

(注意:遇到程序在弄懂之后一定要自己去敲,一定要自己去敲,一定要自己去敲)

(注意:遇到程序在弄懂之后一定要自己去敲,一定要自己去敲,一定要自己去敲)

代码如下:


#include<windows.h>    
#include<mmsystem.h>    
#pragma comment(lib,"WINMM.LIB")   
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);     // LoadIcon() 加载图标
     wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);      // LoadCursor() 加载鼠标光标
     wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);    // 窗口背景色          // GetStockObject() 获取一个图形对象
     wndclass.lpszMenuName = NULL;                    // 窗口菜单                               
     wndclass.lpszClassName = szAppName;             // 窗口类名
     if (!RegisterClass(&wndclass))             // RegisterClass() 为应用程序的窗口注册一个窗口类  
     {   
         MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);    // 显示消息框
         return 0;   
     }   
    hwnd = CreateWindow(szAppName, TEXT("The Hello Program"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
                        CW_USEDEFAULT, CW_U SEDEFAULT, NULL, NULL, hInstance, NULL);     // CreateWindow() 基于窗口类创建一个窗口
    ShowWindow(hwnd, iCmdShow);                      //   显示窗口
    UpdateWindow(hwnd);                             // 指示窗口对其自身进行重绘
    while (GetMessage(&msg, NULL, 0, 0))       // 从消息队列获取消息
    {   
      TranslateMessage(&msg);                 // 翻译键盘消息
      DispatchMessage(&msg);                 // 将消息发送给窗口过程 (即 WndProc()函数 )
    }   
    system("pause");   
    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);   // 返回 默认的消息处理的结果 
}   

 

看起来似乎第二行就懵逼吧!哈哈哈!

因为在程序中使用PlaySound函数时需要在 #include<windows.h> 后面加上 (不能在前面加 ):

#include <mmsystem.h>
#pragma comment(lib, "WINMM.LIB")

 

LRESULT是一个数据类型,指的是从 窗口程序 或者 回调函数 返回的32位值。

在WINNT.H中typedef long LONG;
在WINDEF.H中typedef LONG LRESULT;
所以LRESULT就是长整型。之所以取名类LRESULT,是因为L即long;

result表示结果,说明这个函数的返回值是某个结果。

CALLBACK是由用户设计却由 Windows系统 呼叫的函数,统称为callback函数。

某些 API 函数要求以 callback 作为你参数之一。

实际上CALLBACK就是 __stdcall(回调函数),这里也叫窗口函数,来执行窗口的消息循环。

在建立窗口类的时候,可以指明窗口函数地址。

WndProc是函数名,后面跟着的自然就是参数类型了。这和 C 语言一样,函数的声明可以省略参数名。

 

(HWND, UINT, WPARAM, LPARAM)各个参数类型的意思

前面谈到过:

                     HWND 是窗口的句柄。hwnd用来接收当前消息的窗口句柄。

                     UINT 也谈过,就是unsigned int 无符号整型,两个字节。Messsage是被传过来的消息。

                     WPARAM  WP是前缀名,表示宽字符指针。wParam 是用来附加在消息上的数据。和 MSG 结构体一样

                     LPARAM    LP是前缀名,表示长指针。lParam 也是用来附加在消息上的数据。和 MSG 结构体一样。

 

接下来我们看到函数的定义部分

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);   // 返回 默认的消息处理的结果  
}    

 

或许看到 HDC,PAINTSTRUCT,RECT 你又懵逼了!

HDC:设备上下文 句柄(可以理解为指向DC结构的指针),它指向一块描述设备的相关的内容的内存块。

DC: 设备上下文(设备描述表),是WINDOWS的一种数据类型。

这样说的话,又出现了新的问题,设备上下文 又是啥?

HDC设备上下文 是一种包含有关某个设备(如显示器或打印机)的绘制属性信息的 Windows 数据结构。

所有绘制调用都通过设备上下文对象进行,这些对象封装了用于绘制线条、形状和文本的 Windows API。

 

PAINTSTRUCT 是什么呢?

从名字上不难看出,应该是和绘图有关的结构体。 ps自然就是结构体变量。

typedef struct tagPAINTSTRUCT { 

HDC hdc; 

BOOL fErase; 

RECT rcPaint;

BOOL fRestore;

BOOL fIncUpdate;

BYTE rgbReserved[32]; 

} PAINTSTRUCT, *PPAINTSTRUCT; 
hdc 是用于绘制的句柄,
fErase 如果为非零值则擦除背景,否则不擦除背景,
rcPaint 通过制定左上角和右下角的坐标确定一个要绘制的矩形范围,该矩形单位相对于客户区左上角,
后面三个参数都是系统预留的,编程一般用不到。

PAINTSTRUCT 包含了用于绘制窗口客户区的信息。例如要更新的客户区的矩形区域的大小等等。

程序处理 WM_PAINT 消息时将会用到它,该结构体的作用就是重绘客户区的

每个窗口要有一个PAINTSTRUCT结构来记录一些绘制信息,PAINTSTRUCT结构保存了窗口绘制客户区的一些信息

例如,绘制客户区时是否要清除背景色,要更新的客户区的矩形区域的大小等等。

 

RECT又是什么东西呢?

其实它也是一个结构体,用来显示窗口的位置的。可以看下它的结构体:

typedef struct _RECT {

  LONG left;   

  LONG top;

  LONG right;

  LONG bottom;

} RECT, *PRECT;

这个结构体的意思很明确了,就不强加解释了。

 

接下来我们看到 switch(message) 语句:

看到这段代码,可以知道程序是想针对传入的消息进行处理。

消息的值可能是:WM_CREATE, WM_PAINT, WM_DESTROY 等。

你们肯定想到了,case 后面的都应该是整型常量表达式。

其实消息的值都是这类型,只不过内部把这些数值用宏定义 #define 处理了。

 

现在来看第一个 case 语句WM_CREATE   是窗口消息中的 请求创建窗口时的消息

PlaySound() 原型

BOOL PlaySound(LPCSTR pszSound, HMODULE hmod,DWORD fdwSound);

   PlaySound参数:pszSound 是指定了要播放声音的字符串,该参数可以是WAVE文件的名字,

                               或是WAV资源的名字,或是内存中声音数据的指针,或是在系统注册表WIN.INI中定义的系统事件声音。

                               如果该参数为NULL则停止正在播放的声音。

                    参数:hmod 是应用程序的实例句柄,除非pszSound的指向一个资源标识符

                               (即fdwSound被定义为SND_RESOURCE),否则必须设置为NULL。

                    参数:fdwSound是标志的组合。若成功则函数返回TRUE,否则返回FALSE。

返回值:非零表示成功,零表示失败。

 

第二个case 语句WM_PAINT  是窗口消息中的 客户区重绘消息

这个消息在Windows程序设计中是很重要的。

当窗口显示区域的一部分显示内容或者全部变为“无效”,以致于必须“更新画面”时,将由这个消息通知程序。

当需要绘制一部分应用窗口的时候,这个消息被Windows或者其他应用程序绘制调用。

 对WM_PAINT的处理几乎总是从一个 BeginPaint() 调用开始:hdc = BeginPaint (hwnd, &ps) ;

而以一个 EndPaint() 调用结束:EndPaint (hwnd, &ps) ;

在这两个调用中,第一个参数都是程序的窗口句柄,第二个参数是指向型态为PAINTSTRUCT的结构指针。

PAINTSTRUCT结构中包含一些窗口消息处理程序,可以用来更新显示区域的内容。

BeginPaint调用令整个显示区域有效,并传回一个“设备上下文句柄”。在窗口的显示区域显示文字和图形需要设备上下文句柄。

但是从BeginPaint传回的设备上下文句柄不能在显示区域之外绘图。EndPaint释放设备上下文句柄,使之不再有效。

调用完BeginPaint之后,WndProc接着调用GetClientRect:

GetClientRect (hwnd, &rect) ;

第一个参数是程序窗口的句柄。第二个参数是一个指针,指向一个RECT型态的rectangle结构。

该结构有四个LONG字段,分别为left、top、right和bottom。GetClientRect将这四个字段设定为窗口显示区域的尺寸。

left和top字段通常设定为0,right和bottom字段设定为显示区域的宽度和高度(像素点数)。

WndProc除了将该RECT结构指针作为DrawText的第四个参数传递外,不再对它做其它处理。

DrawText() 原型

        int DrawText(HDC hdc, LPCTSTR lpString, int nCount, LPRECT lpRect, UINT uFormat);

参数:
  hdc:设备环境句柄。
  lpString:指向将被写入的字符串的指针,如果参数nCount是-1,则字符串必须是以\0结束的。
  如果uFormat包含DT_MODIFYSTRING,则函数可为此字符串增加4个字符,存放字符串的缓冲区必须足够大,能容纳附加的字符。
  nCount:指向字符串中的字符数。如果nCount为-1,则lpString指向的字符串被认为是以\0结束的,

                      DrawText() 会自动计算字符数。
  lpRect:指向结构RECT的指针,其中包含正文将被置于其中的矩形的信息(按逻辑坐标)。
  uFormat:指定格式化正文的方法。该值都是 DT_*** 的样式。

返回值:如果函数调用成功,返回值是正文的高度;如果函数调用失败,返回值是0。

 

第三个 case 语句WM_DESTROY  是窗口消息中的 窗口摧毁消息

PostQuitMessage() 该函数向系统表明有个线程有终止请求。通常用来响应 WM_DESTROY 消息。

函数原型:VOID PostQuitMessage(int nExitCode);

参数 nExitCode:指定应用程序退出代码。此值被用作消息 WM_QUIT 的 wParam 参数。

PostQuitMessage寄送一个WM_QUIT消息给线程的消息队列并立即返回;此函数向系统表明有个线程请求在随后的某一时间终止。

 

当线程从消息队列里取得WM_QUIT消息时,应当退出消息循环并将控制返回给系统。返回给系统的退出值必须是消息WM_QUIT的。

返回值:无

 

DefWindowProc() 调用缺省的窗口过程来为应用程序没有处理的任何窗口消息提供缺省的处理。

 函数功能:该调用DefWindowProc函数时使用窗口过程接收的相同参数。

函数原型:LRESULT DefWindowProc(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam);

DefWindowProc这个函数是默认的窗口处理函数,我们可以把不关心的消息都丢给它来处理。

这个函数在处理关闭窗口消息WM_CLOSE时,是调用 DestroyWindow() 关闭窗口并且发 WM_DESTROY 消息给应用程序;

而它对WM_DESTROY这个消息是不处理的(考虑为什么?);我们在应用程序中对这个消息的处理是发出WM_QUIT消息。

因此WM_CLOSE、WM_DESTROY、WM_QUIT这三个消息是先后产生的。

hWnd:指向接收消息的窗口过程的句柄。
Msg:指定消息类型。
wParam:指定其余的、消息特定的信息。该参数的内容与Msg参数值有关。
IParam:指定其余的、消息特定的信息。该参数的内容与Msg参数值有关。
返回值:返回值就是消息处理结果,它与发送的消息有关。
 
我们再回到程序的开头吧:

或许你早已运行该程序了,发现没有声音!其实是声音文件的位置错了。

你可以把TEXT("hellowin.wav")         改成     TEXT("C:\\Windows\\media\\Ring03.wav")

因为在  C:\\Windows\\media 这个目录下有许多的  wav 型的文件。这样就会有声音了。

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);     // LoadIcon() 加载图标
     wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);      // LoadCursor() 加载鼠标光标
     wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);    // 窗口背景色          // GetStockObject() 获取一个图形对象
     wndclass.lpszMenuName = NULL;                    // 窗口菜单                               
     wndclass.lpszClassName = szAppName;             // 窗口类名
     if (!RegisterClass(&wndclass))             // RegisterClass() 为应用程序的窗口注册一个窗口类  
     {   
         MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);    // 显示消息框
         return 0;   
     }   
    hwnd = CreateWindow(szAppName, TEXT("The Hello Program"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
                        CW_USEDEFAULT, CW_U SEDEFAULT, NULL, NULL, hInstance, NULL);     // CreateWindow() 基于窗口类创建一个窗口
    ShowWindow(hwnd, iCmdShow);                      //   显示窗口
    UpdateWindow(hwnd);                             // 指示窗口对其自身进行重绘
    while (GetMessage(&msg, NULL, 0, 0))       // 从消息队列获取消息
    {   
      TranslateMessage(&msg);                 // 翻译键盘消息
      DispatchMessage(&msg);                 // 将消息发送给窗口过程 (即 WndProc()函数 )
    }   
    system("pause");   
    return msg.wParam;   
}   

 

HWND 的数据类型表示 句柄:

一个句柄是指使用的一个唯一的整数值,即一个4字节(64位程序中为8字节)长的数值。

用来标识应用程序中的不同对象和同类中的不同的实例,诸如,一个窗口,按钮,图标,滚动条,输出设备,控件或者文件等。

应用程序能够通过句柄访问相应的对象的信息,但是句柄不是指针,程序不能利用句柄来直接阅读文件中的信息。

如果句柄不再 I/O 文件中,它是毫无用处的。

句柄是Windows用来标志应用程序中建立的或是使用的唯一整数,Windows大量使用了句柄来标识对象。

句柄与普通指针的区别在于,指针包含的是引用对象的内存地址,而句柄则是由系统所管理的引用标识。

该标识可以被系统重新定位到一个内存地址上。这种间接访问对象的模式增强了系统对引用对象的控制。

WINDOWS程序中并不是用物理地址来标识一个内存块,文件,任务或动态装入模块的。

相反,WINDOWS API给这些项目分配确定的句柄,并将句柄返回给应用程序,然后通过句柄来进行操作。

一个句柄,只有当唯一地确定了一个项目的时候,它才开始有意义。

句柄对应着项目表中的一项,而只有WINDOWS本身才能直接存取这个表,应用程序只能通过API函数来处理不同的句柄。

总而言之:句柄就是对窗口及窗口的控件进行标识的,如果要改变窗口或它的控件的话,就需要指定窗口或控件对它进行改变。

 

MSG是 Windows 程序中的结构体。在Windows程序中,消息是由MSG结构体来表示的

typedef struct tagMSG {

HWND hwnd;

UINT message;

WPARAM wParam;

LPARAM lParam;

DWORD time;

POINT pt;

} MSG,*PMSG;

成员变量含义:

第一个成员变量 hwnd 表示消息所属的窗口。我们通常开发的程序都是窗口应用程序,一个消息一般都是与某个窗口相关联的。
例如,在某个活动窗口中按下鼠标左键,产生的按键消息就是发给该窗口的。在Windows程序中,用HWND类型的变量来标识窗口。
第二个成员变量message指定了消息的标识符。在Windows中,消息是由一个数值来表示的,不同的消息对应不同的数值。
但是由于数值不便于记忆,所以Windows将消息对应的数值定义为WM_XXX宏(WM是Window Message的缩写)的形式。
例如,鼠标左键按下消息是WM_LBUTTONDOWN,键盘按下消息是WM_KEYDOWN,字符消息是WM_CHAR,等等。
在程序中我们通常都是以WM_XXX宏的形式来使用消息的。
提示:如果想知道WM_XXX消息对应的具体数值,可以在VC 开发环境中选中WM_XXX,
然后单击鼠标右键,在弹出菜单中选择goto definition,即可看到该宏的具体定义。
跟踪或查看某个变量的定义,都可以使用这个方法。
第三、第四个成员变量wParam和lParam,用于指定消息的附加信息。
例如,当我们收到一个字符消息的时候,message成员变量的值就是WM_CHAR,
但用户到底输入的是什么字符,那么就由wParam和lParam来说明。
wParam、lParam表示的信息随消息的不同而不同。如果想知道这两个成员变量具体表示的信息,
可以在MSDN中关于某个具体消息的说明文档查看到。
读者可以在VC++的开发环境中通过goto definition查看一下WPARAM和LPARAM这两种类型的定义,
可以发现这两种类型实际上就是unsigned int和long。
最后两个变量分别表示消息投递到消息队列中的时间和鼠标的当前位置。
 
那么 WNDCLASS 又是什么呢?

WNDCLASS是一个由系统支持的结构,用来储存某一类窗口的信息,如ClassStyle,消息处理函数,Icon,Cursor,背景Brush等。

也就是说,CreateWindow只是将某个WNDCLASS定义的窗体变成实例。

结构体 WNDCLASS 包含一个窗口类的全部信息,也是Windows编程中使用的基本数据结构之一,

应用程序通过定义一个窗口类确定窗口的属性。

我们再来看一下它的结构体成分:

typedef struct _WNDCLASS {

UINT style;// 窗口类型

WNDPROC lpfnWndProc;//窗口处理函数

int cbClsExtra;//窗口扩展

int cbWndExtra;//窗口实例扩展

HINSTANCE hInstance;//实例句柄

HICON hIcon;//窗口的最小化图标

HCURSOR hCursor;//窗口鼠标光标

HBRUSH hbrBackground;//窗口背景色

LPCTSTR lpszMenuName;//窗口菜单

LPCTSTR lpszClassName;// 窗口类名

} WNDCLASS, *LPWNDCLASS;

 

 RegisterClass() :

RegisterClass注册后再调用 CreatWindow() 中使用的窗口类。

该函数的声明: ATOM  RegisterClass(__inCONST WNDCLASS *lpWndClass);

lpWndClass:指向一个 WNDCLASS 结构的指针。在将它传递给函数之前,必须在该结构中填充适当的类属性。

ATOM类型为Windows中定义的新数据类型,其即unsigned short类型。

如果函数成功,返回值是唯一标识已注册的类的一个原子;如果函数失败,返回值为0。

 

CreatWindow() :

HWND CreateWindow(

LPCTSTR lpClassName,

LPCTSTR lpWindowName,

DWORD dwStyle,

int x,

int y,

int nWidth,

int nHeight,

HWND hWndParent,

HMENU hMenu,

HANDLE hlnstance,

LPVOID lpParam
);

 

主要参数:

lpClassName

指向一个空结束的字符串或整型数atom。如果该参数是一个整型量,它是由此前调用theGlobalAddAtom函数产生的全局量。
这个小于0xC000的16位数必须是lpClassName参数字的低16位,该参数的高位必须是0。
如果lpClassName是一个字符串,它指定了窗口的类名。
这个类名可以是任何用函数RegisterClass注册的类名,或是任何预定义的控制类名。
LPWindowName
指向一个指定窗口名的空结束的字符串指针。
如果窗口风格指定了标题条,由lpWindowName指向的窗口标题将显示在标题条上。
当使用Createwindow函数来创建控制例如按钮,选择框和静态控制时,可使用lpWindowName来指定控制文本。
dwStyle
指定创建窗口的风格。该参数可以是下列窗口风格的组合再加上说明部分的控制风格。
X
指定窗口的初始水平位置。对一个层叠或弹出式窗口,X参数是屏幕坐标系的窗口的左上角的初始X坐标。
对于子窗口,x是子窗口左上角相对父窗口客户区左上角的初始X坐标。
如果该参数被设为CW_USEDEFAULT则系统为窗口选择缺省的左上角坐标并忽略Y参数。
CW_USEDEFAULT只对层叠窗口有效,如果为弹出式窗口或子窗口设定,则X和y参数被设为零。
Y
指定窗口的初始垂直位置。对一个层叠或弹出式窗口,y参数是屏幕坐标系的窗口的左上角的初始y坐标。
对于子窗口,y是子窗口左上角相对父窗口客户区左上角的初始y坐标。
对于列表框,y是列表框客户区左上角相对父窗口客户区左上角的初始y坐标。
如果层叠窗口是使用WS_VISIBLE风格位创建的并且X参数被设为CW_USEDEFAULT,则系统将忽略y参数。
nWidth
以设备单元指明窗口的宽度。对于层叠窗口,nWidth或是屏幕坐标的窗口宽度或是CW_USEDEFAULT。
若nWidth是CW_USEDEFAULT,则系统为窗口选择一个缺省的高度和宽度:
缺省宽度为从初始X坐标开始到屏幕的右边界,缺省高度为从初始Y坐标开始到目标区域的顶部。
CW_USEDEFAULT只对层叠窗口有效;如果为弹出式窗口和子窗口设定CW_USEDEFAULT标志则nWidth和nHeight被设为零。
nHeight
以设备单元指明窗口的高度。对于层叠窗口,nHeight是屏幕坐标的窗口宽度。
若nWidth被设为CW_USEDEFAULT,则系统忽略nHeight参数。
hWndParent
指向被创建窗口的父窗口或所有者窗口的句柄。若要创建一个子窗口或一个被属窗口,需提供一个有效的窗口句柄。
这个参数对弹出式窗口是可选的。Windows NT 5.0;创建一个消息窗口,
可以提供HWND_MESSAGE或提供一个己存在的消息窗口的句柄。
hMenu
菜单句柄,或依据窗口风格指明一个子窗口标识。对于层叠或弹出式窗口,hMenu指定窗口使用的菜单:
如果使用了菜单类,则hMenu可以为NULL。对于子窗口,hMenu指定了该子窗口标识(一个整型量),
一个对话框使用这个整型值将事件通知父类。
应用程序确定子窗口标识,这个值对于相同父窗口的所有子窗口必须是唯一的。
hlnstance
与窗口相关联的模块实例的句柄。
lpParam
指向一个值的指针,该值传递给窗口 WM_CREATE 消息。该值通过在IParam参数中的 CREATESTRUCT 结构传递。
如果应用程序调用CreateWindow创建一个MDI客户窗口,则lpParam必须指向一个CLIENTCREATESTRUCT结构。
返回值:如果函数成功,返回值为新窗口的句柄:如果函数失败,返回值为NULL。

备注:

在返回前,CreateWindow给窗口过程发送一个WM_CREATE消息。

对于层叠,弹出式和子窗口,CreateWindow给窗口发送WM_CREATE,WM_GETMINMAXINFO和WM_NCCREATE消息。

消息WM_CREATE的IParam参数包含一个指向CREATESTRUCT结构的指针。

如果指定了WS_VISIBLE风格,CreateWindow向窗口发送所有需要激活和显示窗口的消息。

 

ShowWindow() :

函数功能:该函数设置指定窗口的显示状态。

函数原型:BOOL ShowWindow(HWND hWnd, int nCmdShow);

参数:

                    hWnd:指窗口句柄。

                    nCmdShow:指定窗口如何显示。

                    如果发送应用程序的程序提供了STARTUPINFO结构,则应用程序第一次调用ShowWindow时该参数被忽略。

                    否则,在第一次调用ShowWindow函数时,该值应为在函数WinMain中nCmdShow参数。
返回值:如果窗口之前可见,则返回值为非零。如果窗口之前被隐藏,则返回值为零。

备注:

应用程序第一次调用ShowWindow时,应该使用WinMain函数的nCmdshow参数作为它的nCmdShow参数。

在随后调用ShowWindow函数时,必须使用列表中的一个给定值,而不是由WinMain函数的nCmdSHow参数指定的值。

 

UpdateWindow() :

如果窗口更新的区域不为空,UpdateWindow函数就发送一个 WM_PAINT 消息来更新指定窗口的客户区。

函数绕过应用程序的消息队列,直接发送WM_PAINT消息给指定窗口的窗口过程,如果更新区域为空,则不发送消息。

函数原型:    

BOOL UpdateWindow(
HWND hWnd // 窗口的句柄

);

返回值:如果函数调用成功,返回值为非零值。如果函数调用不成功,返回值为零。

 
GetMessage() :

函数声明:

GetMessage(LPMSG lpMsg,HWND hWnd,UINT wMsgFilterMin,UINT wMsgFilterMax)

参数:
lpMsg:指向MSG结构的指针,该结构从线程消息队列里接收消息信息。
hWnd:取得其消息的窗口的句柄。当其值取NULL时,GetMessage为任何属于调用线程的窗口检索消息,
             线程消息通过PostThreadMessage寄送给调用线程。
wMsgFilterMin:指定被检索的最小消息值的整数。
wMsgFilterMax:指定被检索的最大消息值的整数。
返回值:如果函数取得WM_QUIT之外的其他消息,返回非零值。
              如果函数取得WM_QUIT消息,返回值是零。如果出现了错误,返回值是 -1。
               例如,当hWnd是无效的窗口句柄或 lpMsg 是无效的指针时。

备注:

应用程序通常用返回值来确定是否终止主消息循环并退出程序。
GetMesssge只接收与参数hWnd标识的窗口或子窗口相联系的消息,子窗口由函数IsChild决定。
消息值的范围由参数wMsgFilterMin和wMsgFilterMax给出。
如果hWnd为NULL,则GetMessage接收属于调用线程的窗口的消息,线程消息由函数PostThreadMessage寄送给调用线程。
GetMessage不接收属于其他线程或其他线程的窗口的消息,即使hWnd为NULL。
由PostThreadMessage寄送的线程消息,其消息hWnd值为NULL。
如果wMsgFilterMin和wMsgFilterMax都为零,GetMessage返回所有可得的消息(即,无范围过滤)。
常数 WM_KEYFIRST和WM_KEYLAST可作为过滤值取得与键盘输入相关的所有消息:
常数WM_MOUSEFIRST和WM_MOUSELST可用来接收所有的鼠标消息。
如果wMsgFilterMin和wMsgFilterMax都为零,GetMessage返回所有可得的消息(即,无范围过滤)。
GetMessage不从队列里清除WM.PAINT消息。该消息将保留在队列里直到处理完毕。
注意,此函数的返回值可非零、零或-1,应避免如下代码出现:
while(GetMessage(IpMsg,hwnd,0,0))…
返回-1时处理错误而不是继续循环。
 
TranslateMessage() :
函数用于将虚拟键消息转换为字符消息
字符消息被寄送到调用线程的消息队列里,当下一次线程调用函数 GetMessage 或 PeekMessage 时被读出。

函数原型:

BOOL TranslateMessage( CONST MSG*lpMsg );
IpMsg:指向含有消息的MSG结构的指针,该结构里含有用函数GetMessage或PeekMessage从调用线程的消息队列里取得的消息信息。
返回值:如果消息被转换(即,字符消息被寄送到调用线程的消息队列里),返回非零值。
如果消息是WM_KEYDOWN,WM_KEYUP WM_SYSKEYDOWN或WM_SYSKEYUP,返回非零值,不考虑转换。
如果消息没被转换(即,字符消息没被寄送到调用线程的消息队列里),返回值是零。
备注:此函数不修改由参数IpMsg指向的消息。
 
DispatchMessage() :

函数功能:该函数分发一个消息给窗口程序。通常消息从GetMessage函数获得或者TranslateMessage函数传递的。

消息被分发到回调函数(过程函数),作用是消息传递给操作系统,

然后操作系统去调用我们的回调函数,也就是说我们在窗体的过程函数中处理消息。

 函数原型:LONG DispatchMessage (CONST MSG*lpmsg);

参数:
lpmsg:指向含有消息的MSG结构的指针。
返回值:返回值是窗口程序返回的值。尽管返回值的含义依赖于被调度的消息,但返回值通常被忽略。
备注:MSG结构必须包含有效的消息值。
           如果参数lpmsg指向一个WM_TIMER消息,并且WM_TIMER消息的参数IParam不为NULL,
           则调用IParam指向的函数,而不是调用窗口程序。
 
(注意,几乎所有的 API 函数发生错误,都可以调用 GetLastError() 来获取错误信息。
GetLastError() 返回一个错误代码,可以根据错误代码找到相关信息。
函数名后带有 EX 的表示该函数的扩展函数)
最后介绍一下值的命名规则
前缀 常量
CS 类风格选项
CW 创建窗口选项
DT 文本绘制选项
IDI 图标的 ID 号
IDC 光标的 ID 号
MB 消息框选项
SND 声音选项
WM 窗口消息
WS 窗口风格
数据结构:
结构 含义
MSG 消息结构
WNDCLASS 窗口类结构
PAINTSTRUCT 绘制结构
RECT 矩形结构
句柄标识符:
标识符 含义
HINSTANCE 实例句柄---程序本身
HWND 窗口句柄
HDC

设备环境句柄

posted @ 2018-07-11 10:27  M-Anonymous  阅读(2069)  评论(0编辑  收藏  举报