鱼C论坛

 找回密码
 立即注册
查看: 5519|回复: 19

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

[复制链接]
发表于 2014-11-20 18:29:42 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

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

一个个的查太痛苦了,所以作为新手我把他们一个个摘录到程序后面的注解里了,有需要的可以去看看,不过需要我们先将代码打上5遍之后才这样做,不要问我为什么,小甲鱼老师是这样说的。这样对于入门所需要了解的函数能够更快的寻找到吧 ,在这里先感谢一下我们的小甲鱼老师
#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 {
        HDC  hdc;
        BOOL fErase;
        RECT rcPaint;
        BOOL fRestore;
        BOOL fIncUpdate;
        BYTE rgbReserved[32];
}        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 结构的指针,其中包含文本将被置于其中的矩形的信息(按逻辑坐标) 
                uFormat  1. 指定格式化文本的方法
                                 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           指定消息的附加消息,确切的含义取决于消息成员的值 

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

}

评分

参与人数 1荣誉 +5 鱼币 +5 收起 理由
freeparty + 5 + 5 支持楼主

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2014-11-20 18:38:33 | 显示全部楼层
自己先坐个沙发
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-11-20 19:57:13 | 显示全部楼层

回帖奖励 +2 鱼币

支持学习了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-12-1 20:04:07 | 显示全部楼层

回帖奖励 +2 鱼币

激动人心  无法言表
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2014-12-6 23:51:22 | 显示全部楼层

回帖奖励 +2 鱼币

支持学习啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-12-13 15:29:56 | 显示全部楼层

回帖奖励 +2 鱼币

哈哈,开始学的时候我也把注释全写了,发现还挺有效的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-12-13 18:19:37 | 显示全部楼层

回帖奖励 +2 鱼币

辛苦楼主。。我也照着敲了好多遍,视频重复看了又看。还是没有楼主理解得如此透,学习了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-12-15 15:30:45 | 显示全部楼层

回帖奖励 +2 鱼币

很详细,很强大
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-1-31 14:09:13 | 显示全部楼层

回帖奖励 +2 鱼币

{:1_1:}拿下
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-2-13 10:27:01 | 显示全部楼层

回帖奖励 +2 鱼币

哪里透明了???
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-2-13 10:51:35 | 显示全部楼层

回帖奖励 +2 鱼币

C++还好一些,要用C#搞这些api能把人郁闷死。:huffy:
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-2-22 22:31:25 | 显示全部楼层
学习了:big
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-2-23 14:07:48 | 显示全部楼层
学习了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-2-27 19:19:33 | 显示全部楼层
有点乱,不过还是来学习学习
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-5-13 14:31:12 | 显示全部楼层
谢谢分享!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-6-13 16:46:46 | 显示全部楼层
:lol:很详细
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-6-13 17:55:09 | 显示全部楼层
支持楼主
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-10-12 20:32:26 | 显示全部楼层
支持啊,基本把所有的都注释了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-10-14 09:20:17 | 显示全部楼层
学习了,里面有些东西一直没有搞懂。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-23 15:12

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表