亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? 新建 文本文檔.txt

?? CRC校驗 CSerialPort串口類C RC校驗 CSerialPort串口類
?? TXT
?? 第 1 頁 / 共 2 頁
字號:
 ASSERT(!(m_nFlags & WF_MODALLOOP)); // window must not already be in modal state

 // for tracking the idle time state
 BOOL bIdle = TRUE;
 LONG lIdleCount = 0;
 BOOL bShowIdle = (dwFlags & MLF_SHOWONIDLE) && !(GetStyle() & WS_VISIBLE);
 HWND hWndParent = ::GetParent(m_hWnd);
 m_nFlags |= (WF_MODALLOOP|WF_CONTINUEMODAL);
 MSG* pMsg = &AfxGetThread()->m_msgCur;

 // acquire and dispatch messages until the modal state is done
 for (;;)
 {
  ASSERT(ContinueModal());

  // phase1: check to see if we can do idle work
  while (bIdle &&
   !::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE))
  {
   ASSERT(ContinueModal());

   // show the dialog when the message queue goes idle
   if (bShowIdle)
   {
    ShowWindow(SW_SHOWNORMAL);
    UpdateWindow();
    bShowIdle = FALSE;
   }

   // call OnIdle while in bIdle state
   if (!(dwFlags & MLF_NOIDLEMSG) && hWndParent != NULL && lIdleCount == 0)
   {
    // send WM_ENTERIDLE to the parent
    ::SendMessage(hWndParent, WM_ENTERIDLE, MSGF_DIALOGBOX, (LPARAM)m_hWnd);
   }
   if ((dwFlags & MLF_NOKICKIDLE) ||
    !SendMessage(WM_KICKIDLE, MSGF_DIALOGBOX, lIdleCount++))
   {
    // stop idle processing next time
    bIdle = FALSE;
   }
  }

  // phase2: pump messages while available
  do
  {
   ASSERT(ContinueModal());

   // pump message, but quit on WM_QUIT
   //PumpMessage(消息泵)的實現和上面講的差不多。都是派送消息到窗口。
   if (!AfxGetThread()->PumpMessage())
   {
    AfxPostQuitMessage(0);
    return -1;
   }

   // show the window when certain special messages rec'd
   if (bShowIdle &&
    (pMsg->message == 0x118 || pMsg->message == WM_SYSKEYDOWN))
   {
    ShowWindow(SW_SHOWNORMAL);
    UpdateWindow();
    bShowIdle = FALSE;
   }

   if (!ContinueModal())
    goto ExitModal;

   // reset "no idle" state after pumping "normal" message
   if (AfxGetThread()->IsIdleMessage(pMsg))
   {
    bIdle = TRUE;
    lIdleCount = 0;
   }

  } while (::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE));
 } //無限循環

ExitModal:
 m_nFlags &= ~(WF_MODALLOOP|WF_CONTINUEMODAL);
 return m_nModalResult;
}

先說說怎么退出這個無限循環,在代碼中:
if (!ContinueModal())
 goto ExitModal;
決定是否退出循環,消息循環函數返回也就是快要結束結束程序了。
BOOL CWnd::ContinueModal()
{
 return m_nFlags & WF_CONTINUEMODAL;
}

NOTE: CWnd::ContinueModal()函數檢查對話框是否繼續模式。返回TRUE,表示現在是模式的;返回FALSE,表示對話框已經不是模式(將要結束)。

如果要結束對話框,在內部最終會調用函數CWnd::EndModalLoop,它取消m_nFlags的模式標志(消息循環中的ContinueModal函數將返回FALSE,消息循環將結束,程序將退出);然后激發消息循環讀取消息。也就是說,結束模式對話框是一個標志,改變這個標志就可以了。他的代碼是:

//wincore.cpp
void CWnd::EndModalLoop(int nResult)
{
 ASSERT(::IsWindow(m_hWnd));

 // this result will be returned from CWnd::RunModalLoop
 m_nModalResult = nResult;

 // make sure a message goes through to exit the modal loop
 if (m_nFlags & WF_CONTINUEMODAL)
 {
  m_nFlags &= ~WF_CONTINUEMODAL;
  PostMessage(WM_NULL);
 }
}

NOTE: PostMessage(NULL)是有用的。如果消息隊列中沒有消息的話,可能消息循環中的ContinueModal()不會馬上執行,發送一個空消息是激發消息循環馬上工作。

下面說一下CWnd::RunModalLoop函數中的消息循環究竟干了些什么事情:
1,第一個內循環。首先從消息隊列中查詢消息,如果對話框空閑,而且消息隊列中沒有消息,他做三件事情,大家應到都能從字面上明白什么意思。最重要的是發送WM_KICKIDLE消息。為什么呢?第一部分講到了,非對話框程序用OnIdle來更新用戶界面(UI),比如工具欄,狀態欄。那么,如果對話框中也有工具欄和狀態欄呢,在哪里更新(網上有很多這樣的程序)?可以處理WM_KICKIDLE消息:
 
LRESULT CDlg_5Dlg::OnKickIdle(WPARAM w,LPARAM l)
 {
      //調用CWnd::UpdateDialogControls更新用戶界面
     UpdateDialogControls(this, TRUE);
     return 0;
 }

NOTE: CWnd::UpdateDialog函數發送CN_UPDATE_COMMAND_UI消息給所有的用戶界面對話框控件。 

2,第二個內循環。最重要的還是PumpMessage派送消息到目標窗口。其他的,像第二個if語句,0x118消息好像是WM_SYSTIMER消息(系統用來通知光標跳動的一個消息)。也就是說,如果消息為WM_SYSTIMER或者WM_SYSKEYDOWN,并且空閑顯示標志為真的話,就顯示窗口并通知窗口立刻重繪。

總之,對話框的消息循環機制和非對話框(比如SDI,MDI)還是類似的,僅僅側重點不同。模式對話框是模式顯示,自然有他的特點。下面部分討論一下模式對話框和非模式對話框的區別。因為模式對話框有自己的特殊消息循環;而非模式對話框,共用程序的消息循環,和普通的窗口已經沒有什么大的區別了。

第三部分:模式對話框和非模式對話框的區別

 

這個話題已經有很多人討論,我說說我所理解的意思。
在MFC框架中,一個對話框對象DoModal一下就能產生一個模式對話框,Create一下就能產生一個非模式對話框。實際上,無論是模式對話框還是非模式對話框,在MFC內部都是調用::CreateDialogIndirect(***)函數來創建非模式對話框。只是模式對話框作了更多的工作,包括使父窗口無效,然后進入自己的消息循環等等。::CreateDialogIndirect(***)函數最終調用CreateWindowEx函數通知系統創建窗體并返回句柄,他內部沒有實現自己的消息循環。
非模式對話框創建之后立即返回,并且和主程序共用一個消息循環。非模式對話框要等對話框結束之后才返回,自己有消息循環。比如下面的代碼:
 CMyDlg* pdlg = new CMyDlg;
 pdlg ->Create(IDD_DIALOG1);
 pdlg->ShowWindow(SW_SHOW);
 MessageBox("abc");
非模式對話框和消息框MessageBox幾乎是同時彈出來。而如果將Create改成DoModal,那么,只能彈出模式對話框,在關閉了對話框之后(模式對話框自己的消息循環結束),消息框才彈出來。

NOTE:可以在模式對話框中調用GetParent()->EnableWindow(true);這樣,主窗口的菜單,工具欄又激活了,能用了。MFC使用非模式對話框來模擬模式對話框,而在win32 SDK程序中,模式對話框激發他的父窗口Enable操作是沒有效果的。

關于消息循環總結:


1,我們站在一個什么高度看消息循環?消息循環其實沒有什么深奧的道理。如果一個郵遞員要不斷在一個城市中送信,我們要求他做什么?要求他來回跑,但他一次只能在一個地方出現。如果我們的應用程序只有一個線程的話,我們要他不斷地為窗口傳遞消息,我們怎么做?在一個循環中不斷的檢測消息,并將他發送到適當的窗口。窗口可以有很多個,但消息循環只有一個,而且每時每刻最多只有一個地方在執行代碼。為什么? 看第二點。

2,因為是單線程的(程序進程啟動的時候,只有而且有一個線程,我們稱他為主線程),所以就像郵遞員一樣,每次只能在某一個地方干活。什么意思呢?舉個例子,用::DiapatchMessage派送消息,在窗口處理過程(WinProc,窗口函數)返回之前,他是阻塞的,不會立即返回,也就是消息循環此時不能再從消息隊列中讀取消息,直到::DispatchMessage返回。如果你在窗口函數中執行一個死循環操作,就算你用PostQuitMessage函數退出,程序也會down掉。
while(1)
{
    PostQuitMessage(0); //程序照樣down.
}
所以,當窗口函數處理沒有返回的時候,消息循環是不會從消息隊列中讀取消息的。這也是為什么在模式對話框中要自己用無限循環來繼續消息循環,因為這個無限循環阻塞了原來的消息循環,所以,在這個無限循環中要用GetMessage,PeekMessage,DispatchMessage來從消息隊列中讀取消息并派送消息了。要不然程序就不會響應了,這不是我們所希望的。
所以說,消息循環放在程序的什么的地方都基本上是過的去的,比如放在DLL里面。但是,最好在任何時候,只有一個消息循環在工作(其他的都被阻塞了)。然后,我們要作好的一件事情,就是怎么從消息循環中退出!當然用WM_QUIT是可以拉~(PostThreadMessage也是個好主意),這個消息循環退出后,可能程序退出,也可能會激活另外一個被阻塞的消息循環,程序繼續運行。這要看你怎么想,怎么去做。最后一個消息循環結束的時候,也許就是程序快結束的時候,因為主線程的執行代碼也快要完了(除非BT的再作個死循環)。

NOTE: 讓windows系統知道創建一個線程的唯一方法是調用API CreatThread函數(__beginthreadex之類的都要在內部調用他創建新線程)。好像windows核心編程說,在win2000下,系統用CreateRemoteThread函數來創建線程,CreateThread在內部調用CreateRemoteThread。不過這不是爭論的焦點,至少win98下CreateRemoteThread并不能正常工作,還是CreateThread主持大局。

3,在整個消息循環的機制中,還必須談到窗口函數的可重入性。什么意思?就是窗口函數(他是個回調函數)的代碼什么時候都可以被系統(調用者一般是user32模塊)調用。比如在窗口過程中,向自己的窗口SendMessage(***);那么執行過程是怎樣的?
我們知道,SendMessage是要等到消息發送并被目標窗口執行完之后才返回的。那么窗口在處理消息,然后又等待剛才發送到本窗口的消息被處理后之后(SendMessage返回)才繼續往下執行,程序不就互相死鎖了嗎? 
其實是不會的。windows設計一套適合SendMessage的算法,他判斷如果發送的消息是屬于本線程創建的窗口的,那么直接由user32模塊調用窗口函數(可能就有窗口重入),并將消息的處理結果結果返回。這樣做體現了窗口重入。上面的例子,我們調用SendMessage(***)發送消息到本窗口,那么窗口過程再次被調用,處理完消息之后將結果返回,然后SendMessage之后的程序接著執行。對于非隊列消息,如果沒有窗口重入,不知道會是什么樣子。

NOTE: 由于窗口的可重入性。在win32 SDK程序中應盡量少用全局變量和靜態變量,因為在窗口函數執行過程中可能窗口重入,如果重入后將這些變量改了,但你的程序在窗口重入返回之后繼續執行,可能就是使用已經改變的全局或靜態變量。在MFC中(所有窗口的窗口函數基本上都是AfxWndProc),按照類的思想進行了組織,一般變量都是類中的,好管理的多。

4,MFC中窗口類(比如C**View,CFrameWnd等)中的MessageBox函數,以及AfxMessageBox函數都是阻塞原有的消息循環的。由消息框內部的一個消息循環來從消息隊列中讀取消息,并派送消息(和模式對話框類似)。實際上,這些消息函數最終調用的是::MessageBox,它在消息框內部實現了一個消息循環(原有的主程序消息循環被阻塞了)。論壇中碰到過幾次關于計時器和消息框的問題,看下面的代碼:
void CTest_recalclayoutView::OnTimer(UINT nIDEvent) 
{
 // TODO: Add your message handler code here and/or call default
 MessageBox("abc");
 while(1); //設計一個死循環
 CView::OnTimer(nIDEvent);
}
咱讓OnTimer大約5秒鐘彈出一個消息框。那么,消息框不斷的被彈出來,只要消息框不被關閉,那么程序就不會進入死循環。實際上,每次彈出對話框,都是最上層的那個消息框掌握著消息循環,其他的消息循環被阻塞了。只要不關閉最上面的消息框,while(1);就得不到執行。如果點了關閉,程序就進入了死循環,只能用ctrl+alt+del來解決問題了。

5,消息循環在很多地方都有應用。比如應用在線程池中。一個線程的執行周期一般在線程函數返回之后結束,那么怎么延長線程的生命周期呢?一種方法就是按照消息循環的思想,在線程中加入消息循環,不斷地從線程隊列讀取消息,并處理消息,線程的生命周期就保持著直到這個消息循環的退出。

NOTE:只要線程有界面元素或者調用GetMessage,或者有線程消息發送過來,系統就會為線程創建一個消息隊列。

6,在單線程程序中,如果要執行一個長時間的復雜操作而且界面要有相應的話,可以考慮用自己的消息泵。比如,可以將一個阻塞等待操作放在一個循環中,并將超時值設置得比較小,然后每個等待的片段中用消息泵繼續消息循環,使界面能夠響應用戶操作。等等之類,都可以應用消息泵(調用一個類似這樣的函數):
BOOL CChildView::PeekAndPump()
{
 MSG msg;
 while(::PeekMessage(&msg,NULL,0,0,PM_NOREMOVE))
 {
  if(!AfxGetApp()->PumpMessage())
  {
   ::PostQuitMessage(0);
   return false;
  }
 } 
 return true;
}
其實,用多線程也能解決復雜運算時的界面問題,但是沒有這么方便,而且一般要加入線程通信和同步,考慮的事情更多一點。

綜上所述,MFC消息循環就那么回事,主要思想還是和SDK中差不多。這種思想主要的特點表現在迎合MFC整個框架上,為整個框架服務,為應用和功能服務。這是我的理解。呵呵~

 

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
91污在线观看| 国产乱子伦视频一区二区三区| 99re免费视频精品全部| 日本一二三四高清不卡| 成人免费观看男女羞羞视频| 中文字幕佐山爱一区二区免费| av在线综合网| 亚洲综合成人网| 欧美一区二区日韩| 国产在线不卡一卡二卡三卡四卡| 国产亚洲精久久久久久| 波多野结衣在线aⅴ中文字幕不卡| 最新日韩av在线| 欧美老年两性高潮| 国产在线国偷精品产拍免费yy| 国产精品国产自产拍在线| 在线一区二区三区| 日本欧美一区二区三区乱码| 国产人伦精品一区二区| 欧美在线你懂得| 精品无码三级在线观看视频| 中文字幕一区二区三| 欧美精品tushy高清| 丁香婷婷综合五月| 五月激情六月综合| 国产精品毛片a∨一区二区三区| 91精品办公室少妇高潮对白| 国产主播一区二区三区| 一区二区三区精品视频| 久久综合色天天久久综合图片| 97精品国产97久久久久久久久久久久| 亚洲一区二区三区四区中文字幕| 日韩欧美在线影院| 色综合色综合色综合| 精品一区免费av| 亚洲已满18点击进入久久| 久久蜜臀精品av| 欧美一区二区视频在线观看| 成人avav影音| 国产一区二区福利| 日韩电影在线一区二区| 1024国产精品| 久久精子c满五个校花| 欧美精品丝袜中出| 99久久精品免费| 国产一区二区在线免费观看| 日韩不卡在线观看日韩不卡视频| 亚洲欧美一区二区视频| 久久久精品欧美丰满| 7777精品伊人久久久大香线蕉 | 成人app在线观看| 青青草国产精品97视觉盛宴 | 欧美电影在哪看比较好| 99国产精品久久久| 国产99久久久精品| 久久精品久久99精品久久| 一区二区在线观看免费| 国产精品视频免费| 久久精品一区二区三区av| 91精品国产麻豆| 欧洲精品一区二区三区在线观看| 成人精品一区二区三区四区 | 香蕉影视欧美成人| 欧美系列在线观看| 国产一区二三区好的| 欧美96一区二区免费视频| 一区二区在线观看不卡| 国产精品久久三区| 国产精品麻豆欧美日韩ww| 精品国产第一区二区三区观看体验| 亚洲免费观看高清完整版在线| 亚洲精品写真福利| 亚洲美女一区二区三区| 亚洲成人福利片| 韩国一区二区三区| 91蝌蚪porny九色| 制服丝袜亚洲色图| 欧美国产综合一区二区| 亚洲天堂2014| 久久99精品久久久久| 91丨国产丨九色丨pron| 日韩精品专区在线影院观看| 中文字幕一区免费在线观看| 日韩国产在线一| 成人伦理片在线| 日韩欧美的一区| 亚洲天天做日日做天天谢日日欢| 视频在线观看一区二区三区| 成人性生交大片免费看中文网站| 欧美人成免费网站| 日本一区二区免费在线| 日本最新不卡在线| 97久久精品人人爽人人爽蜜臀| 日韩免费一区二区三区在线播放| 专区另类欧美日韩| 国产精品香蕉一区二区三区| 欧美群妇大交群的观看方式| 国产精品天干天干在观线| 日韩成人精品在线| 欧美亚洲禁片免费| 欧美国产精品劲爆| 久久99九九99精品| 精品视频123区在线观看| 亚洲欧洲精品一区二区精品久久久| 日韩av在线播放中文字幕| 91久久精品日日躁夜夜躁欧美| 国产婷婷一区二区| 日韩和欧美一区二区三区| 91麻豆国产在线观看| 久久综合精品国产一区二区三区 | 日韩一区日韩二区| 国产一本一道久久香蕉| 日韩三级免费观看| 午夜视频在线观看一区二区| 一本到三区不卡视频| 中文成人综合网| 国产一区二区0| 精品国产乱码久久久久久浪潮| 婷婷开心久久网| 欧美日韩一二三| 亚洲一二三区不卡| 欧美亚洲尤物久久| 亚洲精品免费在线播放| 97精品超碰一区二区三区| 国产精品久线在线观看| 成人美女视频在线观看18| 久久亚洲综合av| 国产麻豆精品一区二区| 久久嫩草精品久久久久| 国产裸体歌舞团一区二区| 精品国产露脸精彩对白 | 国产成人日日夜夜| 久久久久久亚洲综合| 国产精品综合一区二区三区| 久久久久久久久久久黄色| 国产在线精品国自产拍免费| 久久亚洲一级片| 成人永久看片免费视频天堂| 欧美高清在线精品一区| 波多野结衣亚洲| 自拍偷拍国产精品| 欧美亚洲日本国产| 日本不卡在线视频| 精品少妇一区二区三区在线播放| 激情六月婷婷久久| 久久中文娱乐网| 播五月开心婷婷综合| 亚洲色图另类专区| 在线观看日韩毛片| 日韩精品一级中文字幕精品视频免费观看 | 高清免费成人av| 国产精品拍天天在线| 99精品视频在线观看| 亚洲免费伊人电影| 欧美日韩精品欧美日韩精品| 免费视频最近日韩| 国产日韩av一区二区| 99视频在线观看一区三区| 亚洲图片有声小说| 精品奇米国产一区二区三区| 国产91丝袜在线18| 亚洲欧美日韩中文字幕一区二区三区 | 国产精品乱码久久久久久| 在线观看国产91| 久久精品国产一区二区| 亚洲国产精品精华液ab| 欧美色视频在线| 国产一区二区免费视频| 亚洲精品美国一| 7777精品伊人久久久大香线蕉| 国产高清在线精品| 一区二区三区在线观看动漫| 日韩视频一区二区在线观看| 成人动漫精品一区二区| 香蕉乱码成人久久天堂爱免费| 亚洲精品高清视频在线观看| 欧美日韩精品欧美日韩精品 | 日本aⅴ精品一区二区三区| 久久色在线观看| 色欧美日韩亚洲| 精品无码三级在线观看视频| 亚洲欧美另类图片小说| 欧美不卡一区二区三区| 色琪琪一区二区三区亚洲区| 精品亚洲国内自在自线福利| 一区二区在线看| 国产亚洲欧美激情| 欧美久久高跟鞋激| 99久久综合99久久综合网站| 日本伊人午夜精品| 亚洲天堂久久久久久久| 亚洲精品高清在线| 久久亚洲一区二区三区四区| 欧美日韩精品一区视频| av爱爱亚洲一区| 久草精品在线观看| 亚洲成a人v欧美综合天堂| 国产精品成人免费| 久久久.com| 日韩欧美一级精品久久|