第三章 窗口与消息

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. [转]http://makefiletutorial.com/

    Intro This makefile will always run. The default target is some_binary, because it is first. some_bi ...

  2. What does "Rxlch" mean in ENCODE?

    In ENCODE project, we could see some files are called "...rxlch...", which means "rev ...

  3. /proc/uptime详解

    From:http://smilejay.com/2012/05/proc_uptime/ 在Linux中,我们常常会使用到uptime命令去看看系统的运行时间,它与一个文件有关,就是/proc/up ...

  4. Java-->xml的pull解析

    --> pull解析器是android内置的解析器,解析原理与sax类似 --> xml文件student.xml: <?xml version="1.0" en ...

  5. ;function($,undefined) 前面的分号是什么用处

    ;function($,undefined) 前面的分号是什么用处 ;(function($){$.extend($.fn...现般在一些 JQuery 函数前面有分号,在前面加分号可以有多种用途:1 ...

  6. Bank,我只是来完成作业的

    写这个Bank我需要有:开户,取款,存款,转账,查询余额,退出功能. 这样我需要有两个类:Bank,User.一个Main入口. 先看这个User,他定义了各个需要的属性(字段)和字段的属性(虽然在这 ...

  7. Scrollview 嵌套 RecyclerView 及在Android 5.1版本滑动时 惯性消失问题

    标签:scrollview   android   滑动   嵌套 scrollview 嵌套recyclerview 时,recyclerview不显示,这就需要我们自己计算recyclerview ...

  8. 031. aps.net中数据绑定控件两种添加自动编号的方法

    前端HTML代码: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Defaul ...

  9. [ExtJS5学习笔记]第三节 sencha cmd学习笔记 生成应用程序构建的内部细节

    本文地址: http://blog.csdn.net/sushengmiyan/article/details/38316829本文作者:sushengmiyan------------------- ...

  10. SQL总结(五)存储过程

    SQL总结(五)存储过程 概念 存储过程(Stored Procedure):已预编译为一个可执行过程的一个或多个SQL语句. 创建存储过程语法 CREATE proc | procedure pro ...