第三章 窗口与消息

1,windows窗口过程:应用程序所创建的每一个窗口都有一个与之关联的窗口过程,用于处理传递给窗口的消息。

2,窗口依据窗口类来创建。窗口类标识了用于处理传递给窗口的消息的窗口过程。窗口类的使用允许多个窗口共享一个窗口类,因而多个窗口可以使用相同的窗口过程。

3,Windows程序开始执行的时候,Windows首先为该程序创建一个消息队列。该消息队列中存放着应用程序可能创建的所有窗口的消息。Windows应用程序中一般包含一小段称为"消息循环"的代码,该段代码用于从消息队列中检索消息,并将其分发给相应的窗口过程。其他消息则不经过消息队列直接发送给窗口过程。

4,创建显示窗口的代码如下:

/*----------------------------------------------

HelloWindow.c

    Displays "Hello, Window." in client area

    code and compile it with visual studio 2008

 

----------------------------------------------*/

 

#include <windows.h>

 

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

 

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

                 LPSTR lpCmdLine, int iCmdShow)

{

    static TCHAR szWndClassName[] = TEXT("Hello Window");

    HWND hwnd;

    MSG msg;

    WNDCLASS wndClass;

 

    //define property of window class

    wndClass.style = CS_HREDRAW|CS_VREDRAW;

    wndClass.lpfnWndProc = WndProc;

    wndClass.cbClsExtra = 0;

    wndClass.cbWndExtra = 0;

    wndClass.hInstance = hInstance;

    wndClass.hIcon = LoadIcon(NULL, IDI_QUESTION);

    wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);

    wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

    wndClass.lpszMenuName = NULL;

    wndClass.lpszClassName = szWndClassName;

 

    //register window class

    if(!RegisterClass(&wndClass))

    {

        MessageBox(NULL, TEXT("This program requires Windows NT!"),

                    TEXT("Hint"), MB_ICONERROR|MB_OKCANCEL);

        return 0;

    }

 

    //create the window based on the previous registered window class

    hwnd = CreateWindow(szWndClassName,                //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

 

    //show and refresh the window

    ShowWindow(hwnd, iCmdShow);

    UpdateWindow(hwnd);

 

    //set message loop

    while(GetMessage(&msg, NULL, 0,0))

    {

        TranslateMessage(&msg);

        DispatchMessage(&msg);

    }

 

 

    return msg.wParam;

}

 

//window process function

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, Window."), -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);

}

5,一些windows api 函数

LoadIcon:加载图标

LoadCursor:加载鼠标光标

GetStockObject:获取图形对象

RegisterClass:为窗口注册窗口类

CreateWindow:创建窗口

ShowWindow:在屏幕中显示窗口

UpdateWindow:指示窗口对其自身进行重绘

GetMessage:从消息队列中获得消息

TranslateMessage:翻译一些键盘消息

DispatchMessage:将消息发送给窗口过程

BeginPaint:标明窗口绘制开始

EndPaint:结束窗口绘制

DrawText:显示文本字符串

PostQuitMessage:将退出消息插入消息队列

DefWindowProc:执行默认的消息处理

 

6,数值常量前缀:

CS

类风格选项

CW

创建窗口选项

DT

文本绘制选项

IDI

图标ID号

IDC

光标的ID号

MB

消息框选项

SND

声音选项

WM

窗口消息

WS

窗口风格

 

7,一些数据类型

UINT:unsigned int

WPARAM: word param, 16位程序为unsigned short ,32位程序为unsigned int

LPARAM:long

LRESULT:long

WINAPI, CALLBACK: __stdcall

HINSTANCE: 实例句柄,程序本身

HWND:窗口句柄

HDC:设备环境句柄

句柄本质上是引用某个对象的数值,通常为32位。

 

8,窗口的注册

(1)窗口类结构WNDCLASS

参考资料:https://msdn.microsoft.com/zh-cn/library/windows/desktop/ms633576(v=vs.85).aspx

WNDCLASS 的lpszClassName最长为256

(2)窗口类注册使用RegisterWindow或者RegisterWindowEx

 

参考资料:https://msdn.microsoft.com/zh-cn/library/windows/desktop/ms633586(v=vs.85).aspx

RegisterWindow有RegisterWindowA和RegisterWindowW两个版本,程序使用哪个版本注册窗口类,决定着传递给窗口的消息是包含ASCII文本还是Unicode文本

 

关于Windows窗口类:

https://msdn.microsoft.com/zh-cn/library/windows/desktop/ms633574(v=vs.85).aspx#class_styles

9,窗口的创建

由于窗口类只是定义了窗口的一般特征,因此基于同一窗口类可以创建许多不同的窗口。

关于窗口类和窗口的区别:

例:所有下压按钮都是基于相同的窗口类。与该窗口类关联的窗口过程位于Windows内部,并负责处理鼠标和键盘对按钮的输入,以及定义按钮在屏幕上的视觉外观。但是按钮位置尺寸不同,文字不同,这些就属于窗口定义。

窗口的WS_OVERLAPPEDWINDOW:层叠窗口,包含标题栏,标题左边的系统菜单按钮,一个窗口尺寸调整边框以及位于标题栏右方的三个按钮。

连续创建的窗口,Windows会沿水平和垂直做步长为1的偏移。

若新建的窗口为顶级窗口,父窗口句柄为NULL。通常,两个窗口存在父子关系时,子窗口总是位于父窗口的前方。应用程序窗口总是位于桌面窗口的前方。

 

10,窗口的显示

当CreateWindow返回时,窗口已在Windows内部被创建,即Windows已为窗口分配了一块内存。

 

11,消息循环

Windows为当前在其中运行的每一个Windows程序(进程)都维护了一个消息队列,

GetMessage:

https://msdn.microsoft.com/en-us/library/windows/desktop/ms644936(v=vs.85).aspx

GetMessage(&msg, NULL, 0,0)

获取由该程序创建的所有窗口的消息。Windows用从消息队列中得到下一条消息来填充消息结构的各个字段。如果从消息队列中检索到的消息message字段不是WM_QUIT,返回非零,否则返回0.

TranslateMessage(&msg):将消息返回给Windows进行键盘消息的转换,

DispathMessage(&msg):将消息再次返回给Windows。

接下来,Windows将此消息发送给合适的窗口过程来处理。

 

12,窗口过程

一个Windows程序可以包含多个窗口过程,但是一个窗口过程总是与一个通过调用RegisterClass注册的特定窗口类相关联。

窗口过程由Windows进行调用。

 

13,消息的处理

通过switch-case结构来确定窗口过程受到的消息的类型以及相应的处理办法。窗口过程对消息进行处理后,应返回0。所有窗口过程不进行处理的消息都必须传给DefWindowProc的Widows函数。

 

14,WM_PAINT消息

当窗口的客户区部分或者全部无效且必须更新时,应用程序将得到此通知。这也意味着窗口必须被重绘。

当窗口创建后,客户区为无效的,通过调用ShowWindow使窗口重绘,窗口尺寸发生变化,也会重绘。最大最小化也会重绘。窗口被重叠后再次显示,也会发送WM_PAINT消息。

WM_PAINT以调用BeginPaint开始,EndPaint结束。

在调用BeginPaint期间,若客户区背景未被擦除,Windows会调用窗口类中的背景对其进行擦除。BeginPaint返回设备环境句柄。

若一个窗口过程不对WM_PAINT消息进行处理,必须交给DeWindowProc进行处理

 

15,Windows编程的若干难点

  1. WinMain函数只负责定义注册窗口类、创建窗口、从消息队列中检索和分发消息。
  2. WndProc会在如下情况被调用:新建窗口时,窗口被最终销毁时,用户从键盘输入字符时,用户从菜单中选择某个项时,用户用鼠标操作或者单击滚动条时,窗口的客户区需要重绘时。

16,队列消息和非队列消息

队列消息:Windows放入程序消息队列中的消息。在程序的消息循环中,消息被检索,然后被投递(post)到窗口过程中。主要是用户的输入产生,如WM_KEYDOWN,WM_KEYUP,WM_CHAR,WM_TIMER,WM_LBUTTONDOWN,WM_PAINT,WM_QUIT。

非队列消息:由Windows直接对窗口过程进行调用产生的,是被发送到窗口过程中的。包括消息队列以外的其它消息,如WM_CREATE,WM_SIZE,WM_SHOWWINDOW。处理菜单项选择的WM_COMMAND。

 

Windows程序可有多个执行线程。但每个线程的消息队列仅为那些其窗口过程在该线程内执行的窗口进行消息处理。即,消息循环和窗口过程不是并发运行的,当一个消息循环从其自身的消息队列中检索消息,并调用DispatchMessage函数将检索到的消息发送给窗口过程时,只有在窗口过程将控制权返回给Windows后,DispatchMessage才会返回。

Windows程序设计(第五版)学习:第三章 窗口与消息的更多相关文章

  1. Windows程序设计(第五版)学习:第一章 起步

    第一章 起步 1,windows主要的三个动态库: kernel32.dll负责操作系统的传统工作,包括内存管理.文件输入以及任务管理等. user32.dll负责用户界面的操作,即所有窗口的管理 g ...

  2. Windows程序设计(第五版)学习:第二章 Unicode简介

    第二章 Unicode简介 1,Windows通过双字节技术DBCS解决这个问题,代码页定义不同的字符集,称为ANSI字符集,比如日文为CP932,韩文为CP949,繁体中文为CP950,简体中文为C ...

  3. Windows程序设计(第五版)学习:第四章 文本输出

    第四章 文本输出 1,客户区:整个应用程序窗口中没有被标题栏.边框.菜单栏.工具栏.状态栏和滚动条占用的区域.简而言之,客户区就是窗口中程序可以在上面绘制并向用户传达可视化信息的区域.   2,大多数 ...

  4. C#高级编程 (第六版) 学习 第三章:对象和类型

    第三章 对象和类型 1,类和结构 类存储在托管堆上 结构存储在堆栈上   2,类成员 类中的数据和函数称为类成员 数据成员 数据成员包括了字段.常量和事件   函数成员 方法:与某个类相关的函数,可以 ...

  5. 《Windows程序设计第5版》学习进度备忘

    书签:另外跳过的内容有待跟进 __________________学习资源: <Windows程序设计第5版珍藏版> __________________知识基础支持: _________ ...

  6. 《Python学习手册 第五版》 -第18章 参数

    在函数的定义和调用中,参数是使用最多喝最频繁的,本章内容就是围绕函数的参数进行讲解 本章重点内容如下: 1.参数的传递 1)不可变得参数传递 2)可变得参数传递 2.参数的匹配模式 1)位置次序:从左 ...

  7. 《Python学习手册 第五版》 -第15章 文档

    本章主要介绍Python中的文档,会通过多种方式来说明,如果查看Python自带文档和其他参考的资料 本章重点内容 1.#注释:源文件文档 2.dir函数:以列表显示对象中可用的属性 3.文档字符串 ...

  8. 《Python学习手册 第五版》 -第16章 函数基础

    前面的章节讲解的是一些基础数据类型.基本语句使用和一些文档查看的内容,这些都是一些基础,其实还谈不上入门,只有了解了函数,才算入门 函数是编程里面使用最多的也是最基本的程序结构, 本章重点内容 1.函 ...

  9. 《C++Primer》第五版习题答案--第一章【学习笔记】

    C++Primer第五版习题解答---第一章 ps:答案是个人在学习过程中书写,可能存在错漏之处,仅作参考. 作者:cosefy Date: 2022/1/7 第一章:开始 练习1.3 #includ ...

随机推荐

  1. 监听调试web service的好工具TCPMon

    监听调试web service的好工具TCPMonhttp://ws.apache.org/commons/tcpmon/download.cgi TCPMon Tutorial Content In ...

  2. LintCode Binary Tree Paths

    Binary Tree Paths Given a binary tree, return all root-to-leaf paths. Given the following binary tre ...

  3. charles 结合mocky 模拟数据

    重定向(模拟造数据) 例如:E代送商户端订单列表,模拟99+订单 接口:http://api.edaisong.com/20151022/order/consigneeaddressb 打开http: ...

  4. LA 3027 合作网络 并查集

    题目链接: https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show ...

  5. 二叉排序树(BST)的建立

    给一个非递归的吧. /* 已知,二叉树存储结构定义见bstree.h,请编写一个算法函数bstree creatBstree(int a[],int n), 以数组a中的数据作为输入建立一棵二叉排序树 ...

  6. RF 测试代码体会

    这里的需求是完成一个cc2540 RF测试程序.实现功能为开发板按键控制 RF 发射频率的改变. 首先被告知要用PTM来做这个测试程序,然后我去了PTM的介绍文档,地址为 http://process ...

  7. api接口签名验证(MD5)

    不要急,源代码分享在最底部,先问大家一个问题,你在写开放的API接口时是如何保证数据的安全性的?先来看看有哪些安全性问题在开放的api接口中,我们通过http Post或者Get方式请求服务器的时候, ...

  8. github管理代码

    1.首先去github官网申请一个账号 github官网 2.登录github,并新建一个库: 点击: 进去之后,这里填写库名,可以随便填写:  然后直接点击: 3.本地连接github 1)安装gi ...

  9. Perl 随笔

    1.    .pl  文件带入参数: ./auto_cfg.pl ./mconfig.config ./boardconfig.config ./menuconfig.config .ver  ./a ...

  10. CSS基本语法

    这里主要介绍Bootstrap里用到的CSS语法,以便在源码分析时更容易理解和学习.Bootstrap的CSS组件的核心就是选择器的定义以及在各自优先级上的处理. 优先级 如何确定CSS的优先级,这里 ...