消息分流器

消息分流器是作者Bideyore[E.S.T]写的对于熟悉Win API编程的同志们来说,windowsx.h这个头文件应该不会太陌生吧,这次要讲的内容就来自这个windowsx.h头文件。

消息分流器基本信息

中文名 消息分流器 文章作者 Bideyore[E.S.T]
信息来源 邪恶八进制 相    关 windowsx.h这个头文件

Windowsx.h包含了这样一些内容:

宏API,窗口消息分流器,控件API;

所有的这些宏定义,可以使你的程序更加安全,简洁,结构更清晰,大大提高程序的可读性;其中窗口消息分流器(message cracker)是我们今天要讨论的话题,它可以使我们的API程序变得更简洁。下面就进入我们的主题:(有关windowsx.h的更多内容,可以参考 MS Knowledge Base Article #83456.)

消息分流器是Windows提供的一组宏定义,它的两个最大的作用,用MS的话来说,就是:

● 安全的数据类型,因为消息分流器完成了大量的类型转换的工作;

● 使程序向32位windows的转化更简单;

当然,使用消息分流器会大大改变程序的面貌,你也可以选择不使用它。

下面我们就以一个对话框窗口的消息处理过程为例,看看消息分流器到底是怎么运作的。

1.消息分流器的基本使用

先看一个普通的窗口消息处理函数,它可能需要处理一些窗口的初始化,无效客户区重绘等消息:

LRESULT CALLBACK WndProc (HWND hwnd, UINT msg,

WPARAM wParam, LPARAM lParam)

{

switch(msg)

{

case WM_CREATE:

// ...

return 0;

case WM_PAINT:

// ...

return 0;

case WM_DESTROY:

//...

return 0;

}

return DefWindowProc(hwnd, msg, wParam, lParam);

}

而通过使用消息分流器,我们可以把每个case都写到相应的消息处理函数中,就像下面这样:

LRESULT CALLBACK WndProc (HWND hwnd, UINT msg,

WPARAM wParam, LPARAM lParam)

{

switch(msg)

{

case WM_CREATE:

return HANDLE_WM_CREATE(hwnd, wParam, lParam, Cls_OnCreate);

case WM_PAINT:

return HANDLE_WM_PAINT(hwnd, wParam, lParam, Cls_OnPaint);

case WM_DESTROY:

return HANDLE_WM_DESTROY(hwnd, wParam, lParam, Cls_OnDestroy);

}

return DefWindowProc(hwnd, msg, wParam, lParam);

}

这里用到了三个宏定义:HANDLE_WM_CREATE, HANDLE_WM_PAINT, HANDLE_WM_DESTROY;这三个宏定义就是我们的三个消息分流器(别看叫什么分流器,说穿了也不值几个钱,呵呵),它们在windowsx.h中的定义如下:

#define HANDLE_WM_CREATE(hwnd, wParam, lParam, fn)

((fn)((hwnd), (LPCREATESTRUCT)(lParam)) "para" label-module="para">

#define HANDLE_WM_PAINT(hwnd, wParam, lParam, fn)

((fn)(hwnd), 0L)

#define HANDLE_WM_DESTROYCLIPBOARD(hwnd, wParam, lParam, fn)

((fn)(hwnd), 0L)

把这三个宏定义替换回去,就变成:

LRESULT CALLBACK WndProc (HWND hwnd, UINT msg,

WPARAM wParam, LPARAM lParam)

{

switch(msg)

{

case WM_CREATE:

return Cls_OnCreate(hwnd, (LPCREATESTRUCT)(lParam) "para" label-module="para">

// 如果处理了消息,则Cls_OnCreate应返回TRUE,导致WndProc返回0,否则Cls_OnCreate返回FALSE,导致WndProc返回-1;

case WM_PAINT:

return Cls_OnPaint(hwnd), 0L;

// 逗号表达式;Cls_OnPaint是void类型,这里返回0;

case WM_DESTROY:

return Cls_OnDestroy(hwnd), 0L; // 同Cls_OnPaint

}

return DefWindowProc(hwnd, msg, wParam, lParam);

}

之后我们就可以按照消息分流器的定义编写相应的消息处理函数了:

BOOL Cls_OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct){…};

void Cls_OnPaint(HWND hwnd){…};

void Cls_OnDestroyClipboard(HWND hwnd){…};

windowsx.h还提供了一个更加简化的方法:使用HANDLE_MSG宏,这个宏是这样定义的:

#define HANDLE_MSG(hwnd, message, fn)

case (message): return HANDLE_##message((hwnd), (wParam), (lParam), (fn))

这个宏要做的就是根据不同的message(##用来连接前后的字符串),把自己“变成”相应的HANDLE_XXXXMESSAGE形式的宏,再通过相应的宏来执行消息处理代码;

比如实际代码中写入:

HANDLE_MSG(hwnd, WM_CREATE, Cls_OnCreate)

则经过转换就变成:

case (WM_CREATE): return HANDLE_WM_CREATE((hwnd), (wParam), (lParam), (Cls_OnCreate))

这样,我们就可以直接把程序写为:

LRESULT CALLBACK WndProc (HWND hwnd, UINT msg,

WPARAM wParam, LPARAM lParam)

{

switch(msg)

{

HANDLE_MSG(hwnd, WM_CREATE, Cls_OnCreate);

HANDLE_MSG(hwnd, WM_PAINT, Cls_OnPaint);

HANDLE_MSG(hwnd, WM_DESTROY, Cls_OnDestroy);

}

return DefWindowProc(hwnd, msg, wParam, lParam);

}

之后直接编写相应的消息处理过程就可以了。是不是简洁多了?而且把消息处理封装到函数里面,就可以使用VS直接跳转到这个函数,再也不用费劲去找那个 case了。要注意的一点是,虽然windowsx.h里包括了所有消息对应的分流器,但它们的参数是宏定义显式说明的,在编写消息处理函数时,必须遵循宏定义中的参数类型,否则会导致错误;这么多消息分流器,我们每次新写一个消息处理函数时就得看看是否把参数设置正确了,整个过程繁琐冗长。好在已经有一个工具叫Message Cracker Wizard,可以帮助我们生成消息分流器和相关的处理过程。

2.在对话框中使用消息分流器

在对话框消息处理中,窗口子类化是我们经常使用的手段,这也可以通过消息分流器实现,但是有点小问题 :>

下面是一个使用了windowsx.h消息分流器的对话框及其处理过程:

……

int WINAPI _tWinMain(HINSTANCE hinstExe, HINSTANCE, PTSTR pszCmdLine, int)

{

DialogBoxParam(

hinstExe, MAKEINTRESOURCE(IDD_PASSTHRU), NULL, (DLGPROC)Dlg_Proc, 0);

return(0);

}

……

LRESULT CALLBACK Dlg_Proc (HWND hwnd, UINT msg,

WPARAM wParam, LPARAM lParam)

{

switch(msg)

{

HANDLE_MSG(hwnd, WM_INITDIALOG, Cls_OnInitDialog); // 不能直接使用HANDLE_MSG宏

HANDLE_MSG(hwnd, WM_COMMAND, Cls_OnCommand); // 不能直接使用HANDLE_MSG宏

}

return false;

}

以上程序中直接使用HANDLE_MSG可能导致错误;为什么呢?问题出在子类化的消息处理过程的返回值上,msdn中对于对话框消息处理过程的返回值有如下说明:

一般情况下,对话框过程函数应该在处理了消息的情况下返回TRUE,如果没有处理,则返回FALSE。如果对话框过程返回了FALSE,那么对话框管理器为这条消息准备默认的对话操作。

如果对话框处理了一个需要特定返回值的消息,则对话框的返回值应该被设置为调用SetWindowLong(The SetWindowLong function changes an attribute of the specified window. The function also sets a 32-bit (long) value at the specified offset into the extra window memory of a window. )后的返回值,并在返回TRUE之前立即返回这个值。注意你必须立即调用SetWindowLong(这个函数用于调用窗口子类化的过程),这会导致DWL_MSGRESULT值被一个嵌套的对话框消息改写。返回值为特定值的消息有:

· WM_CHARTOITEM

· WM_COMPAREITEM

· WM_CTLCOLORBTN

· WM_CTLCOLORDLG

· WM_CTLCOLOREDIT

· WM_CTLCOLORLISTBOX

· WM_CTLCOLORSCROLLBAR

· WM_CTLCOLORSTATIC

· WM_INITDIALOG

· WM_QUERYDRAGICON

· WM_VKEYTOITEM

看到没有? 我们的消息WM_INITDIALOG也在其中,对这个消息进行处理的过程不能简单的返回TRUE表示对消息进行了处理,而是另有其意;它将转化为:

case (WM_INITDIALOG): return HANDLE_WM_INITDIALOG(hwnd, wParam, lParam, Cls_OnInitDialog);

宏HANDLE_WM_INITDIALOG定义如下:

#define HANDLE_WM_INITDIALOG(hwnd, wParam, lParam, fn)

(LRESULT)(DWORD)(UINT)(BOOL)(fn)((hwnd), (HWND)(wParam), lParam)

对WM_INITDIALOG的处理,如果返回TRUE,则表示设置键盘焦点到对话框的默认控件,否则返回FALSE;这时好像还看不出什么问题,而对于我们的另外一个消息WM_COMMAND,HANDLE_MSG简单的把它变成:

case (WM_COMMAND): return HANDLE_WM_COMMAND(hwnd, wParam, lParam, Cls_OnCommand);

宏HANDLE_WM_COMMAND定义如下:

#define HANDLE_WM_COMMAND(hwnd, wParam, lParam, fn)

((fn)((hwnd), (int)(LOWORD(wParam)), (HWND)(lParam), (UINT)HIWORD(wParam)), 0L)

问题出来了,我们的Cls_OnCommand由于是个void型的函数,是没有返回值的,因此windows默认这种消息处理过程必须返回一个0值,而返回0值不就表示我们的消息过程不处理这个消息么?这个矛盾是HANDLE_MSG无法解决的。怎么办才能使消息过程在处理完WM_COMMAND消息之后正确的返回一个TRUE呢? 答案是使用另一个windowsx.h中的宏:SetDlgMsgResult(hwnd, msg, result)

这个宏定义如下:

#define SetDlgMsgResult(hwnd, msg, result) ((

(msg) == WM_CTLCOLORMSGBOX ||

(msg) == WM_CTLCOLOREDIT ||

(msg) == WM_CTLCOLORLISTBOX ||

(msg) == WM_CTLCOLORBTN ||

(msg) == WM_CTLCOLORDLG ||

(msg) == WM_CTLCOLORSCROLLBAR ||

(msg) == WM_CTLCOLORSTATIC ||

(msg) == WM_COMPAREITEM ||

(msg) == WM_VKEYTOITEM ||

(msg) == WM_CHARTOITEM ||

(msg) == WM_QUERYDRAGICON ||

(msg) == WM_INITDIALOG

) "_blank" href="/item/SetWindowLongPtr">SetWindowLongPtr((hwnd), DWLP_MSGRESULT, (LPARAM)(LRESULT)(result)), TRUE))

(有没有注意到,里面多了一个WM_CTLCOLORMSGBOX ? 这个消息是16位WinAPI中的消息,一度被转换为Win32 API的一个消息;现在在最新的32位API中已经被删除了;保留它可能考虑到兼容性的问题,这里不做进一步讨论)

现在看到了,如果对话框过程处理的消息恰巧为返回特定值中的一个,则如实返回result;不要被前面的BOOL蒙蔽,BOOL在头文件中的定义实际上是一个int型,一旦需要返回非TRUE或FALSE的其他值,照样可以;这样,我们的Cls_OnInitDialog就能够正确的返回它的BOOL值了,而Cls_OnCommand在处理之后,也可以由后面的逗号表达式正确的返回一个TRUE表示消息已处理。

在《Windows核心编程》一书中,大牛Jeffrey自己定义了一个宏,使SetDlgMsgResult宏的使用更加方便:

#define chHANDLE_DLGMSG(hwnd, message, fn)

case (message): return (SetDlgMsgResult(hwnd, uMsg,

HANDLE_##message((hwnd), (wParam), (lParam), (fn))))

可见这个宏只是简单的对SetDlgMsgRseult宏进行了封装。

这样,我们最终的代码可以写成:

LRESULT CALLBACK Dlg_Proc (HWND hwnd, UINT msg,

WPARAM wParam, LPARAM lParam)

{

switch(msg)

{

chHANDLE_DLGMSG(hwnd, WM_INITDIALOG, Cls_OnInitDialog); // 使用大牛的chHANDLE_DLGMSG宏

chHANDLE_DLGMSG(hwnd, WM_COMMAND, Cls_OnCommand);

}

return false;

}

下面把原来程序整个框架列出来:

LRESULT CALLBACK Dlg_Proc(HWND hwnd, UNIT umsg, WPARAM wparam, LPARAM lparam)

{

switch(msg)

{

case WM_COMMAND: // 每个case都被一个message cracker代替,这里使用大牛同志的

// do something; // chHANDLE_DLGMSG宏;这个宏负责对消息筛选,处理并返回相应的值

return true;

case WM_INITDIALOG:

// do something;

return xxxx;

}

return false; // 如果消息不在我们的DlgProc过程中被处理,则告诉调用这个DlgProc的消息,

} //告诉系统的对话框管理器,这个消息我们不处理,交给你了

对比一下,消息分流器的作用不言自明。

以上只是介绍了消息分流器的部分应用,更多创造性的用法还等你自己在实践中发掘。

消息分流器造价信息

市场价 信息价 询价
材料名称 规格/型号 市场价
(除税)
工程建议价
(除税)
行情 品牌 单位 税率 供应商 报价日期
分流器系列 FL-2 100A 电流分流器 查看价格 查看价格

环宇

13% 环宇集团新疆销售有限公司
分流器系列 FL-2 4000A 电流分流器 查看价格 查看价格

13% 环宇集团成都电器销售分公司
分流器系列 FL-2 2500A 电流分流器 查看价格 查看价格

13% 环宇集团成都电器销售分公司
分流器系列 FL-2 150A 电流分流器 查看价格 查看价格

13% 环宇集团成都电器销售分公司
分流器系列 FL-2 1200A 电流分流器 查看价格 查看价格

13% 环宇集团成都电器销售分公司
分流器系列 FL-2 750A 电流分流器 查看价格 查看价格

13% 环宇集团成都电器销售分公司
分流器系列 FL-2-1000A 电流分流器 查看价格 查看价格

环宇

13% 环宇集团新疆销售有限公司
分流器系列 FL-2 600A 电流分流器 查看价格 查看价格

环宇

13% 环宇集团新疆销售有限公司
材料名称 规格/型号 除税
信息价
含税
信息价
行情 品牌 单位 税率 地区/时间
断路 10A 电磁式,AC,30mA 查看价格 查看价格

珠海市2022年10月信息价
断路 25A 电磁式,AC,30mA 查看价格 查看价格

珠海市2022年10月信息价
断路 40A 电磁式,AC,30mA 查看价格 查看价格

珠海市2022年10月信息价
断路 20A 电磁式,AC,30mA 查看价格 查看价格

珠海市2022年9月信息价
断路 40A 电磁式,AC,30mA 查看价格 查看价格

珠海市2022年9月信息价
断路 16A 电磁式,AC,30mA 查看价格 查看价格

珠海市2022年8月信息价
断路 25A 电磁式,AC,30mA 查看价格 查看价格

珠海市2022年8月信息价
断路 40A 电磁式,AC,30mA 查看价格 查看价格

珠海市2022年8月信息价
材料名称 规格/需求量 报价数 最新报价
(元)
供应商 报价地区 最新报价时间
分流器 不锈钢材质,包含10孔分流器含电磁阀.|1.0组 1 查看价格 青岛乐道儿童游乐场设备有限公司    2015-11-11
充电分流器 1.电分流器1分12X2套 X10智能充电桩规格:IP54(防尘防水)设计,支持移动端扫码+刷卡充电方式,总功率≥8KW,12路5A输出插座的智能充电桩.|1套 1 查看价格 广州云酷智能设备有限公司 全国   2021-08-31
分流器 500A|924个 4 查看价格 天津佛瑞达科技有限公司 天津  天津市 2015-12-18
分流器 电缆T接(五芯,120平方以下)1500A以内|822个 4 查看价格 成都德利龙电器制造有限公司 四川  成都市 2015-12-01
分流器 YGH106 DN32×20×4|3048只 4 查看价格 深圳市永高塑业发展有限公司昆明经销商 云南  昆明市 2015-08-11
分流器 电缆T接(五芯,35平方以下)150A以内|69.0个 1 查看价格 深圳润和鹏科技发展有限公司    2015-05-06
分流器 YGH106 Ф32×20×4|7260只 4 查看价格 深圳市永高塑业发展有限公司 广东  深圳市 2015-04-10
分流器 Ф32×20×4|919个 4 查看价格 中山市台塑门窗有限公司 广东  中山市 2015-06-09

文章作者:Bideyore[E.S.T]

对于熟悉Win API编程的同志们来说,windowsx.h这个头文件应该不会太陌生吧,这次要讲的内容就来自这个windowsx.h头文件。

经常能在msdn上查到这样一些函数,明明是个函数,而且模样长得和一般的api函数也一样一样的,可却叫做macro,为什么呢?留意一下函数使用的requirement,你会发现,它的声明正是在windowsx.h这个头文件里。

消息分流器常见问题

  • 分流器安装

    1、一根电缆(YJV22-4*95)在各层需要分支到各个电表箱中用导线分流器是可行的。 2、导线分流器在河南08中套电缆中间接头定额子目

  • USB分流器是什么?

    所谓的USB分流器叫做USB HUB。  USB Hub就是USB接口扩展器。是一种可以将一个USB接口扩展为多个(通常为4个),并可以使这些接口同时使用的装置。  1、USB-HUB是提供扩展通讯的...

  • USB分流器是什么?

    所谓的USB分流器叫做USB HUB。  USB Hub就是USB接口扩展器。是一种可以将一个USB接口扩展为多个(通常为4个),并可以使这些接口同时使用的装置。  1、USB-HUB是提供扩展通讯的...

消息分流器文献

XPC分流器保护电路 XPC分流器保护电路

格式:pdf

大小:191KB

页数: 2页

评分: 4.8

P&H4100XPC电铲运行中,当电枢电流达到额定电流的140%时,分流器模块检测到过流现象,分流器保护电路开始运行。分流电路运行分为三个阶段:分流器电容充电、过流检测、关断晶闸管以及释放电机能量。

立即下载
水利水电消息 水利水电消息

格式:pdf

大小:191KB

页数: 4页

评分: 4.6

FL-2型分流器、FL-2B型分流器、FL-2F型风冷平板分流器、FL-2S型水冷平板分流器、FL-2D型分流器(DIN43703 shunt)、FL-13型分流器(俄罗斯型分流器)、FL-15型美式分流器、FL19型电焊机分流器、FL-21出口型分流器(台湾型分流器)、FL-27型0.2级分流器、FL-29型分流器、FL-39型分流器

选用分流器的方法

(1)按所用电流表(或电流电压两用表)表盘上所标出的mV数选择分流器的额定压降规格(一般常用的是75mV或45mV)。若所用电流表无此值,则用下式计算表的电压量限,然后再选择分流器的额定压降规格。

表的电压量限(mV)=电流表满刻度时的电流(A)×电流表的内阻(Ω)/1000

(2)按欲扩大的电流量程选择分流器的额定电流规格。

(3)将选定的分流器两个电流端分别与电源和负载相连接,电位端接电流表,应注意电流表的端子极性要接对,则电流表的量程就扩大到了分流器上标定的电流值。

分流器使用方法

对于电机试验测量,往往一块电流表要配置多个分流器,以解决在较大测量范围都能保证要求的测量准确度问题。此时要求所用的所有分流器的额定电压降都与所配电流表一致,例如75mV。这样,分流器选定后,电流表的满量程就是所选分流器的额定电流值,电流表的倍数(即其表盘刻度每格电流数)即为分流器的额定电流除于表盘刻度总格数。

用于直流电流测量的分流器有插槽式和非插槽式。分流器有锰镍铜合金电阻棒和铜带,并镀有镍层。其额定压降是60mV,但也可被用作75、100、120、150及300mV。插槽式分流器额定电流有以下几种:5A,10A,15A,20A和25A。

分流器是分流器是测量直流电流用的,根据直流电流通过电阻时在电阻两端产生电压的原理制成。分流器实际就是一个阻值很小的电阻,当有直流电流通过时,产生压降,供直流电流表显示; 直流电流表实际是电压表,满度值75mV; 直流电流表和分流器是配套使用的; 比如:100A电流表配套的分流器阻值为0.00075欧; 即100A*0.00075欧=75mV; 50A电流表配套的分流器阻值为0.0015欧; 50A*0.0015欧=75mV。

消息分流器相关推荐
  • 相关百科
  • 相关知识
  • 相关专栏