漠水 发表于 2014-11-20 18:29:42

windows窗口创建过程对应API解释(取自小甲鱼老师的API档案)

本帖最后由 freeparty 于 2015-6-19 12:53 编辑

一个个的查太痛苦了,所以作为新手我把他们一个个摘录到程序后面的注解里了,有需要的可以去看看,不过需要我们先将代码打上5遍之后才这样做,不要问我为什么,小甲鱼老师是这样说的。{:5_91:}这样对于入门所需要了解的函数能够更快的寻找到吧 ,在这里先感谢一下我们的小甲鱼老师{:9_236:} #include<windows.h>

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
/*
Windows 的窗口总是基于窗口类来创建的,窗口类同时确定了处理窗口消息的窗口过程(回调函数)。
回调函数需要到函数最后面几行找
*/

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hprevInstance,PSTR szCmdLine,int iCmdShow)
/*
hInstance:应用程序当前事例的句柄。
hPrelnstance:应用程序的先事例的句柄。对于同一个程序打开两次,出现两个窗口第一次打开的窗口就是先前实例的窗口。对于一个32的位程序,该参数总为NULL。
lpCmdLine:指向应用程序命令行的空字符串的指针,不包括函数名。获得整个命令行,参看GetCommandLine。
iCmdShow:指明窗口如何显示(是隐藏还是显示,有没有最大化按钮之类的)。取值可以参考MSDN

这里我相信有一个词大家好应该比较陌生,句柄(HANDLE)是吧。下面我就来简单的说下
句柄其实就是Windows系统中一个东西的唯一标识。就是系统中有很多运行的程序或者资源之类的,为了更好的管理使用,
Windows系统给它们每人一个ID一样。懂得网页制作的人应该知道网页中各个元素的ID吧,网页的ID如果重复话可能出现错误。
那么系统的句柄会不会有相同的,那是肯定不会有的了,就和我们的学号一样,系统自动分配每一个模块的句柄,是不会相同的了。
*/
{
      static      TCHAR szAppName[] = TEXT("开始坑爹之旅");
      HWND hwnd;
      MSG msg;
      WNDCLASS wndclass;
/*在创建应用程序窗口之前,必须调用 RegisterClass 函数来注册窗口类。
该函数只需要一个参数,即指向 WNDCLASS 窗口类的指针。因为 WNDCLASS 类包含了窗口所拥有的基本属性。
      结构原型:
typedef struct tagWNDCLASSW {
    UINT      style;
    WNDPROC   lpfnWndProc;
    int         cbClsExtra;
    int         cbWndExtra;
    HINSTANCE   hInstance;
    HICON       hIcon;
    HCURSOR   hCursor;
    HBRUSH      hbrBackground;
    LPCWSTR   lpszMenuName;
    LPCWSTR   lpszClassName;
} WNDCLASSW, *PWNDCLASSW, NEAR *NPWNDCLASSW, FAR *LPWNDCLASSW;
成员 含义
style 指定窗口类型,各种“类风格”(详见下方↓)可以使用按位或操作符组合起来
lpfnWndProc 指定窗口过程(必须是回调函数)
cbClsExtra 预留的额外空间,一般为 0
cbWndExtra 预留的额外空间,一般为 0
hInstance 应用程序的实例句柄
hIcon 为所有基于该窗口类的窗口设定一个图标
hCursor 为所有基于该窗口类的窗口设定一个鼠标指针
hbrBackground 指定窗口背景色
lpszMenuName 指定窗口菜单
lpszClassName 指定窗口类名 */

      wndclass.style = CS_HREDRAW;
      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(COLOR_CAPTIONTEXT);      //背景色
      wndclass.lpszMenuName = NULL;
      wndclass.lpszClassName = szAppName;


      if(!RegisterClass(&wndclass))
      {
      
                MessageBox(NULL,TEXT("这个程序无法执行"),szAppName,MB_OK);
                return 0;
      }


      hwnd =CreateWindow(szAppName,
                TEXT("开始坑爹了"),
                WS_OVERLAPPEDWINDOW,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                NULL,
                NULL,
                hInstance,
                NULL);

      ShowWindow(hwnd,iCmdShow);   //显示窗口      
      UpdateWindow(hwnd);                              //更新窗口

      while(GetMessage(&msg,NULL,0,0))
                /*
注释:_In_ 说明该参数是输入的,_opt_ 说明该参数是可选参数。
BOOL WINAPI GetMessage(
_Out_   LPMSG lpMsg,
_In_opt_HWND hWnd,
_In_      UINT wMsgFilterMin,
_In_      UINT wMsgFilterMax
);

lpMsg 指向 MSG 结构的指针
hWnd      1. 需要检索消息的窗口的句柄,该窗口必须属于当前线程
                2. 当其值是 NULL 时,将检索所有的当前线程的窗口消息和线程消息
                3. 当其值是 -1 时,只检索当前线程消息
wMsgFilterMin 指定被检索的最小消息值的整数
wMsgFilterMax 指定被检索的最大消息值的整数

返回值:
1. 如果函数取得 WM_QUIT 之外的其他消息,返回非零值;
2. 如果函数取得 WM_QUIT 消息,返回值是零;
3. 如果出现了错误,返回值是 -1。

*/
      {
                TranslateMessage(&msg);
/*
TranslateMessage 函数将虚拟键消息转换为字符消息,字符消息被寄送到当前线程的消息队列里。
当下一次线程调用函数 GetMessage 或 PeekMessage 时被读出。
BOOL WINAPI TranslateMessage(_In_const MSG *lpMsg);
lpMsg 指向含有消息的 MSG 结构的指针
返回值:
1. 如果消息被转换(字符消息被寄送到当前线程的消息队列里)则返回非零值;
2. 如果消息是 WM_KEYDOWN,WM_KEYUP WM_SYSKEYDOWN 或 WM_SYSKEYUP,返回非零值,不考虑转换;
3. 如果消息没被转换(字符消息没被寄送到调用线程的消息队列里)则返回值是零。
                */

                DispatchMessage(&msg);
/*
DispatchMessage 函数分派一个消息给窗口过程(回调函数),通常该消息从 GetMessage 函数获得。Windows 的控制权在该函数交给了应用程序。
LRESULT WINAPI DispatchMessage(_In_const MSG *lpmsg);
lpmsg 指向含有消息的 MSG结构 的指针
返回值:
1. 返回值是窗口过程返回的值;
2. 尽管返回值的含义依赖于被分派的消息,但返回值通常被忽略。
备注:
1. MSG 结构必须包含有效的消息值。
2. 如果参数 lpmsg 指向一个 WM_TIMER 消息,并且 WM_TIMER 消息的参数 lParam 不为 NULL,则调用 lParam 指向的函数,而不是调用窗口程序。
*/
      }
      return msg.wParam;


}

LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
/*
      PAINTSTRUCT 结构包含一些窗口过程用来对客户区进行绘制的信息。
      typedef struct tagPAINTSTRUCT {
      HDChdc;
      BOOL fErase;
      RECT rcPaint;
      BOOL fRestore;
      BOOL fIncUpdate;
      BYTE rgbReserved;
}      PAINTSTRUCT, *PPAINTSTRUCT;

成员 含义
hdc                              用于绘制的设备环境句柄
fErase                        1. 表示背景是否必须擦除,如果为非零值则擦除背景,否则不擦除背景
                              2. 如果创建窗口类的时候没有设置背景画刷,则负责擦除背景
rcPaint                        一个 RECT 结构,指定左上角和右下角的坐标确定一个要绘制的矩形范围
fRestore                系统保留
fIncUpdate                系统保留
rgbReserved                系统保留
      */      
      HDC hdc;
      PAINTSTRUCT ps;                        //声明一个PAINTSTRUCT 结构变量ps
      RECT rect;
      /*
      RECT 结构定义了一个矩形的左上角和右下角的坐标。
      typedef struct _RECT {
      LONG left;      指定矩形左上角的 x 坐标
      LONG top;       指定矩形左上角的 y 坐标
      LONG right;   指定矩形右下角的 x 坐标
      LONG bottom;    指定矩形右下角的 y 坐标
}      RECT, *PRECT;

      */

                switch (message)
      {
                case WM_PAINT:                //WM_PAINT 0x000F 要求一个窗口重绘自己
                hdc = BeginPaint(hwnd, &ps);      
      /*
      BeginPaint 函数为指定窗口进行绘画工作的准备,并用将和绘画有关的信息填充到一个 PAINTSTRUCT 结构中。

      HDC BeginPaint(
         _In_   HWND hwnd,
         _Out_LPPAINTSTRUCT lpPaint
      );
      hwnd 需要重新绘制的窗口句柄
      lpPaint 指向 PAINTSTRUCT 结构的指针,用于存放绘画相关的信息         
      返回值:
      1. 如果函数成功,返回值是指定窗口的“显示设备描述表”句柄;
      2. 如果函数失败,返回值是 NULL,表明没有得到显示设备的内容。
      备注:
      1. BeginPaint 函数自动设置显示设备内容的剪切区域,而排除任何更新区域外的区域。
      该更新区域可以通过 InvalidateRect 或 InvalidateRgn 函数设置,也可以是系统在改变大小、移动、创建、滚动后设置的,或者其他的影响客户区的操作来设置的。
      2. 如果更新区域被标记为可擦除的,BeginPaint 发送一个 WM_ERASEBKGND 消息给窗口。
      3. 一个应用程序除了响应 WM_PAINT 消息外,不应该调用 BeginPaint。
      4. 每次调用 BeginPaint 都应该有相应的 EndPaint 函数。
      5. 如果被绘画的客户区中有一个 caret(caret:插入符。是窗口客户区中的一个闪烁的线,块,或位图。插入符通常表示文本或图形将被插入的地方。
      即一闪一闪的光标),BeginPaint 自动隐藏该符号,而保证它不被擦除。
      6. 如果窗口类有一个背景刷,BeginPaint 使用这个刷子来擦除更新区域的背景

    */
                GetClientRect(hwnd, &rect);
      /*GetClientRect 函数用于获取窗口客户区的坐标,客户区坐标指定客户区的左上角和右下角。
      由于客户区坐标是相对窗口客户区的左上角而言的,因此左上角坐标为(0,0)
      BOOL WINAPI GetClientRect(
         _In_   HWND hWnd,
         _Out_LPRECT lpRect
      );
      hWnd 需要获取客户区坐标的窗口句柄
      lpRect      1. 指向 RECT 结构的指针,该结构有四个成员,分别为 left、top、right 和 bottom
                        2. GetClientRect 将这四个成员设定为窗口显示区域的尺寸。
                           left 和 top 字段通常设定为 0,right 和 bottom 字段设定为显示区域的宽度和高度(像素点数)
                */
                DrawText(hdc, TEXT("大家好,这是我的第一个窗口程序!"), -1, &rect,
                        DT_SINGLELINE | DT_CENTER | DT_VCENTER);
                /*
                DrawText 函数在指定的矩形里写入格式化的正文,根据指定的方法对正文格式化(扩展的制表符,字符对齐、折行等)。
                int DrawText(
               _In_   HDC hDC,
               _Inout_LPCTSTR lpchText,
               _In_   int nCount,
               _Inout_LPRECT lpRect,
               _In_   UINT uFormat
                );
                hDC 指定“显示设备描述表”句柄
                lpchText 1. 指向将被写入的字符串的指针,如果参数 nCount 是 -1,则字符串必须是以 \0 结束的
                                 2. 如果 uFormat 包含 DT_MODIFYSTRING,则函数可为此字符串增加 4 个字符,存放字符串的缓冲区必须足够大,能容纳附加的字符
                nCount   1. 指向字符串中的字符数
                                 2. 如果 nCount 为 -1,则 lpchText 指向的字符串被认为是以 \0 结束的,DrawText 会自动计算字符数
                lpRect 指向 RECT 结构的指针,其中包含文本将被置于其中的矩形的信息(按逻辑坐标)
                uFormat1. 指定格式化文本的方法
                                 2. 此参数可以通过指定下列标志或标志的组合         
                返回值:
                1. 如果函数调用成功,返回值是正文的高度(逻辑单位);
                2. 如果指定了 DT_VCENTER 或 DT_BOTTOM,返回值是 lpRect -> top 到绘制的正文的底部的偏移值;
                3. 如果 函数调用失败,返回值是 0。
                备注:
                1. 函数 DrawText 用设备环境中的字体选择、正文颜色和背景颜色来写正文。
                2. DrawText 裁剪正文,使之不会出现在指定矩形的外面,除非指定了 DT_NOCLIP。
                3. 除非使用 DT_SINGLELINE 格式化,否则其余的格式都认为正文有多行。
                4. 如果选择的字体对指定的矩形而言太大,DrawText 并不会试图去换成一种小字体。
                5. 设备环境的正文对齐方式必须包括 TA_LEFT, TA_TOP 和 TA_NOUPDATECP 标志。
                */
                EndPaint(hwnd, &ps);
                /*EndPaint 函数标记指定窗口的绘画过程结束。
                BOOL EndPaint(
                _In_HWND hWnd,
               _In_const PAINTSTRUCT *lpPaint
               );
               hWnd 已经被重新绘制的窗口句柄
                lpPaint 指向 PAINTSTRUCT 结构的指针,用于存放绘画相关的信息(该指针在调用 BeginPaint 时被赋值)
                */
                return 0;
                case WM_DESTROY:                //WM_DESTROY 0x0002 一个窗口被销毁
                PostQuitMessage(0);
                /*PostQuitMessage 函数向系统表明有个线程有终止(退出)请求。
                这个函数通常用来响应 WM_DESTROY 消息。
                VOID WINAPI PostQuitMessage(
               _In_int nExitCode
                );
                nExitCode 指定应用程序的退出代码,此值被用作 WM_QUIT 消息的 wParam 参数
                返回值:该函数没有返回值。      
                备注:
                1. PostQuitMessage 函数的功能是发送一个 WM_QUIT 消息给线程的消息队列并立即返回。
                2. 当线程从消息队列里取得 WM_QUIT 消息时,应当退出消息循环并将返回系统,
                返回给系统的退出值必须是消息 WM_QUIT 的 wParam 参数(所以 WinMain 函数的返回值是 msg.wParam)。
*/
                return 0;
      }

return DefWindowProc(hwnd, message, wParam, lParam);
/*DefWindowProc 函数调用缺省的窗口过程来处理那些窗口过程没有处理的任何消息,该函数是为了确保每个消息都被处理。
      DefWindowProc 函数传入和窗口过程同样的参数。

LRESULT WINAPI DefWindowProc(
_In_HWND hWnd,
_In_UINT Msg,
_In_WPARAM wParam,
_In_LPARAM lParam
);
hWnd         指定接收消息的窗口句柄
Msg                1. 消息的标识符,由于数值不便于记忆,所以 Windows 将消息对应的数值定义为 WM_XXX 宏的形式
                2. 应用程序消息只能使用低 16 位,高 16 位被系统保留
                3. 传送门:Windows 常用消息及含义
wParam         指定消息的附加消息,确切的含义取决于消息成员的值
lParam         指定消息的附加消息,确切的含义取决于消息成员的值

返回值就是消息处理结果,它取决于发送的消息
*/

}

漠水 发表于 2014-11-20 18:38:33

自己先坐个沙发

小人 发表于 2014-11-20 19:57:13

支持学习了{:9_217:}

疯子~ 发表于 2014-12-1 20:04:07

激动人心无法言表

HALLDY 发表于 2014-12-6 23:51:22

支持学习啊

GRRRARD 发表于 2014-12-13 15:29:56

哈哈,开始学的时候我也把注释全写了,发现还挺有效的

零度C 发表于 2014-12-13 18:19:37

{:9_240:}辛苦楼主。。我也照着敲了好多遍,视频重复看了又看。还是没有楼主理解得如此透,学习了

wswgy315 发表于 2014-12-15 15:30:45

很详细,很强大

You0 发表于 2015-1-31 14:09:13

{:1_1:}拿下

电气学员 发表于 2015-2-13 10:27:01

哪里透明了???

cxd_hui 发表于 2015-2-13 10:51:35

C++还好一些,要用C#搞这些api能把人郁闷死。:huffy:

air-C 发表于 2015-2-22 22:31:25

学习了:big

xx6625303 发表于 2015-2-23 14:07:48

学习了

694861283 发表于 2015-2-27 19:19:33

有点乱,不过还是来学习学习{:9_230:}

citian3094 发表于 2015-5-13 14:31:12

谢谢分享!!

w120699 发表于 2015-6-13 16:46:46

:lol:很详细

freeparty 发表于 2015-6-13 17:55:09

支持楼主

fgl999 发表于 2015-10-12 20:32:26

支持啊,基本把所有的都注释了

741712547 发表于 2015-10-14 09:20:17

学习了,里面有些东西一直没有搞懂。
页: [1]
查看完整版本: windows窗口创建过程对应API解释(取自小甲鱼老师的API档案)