青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

牽著老婆滿街逛

嚴(yán)以律己,寬以待人. 三思而后行.
GMail/GTalk: yanglinbo#google.com;
MSN/Email: tx7do#yahoo.com.cn;
QQ: 3 0 3 3 9 6 9 2 0 .

從SetTimer看Windows消息處理機(jī)制

轉(zhuǎn)載自:http://blog.csdn.net/dog250/archive/2010/02/09/5303603.aspx


本文說(shuō)明兩個(gè)問(wèn)題:
   1.windows的消息處理機(jī)制;
   2.怎么往SetTimer的回調(diào)函數(shù)傳遞參數(shù)。

   首先看第一個(gè)問(wèn)題,我們都知道windows是消 息驅(qū)動(dòng)的,windows呈現(xiàn)給用戶的任何可以看到聽(tīng)到的東西幾乎都是消息驅(qū)動(dòng)的,在底層windows為每個(gè)線程準(zhǔn)備了一個(gè)消息隊(duì)列,如果用戶線程注冊(cè) 了某個(gè)消息,那么在適當(dāng)?shù)臅r(shí)候windows就會(huì)將消息投遞到該線程的消息隊(duì)列中,然后由該線程取出隊(duì)列中的消息,然后處理之,這個(gè)過(guò)程有兩個(gè)參與者,一 個(gè)是windows系統(tǒng),它主要負(fù)責(zé)投遞消息,收不收是用戶線程的事,另一個(gè)就是用戶線程,它主要負(fù)責(zé)取出消息并處理消息,即使用戶線程因?yàn)樗呋蛘吒揪蜎](méi)有設(shè)定消息循環(huán),系統(tǒng)還是會(huì)投遞的,系統(tǒng)和用戶線程的消息接口就是消息隊(duì)列,這就在用戶和系統(tǒng)之間關(guān)于消息解除了耦合,在用戶線程處理消息的時(shí)候,其實(shí)還有一個(gè)消息隊(duì)列,因?yàn)橐粋€(gè)線程不一定只接收一種消息而且不一定馬上就能處理完并返回,這個(gè)消息隊(duì)列我們把它叫做消息分發(fā)隊(duì)列或者簡(jiǎn)稱分發(fā)隊(duì)列用來(lái)與系統(tǒng)的消息隊(duì)列區(qū)分,注意分發(fā)隊(duì)列里面的消息都是已經(jīng)格式化后的消息,分發(fā)給誰(shuí)呢?當(dāng)然是分發(fā)給消息的回調(diào)函數(shù)了,對(duì)于有窗口的就是先分發(fā)給窗口過(guò)程,然后 由窗口過(guò)程分發(fā)給具體的處理函數(shù)。

下面我們來(lái)通過(guò)一個(gè)例子說(shuō)明一下,用vs2005或VC建立一個(gè)Win32工程,然后看自動(dòng)生成的代碼: 

int APIENTRY _tWinMain(HINSTANCE hInstance,

                     HINSTANCE hPrevInstance,

                     LPTSTR    lpCmdLine,

                     
int       nCmdShow)
{
     
    
// 主消息循環(huán):
    while (GetMessage(&msg, NULL, 00)) 
    
{
        
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
        
{
            TranslateMessage(
&msg);
            DispatchMessage(
&msg);//msg中按照消息號(hào)識(shí)別
        }

    }

    
return (int) msg.wParam;
}

以上就是消息循環(huán),該線程循環(huán)接收消息,然后DispatchMessage消息,Dispatch到窗口過(guò)程:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    
int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;

    
switch (message)//message就是消息號(hào)
    {
    
case WM_COMMAND:

    
default:
        
return DefWindowProc(hWnd, message, wParam, lParam);
    }

    
return 0;
}

以上實(shí)際上就是windows消息機(jī)制的全景,對(duì)于windows的timer當(dāng)然也要套用上面的模式了,在SetTimer調(diào)用后,實(shí)際上就注冊(cè)了WM_TIMER消息,以下是函數(shù)定義:

UINT_PTR SetTimer(       

    HWND hWnd,

    UINT_PTR nIDEvent,

    UINT uElapse,

    TIMERPROC lpTimerFunc

);

lpTimerFunc就是回調(diào)函數(shù),其形式為:

VOID CALLBACK TimerProc(         

    HWND hwnd,

    UINT uMsg,

    UINT_PTR idEvent,

    DWORD dwTime

);

SetTimer的參數(shù)uElapse就是時(shí)間間隔,比如設(shè)置為1000即1秒,現(xiàn)在有了一個(gè)問(wèn)題,請(qǐng)看下列代碼:

VOID CALLBACK TimerFunc(HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime)

{

    Sleep(
5000);

}


DWORD CALLBACK AutoBakup( PVOID lpParam )
{
    MSG  msg;

    UINT id
=SetTimer(NULL,1,1000,TimerFunc);

        BOOL bRet;

    
while( ((bRet = GetMessage(&msg,NULL,0,0))!= 0) )
    
{
        
if(bRet==-1)
        
{
            
break;
        }

        
else  
        
{
            TranslateMessage(
&msg);
            DispatchMessage(
&msg);
        }

    }


    KillTimer(NULL,id);
    
return 0;
}

竟然在timer的處理函數(shù)中睡眠了,那么SetTimer時(shí)的1000毫秒觸發(fā)一次timer回調(diào)還會(huì)進(jìn)行嗎?其實(shí)不會(huì)進(jìn)行了,本質(zhì)上那個(gè)1000毫秒就 不是說(shuō)觸發(fā)回調(diào)函數(shù)的間隔,而是產(chǎn)生WM_TIMER消息的間隔,因?yàn)榛卣{(diào)函數(shù)中睡眠了,所以也就阻塞了本線程,這個(gè)線程就不再往前走了,但是底層的 WM_TIMER消息也會(huì)因此而不再投遞嗎?不會(huì),消息的投遞其實(shí)不是本線程進(jìn)行的,而是系統(tǒng)進(jìn)行的,本線程已經(jīng)睡眠了,但是系統(tǒng)卻沒(méi)有睡眠,它會(huì)繼續(xù)往該線程的消息隊(duì)列投遞WM_TIMER消息,只不過(guò)這些消息不再由該線程的GetMessage取出了,因?yàn)樗吡耍ㄈ绻麑?duì)回調(diào)函數(shù)是否和 GetMessage是否為統(tǒng)一線程有疑義,那么用GetCurrentThreadId()檢測(cè)一下就好),消息全部堆積在隊(duì)列里面,然后等待睡眠結(jié)束后再一個(gè)一個(gè)處理。好吧,這個(gè)問(wèn)題解決了,下一個(gè)問(wèn)題又來(lái)了,試著將回調(diào)函數(shù)改為下面的: 

VOID CALLBACK TimerFunc(HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime) 
{
    MessageBoxA(NULL,
"zhaoya","msg",MB_OK);
    Sleep(
5000);
}

發(fā)現(xiàn)完全按照SetTimer時(shí)設(shè)置的那樣,1秒彈出一個(gè)消息框,一個(gè)一個(gè)出來(lái),Sleep好像根本就沒(méi)有執(zhí)行,線程根本沒(méi)有睡眠阻塞,我把 MessageBoxA(NULL,"","",MB_OK)換成printf就不行了,線程立即執(zhí)行Sleep,這是為何?關(guān)鍵就在 MessageBoxA上,它實(shí)際上是一個(gè)模態(tài)對(duì)話框,既然是對(duì)話框它就有消息循環(huán),它并沒(méi)有開(kāi)獨(dú)立的線程,因此可以肯定還是原來(lái)的線程,原來(lái) MessageBoxA的內(nèi)部實(shí)現(xiàn)了GetMessage-->TranslateMessage-->DispatchMessage的循環(huán),由于還是原來(lái)的線程,所以它GetMessage將還包括WM_TIMER,另外還有消息框自己的一些關(guān)于界面的消息,比如WM_PAINT,消息框 的出現(xiàn)只是在系統(tǒng)中又注冊(cè)了一些需要的消息,就是消息框的關(guān)于界面事件的消息。WM_TIMER回調(diào)函數(shù)在那,于是調(diào)用之,于是又是一個(gè)消息框出來(lái)了,但 是一旦你點(diǎn)擊最上面的OK鍵,那么程序立即向下進(jìn)行,進(jìn)入Sleep,開(kāi)始睡眠,所有的消息框好像死掉一般,因?yàn)榫鸵粋€(gè)線程,它睡眠了,消息循環(huán)不再進(jìn)行,當(dāng)然所有消息框的消息循環(huán)也不再進(jìn)行,什么WM_PANIT之類的消息都將阻塞,于是消息框們都和死了一樣。

通過(guò)以上論述,我想關(guān)于windows消息大致已經(jīng)說(shuō)清了,下面解決第二個(gè)問(wèn)題,如何向SetTimer的回調(diào)函數(shù)傳遞自定義參數(shù)。再看TimerProc:

VOID CALLBACK TimerPro(HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime);

看看MSDN關(guān)于第三個(gè)參數(shù)idEvent的解釋,就是Timer的id,我們可以用SetTimer的返回值來(lái)作為自定義參數(shù)的指針,然后在 TimerProc回調(diào)函數(shù)中通過(guò)idEvent取出,強(qiáng)制轉(zhuǎn)換為自己定義的類型,可是SetTimer的返回值并不是我們所能左右的啊,那么還是要從 MSG結(jié)構(gòu)下手了: 

typedef struct tagMSG {     // msg

   HWND hwnd;

   UINT message;

   WPARAM wParam;

   LPARAM lParam;

   DWORD time;

   POINT pt;

}
 MSG;

看看wParam和lParam,MSDN上說(shuō)是額外參數(shù),我們只需要重新設(shè)置值就可以了,于是我們要取wParam和lParam這兩個(gè)參數(shù)與 TimerProc形參的交集,這個(gè)交集就是我們可以自定義的參數(shù),經(jīng)過(guò)測(cè)試,發(fā)現(xiàn)wParam其實(shí)就是SetTimer返回的id,也就是 TimerProc的形參idEvent,于是例子如下:

 

VOID CALLBACK TimerFunc(HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime) 
{

    
char * buf = (char*)idEvent;

    printf( 
"%s\n", buf );//這里打印的就是"abcde"

}


DWORD CALLBACK AutoBakup( PVOID lpParam ) 

{

    
char * buf = "abcde";

    MSG  msg;

    UINT id
=SetTimer(NULL,1,1000,TimerFunc);

        BOOL bRet;

    
while( ((bRet = GetMessage(&msg,NULL,0,0))!= 0) )

    
{  

        
if(bRet==-1

        
{

            
break
        }
 

        
else  

        


            TranslateMessage(
&msg);

            msg.wParam 
= (WPARAM)buf;//這里設(shè)置參數(shù)

            DispatchMessage(
&msg);

        }


    }


    KillTimer(NULL,id);

    
return 0;

}

如果你說(shuō),這么把idEvent占了的話,真正的timer的id不就得不到了嗎?唉,暈!如果能傳遞一個(gè)指針那么就沒(méi)有設(shè)呢沒(méi)不能傳遞了,X位機(jī)器上的X 位指針是可以指遍整個(gè)虛擬內(nèi)存的,你可以把自定義參數(shù)包裝成一個(gè)結(jié)構(gòu),該結(jié)構(gòu)的一個(gè)字段指向真正的timer的id,一切..

posted on 2011-01-18 01:27 楊粼波 閱讀(3050) 評(píng)論(1)  編輯 收藏 引用

評(píng)論

# re: 從SetTimer看Windows消息處理機(jī)制 2013-09-10 17:14 我在黃河邊

寫(xiě)得很不錯(cuò),看了很受啟發(fā)。謝謝!  回復(fù)  更多評(píng)論   


只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲网在线观看| 久久久久**毛片大全| 欧美一区二区三区免费看 | 欧美日韩午夜剧场| 国产伦精品一区二区三区高清版| 国精品一区二区| 99精品久久久| 久久九九电影| 亚洲精品美女在线| 99热免费精品在线观看| 欧美一区二区视频网站| 欧美激情中文字幕一区二区| 国产精品视频精品视频| 最新成人av在线| 午夜国产精品影院在线观看 | 欧美高清在线| 国产精品一区二区久久精品| 亚洲国产日韩综合一区| 亚洲欧美影院| 亚洲国产成人高清精品| 亚洲女爱视频在线| 欧美激情视频一区二区三区不卡| 国产欧美日韩一区二区三区在线| 亚洲精品资源| 久久亚洲精品一区二区| 中文国产成人精品久久一| 狂野欧美激情性xxxx| 国产欧美91| 一区二区三区精品视频| 欧美1区免费| 午夜精品亚洲一区二区三区嫩草| 欧美日韩999| 亚洲福利精品| 久久久夜精品| 亚洲制服少妇| 欧美日韩在线观看视频| 91久久国产精品91久久性色| 久久久久久一区二区三区| 中文高清一区| 欧美三级电影一区| 日韩视频在线一区| 男女精品网站| 欧美一级欧美一级在线播放| 国产精品国产三级国产普通话99| 亚洲精品一区在线观看| 欧美成人国产| 久久人人爽人人爽爽久久| 国产亚洲欧美一区在线观看 | 久久se精品一区二区| 日韩一级在线观看| 欧美激情一区二区三区| 最新69国产成人精品视频免费| 久久综合中文| 久久大综合网| 狠狠色丁香久久婷婷综合丁香| 欧美在线免费视屏| 亚洲综合色自拍一区| 国产精品剧情在线亚洲| 亚洲资源av| 一区二区不卡在线视频 午夜欧美不卡在 | 亚洲一区二区在线免费观看| 亚洲啪啪91| 欧美凹凸一区二区三区视频| 亚洲国产精品高清久久久| 免费不卡在线观看| 久久久久久久久久久一区| 韩国成人理伦片免费播放| 久久精品亚洲精品国产欧美kt∨| 午夜精品在线看| 国产午夜精品一区二区三区欧美| 欧美永久精品| 欧美一区在线直播| 狠狠爱综合网| 欧美v日韩v国产v| 免费国产自线拍一欧美视频| 亚洲日本欧美天堂| 亚洲人成人77777线观看| 欧美日韩精品免费观看视频| 亚洲视频自拍偷拍| 亚洲午夜精品视频| 国产欧美一区视频| 久久久久久久久一区二区| 久久精品国产亚洲精品| 在线观看日韩国产| 亚洲高清在线观看| 欧美日本一区| 午夜精品久久| 欧美在线一级va免费观看| 伊人男人综合视频网| 欧美激情精品久久久久久黑人 | 亚洲天堂成人在线视频| 亚洲视频福利| 国产一区成人| 欧美高清在线观看| 欧美日韩小视频| 欧美一区二区三区久久精品茉莉花 | 亚洲一区中文字幕在线观看| 国产日韩欧美精品| 女人天堂亚洲aⅴ在线观看| 欧美大片网址| 欧美一区国产二区| 久久全国免费视频| 亚洲视频播放| 欧美亚洲一区二区在线观看| 亚洲国产成人91精品| 日韩一级在线观看| 韩国精品在线观看| 亚洲激情一区| 国产欧美在线播放| 亚洲国产另类久久久精品极度| 欧美日韩网址| 免费观看日韩av| 欧美日韩一区二区三区在线视频 | 久久久99国产精品免费| 日韩亚洲一区在线播放| 亚洲在线中文字幕| 亚洲国产日韩一区| 午夜国产欧美理论在线播放| 亚洲黄色成人| 亚洲欧美国内爽妇网| 91久久午夜| 亚洲女同在线| 亚洲美女免费精品视频在线观看| 亚洲影音先锋| 日韩午夜一区| 久久精品日产第一区二区三区| 一区二区三区久久| 久久尤物电影视频在线观看| 亚洲女人天堂av| 欧美成人免费全部观看天天性色| 欧美一级视频免费在线观看| 欧美高清视频一区二区三区在线观看| 欧美一区91| 欧美人与禽猛交乱配视频| 久久人人爽人人| 欧美天天视频| 欧美激情视频一区二区三区免费| 国产精品一区二区在线观看| 亚洲精品久久久久久久久| 国内精品久久久久影院 日本资源 国内精品久久久久伊人av | 欧美一区二区播放| 亚洲视频香蕉人妖| 欧美成人免费观看| 麻豆成人在线观看| 国产欧美日本一区视频| 日韩亚洲精品视频| 亚洲激情专区| 久久久久久噜噜噜久久久精品| 午夜欧美精品久久久久久久| 欧美日韩精品一区| 亚洲国产清纯| 在线日韩日本国产亚洲| 亚洲一区免费看| 亚洲视频精品| 欧美精品日本| 亚洲欧洲精品一区| 亚洲欧洲在线视频| 久久久久久久精| 久久婷婷国产综合精品青草| 国产欧美日韩在线播放| 中文一区二区| 亚洲私人影院在线观看| 欧美精品 日韩| 亚洲国产免费| 91久久久在线| 欧美激情 亚洲a∨综合| 亚洲国产精品ⅴa在线观看 | 欧美日韩国产一中文字不卡| 欧美大片一区| 尤物在线观看一区| 久久人人爽人人爽爽久久| 久久综合五月| 在线观看一区二区精品视频| 久久九九免费视频| 另类尿喷潮videofree | 欧美国产日韩一区二区在线观看| 免费不卡在线视频| 亚洲成色最大综合在线| 久久夜色精品一区| 欧美电影在线免费观看网站| 亚洲国产精品一区二区久| 美女国产一区| 亚洲三级免费电影| 亚洲视频一区在线观看| 欧美色中文字幕| 亚洲综合首页| 久久久777| 在线成人免费观看| 麻豆国产精品va在线观看不卡| 欧美电影打屁股sp| 日韩视频二区| 欧美天堂亚洲电影院在线观看 | 欧美在线免费观看| 老司机一区二区三区| 亚洲国产一区二区视频| 欧美福利在线| 中文在线资源观看网站视频免费不卡 | 欧美国产乱视频| 9久草视频在线视频精品| 欧美日韩国产综合视频在线|