选择特殊符号

选择搜索类型

热门搜索

首页 > 百科 > 电气百科

消息分流器简介

消息分流器简介

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

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

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

查看详情

消息分流器造价信息

  • 市场价
  • 信息价
  • 询价

分流器系列

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

分流器

  • 品种:导线分流器;型号:FL-2;规格:10A;
  • 宁波培正电子
  • 13%
  • 宁夏惠明电气有限公司
  • 2022-12-08
查看价格

分流器

  • 品种:导线分流器;型号:FL-2;规格:20A;
  • 惠明电气
  • 13%
  • 宁夏惠明电气有限公司
  • 2022-12-08
查看价格

分流器

  • 品种:导线分流器;型号:FL-2;规格:10A;
  • 深圳福永旺电子
  • 13%
  • 宁夏惠明电气有限公司
  • 2022-12-08
查看价格

分流器系列

  • FL-2 100A 电流分流器
  • 环宇
  • 13%
  • 环宇集团新疆销售有限公司
  • 2022-12-08
查看价格

断路

  • 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月信息价
  • 建筑工程
查看价格

分流器

  • 不锈钢材质,包含10孔分流器含电磁阀.
  • 1.0组
  • 1
  • 美国WATERODYSSEY
  • 不含税费 | 不含运费
  • 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
查看价格

消息分流器包含内容

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的消息,

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

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

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

查看详情

消息分流器简介常见问题

查看详情

消息分流器简介文献

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

XPC分流器保护电路

格式:pdf

大小:191KB

页数: 2页

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

西崎分流器分流器型号

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。

查看详情

相关推荐

立即注册
免费服务热线: 400-888-9639