消息分流器

消息分流器是作者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的話來說,就是:

● 安全的數(shù)據(jù)類型,因為消息分流器完成了大量的類型轉換的工作;

● 使程序向32位windows的轉化更簡單;

當然,使用消息分流器會大大改變程序的面貌,你也可以選擇不使用它。

下面我們就以一個對話框窗口的消息處理過程為例,看看消息分流器到底是怎么運作的。

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

先看一個普通的窗口消息處理函數(shù),它可能需要處理一些窗口的初始化,無效客戶區(qū)重繪等消息:

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都寫到相應的消息處理函數(shù)中,就像下面這樣:

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

}

之后我們就可以按照消息分流器的定義編寫相應的消息處理函數(shù)了:

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))

這個宏要做的就是根據(jù)不同的message(##用來連接前后的字符串),把自己“變成”相應的HANDLE_XXXXMESSAGE形式的宏,再通過相應的宏來執(zhí)行消息處理代碼;

比如實際代碼中寫入:

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

}

之后直接編寫相應的消息處理過程就可以了。是不是簡潔多了?而且把消息處理封裝到函數(shù)里面,就可以使用VS直接跳轉到這個函數(shù),再也不用費勁去找那個 case了。要注意的一點是,雖然windowsx.h里包括了所有消息對應的分流器,但它們的參數(shù)是宏定義顯式說明的,在編寫消息處理函數(shù)時,必須遵循宏定義中的參數(shù)類型,否則會導致錯誤;這么多消息分流器,我們每次新寫一個消息處理函數(shù)時就得看看是否把參數(shù)設置正確了,整個過程繁瑣冗長。好在已經有一個工具叫Message Cracker Wizard,可以幫助我們生成消息分流器和相關的處理過程。

2.在對話框中使用消息分流器

在對話框消息處理中,窗口子類化是我們經常使用的手段,這也可以通過消息分流器實現(xiàn),但是有點小問題 :>

下面是一個使用了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中對于對話框消息處理過程的返回值有如下說明:

一般情況下,對話框過程函數(shù)應該在處理了消息的情況下返回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(這個函數(shù)用于調用窗口子類化的過程),這會導致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型的函數(shù),是沒有返回值的,因此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的一個消息;現(xiàn)在在最新的32位API中已經被刪除了;保留它可能考慮到兼容性的問題,這里不做進一步討論)

現(xiàn)在看到了,如果對話框過程處理的消息恰巧為返回特定值中的一個,則如實返回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的消息,

} //告訴系統(tǒng)的對話框管理器,這個消息我們不處理,交給你了

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

以上只是介紹了消息分流器的部分應用,更多創(chuàng)造性的用法還等你自己在實踐中發(fā)掘。

消息分流器造價信息

市場價 信息價 詢價
材料名稱 規(guī)格/型號 市場價
(除稅)
工程建議價
(除稅)
行情 品牌 單位 稅率 供應商 報價日期
分流器系列 FL-2 100A 電流分流器 查看價格 查看價格

環(huán)宇

13% 環(huán)宇集團新疆銷售有限公司
分流器系列 FL-2 4000A 電流分流器 查看價格 查看價格

13% 環(huán)宇集團成都電器銷售分公司
分流器系列 FL-2 2500A 電流分流器 查看價格 查看價格

13% 環(huán)宇集團成都電器銷售分公司
分流器系列 FL-2 150A 電流分流器 查看價格 查看價格

13% 環(huán)宇集團成都電器銷售分公司
分流器系列 FL-2 1200A 電流分流器 查看價格 查看價格

13% 環(huán)宇集團成都電器銷售分公司
分流器系列 FL-2 750A 電流分流器 查看價格 查看價格

13% 環(huán)宇集團成都電器銷售分公司
分流器系列 FL-2-1000A 電流分流器 查看價格 查看價格

環(huán)宇

13% 環(huán)宇集團新疆銷售有限公司
分流器系列 FL-2 600A 電流分流器 查看價格 查看價格

環(huán)宇

13% 環(huán)宇集團新疆銷售有限公司
材料名稱 規(guī)格/型號 除稅
信息價
含稅
信息價
行情 品牌 單位 稅率 地區(qū)/時間
斷路 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月信息價
材料名稱 規(guī)格/需求量 報價數(shù) 最新報價
(元)
供應商 報價地區(qū) 最新報價時間
分流器 不銹鋼材質,包含10孔分流器含電磁閥.|1.0組 1 查看價格 青島樂道兒童游樂場設備有限公司    2015-11-11
充電分流器 1.電分流器1分12X2套 X10智能充電樁規(guī)格: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 查看價格 深圳市永高塑業(yè)發(fā)展有限公司昆明經銷商 云南  昆明市 2015-08-11
分流器 電纜T接(五芯,35平方以下)150A以內|69.0個 1 查看價格 深圳潤和鵬科技發(fā)展有限公司    2015-05-06
分流器 YGH106 Ф32×20×4|7260只 4 查看價格 深圳市永高塑業(yè)發(fā)展有限公司 廣東  深圳市 2015-04-10
分流器 Ф32×20×4|919個 4 查看價格 中山市臺塑門窗有限公司 廣東  中山市 2015-06-09

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

對于熟悉Win API編程的同志們來說,windowsx.h這個頭文件應該不會太陌生吧,這次要講的內容就來自這個windowsx.h頭文件。

經常能在msdn上查到這樣一些函數(shù),明明是個函數(shù),而且模樣長得和一般的api函數(shù)也一樣一樣的,可卻叫做macro,為什么呢?留意一下函數(shù)使用的requirement,你會發(fā)現(xiàn),它的聲明正是在windowsx.h這個頭文件里。

消息分流器常見問題

  • 分流器安裝

    1、一根電纜(YJV22-4*95)在各層需要分支到各個電表箱中用導線分流器是可行的。 2、導線分流器在河南08中套電纜中間接頭定額子目

  • USB分流器是什么?

    所謂的USB分流器叫做USB HUB?! SB Hub就是USB接口擴展器。是一種可以將一個USB接口擴展為多個(通常為4個),并可以使這些接口同時使用的裝置?! ?、USB-HUB是提供擴展通訊的...

  • USB分流器是什么?

    所謂的USB分流器叫做USB HUB?! SB Hub就是USB接口擴展器。是一種可以將一個USB接口擴展為多個(通常為4個),并可以使這些接口同時使用的裝置。  1、USB-HUB是提供擴展通訊的...

消息分流器文獻

XPC分流器保護電路 XPC分流器保護電路

格式:pdf

大小:191KB

頁數(shù): 2頁

評分: 4.8

P&H4100XPC電鏟運行中,當電樞電流達到額定電流的140%時,分流器模塊檢測到過流現(xiàn)象,分流器保護電路開始運行。分流電路運行分為三個階段:分流器電容充電、過流檢測、關斷晶閘管以及釋放電機能量。

立即下載
水利水電消息 水利水電消息

格式:pdf

大?。?span id="htvxp5p" class="single-tag-height">191KB

頁數(shù): 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數(shù)選擇分流器的額定壓降規(guī)格(一般常用的是75mV或45mV)。若所用電流表無此值,則用下式計算表的電壓量限,然后再選擇分流器的額定壓降規(guī)格。

表的電壓量限(mV)=電流表滿刻度時的電流(A)×電流表的內阻(Ω)/1000

(2)按欲擴大的電流量程選擇分流器的額定電流規(guī)格。

(3)將選定的分流器兩個電流端分別與電源和負載相連接,電位端接電流表,應注意電流表的端子極性要接對,則電流表的量程就擴大到了分流器上標定的電流值。

分流器使用方法

對于電機試驗測量,往往一塊電流表要配置多個分流器,以解決在較大測量范圍都能保證要求的測量準確度問題。此時要求所用的所有分流器的額定電壓降都與所配電流表一致,例如75mV。這樣,分流器選定后,電流表的滿量程就是所選分流器的額定電流值,電流表的倍數(shù)(即其表盤刻度每格電流數(shù))即為分流器的額定電流除于表盤刻度總格數(shù)。

用于直流電流測量的分流器有插槽式和非插槽式。分流器有錳鎳銅合金電阻棒和銅帶,并鍍有鎳層。其額定壓降是60mV,但也可被用作75、100、120、150及300mV。插槽式分流器額定電流有以下幾種:5A,10A,15A,20A和25A。

分流器是分流器是測量直流電流用的,根據(jù)直流電流通過電阻時在電阻兩端產生電壓的原理制成。分流器實際就是一個阻值很小的電阻,當有直流電流通過時,產生壓降,供直流電流表顯示; 直流電流表實際是電壓表,滿度值75mV; 直流電流表和分流器是配套使用的; 比如:100A電流表配套的分流器阻值為0.00075歐; 即100A*0.00075歐=75mV; 50A電流表配套的分流器阻值為0.0015歐; 50A*0.0015歐=75mV。

消息分流器相關推薦
  • 相關百科
  • 相關知識
  • 相關專欄