分享
 
 
 

Programming Windows3~4章摘要

王朝vc·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

第一章—— 窗口与消息

一、HelloWin程序如下:

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

HELLOWIN.C -- Displays "Hello, Windows 98!" in client area

(c) Charles Petzold, 1998

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

#include <windows.h>

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

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,

PSTR szCmdLine, int iCmdShow)

{

static TCHAR szAppName[] = TEXT ("HelloWin") ;

HWND hwnd ;

MSG msg ;

WNDCLASS wndclass ;

wndclass.style = CS_HREDRAW | CS_VREDRAW ;

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 (WHITE_BRUSH) ;

wndclass.lpszMenuName = NULL ;

wndclass.lpszClassName = szAppName ;

if (!RegisterClass (&wndclass))

{

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

szAppName, MB_ICONERROR) ;

return 0 ;

}

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

ShowWindow (hwnd, iCmdShow) ;

UpdateWindow (hwnd) ;

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

{

TranslateMessage (&msg) ;

DispatchMessage (&msg) ;

}

return msg.wParam ;

}

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, Windows 98!"), -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) ;

}

二、Windows与消息机制

1、进队与不进队的消息

Windows是一种面向对象的体系结构,Windows环境和应用程序都是通过消息来交互的。Windows应用程序开始执行后,Windows为该程序创建一个"消息队列(message queue)",用以存放邮寄给该程序可能创建的各种不同窗口的消息。消息队列中消息的结构(MSG)为:

typedef struct tagMSG{

HWND hwnd;

UINT message;

WPARAM wParam;

LPARAM lParam;

DWORD time;

POINT pt;

}MSG;

其中第一个成员变量是用来标识接收消息的窗口句柄;第二个参数便是消息标识号,如WM_PAINT;第三个和第四个参数的具体意义同message值有关,均为消息参数。前四个参数是非常重要和经常用到的,至于后两个参数则分别表示邮寄消息的时间和光标位置(屏幕坐标)。

把消息传送到应用程序有两种方法:一种是由系统将消息"邮寄(post)"到应用程序的"消息队列"。这是"进队消息",Win32 API有对应的函数: PostMessage(),此函数不等待该消息处理完就返回;而另一种则是由系统在直接调用窗口函数时将消息"发送(send)"给应用程序的特定窗口的函数,属于"不进队消息"。对应的函数是SendMessage(),其必须等待该消息处理完后方可返回。

进队的消息基本上是用户输入的结果,如击键(WM_KEYDOWN和WM_KEYUP消息)、击键产生的字符(WM_CHAR)、鼠标移动(WM_MOUSEMOVE)和鼠标击键(WM_LBUTTONDOWN)形式给出。进队消息还包含时钟消息(WM_TIMER)、刷新消息(WM_PAINT)和退出消息(WM_QUIT)等等。

不进队的消息往往来自调用特定的WINDOWS函数。例如WinMain调用CreateWindows函数时,Windows将创建窗体并在处理中给窗口过程发送一个WM_CREATE消息。当WinMain调用ShowWindow时,Windows将给窗口过程发送WM_SIZE和WM_SHOWWINDOW消息。当WinMain调用UpdateWindow时Windows将给窗口过程发送WM_PAINT。

Windows调用窗口过程,意味着Windows本身也有一个消息循环,它调用GetMessage从消息队列中取出消息,并且用DispatchMessage将消息发送给窗口过程。除了具有操作系统本身的消息循环外,对于每一个正在执行的Windows应用程序,系统为其建立一个"消息队列",即应用程序队列,用来存放该程序可能创建的各种窗口的消息。应用程序中含有一段称作"消息循环"的代码,用来从消息队列中检索这些消息并把它们分发到相应的窗口函数中。

消息循环代码是应用程序中主函数winmain ( )中类似如下的程序段:

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

{ file://从消息队列中取得消息

TranslateMessage(&&msg);

file://检索并生成字符消息WM_CHAR

DispatchMessage(&&msg);

file://将消息发送给相应的窗口函数

}

由此可见,所谓"消息循环",实际是程序循环。

2、窗口过程的可重入

虽然Windows程序可以多线程执行,但是每个线程的消息只为窗口过程在该线程中执行的窗口处理消息。也就是说,消息循环和窗口过程不是并发执行的。当消息循环从消息队列中接受到一个消息时,然后调用DispatchMessage消息发送给窗口过程时,直到窗口过程将控制返回给Windows,DispatchMessage才能返回。

窗口过程能调用给Windows窗口过程发送另一个消息的函数,这时窗口过程必须在函数调用返回之前完成对第二个消息的处理。如窗口过程调用UpdateWindow产生WM_PAINT消息时,窗口过程必须先处理完WM_PAINT消息后,UpdateWindow调用才能恢复控制权给窗口过程。

三、详细说明:

1、windows.h

这个头文件包含了其他的windows头文件:

WINDEF.H——基本类型定义

WINNT.H——支持Unicode的类型定义

WINBASE.H——内核函数

WINUSER.H——用户接口函数

WINGDI.H——图形设备借口函数

2、WinMain函数的说明:

WinMain函数是windows程序的入口点,声明如下:

int WINAPI WinMain(HINSTANCE hinstance,

HINSTANCE hPreInstance,

LPSTR lpCmdLine,

int nShowCmd

);

WINAPI——许多Windows的函数调用声明为WINAPI

实际情况如下:

#define WINAPI _stdcall

而另一种是CALLBACK类型

四个形参声明如下:

第一个参数:一个实例句柄,句柄是一个32位数,代表一个对象。

第二个参数:16位windows中程序通过检查hPreInstance参数就能够确定自身的其他实例是否正在运行。但是在32位windows中被废弃,全部为NULL

第三个参数:运行程序的命令行。

第四个参数:指出程序最初显示的方式:最大化最小化等等。

3、关于匈牙利命名

句柄声明如下:

类型 说明

HANDLE 通用句柄类型

HWND 标识一个窗口对象

HDC 标识一个设备对象

HMENU 标识一个菜单对象

HICON 标识一个图标对象

HCURSOR 标识一个光标对象

HBRUSH 标识一个刷子对象

HPEN 标识一个笔对象

HFONT 标识一个字体对象

HINSTANCE 标识一个应用程序模块的一个实例

HLOCAL 标识一个局部内存对象

HGLOBAL 标识一个全局内存对象

下面是Windows中常使用的一些字母前缀和它们所代表的数据类型:

类型 说明

b BOOL,布尔类型

by BYTE类型

c char类型

dw DWORD类型

fn 函数类型

i 整型

l LONG类型

lp 远(长)指针(long pointer)

n 短整型

np 近(短)指针(near pointer)

p 指针

s 字符串

sz 以'\0'结尾的字符串

w WORD类型

x short,用于表示X坐标时

y short,用于表示Y坐标时

pstr Char *

UINT Unsigned int 32位

以下是几个前缀:

前缀 类别

CS 类风格选项

CW 创建窗口选项

DT 绘制文本选项

IDI 图表ID号

IDC 光标ID号

MB 消息框选项

SND 声音选项

WM 窗口消息

WS 窗口风格

4、关于几个重要的结构:

MSG——消息结构

WNDCLASS——窗口类结构

PAINTSTRUCT——绘图结构

RECT——矩形结构

本章说明MSG与WNDCLASS结构如下:

MSG结构包含了一条Windows消息的完整信息,

在WINUSER.H中定义如下:

typedef struct tagMSG {

HWND hwnd; //接受消息的窗口句柄

UINT message; //主消息值,具体消息内容

WPARAM wParam; //副消息值,其具体含义依赖于主消息值

LPARAM lParam; //副消息值,其具体含义依赖于主消息值

DWORD time; //消息放入消息队列中的时间

POINT pt; //消息放入消息队列中鼠标的位置

} MSG;

顺便对POINT如下声明

typedefstructtagPOINT {

int x; /* X坐标 */

int y;/* Y坐标 */

} POINT;

WNDCLASS在WINUSER.H中定义如下:

typedefstructtagWNDCLASS{

DWORD style; /* 窗口风格 */

WNDPROC*lpfnWndProc; /* 窗口函数 */

intcbClsExtra; /* 类变量占用的存储空间 */

intcbWndExtra; /* 实例变量占用的存储空间 */

HINSTANCEhinstance;/* 定义该类的应用程序实例的句柄

HICONhicon;/* 图标对象的句柄 */

HCURSORhCursor;/* 光标对象的句柄 */

HBRUSHhbrBackground;/* 用于擦除用户区的刷子对象的句柄 */

LPCSTRlpszMenuName;/* 标识菜单对象的字符串 */

LPCSTRlpszClassName;/* 标识窗口类的名字的字符串*/}

WNDCLASS;

5、RegisterClass函数

该函数只有一个参数,,通过调用后返回0表示错误。

6、创建窗口过程中的几个函数

CreateWindows

HWND CreateWindow(

LPCSTR lpClassName, 类名,指定该窗口所属的窗体类。

LPCSTR lpWindowName, 窗口的名字,即在标题栏中显示的文本。

DWORD dwStyle, 该窗口的风格,在后面详细介绍。

int x, 窗口左上角相对于屏幕左上角的初始X坐标。

int y, 窗口左上角相对于屏幕左上角的初始Y坐标。

int nWidth, 窗口的宽度。

int nHeight, 窗口的高度。

HWND hWndParent, 一个子窗口的父窗口的句柄,或隶属窗口的拥有者窗口的句柄,若没有拥有或者父窗口,则为NULL。

HMENU hMenu, 选单句柄,如果为NULL,则使用类中定义的选单。如果建立的是一个子窗口,该参数是一个子窗口标识符,使用此标识符来区分多个窗口。

HINSTANCE hInstance, 创建窗口对象的应用程序的实例句柄。

VOID FAR * lpParam 创建窗口时指定的额外参数,一般设为NULL);

窗口风格类型说明 :

WS_BORDER 创建一个有边框的窗口

WS_CAPTION 创建一个有标题栏的窗口

WS_CHILDWINDOW(or WS_CHILD)

创建一个子窗口(不能与WS_POPUP一起使用)

WS_CLIPCHILDREN 当在父窗口内绘制时,把子窗口占据的区域剪切在外,即不在该区域内绘图

WS_CLIPSIBLINGS 裁剪相互有关系的子窗口,不在被其它子窗口覆盖的区域内绘图,仅与WS_CHILD一起使用

WS_DISABLED 创建一个初始被禁止的窗口

WS_DLGFRAME 创建一个有双边框但无标题的窗口

WS_HSCROLL 创建一个带水平滚动杠的窗口

WS_VSCROLL 创建一个带垂直滚动杠的窗口

WS_ICONIC 创建一个初始为图标的窗口,仅可以与WS_OVERLAPPEDWINDOWS一起使用

WS_MAXIMIZE 创建一个最大尺寸的窗口

WS_MINIMIZE 创建一个最小尺寸的窗口(即图标)

WS_MAXIMIZEBOX 创建一个带有极大框的窗口

WS_MINIMIZEBOX 创建一个带有极小框的窗口

WS_OVERLAPPED 创建一个重叠式窗口,重叠式窗口带有标题和边框

WS_POPUP 创建一个弹出式窗口,不能与WS_CHILD一起使用

WS_SYSMENU 窗口带有系统选单框,仅用于带标题栏的窗口

WS_THICKFRAME 创建一个边框的窗口,使用户可以直接缩放窗口

WS_VISIBLE 创建一个初始可见的窗口

ShowWindow函数

声明如下:

ShowWindows(hwnd,iCmdShow)

iCmdShow是WinMain接受并传递的,其中包含着窗体的现实方式

如:SW_SHOWNORMAL或SW_SHOWMAXIMIZED

或SW_SHOWMINOACTIVE(显示在任务栏上)

当第二个参数是SW_SHOWNORMAL时,就调用UpdateWindow(hwmd)来重画客户区,通过给窗体过程发出WM_PAINT消息来做到这一点。

7、关于消息循环的函数

BOOL GetMessage(

LPMSG lpMsg, 指向MSG类型的变量的远指针,它包含有从应用程序消息队列中检索到的一条消息的数据。

HWND hWnd, 指定为哪个窗口检索消息,如果hWnd为NULL,则检索调用该函数的应用程序的所有的消息(不检索属于其它应用程序的消息)。

UINT wMin,

UINT wMax 以下两个基本参数指定检索在wMin和wMax范围内的消息。如果这两个参数都为零,该函数检索所有的可用的消息。

);

返回值 在检索出WM_QUIT消息时,返回零值,在其它情况下返回非零值。

一个例子如下

GetMessage(&msg,NULL,0,0)

Windows就是从消息队列中取出消息来填充msg中的各个域。

如下:

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

{

TranslateMessage (&msg) ; //将msg结构传给Windows进行一些键盘转换

DispatchMessage (&msg) ; //将msg结构回传给windows

}

在窗体过程中注意使用

DefWindowsPro(hwnd,iMsg,wParam,lParam)

来处理一些默认的消息

另外注意在窗体销毁的时候(WM_DESTORY后)使用一条

PostQuitMessage(0)命令来结束。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有