第4章 第一个窗口程序

1 了解窗口

2 窗口程序原理

事件驱动模式


image.png

窗口程序的运行过程


窗口程序的运行过程

DispatchMessage会在内部调用消息处理的回调函数
窗口程序的运行过程

应用程序之间也可互相发送消息
PostMessage 将一个消息放到其他程序的消息队列中
SendMessage 越过消息队列直接调用目标程序的窗口过程

RegisterClassEx 用来注册窗口过程 即用来注册处理窗口消息的回调函数

2 分析窗口程序

2.1 模块与句柄

exe dll装入内存后称为模块,每个模块都有一个唯一标识的句柄,在win32中,模块句柄在数值上等于内存中装入的起始地址,用来标识各种资源
使用GetModuleHandle来获取模块句柄
例子


获取user32.dll的句柄

当参数为NULL,会获取调用者本模块的句柄


image.png

在win32中实例句柄就是模块句柄
hInstance hModule
在C语言编程中 hInstance通过WinMain由系统传入
在win32汇编中,hInstance需要自己获取

windows中几乎所有的东西都是用句柄标识的,如文件句柄、窗口句柄、线程句柄、模块句柄等

2.2 创建窗口

窗口类中定义窗口的属性


窗口类的定义

初始化


窗口类的初始化
hIcon 窗口图标句柄 预定义 可通过LoadIcon指定
hCursor 光标句柄 预定义(IDC_ARROW...) 可通过LoadCursor指定
lpszMenuName 菜单字符串
hInstance 指定窗口类属于哪个模块 GetModuleHandle
cbSize 指定结构的长度
style 窗口风格 CS_HREDRAW CS_VREDRAW CS_DBLCLKS
hbrBackground  刷子句柄 指定窗口客户区的背景色  如BLACK_BRUSH、WHITE_BRUSH 使用 GetStockObject来获取刷子句柄 也可以指定颜色值 如 COLOR_BACKGROUND,COLOR_HIGHLIGHT,COLOR_MENU,COLOR_WINDOW等,需要加1
lpszClassName 指定类的名称
cbWndExtra cbClsExtra 预留的空间 用来存放自定义数据
lpfnWndProc 回调函数

使用CreateWindowEx来建立窗口

HWND CreateWindowEx(
    DWORD dwExStyle,    // extended window style WS_EX_* 可参考MSDN
    LPCTSTR lpClassName,    // pointer to registered class name
    LPCTSTR lpWindowName,   // pointer to window name
    DWORD dwStyle,  // window style 可参考MSDN WS_*
    int x,  // horizontal position of window
    int y,  // vertical position of window
    int nWidth, // window width
    int nHeight,    // window height
    HWND hWndParent,    // handle to parent or owner window 上级窗口,上级窗口销毁时,下级窗口也会被销毁
    HMENU hMenu,    // handle to menu, or child-window identifier 菜单句柄 可替换窗口类中的菜单 当dwStyle为WS_CHILD时,表示子窗口的ID
    HINSTANCE hInstance,    // handle to application instance 模块句柄
    LPVOID lpParam  // pointer to window-creation data 传给窗口的参数  这个参数在WM_CREATE消息中可以被获取
   );
style的预定义值
style的预定义组合
ExStyle的预定义值

常见的窗口样式


image.png

ShowWindow用来显示窗口

BOOL ShowWindow(
    HWND hWnd,  // handle of window
    int nCmdShow    // show state of window
   );
窗口的显示方式

UpdateWindow绘制客户区 向窗口发送了一条WM_PAINT消息

BOOL UpdateWindow(
    HWND hWnd   // handle of window  
   );

CreateWindowEx也可以创建子窗口 如Button Edit
创建一个button


创建一个button

注意 hMenu在这里表示子窗口的ID

2.3 消息循环

消息循环的一般形式

image.png

消息格式


image.png
image.png

lpMsg为指向MSG结构体的指针,接收返回消息
若获取的消息WM_QUIT eax中的返回值为0

TranslateMessage进行一些键盘消息的转换,将键盘消息的扫描码转换成ASC码在消息队列中插入WM_CHAR WM_SYSCHAR消息 遇到非键盘消息不处理

DispathMessage将消息发送到窗口处理过程,窗口过程返回后DispathMessage才返回

其它形式的消息循环

PeekMessage

BOOL PeekMessage(
    LPMSG lpMsg,    // pointer to structure for message
    HWND hWnd,  // handle to window
    UINT wMsgFilterMin, // first message
    UINT wMsgFilterMax, // last message
    UINT wRemoveMsg     // removal flags PM_NOREMOVE 取一条消息后在消息队列中删除该消息 PM_REMOVE 取一条消息不删除
   );   
 

无论应用程序消息队列是否有消息,PeekMessage函数都立即返回,程序得以继续执行后面的语句(无消息则执行其它指令,有消息时一般要将消息派发出去,再执行其它指令)。
GetMessage函数只有在消息队列中有消息时返回,队列中无消息就会一直等,直至下一个消息出现时才返回。在等的这段时间,应用程序不能执行任何指令。

2.4 窗口过程

窗口过程的一般结构


image.png

注意 proc后面的uses伪操作在子程序进入和退出时自动插上push和pop寄存器指令,来保护这些寄存器的值

uMsg的windows标准窗口预定义的值的范围为0-03ffh
用户自定义的消息可以从04ooh开始 一般为WM_USER+1,WM_USER+2,...

wParam和lParam为消息附带的参数,不同消息不一样

当窗口决定关闭时,需要程序调用DestoryWindow来摧毁窗口,并用PostQuitMessage向消息循环发送WM_QUIT消息来退出消息循环。

DefWindowProc来处理用户不管的消息,采取默认方式来处理窗口消息


DefWindowProc对一些消息的默认处理方式

附录 B实验

3 窗口间的通信

3.1 窗口间消息的互发

不同的应用程序之间可以使用SendMessage和PostMessage互相发送消息

LRESULT SendMessage(

    HWND hWnd,  // handle of destination window
    UINT Msg,   // message to send
    WPARAM wParam,  // first message parameter
    LPARAM lParam   // second message parameter
   );
BOOL PostMessage(

    HWND hWnd,  // handle of destination window
    UINT Msg,   // message to post 
    WPARAM wParam,  // first message parameter
    LPARAM lParam   // second message parameter
   );

对于不同的msg, wParam和lParam的含义是不同的
wsprintf win32 api中用来格式化字符串输出的函数
windows在处理SendMessage时 传递字符串时使用了共享内容
注意 在用户自定义的消息中,不要在消息参数中传递指针 会引发非法访问内存

3.2 在窗口间传递数据

WM_COPYDATA消息用于在不同应用间传递数据

WM_COPYDATA  
wParam = (WPARAM) (HWND) hwnd;            // handle of sending window 
lParam = (LPARAM) (PCOPYDATASTRUCT) pcds; // pointer to structure with data 

数据包含在COPYDATASTRUCT结构体中

typedef struct tagCOPYDATASTRUCT {  // cds  
    DWORD dwData; //Specifies up to 32 bits of data to be passed to the receiving application
    DWORD cbData; //Specifies the size, in bytes, of the data pointed to by the lpData member.
    PVOID lpData; //Points to data to be passed to the receiving application. This member can be NULL. 
} COPYDATASTRUCT; 

3.3 SendMessage和PostMessage的区别

SendMessage相当于直接调用其他窗口的窗口过程来处理某个消息,并等待窗口过程处理完成后返回
PostMessage则将某个消息放入目标窗口的消息队列中并直接返回,不能用于任何参数中用到指针的消息

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,002评论 6 509
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,777评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,341评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,085评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,110评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,868评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,528评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,422评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,938评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,067评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,199评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,877评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,540评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,079评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,192评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,514评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,190评论 2 357

推荐阅读更多精彩内容