中文名 | 消息結(jié)構(gòu) | 分????類 | 寫作術(shù)語(yǔ) |
---|
當(dāng)然,也不是每條消息都具備這四個(gè)部分,有時(shí)可根據(jù)情況省略背景或結(jié)尾。從外部結(jié)構(gòu)形態(tài)來看,常見的有:一、倒敘式,也稱“倒金字塔”結(jié)構(gòu),即把最重要的事實(shí)或結(jié)果放到導(dǎo)語(yǔ)中加以陳述。二、順敘式,也叫“金字塔”結(jié)構(gòu)或編年結(jié)構(gòu),即按照事件發(fā)生的時(shí)間順序?qū)懀阌趯?duì)事件發(fā)展的各階段作明晰的介紹和概括的描述。三、懸念式,在開頭設(shè)置疑團(tuán),使讀者急于了解事件的發(fā)展和結(jié)果。然后在主體部分或結(jié)尾處解開懸念。四、視覺式,用形象化、立體化方法來寫,以典型細(xì)節(jié)、生動(dòng)畫面反映和報(bào)道新聞事實(shí)。五、散文式。形式不拘一格,內(nèi)容博而不雜,類似自由活潑的散文結(jié)構(gòu)。
2100433B
在自己的個(gè)人中心最后一項(xiàng)有培訓(xùn)報(bào)名,可以查找。
遇到這種情況時(shí): 1. 一律拒絕加入為你的好友。 2. 千萬(wàn)不用聽信,不去理睬就行了。否則一旦理睬即會(huì)接連不斷的騷擾你了。 3. 建議廣聯(lián)達(dá)管理系統(tǒng)及時(shí)清除和阻止這類無關(guān)...
估計(jì)是這個(gè)是還需要一段時(shí)間,最少出通知還要有四五個(gè)月的樣子國(guó)家為了保護(hù)拆遷戶的利益,頒布法律明確規(guī)定,先安置后搬遷,如果房子就近安置不是現(xiàn)房,則拆遷方違法,不能簽訂房屋安置協(xié)議。退一步講,即使就近安置...
格式:pdf
大?。?span id="m2vscjg" class="single-tag-height">417KB
頁(yè)數(shù): 2頁(yè)
評(píng)分: 4.5
新西蘭克萊德壩的一些新問題據(jù)英刊《水力發(fā)電與壩工建設(shè)》1989年11月號(hào)報(bào)道,目前建在新西蘭克盧薩河上,高102m的克萊德壩壩址的各項(xiàng)調(diào)查發(fā)現(xiàn),當(dāng)水庫(kù)蓄水,有可能加速庫(kù)區(qū)許多岸坡發(fā)生重力位移。對(duì)此成立了一個(gè)由澳大利亞、英國(guó)和美國(guó)的專家組成的專家組,重點(diǎn)補(bǔ)救措施的計(jì)劃正在擬訂中。
又稱時(shí)間邏輯交叉順序結(jié)構(gòu),時(shí)間順序和邏輯順序可以互相滲入,也可不分主次地將兩種順序穿插、揉合起來寫.好處是既有利于面的展示,顯示出清晰的條理,又有利于點(diǎn)的深入,使消息具有剖析的色彩。
Windowsx.h包含了這樣一些內(nèi)容:
宏API,窗口消息分流器,控件API;
所有的這些宏定義,可以使你的程序更加安全,簡(jiǎn)潔,結(jié)構(gòu)更清晰,大大提高程序的可讀性;其中窗口消息分流器(message cracker)是我們今天要討論的話題,它可以使我們的API程序變得更簡(jiǎn)潔。下面就進(jìn)入我們的主題:(有關(guān)windowsx.h的更多內(nèi)容,可以參考 MS Knowledge Base Article #83456.)
消息分流器是Windows提供的一組宏定義,它的兩個(gè)最大的作用,用MS的話來說,就是:
● 安全的數(shù)據(jù)類型,因?yàn)橄⒎至髌魍瓿闪舜罅康念愋娃D(zhuǎn)換的工作;
● 使程序向32位windows的轉(zhuǎn)化更簡(jiǎn)單;
當(dāng)然,使用消息分流器會(huì)大大改變程序的面貌,你也可以選擇不使用它。
下面我們就以一個(gè)對(duì)話框窗口的消息處理過程為例,看看消息分流器到底是怎么運(yùn)作的。
1.消息分流器的基本使用
先看一個(gè)普通的窗口消息處理函數(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);
}
而通過使用消息分流器,我們可以把每個(gè)case都寫到相應(yīng)的消息處理函數(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);
}
這里用到了三個(gè)宏定義:HANDLE_WM_CREATE, HANDLE_WM_PAINT, HANDLE_WM_DESTROY;這三個(gè)宏定義就是我們的三個(gè)消息分流器(別看叫什么分流器,說穿了也不值幾個(gè)錢,呵呵),它們?cè)趙indowsx.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)
把這三個(gè)宏定義替換回去,就變成:
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應(yīng)返回TRUE,導(dǎo)致WndProc返回0,否則Cls_OnCreate返回FALSE,導(dǎo)致WndProc返回-1;
case WM_PAINT:
return Cls_OnPaint(hwnd), 0L;
// 逗號(hào)表達(dá)式;Cls_OnPaint是void類型,這里返回0;
case WM_DESTROY:
return Cls_OnDestroy(hwnd), 0L; // 同Cls_OnPaint
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
之后我們就可以按照消息分流器的定義編寫相應(yīng)的消息處理函數(shù)了:
BOOL Cls_OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct){…};
void Cls_OnPaint(HWND hwnd){…};
void Cls_OnDestroyClipboard(HWND hwnd){…};
windowsx.h還提供了一個(gè)更加簡(jiǎn)化的方法:使用HANDLE_MSG宏,這個(gè)宏是這樣定義的:
#define HANDLE_MSG(hwnd, message, fn)
case (message): return HANDLE_##message((hwnd), (wParam), (lParam), (fn))
這個(gè)宏要做的就是根據(jù)不同的message(##用來連接前后的字符串),把自己“變成”相應(yīng)的HANDLE_XXXXMESSAGE形式的宏,再通過相應(yīng)的宏來執(zhí)行消息處理代碼;
比如實(shí)際代碼中寫入:
HANDLE_MSG(hwnd, WM_CREATE, Cls_OnCreate)
則經(jīng)過轉(zhuǎn)換就變成:
case (WM_CREATE): return HANDLE_WM_CREATE((hwnd), (wParam), (lParam), (Cls_OnCreate))
這樣,我們就可以直接把程序?qū)憺椋?
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);
}
之后直接編寫相應(yīng)的消息處理過程就可以了。是不是簡(jiǎn)潔多了?而且把消息處理封裝到函數(shù)里面,就可以使用VS直接跳轉(zhuǎn)到這個(gè)函數(shù),再也不用費(fèi)勁去找那個(gè) case了。要注意的一點(diǎn)是,雖然windowsx.h里包括了所有消息對(duì)應(yīng)的分流器,但它們的參數(shù)是宏定義顯式說明的,在編寫消息處理函數(shù)時(shí),必須遵循宏定義中的參數(shù)類型,否則會(huì)導(dǎo)致錯(cuò)誤;這么多消息分流器,我們每次新寫一個(gè)消息處理函數(shù)時(shí)就得看看是否把參數(shù)設(shè)置正確了,整個(gè)過程繁瑣冗長(zhǎng)。好在已經(jīng)有一個(gè)工具叫Message Cracker Wizard,可以幫助我們生成消息分流器和相關(guān)的處理過程。
2.在對(duì)話框中使用消息分流器
在對(duì)話框消息處理中,窗口子類化是我們經(jīng)常使用的手段,這也可以通過消息分流器實(shí)現(xiàn),但是有點(diǎn)小問題 :>
下面是一個(gè)使用了windowsx.h消息分流器的對(duì)話框及其處理過程:
……
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可能導(dǎo)致錯(cuò)誤;為什么呢?問題出在子類化的消息處理過程的返回值上,msdn中對(duì)于對(duì)話框消息處理過程的返回值有如下說明:
一般情況下,對(duì)話框過程函數(shù)應(yīng)該在處理了消息的情況下返回TRUE,如果沒有處理,則返回FALSE。如果對(duì)話框過程返回了FALSE,那么對(duì)話框管理器為這條消息準(zhǔn)備默認(rèn)的對(duì)話操作。
如果對(duì)話框處理了一個(gè)需要特定返回值的消息,則對(duì)話框的返回值應(yīng)該被設(shè)置為調(diào)用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之前立即返回這個(gè)值。注意你必須立即調(diào)用SetWindowLong(這個(gè)函數(shù)用于調(diào)用窗口子類化的過程),這會(huì)導(dǎo)致DWL_MSGRESULT值被一個(gè)嵌套的對(duì)話框消息改寫。返回值為特定值的消息有:
· WM_CHARTOITEM
· WM_COMPAREITEM
· WM_CTLCOLORBTN
· WM_CTLCOLORDLG
· WM_CTLCOLOREDIT
· WM_CTLCOLORLISTBOX
· WM_CTLCOLORSCROLLBAR
· WM_CTLCOLORSTATIC
· WM_INITDIALOG
· WM_QUERYDRAGICON
· WM_VKEYTOITEM
看到?jīng)]有? 我們的消息WM_INITDIALOG也在其中,對(duì)這個(gè)消息進(jìn)行處理的過程不能簡(jiǎn)單的返回TRUE表示對(duì)消息進(jìn)行了處理,而是另有其意;它將轉(zhuǎn)化為:
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)
對(duì)WM_INITDIALOG的處理,如果返回TRUE,則表示設(shè)置鍵盤焦點(diǎn)到對(duì)話框的默認(rèn)控件,否則返回FALSE;這時(shí)好像還看不出什么問題,而對(duì)于我們的另外一個(gè)消息WM_COMMAND,HANDLE_MSG簡(jiǎn)單的把它變成:
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由于是個(gè)void型的函數(shù),是沒有返回值的,因此windows默認(rèn)這種消息處理過程必須返回一個(gè)0值,而返回0值不就表示我們的消息過程不處理這個(gè)消息么?這個(gè)矛盾是HANDLE_MSG無法解決的。怎么辦才能使消息過程在處理完WM_COMMAND消息之后正確的返回一個(gè)TRUE呢? 答案是使用另一個(gè)windowsx.h中的宏:SetDlgMsgResult(hwnd, msg, result)
這個(gè)宏定義如下:
#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))
(有沒有注意到,里面多了一個(gè)WM_CTLCOLORMSGBOX ? 這個(gè)消息是16位WinAPI中的消息,一度被轉(zhuǎn)換為Win32 API的一個(gè)消息;現(xiàn)在在最新的32位API中已經(jīng)被刪除了;保留它可能考慮到兼容性的問題,這里不做進(jìn)一步討論)
現(xiàn)在看到了,如果對(duì)話框過程處理的消息恰巧為返回特定值中的一個(gè),則如實(shí)返回result;不要被前面的BOOL蒙蔽,BOOL在頭文件中的定義實(shí)際上是一個(gè)int型,一旦需要返回非TRUE或FALSE的其他值,照樣可以;這樣,我們的Cls_OnInitDialog就能夠正確的返回它的BOOL值了,而Cls_OnCommand在處理之后,也可以由后面的逗號(hào)表達(dá)式正確的返回一個(gè)TRUE表示消息已處理。
在《Windows核心編程》一書中,大牛Jeffrey自己定義了一個(gè)宏,使SetDlgMsgResult宏的使用更加方便:
#define chHANDLE_DLGMSG(hwnd, message, fn)
case (message): return (SetDlgMsgResult(hwnd, uMsg,
HANDLE_##message((hwnd), (wParam), (lParam), (fn))))
可見這個(gè)宏只是簡(jiǎn)單的對(duì)SetDlgMsgRseult宏進(jìn)行了封裝。
這樣,我們最終的代碼可以寫成:
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;
}
下面把原來程序整個(gè)框架列出來:
LRESULT CALLBACK Dlg_Proc(HWND hwnd, UNIT umsg, WPARAM wparam, LPARAM lparam)
{
switch(msg)
{
case WM_COMMAND: // 每個(gè)case都被一個(gè)message cracker代替,這里使用大牛同志的
// do something; // chHANDLE_DLGMSG宏;這個(gè)宏負(fù)責(zé)對(duì)消息篩選,處理并返回相應(yīng)的值
return true;
case WM_INITDIALOG:
// do something;
return xxxx;
}
return false; // 如果消息不在我們的DlgProc過程中被處理,則告訴調(diào)用這個(gè)DlgProc的消息,
} //告訴系統(tǒng)的對(duì)話框管理器,這個(gè)消息我們不處理,交給你了
對(duì)比一下,消息分流器的作用不言自明。
以上只是介紹了消息分流器的部分應(yīng)用,更多創(chuàng)造性的用法還等你自己在實(shí)踐中發(fā)掘。
其實(shí)這個(gè)不是一個(gè)專業(yè)的定義詞匯 。
消息服務(wù)器作為網(wǎng)絡(luò)的節(jié)點(diǎn),專門用來存儲(chǔ)、轉(zhuǎn)發(fā)網(wǎng)絡(luò)上的數(shù)據(jù)、信息(例如:聊天信息)。做一個(gè)形象的比喻:消息服務(wù)器就像是郵局的交換機(jī),而微機(jī)、筆記本、PDA、手機(jī)等固定或移動(dòng)的網(wǎng)絡(luò)終端,就如散落在家庭、各種辦公場(chǎng)所、公共場(chǎng)所等處的電話機(jī)。我們與外界日常的生活、工作中的電話交流、溝通,必須經(jīng)過交換機(jī),才能到達(dá)目標(biāo)電話;同樣如此,我們利用個(gè)人電腦,PDA,手機(jī)等,發(fā)送消息,也必須經(jīng)過消息服務(wù)器,因此也可以說是消息服務(wù)器在“組織”和“領(lǐng)導(dǎo)”這些接收消息設(shè)備。
它是網(wǎng)絡(luò)上一種為客戶端計(jì)算機(jī)提供各種消息服務(wù)的高性能的計(jì)算機(jī)。它的高性能主要體現(xiàn)在高速度的運(yùn)算能力、長(zhǎng)時(shí)間的可靠運(yùn)行、強(qiáng)大的外部數(shù)據(jù)吞吐能力等方面。2100433B