win32学习记录-day03-04


上半天讲窗口和窗口类附加数据区别以及子窗口的创建
下半天讲消息的组成

子窗口的创建

创建时要设置父窗口句柄
创建风格要增加 WS_CHILD|WS_VISIBLE

BOOL MoveWindow(
    HWND hWnd,//窗口句柄
    int x,
    int y,
    int nWidth,//窗口的宽
    int nHeight,//窗口的高
    BOOL bRepaint);//擦出标识

  • 窗口类附加数据缓冲区的用法
  1. 申请缓冲区
    int cbClsExtra; 值一般是4的倍数 200

  2. 写数据
DWORD SetClassLong(
    HWND hWnd,//窗口句柄
    int nIndex,//字节索引号
    LONG dwNewLong);//存入的数据
  1. 读数据
DWORD GetClassLong(
    HWND hWnd, //窗口句柄
    int nIndex);//字节索引号(从哪个字节开始读取)
返回值获取读到的数据
  • 窗口附加数据缓冲区的用法
  1. 申请缓冲区
    int cbWndExtra;

  2. 写数据
DWORD SetWindowLong(
    HWND hWnd,//窗口句柄
    int nIndex,//字节索引号
    LONG dwNewLong);//存入的数据
  1. 读数据
DWORD GetWondowLong(
    HWND hWnd, //窗口句柄
    int nIndex);//字节索引号(从哪个字节开始读取)
返回值获取读到的数据

窗口类附加数据缓冲区和窗口附加数据缓冲区区别:

窗口类附加数据-buffer 基于同一个窗口类创建出来的所有窗口共享buffer
窗口附加数据buffer 窗口自己私有的buffer,即便是基于同一个窗口类创建的窗口相互之间也不共享

—————————————————————————————————————

程序执行驱动

过程驱动:程序的执行过程是按照预定好的顺序执行
事件驱动:程序执行是无序的,用户根据需要随机触发相应的事件
win32窗口程序就是采用事件驱动方式执行,也就是消息机制

—————————————————————————————————————

windows平台下的消息组成(缺一不可)

窗口句柄
消息ID
消息的两个参数(附带信息)
消息产生的时间
消息产生时的鼠标位置

派发消息:
DispatchMessage(&nMsg)
{
    nMsg.hwnd   ------>保存窗口数据内存 ------>"Main"   通过main函数拿到WndProc
return WndProc(nMsg.hwnd,nMsg.message,nMsg.wParam, nMsg.lParam);
}
消息三大特性(学习方法)
  • 消息什么时候产生(产生时间)
  • 消息产生后用该消息干什么(用法)
  • 该消息附带的信息是什么(附加信息)
举例:
  • WM_DESTROY - 窗口被销毁时的消息,无消息参数。常用于在窗口被销毁(保存窗口数据的那块内存被释放)之前,做相应的善后处理,例如资源、内存等。
  • WM_SYSCOMMAND - 系统命令消息,当点击窗口的最大化、最小化、关闭、标题栏、边框等命令时,收到这个消息。常用在窗口关闭时,提示用户处理。
        wParam - 具体点击的位置,例如关闭SC_CLOSE等
        lParam - 鼠标位置(长整型,以下是两个宏)
       LOWORD 低字 - 水平位置
        HIWORD 高字 - 垂直位置

               取低字段的水平位置
              int x = LOWORD(IParam)
              取高字段的锤子位置
              int x = HIWORD(IParam)
  • WM_CREATE - 在窗口创建成功还未显示之前,收到这个消息。
    常用于初始化窗口的参数、资源等等,包括创建子窗口、控件等。
    WPARAM - 不使用
    LPARAM - 是CREATESTRUCT结构类型的指针,保存了CreatWindowEx中的12个参数。

  • WM_SIZE - 在窗口的大小发生变化后,会收到WM_SIZE。
    常用于窗口大小变化后,调整窗口内各个部分控件的布局。
    WPARAM - 窗口大小变化的原因。比如点击关闭,最大化,最小化
    LPARAM - 变化窗口客户区的大小
    LOWORD - 变化后的宽度
    HIWORD- 变化后的高度

  • WM_QUIT - 用于结束消息循环处理。
    wParam - PostQuitMessage 函数传递的参数
    lParam - 不使用
    当GetMessage收到这个消息后,会返回FALSE,结束while处理,退出消息循环。
  • WM_PAINT - 绘图消息
    键盘消息
    鼠标消息
    定时器消息


调试程序的方法:

控制台窗口
HANDLE g_hOutput = NULL;//标准输出句柄,全局变量

AllocConsole();//给窗口程序添加一个附带的DOS窗口,主程序中

g_hOutput=GetStdHandle(STD_OUTPUT_HANDLE);

WriteConsole(g_hOutput, szText, strlen(szText), NULL, NULL);//标准输出句柄,输出字符串, 字符串长度, 实际输出字符串长度,未输出的窗口

BOOL MoveWindow(   
HWND hWnd, //   
int X, // horizontal position  
int Y, // vertical position    
int nWidth, // width    
int nHeight, // height    
BOOL bRepaint // repaint option
 );移动窗口控件

在上文的程序实例中有演示


获取消息

GetMessage - 从系统获取消息,将消息从系统中移除,阻塞函数。当系统无消息时,GetMessage会等候下一条消息。
PeekMessage - 以查看的方式从系统获取消息,可以不将消息从系统移除,非阻塞函数。当系统无消息时,返回FALSE,继续执行后续代码。

BOOL PeekMessage(
LPMSG lpMsg,         // message information
HWND hWnd,           // handle to window
UINT wMsgFilterMin,  // first message
UINT wMsgFilterMax,  // last message
UINT wRemoveMsg //移除标识,是否从操作系统提取消息
);
获取消息机制(重点):
  • peekMessage投递消息,消息发出后立刻返回,不等待消息执行结果
  • peekMessage会返回目的地是否有消息,如果有消息则返回true,返回true则派getMessage去获取消息(getMessage会一直等待消息直到获取到消息才返回) ,返回false则什么都不干或者向窗口打印消息等等(自定义返回false后的动作)
  • getMessage去获取消息也会返回值,返回true表示获取消息,获取到消息则翻译和派发消息,返回false则return
获取消息示例:
  • 这种方式可能会让cpu阻塞,因为getMessage一直在等待消息,不获取到不返回
    while (GetMessage(&nMsg, NULL, 0, 0))
    {
        TranslateMessage(&nMsg);
        DispatchMessage(&nMsg);
    }
  • 这种方式cpu有消息就获取,然后马上返回
while (1)
        {
            if (peekMessage(&nMsg, NULL, 0, 0, PM_NOREMOVE))
            {
                //peekMessage返回true代表有消息
                if (GetMessage(&nMsg, NULL, 0, 0))
                {
                    TranslateMessage(&nMsg);
                    DispatchMessage(&nMsg);
                }
                else
                {
                    return;
                }
            }
            else
            {
                //空闲处理,此处是向DOS窗口发送消息,也定义其他空闲处理
                WriteConsole(g_hOutput, "OnIdle", 6, NULL, NULL);
            }
        }

发送消息

SendMessage - 发送消息,会等候消息处理的结果。
PostMessage - 投递消息,消息发出后立刻返回,不等候消息执行结果。

   BOOL SendMessage/PostMessage(//消息由六部分组成,此时该消息只有四个参数,另外两个消息由系统默认
                                    HWND hWnd,//消息发送的目的窗口
            UINT Msg, //消息ID
            WPARAM wParam, //消息参数
            LPARAM lParam  //消息参数
    );//消息的后两个参数由该函数内部自动填写
处理消息函数
//主窗口处理函数(处理消息)
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_SIZE:
        OnSize(hWnd, lParam);
        break;
    case WM_CREATE:
        OnCreate(hWnd, lParam);
        break;
    case WM_SYSCOMMAND:
        if (wParam == SC_CLOSE)
        {
            int nRet = MessageBox(hWnd, "是否退出", "Infor", MB_YESNO);
            if (nRet == IDYES)
            {
                //什么都不写
            }
            else
            {
                return 0;
            }
        }
        break;
    case WM_DESTROY:
        //PostQuitMessage(0);//该函数内调用postMessage发送消息
        SendMessage(hWnd, WM_QUIT, 0, 0);
        break;
    }
    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
发送消息分类
  1. 系统消息 - ID范围 0 - 0x03FF
    由系统定义好的消息,可以在程序中直接使用。
  2. 用户自定义消息 - ID范围 0x0400 - 0x7FFF (31743)
    由用户自己定义,满足用户自己的需求。由用户自己发出消息,并响应处理。
    #define WM_MYMESSAGE WM_USER+n
    自定义消息宏:WM_USER
  3. 应用程序消息 - ID范围 0x8000 - 0xBFFF
    程序之间通讯时使用的消息。多用于底层驱动
    应用程序消息宏:WM_APP
    4 系统注册消息 - ID范围 0xC000 - 0xFFFF
    在系统注册并生成相应消息,然后可以在各个程序中使用这个消息。
消息队列
  • 消息队列用于存放消息的一个队列,消息在队列中先入先出。所有窗口程序都具有消息队列。程序可以从队列中获取消息。
  • 消息队列的类型
    • 系统消息队列-由系统维护的消息队列。存放系统产生的消息,例如鼠标、键盘等。
    • 程序消息队列-属于每一个应用程序(线程)的消息队列。由应用程序(线程)维护。
  • 消息队列的关系
    1. 当鼠标、键盘产生消息时,会将消息存放到系统消息队列
    2. 系统会根据存放的消息,找到对应窗口的消息队列。
    3. 将消息投递到程序的消息队列中。
  • 根据消息和消息队列之间使用关系,将消息分成两类:
    • 队列消息 - 消息的发送和获取,都是通过消息队列完成。
      • 队列消息-消息发送后,首先放入队列,然后通过消息循环,从队列当中获取。
      • GetMessage – 只能从本进程消息队列中获取消息
      • PostMessage - 将消息投递到系统消息队列(系统消息对->进程消息队列)
      • 常见队列消息:WM_PAINT、键盘、鼠标、定时器。
    • 非队列消息 - 消息的发送和获取,是直接调用消息的窗口处理完成。

      • 非队列消息-消息发送时,首先查找消息接收窗口的窗口处理函数,直接调用处理函数,完成消息。
      • SendMessage - 直接将消息发送给窗口的处理函数,并等候处理结果,不发送给消息队列。
      • 常见消息:WM_CREATE、WM_SIZE等。
消息循环
  • GetMessage /PeekMessage从程序的消息队列当中,获取到消息。
  • TranslateMessage 检查获取到的消息,如果发现是按键消息,产生一个字符消息WM_CHAR,并放入程序的消息队列。
  • DispatchMessage 根据消息,找到窗口处理函数,调用窗口处理函数,完成消息的处理
GetMessage/PeekMessage获取消息过程
  1. 在程序(线程)消息队列查找消息,如果队列有消息,检查消息是否满足指定条件(HWND,ID范围),不满足条件就不会取出消息,否则从队列取出消息返回。
  2. 如果程序(线程)消息队列没有消息,向系统消息队列获取属于本程序的消息。如果系统队列的当前消息属于本程序,系统会将消息转发到程序的消息队列
  3. 如果系统消息队列也没有消息,检查当前窗口的需要重新绘制的区域,如果发现有需要绘制的区域,GetMessage产生WM_PAINT消息,取得消息返回处理。
  4. 如果没有重新绘制区域,检查定时器如果有到时的定时器,GetMessage产生WM_TIMER,返回处理执行。
  5. 如果没有到时的定时器,整理程序的资源、内存等等。
  6. GetMessage会继续等候下一条消息。PeekMessage会返回FALSE,交出程序的控制权。

注意:GetMessage如果获取到是WM_QUIT,函数会返回FALSE。

消息的发送
  1. SendMessage
    发送消息到指定的窗口,并等候对方将消息处理,然后消息执行结果,用于非队列消息的发送。
  2. PostMessage
    将消息放到系统消息队列中,立刻返回,用于队列消息的发送。
    无法获知消息是否被对方处理。
绘图消息-WM_PAINT
  • 当窗口需要绘制的时候,会发送窗口处理函数:WM_PAINT
  • 当窗口重新显示和窗口变大时,就需要重画,被遮挡和小化不需要重画
  • 窗口无效区域(被声明成需要重新绘制的区域)
    BOOL InvalidateRect(
    HWND hWnd, //窗口句柄
    CONST RECT* lpRect, //区域的矩形坐标,为空则整个窗口都重画
    BOOL bErase //重绘前是否先擦除
    );
    在程序中,如果需要绘制窗口,调用函数声明窗口无效区域。

转载于:https://www.cnblogs.com/lhfen/p/5965996.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值