《Windows程序设计 第5版》第3章 窗口与消息 笔记

广告先:

LibUIDK界面库:制作QQ、360界面时,你能找到的最强大的界面库。基于DirectHWND技术!

3.1 窗口的创建

一个简单的win32程序如下(假设工程名为“HelloWin32”,下面的代码是使用vc6.0创建一个名为HelloWin32的“Win32 Application”,并且选择“A typical "Hello World" application”后创建的代码精简后得到):

// HelloWin32.cpp : Defines the entry point for the application.

//

#include "stdafx.h"

#include "resource.h"

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

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)

{

// Register class.

static TCHAR szClassName[] = _T("HelloWin32");

WNDCLASSEX wcex;

wcex.cbSize = sizeof(WNDCLASSEX);

wcex.style   = CS_HREDRAW | CS_VREDRAW;

wcex.lpfnWndProc = (WNDPROC)WndProc;

wcex.cbClsExtra  = 0;

wcex.cbWndExtra  = 0;

wcex.hInstance  = hInstance;

wcex.hIcon   = LoadIcon(hInstance, (LPCTSTR)IDI_HELLOWIN32);

wcex.hCursor  = LoadCursor(NULL, IDC_ARROW);

wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);

wcex.lpszMenuName = (LPCSTR)IDC_HELLOWIN32;

wcex.lpszClassName = szClassName;

wcex.hIconSm  = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);

RegisterClassEx(&wcex);

// Perform application initialization:

HWND hWnd = CreateWindow(szClassName, _T("The hello win32 app"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

if (hWnd == NULL)

{

return 0;

}

ShowWindow(hWnd, nCmdShow);

UpdateWindow(hWnd);

HACCEL hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_HELLOWIN32);

// Main message loop:

MSG msg;

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

{

if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))

{

TranslateMessage(&msg);

DispatchMessage(&msg);

}

}

return msg.wParam;

}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

PAINTSTRUCT ps;

HDC hdc;

static TCHAR szHello[] = _T("Hello win32");

switch (message)

{

case WM_CREATE:

break;

case WM_PAINT:

hdc = BeginPaint(hWnd, &ps);

// TODO: Add any drawing code here...

RECT rt;

GetClientRect(hWnd, &rt);

DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);

EndPaint(hWnd, &ps);

break;

case WM_DESTROY:

PostQuitMessage(0);

break;

default:

return DefWindowProc(hWnd, message, wParam, lParam);

}

return 0;

}

我们单步调试上面的代码,在WndProc的WM_PAINT消息中加个断点,在执行UpdateWindow(hWnd)这行代码时,我们就会发现会进入到WM_PAINT中,但这时,还没有进入下面的消息循环。我们知道,消息循环是从消息队列中取消息,既然没有执行消息循环前就可以处理WM_PAINT消息,说明这个WM_PAINT消息是直接发往窗口、而没有进入消息队列的。这句话的意思是:消息循环会调用WndProc,但并不是只有消息循环可以调用WndPorc,windows本身也可以调用。我们可以想像一下CreateWindow的伪代码:

HWND CreateWindow(...)

{

HWND hWnd = NULL;

// 分配窗口内存,生成窗口

hWnd = ...;

CREATESTRUCT cs;

// 初始化cs.

WndProc(hWnd, WM_CREATE, 0, LPARAM(&cs));  // CreateWindow内部不经消息循环,直接调用WndProc

// 执行其它操作

return hWnd;

}

DispatchMessage的伪代码可能如下:

LRESULT DispatchMessage(const MSG *lpmsg)

{

// 执行其它操作

WndProc(lpmsg->hwnd, lpmsg->message, lpmsg->wParam, lpmsg->lParam);

// 执行其它操作

return 0;

}

其实,早在CreateWindow时,Windows就调用WndProc并传递了WM_CREATE消息。WM_CREATE是程序收到的第一个消息。类似的,ShowWindow可能会触发WM_SIZE和WM_SHOWWINDOW消息。

被投递到消息队列中的消息叫“队列消息”,不在队列中的为“非队列消息”。一个消息是队列消息还是非队列消息并不是绝对的,比如WM_PAINT可以是队列消息(窗口显示之后调用InvalidateRect,就会往消息队列中增加一条WM_PAINT消息),也可以是非队列消息(上面UpdateWindow发出的那个),对于程序员,大部分时间,不用关心某个消息是队列消息,还是非队列消息,你只需知道它们都最终是交给WndProc窗口过程、以同步方式 处理的就可以了。

在CreateWindow时,指定窗口初始位置和尺寸时,CW_USEDEFAULT参数表示使用默认值,默认值意味着:Windows会将连续新建的窗口的左上角位置沿水平方向和垂直方向分别作步长为1的偏移。

时间: 2024-10-14 14:31:22

《Windows程序设计 第5版》第3章 窗口与消息 笔记的相关文章

Java 线程第三版 第四章 Thread Notification 读书笔记

一.等待与通知 public final void wait() throws InterruptedException 等待条件的发生. public final void wait(long timeout) throws InterruptedException 等待条件的发生.如果通知没有在timeout指定的时间内发生,它还是会返回. public final void wait(long timeout, int nanos) throws InterruptedException

Java 线程第三版 第三章数据同步 读书笔记

多线程间共享数据问题 一.Synchronized关键字 atomic一词与"原子"无关,它曾经被认为是物质的最小的单元,不能再被拆解成更小的部分. 当一个方法被声明成synchronized,要执行此方法的thread必须先取得一个token,我们将它称为锁.一旦该方法取得(或者说是获得)锁,它将运行此方法然后释放掉(或者返回)此锁.不管方法时怎样返回的(包括通过异常)该锁会被释放. 二.Volatile关键字 如果变量被标示为volatile,每次使用该变量时都必须从主寄存器中读出

第27章 窗口与消息(1)

27.1 线程的消息队列 (1)Windows用户对象(User Object) ①类型:图标.光标.窗口类.菜单.加速键表等 ②当一个线程创建某个对象时,则该对象归这个线程的进程所有,当进程结束时,如果用户没有明确删除这个对象,则操作系统会自动删除这个对象. ③窗口和钩子(hook)这两种用户对象,它们分别由建立窗口和安装钩子的线程所拥有(注意,不是进程).如果一个线程建立一个窗口或安装一个钩子.然后线程结束,操作系统会自动删除窗口或卸载钩子. ④窗口及线程的拥有关系使得建立窗口的线程必须为它

js高级程序设计第三版---1~3章

DOM并不只是会对js的,很多其它语言也实现了DOM,但DOM已经是js的一个重要组成部分. BOM是js实现的一部分,但是没有相关的标准,所以每个浏览器都有自己的实现,这个问题在HTML5中得到了解决. 1.<script>的属性: async(异步加载):表示立即下载脚本,不会影响页面中的其它操作,只对外部脚本有效.<script async="async" type="text/javascript"</script> chars

读Javascript高级程序设计第三版第六章面向对象设计--创建对象

虽然Object构造函数或者对象字面量都可以用来创建单个对象,但是缺点非常明显:使用同一接口创建很多对象,会产生大量重复代码. 工厂模式  1 function CreatePerson(name,age,job){ 2         var o=new Object(); 3         o.name=name; 4         o.age=age; 5         o.job=job; 6         o.sayName=function(){ 7            

js高级程序设计第4版(第5章)数据类型与算法

/** * Created by Administrator on 2015/7/11 0011. */ //引用类型:它的值是引用类型的一个实例(数据结构):用于将数据和功能组织起来,也称为类, //创建新对象 var person=new Object(); //这样创建了Object()一个实例,然后将这个实例赋值给person变量<它可以用于存储和传输数据> //创建object()方式,如下 var person=new Object(); //第2种通过键值对方式,如下 var p

Java 螺纹第三版 第三章数据同步 读书笔记

多线程间共享数据问题 一.Synchronizedkeyword atomic一词与"原子"无关,它以前被觉得是物质的最小的单元,不能再被拆解成更小的部分. 当一个方法被声明成synchronized,要执行此方法的thread必须先取得一个token,我们将它称为锁. 一旦该方法取得(或者说是获得)锁,它将执行此方法然后释放掉(或者返回)此锁.无论方法时如何返回的(包含通过异常)该锁会被释放. 二.Volatilekeyword 假设变量被标示为volatile.每次使用该变量时都必

第3章 窗口与消息_3.2面向对象的窗口类的封装

3.2.1 MFC单文档大致框架 (1)MFC类继承略图 (2) MFC单文档应用程序类层次结构图 CWinApp:应用程序类,每个应用程序有且只有一个继承于CWinApp的派生类对象 CWnd:是一个通用的窗口类,用于提供Windows中的所有通用特性.对话框和控件. (3)应用程序执行过程图 3.2.2 应用程序QWinApp的设计 //QWinApp.h文件 #include "stdAfx.h" class QWinApp { public: QWinApp(); ~QWinA

MFC Windows程序设计源码免费下载

本人最近在网上找到了<MFC Windows程序设计>第二版的书内程序的源码,特意上传CSDN上面,供学习MFC的程序员们免费下载. 源码下载: http://download.csdn.net/detail/bboot/7486011 还有该书的电子版下载地址: 现在不方面上传,晚上回去上传. MFC Windows程序设计源码免费下载