一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Windows消息機制 vc

 昵稱3972135 2010-12-18

在Windows中,用戶或系統(tǒng)中所發(fā)生的任何活動被當(dāng)作事件來處理,例如,用戶按下了鼠標(biāo)按鈕,就產(chǎn)生一鼠標(biāo)事件。對于所發(fā)生的每一個事件,Windows將其轉(zhuǎn)換成消息的形式放在一個稱為消息隊列的內(nèi)存區(qū)中,然后由Windows的消息發(fā)送程序選擇適合的對象,將消息隊列中的消息發(fā)送到欲接受消息的對象上。Windows的消息可分為四種類型:  
   ?。?)輸入消息:對鍵盤和鼠標(biāo)輸入作反應(yīng)。這類輸入消息首先放在系統(tǒng)消息隊列中,然后Windows將它們送入應(yīng)用程序的消息隊列,使消息得到處理。  
   ?。?)控制消息:用來與Windows的特殊控制對象,例如,對話框、列表框、按鈕等進(jìn)行雙向通信。這類消息一般不通過應(yīng)用程序的消息隊列,而是直接發(fā)送到控制對象上。  
   ?。?)系統(tǒng)消息:對程式化的事件或系統(tǒng)時鐘中斷作出反應(yīng)。有些系統(tǒng)消息,例如大部分DDE消息(程序間進(jìn)行動態(tài)數(shù)據(jù)交換時所使用的消息)要通過Windows的系統(tǒng)消息隊列。而有些系統(tǒng)消息,例如窗口的創(chuàng)建及刪除等消息直接送入應(yīng)用程序的消息隊列。  
   ?。?)用戶消息:這些消息是程序員創(chuàng)建的,通常,這些消息只從應(yīng)用程序的某一部分進(jìn)入到該應(yīng)用程序的另一部分而被處理,不會離開應(yīng)用程序。用戶消息經(jīng)常用來處理選單操作:一個用戶消息與選單中的一選項相對應(yīng),當(dāng)它在應(yīng)用程序隊列中出現(xiàn)時被處理。  
    Windows應(yīng)用程序通過執(zhí)行一段稱為消息循環(huán)的代碼來輪詢應(yīng)用程序的消息隊列,從中檢索出該程序要處理的消息,并立即將檢索到的消息發(fā)送到有關(guān)的對象上。典型的Windows應(yīng)用程序的消息循環(huán)的形式為:  
   
    MSG  msg;  
    while   (GetMessage(&msg,   NULL,   0,   0L))  
    {  
      TranslateMessage(&msg);  
      DispatchMessage(&msg);  
    }  
   
    函數(shù)GetMessage從應(yīng)用程序隊列中檢索出一條消息,并將它存于具有MSG類型的一個變量中,然后交由函數(shù)TranslateMessage對該消息進(jìn)行翻譯,緊接著,函數(shù)DispatchMessage將消息發(fā)送到適當(dāng)?shù)膶ο笊稀?

關(guān)于自定義消息的參數(shù)

自定義消息如果光是消息那只能是一個通知。  
  你知道什么時候該干什么事了。但是有的情況下需要具體的數(shù)據(jù)。這樣參數(shù)就起作用了。  
  比如說要在消息處理中填充一個結(jié)構(gòu)。  
  如struct   mystruct{  
  int   i;  
  char   buf[255];  
  }  
  可以把這個結(jié)構(gòu)的一個指針強制轉(zhuǎn)換為long  ,即(lparam)&mystruct,然后做為消息參數(shù)進(jìn)入消息處理函數(shù)。   其他結(jié)構(gòu)可以此類推。
  消息處理函數(shù)只要將WParam   或是LParam   強制轉(zhuǎn)換為mystruct   *   就可以只用這個結(jié)構(gòu)指針??梢詾檫@個結(jié)構(gòu)中的成員附值?;蚴鞘褂眠@個結(jié)構(gòu)中的數(shù)據(jù)。

1.SendMessage函數(shù)功能描述:將指定的消息發(fā)送到一個或多個窗口。此函數(shù)為指定的窗口調(diào)用窗口過程,直到窗口過程處理完消息后才返回。

.函數(shù)原型:
LRESULT SendMessage(
HWND hWnd, // 目標(biāo)窗口句柄
UINT Msg, // 被發(fā)送的消息
WPARAM wParam, // 第一個消息參數(shù)
LPARAM lParam // 第二個消息參數(shù)
);


.參數(shù):
hWnd
窗口過程接收消息的窗口句柄。如果此參數(shù)為HWND_BROADCAST,則消息被送到系統(tǒng)的所有頂層窗口,包括無效或不可見的非自身擁有的窗口、被覆蓋的窗口和彈出式窗口。消息不被送到子窗口。
Msg
指定被發(fā)送的消息;
wParam
指定附加消息的特定信息;
lParam
指定附加消息的特定信息。


.返回值:
返回值返回消息處理的結(jié)果,其依賴于所發(fā)送的消息。


.備注:
需要以 HWND_BROADCAST 方式通信的應(yīng)用程序應(yīng)該使用 RegisterWindowMessage 函數(shù)來獲得應(yīng)用程序間通信的獨特消息。
如果指定的窗口通過調(diào)用線程被創(chuàng)建,則窗口過程作為子程序被立即調(diào)用。如果指定的窗口通過調(diào)用不同線程被創(chuàng)建,則系統(tǒng)切換到該線程并調(diào)用適當(dāng)?shù)拇翱谶^程。線程間的消息只有在接收線程執(zhí)行消息檢索代碼時才被處理。發(fā)送線程將被阻塞到接收線程處理完消息為止。
Windows CE:Windows CE不支持Windows桌面平臺所支持的所有消息。在使用SendMessage函數(shù)之前,應(yīng)檢查發(fā)送的消息是否被Windows CE所支持。


.使用環(huán)境:
Windows NT: 3.1及以上版本;
Windows:95及以上版本;
Windows CE:1.0及以上版本;
頭文件:winuser.h;
輸入庫:user32.lib;
Unicode:在WindowsNT(Windows2000)環(huán)境下以Unicode和ANSI方式實現(xiàn)。


.示例代碼:

case WM_KEYDOWN:
switch (wParam)
{
case VK_HOME:
SendMessage (hwnd, WM_VSCROLL, SB_TOP, 0) ;
break ;
case VK_END:
SendMessage (hwnd, WM_VSCROLL, SB_BOTTOM, 0) ;
break ;
case VK_PRIOR:
SendMessage (hwnd, WM_VSCROLL, SB_PAGEUP, 0) ;
break ;
...
}
return 0 ;
...


.常見問題
1)使用SendMessage來實現(xiàn)剪切、復(fù)制和粘貼

SendMessage(hwnd, WM_COPY, 0, 0);
SendMessage(hwnd, WM_CUT, 0, 0);
SendMessage(hwnd, WM_PASTE, 0, 0);

2)SendMessage與PostMessage的區(qū)別
PostMessage將消息放入消息隊列后馬上返回,而SendMessage直到窗口過程處理完消息后才返回

3)SendMessage發(fā)送WM_COPYDATA消息在進(jìn)程間傳送數(shù)據(jù)
WM_COPYDATA消息主要目的是允許在進(jìn)程間傳遞少量只讀數(shù)據(jù)。SDK文檔推薦用戶使用SendMessage()函數(shù),接收方在數(shù)據(jù)復(fù)制完成前不返回,這樣發(fā)送方就不可能刪除和修改數(shù)據(jù)。
例如:

std:string strData = "VC知識庫 VCKBASE.COM";
COPYDATASTRUCT cds;
cds.dwData = 0;
cds.cbData = strData.Length();
cds.lpData = strData.c_str();
::SendMessage(hwnd, WM_COPYDATA, NULL, (LPARAM)&cds); 
2.SendMessageCallback
  函數(shù)功能:該函數(shù)將指定的消息發(fā)送到一個或多個窗口。此函數(shù)為指定的窗口調(diào)用窗口程序,并立即返回。當(dāng)窗口程序處理完消息后,系統(tǒng)調(diào)用指定的回調(diào)函數(shù),將消息處理的結(jié)果和一個應(yīng)用程序定義的值傳給回調(diào)函數(shù)。
  函數(shù)原型:BOOL SendMessageCallback(HWND hwnd,UINT Msg,WPARAM wParam,LPARAM IParam,
  SEhDASYNCPROC IpResultCallBack,DWORD dwData);
  參數(shù):
  hWnd:其窗口程序?qū)⒔邮障⒌拇翱诘木浔H绻藚?shù)為HWND_BROADCAST,則消息將被發(fā)送到系統(tǒng)中所有頂層窗口,包括無效或不可見的非自身擁有的窗口、被覆蓋的窗口和彈出式窗口,但消息不被發(fā)送到子窗口。
  Msg:指定被發(fā)送的消息。
  wParam:指定附加的消息指定信息。
  IParam:指定附加的消息指定信息。
  IpResultCallBack:指向回收函數(shù)的指針,窗曰程序處理完消息后調(diào)用該回調(diào)函數(shù)。參見SendAsyncProc可得到合適的回調(diào)函數(shù)的信息。如果hwnd為HWND_BROADCAST,系統(tǒng)為每個頂層窗口調(diào)用一次SendASyncProc回調(diào)函數(shù)。
  dwData:一個應(yīng)用程序定義的值,被傳給由參數(shù)IPResultCallBack指向的回調(diào)函數(shù)。
  返回值:如果函數(shù)調(diào)用成功,返回非零值。如果函數(shù)調(diào)用失敗,返回值是零。若想獲得更多的錯誤信息,請調(diào)用GetLastError函數(shù)。
  備注:如果發(fā)送一個低于WM_USER范圍的消息給異步消息函數(shù)(PostMessage,SendNotifyMesssge;SendMessageCallback),消息參數(shù)不能包含指針。否則,操作將會失敗。函數(shù)將在接收線程處理消息之前返回,發(fā)送者將在內(nèi)存被使用之前釋放。
  需要以HWND_BROADCAST方式通信的應(yīng)用程序應(yīng)當(dāng)用函數(shù)RegisterWindwosMessage來獲得應(yīng)用程序間通信的獨特的消息。
  此回調(diào)函數(shù)僅當(dāng)調(diào)用SendMessagecallback的線程調(diào)用GetMessage,PeekMessage或WaitMessage時調(diào)用。
 
例如:
case WM_LBUTTONDOWN:
  SendMessageCallback(hWnd,WM_LBUTTONUP,0,0,SendAsyncProc,0);
 
//具體的回調(diào)函數(shù)實現(xiàn)
VOID CALLBACK SendAsyncProc(HWND hwnd,UINT uMsg,DWORD dwData,LRESULT lResult)
{
  MessageBox(NULL,"Back From Main Window","SendMessageCallback",MB_OK);
  //下面可以進(jìn)行更進(jìn)一步的處理
}
 
還有這樣一個例子:
在《windows高級編程指南》中說道SendMessageCallback()在發(fā)送后就立即返回。但是我在堵塞測試的時候發(fā)現(xiàn),調(diào)用SendMessageCallback
的線程也死掉了,
下面是我的代碼
大概就是在用SendMessageCallback發(fā)送消息給對話框之前,創(chuàng)建一個Event,設(shè)置為無信號,然后在
對話框的消息響應(yīng)中等待Event變?yōu)橛行盘柌爬^續(xù)執(zhí)行,根據(jù)書上所說,SendMessageCallback()在發(fā)送會就返回,
那么發(fā)送消息的線程就應(yīng)該不會因為對話框在處理消息時候因為等待Event而給堵塞住,這樣發(fā)送線程就可以繼續(xù)執(zhí)行下面的SetEvent,
這樣對話框WaitForSingleObject()得以返回,這樣它也可以得以繼續(xù)執(zhí)行
。
void   CMainFrame::OnOpendialog()  
{
  //該函數(shù)創(chuàng)建一個無模式對話框

    CWorkingDialog*   pdlg=new   CWorkingDialog;
    ASSERT_VALID(pdlg);  
  //Create   the   modeless   dialog   .   represents   this   dialog.
  BOOL   bResult   =   pdlg-> Create(IDD_DIALOG1);

  CString   strMsg= "From   MainFrame ";
  HANDLE   hEvent=CreateEvent(NULL,TRUE,FALSE, "wait ");//創(chuàng)建事件通知   ,手動,無信號

  SendMessageCallback(pdlg-> GetSafeHwnd(),WM_MSG,(WPARAM)(LPCTSTR)strMsg,0,FunCallback,0);
 
strMsg= "Yes ";
  SetEvent(hEvent);
}

//響應(yīng)wm_msg  
void   CWorkingDialog::OnTestMsg(WPARAM   wParam   ,LPARAM   lParam)
{
HANDLE   hEvent   =   CreateEvent(NULL,TRUE,FALSE, "wait ");
ASSERT(GetLastError()==ERROR_ALREADY_EXISTS);
CString   str((LPCTSTR)wParam);

                WaitForSingleObject(hEvent,INFINITE);//等到有信號才執(zhí)行下面的代碼

MessageBox(str);
}

但是這段代碼運行結(jié)果跟我上面的猜想不一致,是不是我對SendMessageCallback的“發(fā)送就返回”理解錯誤?
原因是對于SendMessageCallback()函數(shù), 如果發(fā)送到當(dāng)前線程中,則直接調(diào)用窗口過程,發(fā)送到其它線程中則立即返回。
 
3. SendNotifyMessage
  函數(shù)功能:該函數(shù)將指定的消息發(fā)送到一個窗口。如果該窗口是由調(diào)用線程創(chuàng)建的;此函數(shù)為該窗口調(diào)用窗口程序,并等待窗口程序處理完消息后再返回。如果該窗口是由不同的線程創(chuàng)建的,此函數(shù)將消息傳給該窗口程序,并立即返回,不等待窗口程序處理完消息。
  函數(shù)原型:BOOL SendNotifyMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam);
  參數(shù):
  hWnd:其窗口程序?qū)⒔邮障⒌拇翱诘木浔?。如果此參?shù)為HWND_BROADCAST,則消息將被發(fā)送到系統(tǒng)中所有頂層窗口,包括無效或不可見的非自身擁有的窗口、被覆蓋的窗口和彈出式窗口,但消息不被發(fā)送到子窗口。
  Msg:指定被發(fā)送的消息。
  wParam:指定附加的消息指定信息。
  IParam:指定附加的消息指定信息。
  返回值:如果函數(shù)調(diào)用成功,返回非零值;如果函數(shù)調(diào)用失敗,返回值是零。若想獲得更多的錯誤信息,請調(diào)用GetLastError函數(shù)。
  備注:如果發(fā)送一個低于WM_USER范圍的消息給異步消息函數(shù)(PostMessage,SendNotifyMessage,SendMesssgeCallback),消息參數(shù)不能包含指針。否則,操作將會失敗。函數(shù)將在接收線程處理消息之前返回,發(fā)送者將在內(nèi)存被使用之前釋放。
  需要以HWND_BROADCAST方式通信的應(yīng)用程序應(yīng)當(dāng)用函數(shù)RegisterWindwosMessage來獲得應(yīng)用程序間通信的獨特的消息。
例子:
case WM_RBUTTONDOWN:
  HANDLE hThread;
  DWORD ThreadID;
  //創(chuàng)建一個線程,把當(dāng)前的窗口句柄作為參數(shù)傳遞給新線程
  hThread=CreateThread(NULL,0,Thread1,hWnd,NULL,&ThreadID);
  break;
case WM_LBUTTONDOWN:
  MessageBox(NULL,"Receiving Message:WM_LBUTTONDOWN","MESSAGE",MB_OK);
  break; 
 
//具體的線程函數(shù)實現(xiàn)
DWORD WINAPI  Thread1(LPVOID param)
{
  HWND hWnd=(HWND)param;
   SendNotifyMessage(hWnd,WM_LBUTTONDOWN,0,0);
  //一般情況下,這個消息框要比上面那個消息框早出現(xiàn),因為函數(shù)并不等待消息
  //處理完成之后才返回
  MessageBox(NULL,"Return From SendNotifyMessage","SendNotifyMessage",MB_OK);
  return 1;
}
 
4. SendMessageTimeout
  函數(shù)功能:該函數(shù)將指定的消息發(fā)送到一個或多個窗口。此函數(shù)為指定的窗口調(diào)用窗口程序,并且,如果指定的窗口屬于不同的線程,直到窗口程序處理完消息或指定的超時周期結(jié)束函數(shù)才返回。如果接收消息的窗口和當(dāng)前線程屬于同一個隊列,窗口程序立即調(diào)用,超時值無用。
  函數(shù)原型:LRESULT SendMessageTimeout(HWND hwnd,UINT Msg,WPARAM wParam,LPARAM IParam,UINTfuFlags,UIUT uTimeout,LPDWORD lpdwResultult);
  參數(shù):
  hWnd:其窗口程序?qū)⒔邮障⒌拇翱诘木浔H绻藚?shù)為HWND_BROADCAST,則消息將被發(fā)送到系統(tǒng)中所有頂層窗口,包括無效或不可見的非自身擁有的窗口。
  Msg:指定被發(fā)送的消息。
  wParam:指定附加的消息指定信息。
  IParam:指定附加的消息指定信息。
  fuFlags;指定如何發(fā)送消息。此參數(shù)可為下列值的組合:
  SMTO_ABORTIFHUNG:如果接收進(jìn)程處于“hung”狀態(tài),不等待超時周期結(jié)束就返回。
  SMTO_BLOCK:阻止調(diào)用線程處理其他任何請求,直到函數(shù)返回。
  SMTO_NORMAL:調(diào)用線程等待函數(shù)返回時,不被阻止處理其他請求。
  SMTO_NOTIMEOUTIFNOTHUNG:Windows 95及更高版本:如果接收線程沒被掛起,當(dāng)超時周期結(jié)束時不返回。
  uTimeout:為超時周期指定以毫秒為單位的持續(xù)時間。如果該消息是一個廣播消息,每個窗口可使用全超時周期。例如,如果指定5秒的超時周期,有3個頂層窗回未能處理消息,可以有最多15秒的延遲。
  IpdwResult:指定消息處理的結(jié)果,依賴于所發(fā)送的消息。
  返回值:如果函數(shù)調(diào)用成功,返回非零值。如果函數(shù)調(diào)用失敗,或超時,返回值是零。若想獲得更多的錯誤信息,請調(diào)用GetLastError函數(shù)。如果GetLastError返回零,表明函數(shù)超時。如果使用HWND_BROADCAST,SenddMessaggTimeout不提供單個窗口超時信息。
 
DWORD WINAPI  Thread1(LPVOID param);
 
case WM_RBUTTONDOWN:
  HANDLE hThread;
  DWORD ThreadID;
  //創(chuàng)建一個線程,把當(dāng)前的窗口句柄作為參數(shù)傳遞給新線程
  hThread=CreateThread(NULL,0,Thread1,hWnd,NULL,&ThreadID);
  break;
case WM_LBUTTONDOWN:
  Sleep(5000);//睡眠5秒
  MessageBox(NULL,"Receving Messageg:LBUTTONDOWN","MESSAGE",MB_OK);
  break;
 
DWORD WINAPI  Thread1(LPVOID param)
{
  HWND hWnd=(HWND)param;
  DWORD dwResult;
  LRESULT ret;
  //只等待三秒
  ret=SendMessageTimeout(hWnd,WM_LBUTTONDOWN,0,0,SMTO_BLOCK,3000,&dwResult);
  if(ret==0)
   MessageBox(NULL,"Fail To Process Message","SendMessageTimeout",MB_OK);
  else
   MessageBox(NULL,"Success To Process Message","SendMessageTimeout",MB_OK);
  return 1;
}
 
如果不 Sleep(5000);//睡眠5秒。先  MessageBox(NULL,"Receving Messageg:LBUTTONDOWN","MESSAGE",MB_OK);
后 if(ret==0);但是Sleep(5000);先 if(ret==0)后MessageBox(NULL,"Receving Messageg:LBUTTONDOWN","MESSAGE",MB_OK);
 
5.PostThreadMessage
函數(shù)功能:該函數(shù)將一個消息放入(寄送)到指定線程的消息隊列里,不等待線程處理消息就返回。
  函數(shù)原型:BOOL PostThreadMessage(DWORD idThread,UINT Msg,WPARAM wParam,LPARAM IParam);
  參數(shù)
  idThread:其消息將被寄送的線程的線程標(biāo)識符。如果線程沒有消息隊列,此函數(shù)將失敗。當(dāng)線程第一次調(diào)用一個Win 32 USER或GDI函數(shù)時,系統(tǒng)創(chuàng)建線程的消息隊列。要得到更多的信息,參見備注。
  Msg:指定將被寄送的消息的類型。
  wParam:指定附加的消息特定信息。
  IParam:指定附加的消息特定信息。
  返回值:如果函數(shù)調(diào)用成功,返回非零值。如果函數(shù)調(diào)用失敗,返回值是零。若想獲得更多的錯誤信息,請調(diào)用GetLastError函數(shù)。如果idThread不是一個有效的線程標(biāo)識符或由idThread確定的線程沒有消息隊
  列,GetLastError返回ERROR_INVALID_THREAD。
  備注:消息將寄送到的線程必須創(chuàng)建消息隊列,否則調(diào)用PostThreadMessage會失敗。用下列方法之一來處理這種情況:
  調(diào)用PostThreadMessage。如果失敗,調(diào)用Sleep,再調(diào)用PostThreadMessage,反復(fù)執(zhí)行,直到PostThreadMessage成功。
  創(chuàng)建一個事件對象,再創(chuàng)建線程。在調(diào)用PostThreadMessage之前,用函數(shù)WaitForSingleObject來等特事件被設(shè)置為被告知狀態(tài)。消息將寄送到的線程調(diào)用PeekMessage(&msg,NULL,WM_USER,WM_USER,PM_NOREMOVE)來強制系統(tǒng)創(chuàng)建消息隊列。設(shè)置事件,表示線程已準(zhǔn)備好接收寄送的消息。
  消息將寄送到的線程通過調(diào)用GetMesssge或PeekMesssge來取得消息。返回的MSG結(jié)構(gòu)中的hwnd成員為NULL。
case WM_RBUTTONDOWN:
  HANDLE hThread;
  DWORD ThreadID,LocalThreadID;
  //將當(dāng)前線程ID作為參數(shù)傳遞給新線程
  LocalThreadID=GetCurrentThreadId();
  hThread=CreateThread(NULL,0,Thread1,(LPVOID)LocalThreadID,NULL,&ThreadID);
  break;
 
//具體的線程函數(shù)實現(xiàn)
DWORD WINAPI  Thread1(LPVOID param)
{
  DWORD MainThreadID;
  MainThreadID=(DWORD)param;
  //向主線程發(fā)送一條消息
  PostThreadMessage(MainThreadID,WM_LBUTTONDOWN,0,0);
  return 1;
}
 
6.函數(shù)功能:該函數(shù)將一個消息放入(寄送)到與指定窗口創(chuàng)建的線程相聯(lián)系消息隊列里,不等待線程處理消息就返回,是異步消息模式。消息隊列里的消息通過調(diào)用GetMessage和PeekMessage取得。
  函數(shù)原型:B00L PostMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam);
  參數(shù)
  hWnd:其窗口程序接收消息的窗口的句柄。可取有特定含義的兩個值:
  HWND_BROADCAST:消息被寄送到系統(tǒng)的所有頂層窗口,包括無效或不可見的非自身擁有的窗口、被覆蓋的窗口和彈出式窗口。消息不被寄送到子窗口。
  NULL:此函數(shù)的操作和調(diào)用參數(shù)dwThread設(shè)置為當(dāng)前線程的標(biāo)識符PostThreadMessage函數(shù)一樣。
  Msg:指定被寄送的消息。
  wParam:指定附加的消息特定的信息。
  IParam:指定附加的消息特定的信息。
  返回值:如果函數(shù)調(diào)用成功,返回非零值:如果函數(shù)調(diào)用失敗,返回值是零。若想獲得更多的錯誤信息,請調(diào)用GetLastError函數(shù)。
  備注:需要以 HWND_BROADCAST方式通信的應(yīng)用程序應(yīng)當(dāng)用函數(shù) RegisterwindwosMessage來獲得應(yīng)用程序間通信的獨特的消息。
  如果發(fā)送一個低于WM_USER范圍的消息給異步消息函數(shù)(PostMessage.SendNotifyMessage,SendMesssgeCallback),消息參數(shù)不能包含指針。否則,操作將會失敗。函數(shù)將再接收線程處理消息之前返回,發(fā)送者將在內(nèi)存被使用之前釋放。
  速查:Windows NT: 3.1及以上版本;Windows:95及以上版本;Windows CE:1.0及以上版本;頭文件:winuser.h;輸入庫:user32.lib;Unicode:在Windows NT環(huán)境下以Unicode和ANSI方式實現(xiàn)。
  P.S. 為什么 “如果發(fā)送一個低于WM_USER范圍的消息給異步消息函數(shù)(PostMessage.SendNotifyMessage,SendMesssgeCallback),消息參數(shù)不能包含指針。否則,操作將會失敗。
#define WM_SENDMESSAGE WM_USER+1
#define WM_POSTMESSAGE WM_USER+2
 
DWORD WINAPI  Thread1(LPVOID param)
 
case WM_SENDMESSAGE:
  MessageBox(NULL,"本對話框結(jié)束之后SendMessage才會返回!","SendMessage",MB_OK);
 break;
case WM_POSTMESSAGE:
  MessageBox(NULL,"本對話框結(jié)束之前PostMessage已經(jīng)返回!","SendMessage",MB_OK);
  break;
case WM_RBUTTONDOWN:
  HANDLE hThread;
  DWORD ThreadID;
  //創(chuàng)建一個線程,將當(dāng)前的窗口句柄作為參數(shù)傳遞給該新創(chuàng)建的線程
  hThread=CreateThread(NULL,0,Thread1,hWnd,NULL,&ThreadID);
  break;
 
//具體的線程函數(shù)實現(xiàn)
DWORD WINAPI  Thread1(LPVOID param)
{
  HWND hWnd;
  hWnd=(HWND)param;
  //可以比較下面兩種發(fā)送消息的差別
  PostMessage(hWnd,WM_POSTMESSAGE,0,0);
// SendMessage(hWnd,WM_SENDMESSAGE,0,0);
  return 1;
}
 
7. PostQuitMessage
函數(shù)功能:該函數(shù)向系統(tǒng)表明有個線程有終止請求。通常用來響應(yīng)WM_DESTROY消息。
  函數(shù)原型:VOID PostQuitMessage(int nExitCode);
  參數(shù):
  nExitCode:指定應(yīng)用程序退出代碼。此值被用作消息WM_QUIT的wParam參數(shù)。
  返回值:無。
  備注:PostQuitMessage寄送一個WM_QUIT消息給線程的消息隊列并立即返回;此函數(shù)向系統(tǒng)表明有個線程請求在隨后的某一時間終止。
  當(dāng)線程從消息隊列里取得WM_QUIT消息時,應(yīng)當(dāng)退出消息循環(huán)并將控制返回給系統(tǒng)。返回給系統(tǒng)的退出值必須是消息WM_QUIT的wParam參數(shù)。
 
case WM_LBUTTONDOWN:
   PostQuitMessage(1);
 
8.BroadcastSystemMessage
該函數(shù)發(fā)送消息給指定的接受者。接受者可以是一個應(yīng)用程序、安裝驅(qū)動器、網(wǎng)絡(luò)驅(qū)動器、系統(tǒng)級設(shè)備驅(qū)動器或這些系統(tǒng)組件的組合。
  函數(shù)原型:long BroadcastSystemMessage(DWORD dwFIags,LPDWORD IpdwRecipients,UINT UiMessage,WPARAMwParam,LPARAM IParam);
  參數(shù): dwFlags:選項標(biāo)志??扇∠铝兄档慕M合:
  BSF_FLUSHDISK:接受者處理消息之后清洗磁盤。
  BSF_FORCEIFHUNG:繼續(xù)廣播消息,即使超時周期結(jié)束或一個接受者已掛起。 BSF_IGNORECURRENTTASK:不發(fā)送消息給屬于當(dāng)前任務(wù)的窗口。這樣,應(yīng)用程序就不會接收自己的消息。
  BSF_NOHANG:強制掛起的應(yīng)用程序超時。如果一個接受者超時,不再繼續(xù)廣播消息。 BSF_NOTIMEOUTIFNOTHUNG:只要接受者沒掛起,一直等待對消息的響應(yīng)。不會出現(xiàn)超時。 BSF_POSTMESSAGE:寄送消息。不能和BSF_QUERY組合使用。
  BSF_QUERY:每次發(fā)送消息給一個接受者,只有當(dāng)前接受者返回TRUE后,才能發(fā)送給下一個接受者。 lpdwRecipients:指向變量的指針,該變量含有和接收消息接受者的信息。此變量可為下列值的組合: BSM_ALLCOMPONENTS:廣播到所有的系統(tǒng)組件。
  BSM_ALLDESKTOPS:Windows NT下,廣播到所有的桌面。要求SE_TCB_NAME特權(quán)。
  BSM_APPLICATIONS:廣播到應(yīng)用程序。
  BSM_INSTALLABLEDRIVERS:Windows 95下,廣播到安裝驅(qū)動器。
  BSM_INTDRIVER:Windows 95下,廣播到網(wǎng)絡(luò)驅(qū)動器。
  BSM_VXDS:Windows 95下,廣播到所有系統(tǒng)級設(shè)備驅(qū)動器。
  當(dāng)函數(shù)返回時,此變量接受上述值的組合,以確定真正接受消息的接受者。如果此參數(shù)為NULL,則將消息廣播到所有的組件。
  uiMessage:系統(tǒng)消息標(biāo)識符。
  WParam:32位消息特定值。
  IParam:32位消息特定值。
  返回值:如果函數(shù)調(diào)用成功,返回值是正數(shù)。如果函數(shù)不能廣播消息,返回值是C1。如果參數(shù)dwFlags為BSF_QUERY且至少一個接受者返回BROADCAST_QUERY_DENY給相應(yīng)的消息,返回值是零。若想獲得更多的錯誤信息,請調(diào)用GetLastError函數(shù)。 備注:如果BSF_QUERY沒指定,函數(shù)發(fā)送指定的消息給所有請求的接受者,并忽略這些接受者返回的值。
 
 
RegisterWindowMessage中的BroadcastSystemMessage如何處理
我想用BroadcastSystemMessage來在兩個進(jìn)程之間通訊,我從一個進(jìn)程發(fā)送了一個用 RegisterWindowMessage注冊過的消息,但在目的進(jìn)程中卻沒有收到該消息.
A:我認(rèn)為你應(yīng)該在兩個進(jìn)程的最高級窗口中都注冊該消息.請看下例:
static UINT sBroadcastCommand = ::RegisterWindowMessage( _T("BroadcastCommand"));
BEGIN_MESSAGE_MAP( Gui_Top_Level_MainFrame, Gui_MainFrame )
ON_REGISTERED_MESSAGE( sBroadcastCommand, onBroadcastCommand )
END_MESSAGE_MAP()
LRESULT Gui_MainFrame :: onBroadcastCommand( UINT aMsg, LPARAM lParam )
{
your code...
}
然后發(fā)送進(jìn)行應(yīng)該包含:
While the sending process would contain:
static UINT sBroadcastCommand = ::RegisterWindowMessage( _T("BroadcastCommand"));
void Someclass :: someMethod( void )
{
::PostMessage( (HWND)HWND_BROADCAST,sBroadcastCommand, 0,yourMessageId );
}
9.ReplyMessage
函數(shù)功能:該函數(shù)用于應(yīng)答由函數(shù)SendMessage發(fā)送的消息,不返回控制給調(diào)用SendMessage的函數(shù)。
  函數(shù)原型:BOOL ReplyMessage(LRESULTIResult);
  參數(shù):
  IResult:指定消息處理的結(jié)果??赡艿闹涤伤l(fā)送的消息確定。
  返回值:如果調(diào)用線程正處理從其他線程或進(jìn)程發(fā)送的消息,返回非零值。如果調(diào)用線程不是正處理從其他線程或進(jìn)程發(fā)送的消息,返回值是零。
  備注:調(diào)用此函數(shù),接收消息的窗口程序允許調(diào)用SendMessage的線程繼續(xù)運行,盡管接收消息的線程已返回控制。調(diào)用ReplyMessage的線程也繼續(xù)運行。
  如果消息不是通過SendMessage發(fā)送的,或者消息由同一個線程發(fā)送,ReplyMessage不起作用。
case WM_LBUTTONDOWN:
  LRESULT result;
  result=1;
  //去掉下面語句,則SendMessage函數(shù)將等待5秒鐘才會返回
  ReplyMessage(result);
  Sleep(5000);
  break;
//具體的線程函數(shù)實現(xiàn)
DWORD WINAPI  Thread1(LPVOID param)
{
  HWND hWnd=(HWND)param;
  SendMessage(hWnd,WM_LBUTTONDOWN,0,0);
  MessageBox(NULL,"Come Back","SendMessage",MB_OK);
  return 1;
}
 
while (WaitMessage())
{
  PeekMessage(&msg,NULL,0,0,PM_REMOVE);
  if(msg.message==WM_QUIT)
   break;
  //上面的幾條語句相當(dāng)于while(GetMessage(&msg,NULL,0,0)
  if(msg.hwnd==NULL)
   MessageBox(NULL,"Receive Message From PostThreadMessage",
              "PostThreadMessage",MB_OK);
  if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
  {
   TranslateMessage(&msg);
   DispatchMessage(&msg);
  }
 }
 
10.

函數(shù)GetMessage 是 從調(diào)用線程的消息隊列里取得一個消息并將其放于指定的結(jié)構(gòu)。此函數(shù)可取得與指定窗口聯(lián)系的消息和由PostThreadMesssge寄送的線程消息。此函數(shù)接收一定范圍的消息值。GetMessage不接收屬于其他線程或應(yīng)用程序的消息。獲取消息成功后,線程將從消息隊列中刪除該消息。函數(shù)會一直等待直到有消息到來才有返回值。

GetMessage
  
 
 
BOOL GetMessage(LPMSG lpMsg,HWND hWnd,UINT wMsgFilterMin,UINT wMsgFilterMax
  參數(shù):
  lpMsg:指向MSG結(jié)構(gòu)的指針,該結(jié)構(gòu)從線程的消息隊列里接收消息信息。
  hWnd:取得其消息的窗口的句柄。這是一個有特殊含義的值(NULL)。GetMessage為任何屬于調(diào)用線程的窗口檢索消息,線程消息通過PostThreadMessage寄送給調(diào)用線程。
  wMsgFilterMin:指定被檢索的最小消息值的整數(shù)。
  wMsgFilterMax:指定被檢索的最大消息值的整數(shù)。
  返回值:如果函數(shù)取得WM_QUIT之外的其他消息,返回非零值。如果函數(shù)取得WM_QUIT消息,返回值是零。如果出現(xiàn)了錯誤,返回值是-1。例如,當(dāng)hWnd是無效的窗口句柄或lpMsg是無效的指針時。若想獲得更多的錯誤信息,請調(diào)用GetLastError函數(shù)。
 
  應(yīng)用程序通常用返回值來確定是否終止主消息循環(huán)并退出程序。
  GetMesssge只接收與參數(shù)hWnd標(biāo)識的窗口或子窗口相聯(lián)系的消息,子窗口由函數(shù)IsChild決定,消息值的范圍由參數(shù)wMsgFilterMin和wMsgFilterMax給出。如果hWnd為NULL,則GetMessage接收屬于調(diào)用線程的窗口的消息,線程消息由函數(shù)PostThreadMessage寄送給調(diào)用線程。GetMessage不接收屬于其他線程或其他線程的窗口的消息,即使hWnd為NULL。由PostThreadMessage寄送的線程消息,其消息hWnd值為NULL。如果wMsgFilterMin和wMsgFilterMax都為零,GetMessage返回所有可得的消息(即,無范圍過濾)。
  常數(shù) WM_KEYFIRST和WM_KEYAST可作為過濾值取得與鍵盤輸入相關(guān)的所有消息:常數(shù)WM_MOUSEFIRST和WM_MOUSELST可用來接收所有的鼠標(biāo)消息。如果wMsgFilterMin和wMsgFilterMax都為零,GetMessage返回所有可得的消息(即,無范圍過濾)。
  GetMessage不從隊列里清除WM.PAINT消息。該消息將保留在隊列里直到處理完畢。
  注意,此函數(shù)的返回值可非零、零或-1,應(yīng)避免如下代碼出現(xiàn):
  while(GetMessage(IpMsg,hwnd,0,0))…
  -1返回值的可能性表示這樣的代碼會導(dǎo)致致命的應(yīng)用程序錯誤。
 
11.WaitMessage
函數(shù)功能:該函數(shù)產(chǎn)生對其他線程的控制,如果一個線程沒有其他消息在其消息隊列里。此函數(shù)中止線程,直到一個新消息被放入該線程的消息隊列里,再返回。
  函數(shù)原型;BOOL WaitMessage(VOID)
  參數(shù):無。
  返回值:如果函數(shù)調(diào)用成功,返回非零值;如果函數(shù)調(diào)用失敗,返回值是零。若想獲得更多的錯誤信息,請調(diào)用GetLastError函數(shù)。
  備注:在線程調(diào)用一個函數(shù)來檢查隊列后,如果有未經(jīng)閱讀的輸入在消息隊列里,WaitMessage不返回。這是因為PeekMessage,GetMessage,GetQueueStatus:WaitMessage,MsgWaitForMultipleObjects,MsgWaitForMulitpleObjectEx等函數(shù)檢查隊列后,改變隊列的狀態(tài)信息這樣輸入不再被認(rèn)為是新的。如果連續(xù)調(diào)用WaitMessage,將等到指定類型的新輸入到達(dá)后才返回。已存在的未讀過的輸入(在上次線程檢查隊列之前接收的)被忽略。
 
12.TranslateAccelerator
函數(shù)功能:翻譯加速鍵表。該函數(shù)處理菜單命令中的加速鍵。該函數(shù)將一個WM_KEYDOWN或WM_SYSKEYDOWN消息翻譯成一個WM_COMMAND或WM_SYSCOMMAND消息(如果在給定的加速鍵表中有該鍵的入口),然后將WM_COMMAND或WM_SYSCOMMAND消息直接送到相應(yīng)的窗口處理過程。
  TranslateAccelerator直到窗口過程處理完消息后才返回。
  函數(shù)原型:int TranslateAccelerator(HWND hWnd,HACCEL hAccTable,LPMSG IpMsg);  ?。?
  hWnd:窗口句柄,該窗口的消息將被翻譯。
  hAccTable:加速鍵表句柄。加速鍵表必須由LoadAccelerators函數(shù)調(diào)用裝入或由CreateAccd_eratorTable函數(shù)調(diào)用創(chuàng)建。
  LpMsg:MSG結(jié)構(gòu)指針,MSG結(jié)構(gòu)中包含了從使用GetMessage或PeekMessage函數(shù)調(diào)用線程消息隊列中得到的消息內(nèi)容。
  返回值:若函數(shù)調(diào)用成功,則返回非零值;若函數(shù)調(diào)用失敗,則返回值為零。若要獲得更多的錯誤信息,可調(diào)用GetLastError函數(shù)。   :為了將該函數(shù)發(fā)送的消息與菜單或控制發(fā)送的消息區(qū)別開來,使WM_COMMAND或WM_SYSCOMMAND消息的wParam參數(shù)的高位字值為1。用于從窗口菜單中選擇菜單項的加速鍵組合被翻譯成WM_SYSCOMMAND消息:所有其他的加速鍵組合被翻譯成WM_COMMAND。若TransLateAccelerator返回非零值且消息已被翻譯,應(yīng)用程序就不能調(diào)用TranslateMessage函數(shù)對消息再做處理。每個加速鍵不一定都對應(yīng)于菜單命令。若加速鍵命令對應(yīng)于菜單項,則WM_INITMEMU和WM_INITMENUPOPUP消息將被發(fā)送到應(yīng)用程序,就好像用戶正試圖顯示該菜單。然而,如下的任一條件成立時,這些消息將不被發(fā)送:窗口被禁止,菜單項被禁止。
  加速鍵組合無相應(yīng)的窗口菜單項且窗口己被最小化。鼠標(biāo)抓取有效。有關(guān)鼠標(biāo)抓取消息,參看SetCapture函數(shù)。若指定的窗口為活動窗口且窗口無鍵盤焦點(當(dāng)窗口最小化時一般是這種情況), TranslateAccelerator 翻譯WM_SYSDEYUP和WM_SYSKEYDOWN消息而不是WM_KEYUP和WM_KEYDOWN消息。
  當(dāng)按下相應(yīng)于某菜單項的加速鍵,而包含該菜單的窗口又已被最小化時, TranslateAccelerator 不發(fā)送WM_COMMAND消息。但是,若按下與窗口菜單或某單項的任一項均不對應(yīng)的加速鍵時, TranslateAccelerator 將發(fā)送一WM_COMMAND消息,即使窗口己被最小化。
  Windows CE:所有的加速鍵消息被翻譯成WM_COMMAND消息;Windows CE不支持WM_SYSCOMMAND消息。
 
13.TranslateMessage
函數(shù)功能:該函數(shù)將虛擬鍵消息轉(zhuǎn)換為字符消息。字符消息被寄送到調(diào)用線程的消息隊列里,當(dāng)下一次線程調(diào)用函數(shù)GetMessage或PeekMessage時被讀出。
  函數(shù)原型:BOOL TranslateMessage(CONST MSG*lpMsg);
  IpMsg:指向含有消息的MSG結(jié)構(gòu)的指針,該結(jié)構(gòu)里含有用函數(shù)GetMessage或PeekMessage從調(diào)用線程的消息隊列里取得的消息信息。
  返回值:如果消息被轉(zhuǎn)換(即,字符消息被寄送到調(diào)用線程的消息隊列里),返回非零值。如果消息是WM_KEYDOWN,WM_KEYUP WM_SYSKEYDOWN或WM_SYSKEYUP,返回非零值,不考慮轉(zhuǎn)換。如果消息沒被轉(zhuǎn)換(即,字符消息沒被寄送到調(diào)用線程的消息隊列里),返回值是零。
  備注:此函數(shù)不修改由參數(shù)IpMsg指向的消息。
  WM_KEYDOWN和WM_KEYUP組合產(chǎn)生一個WM_CHAR或WM_DEADCHAR消息。
  WM_SYSKEYDOWN和WM_SYSKEYUP組合產(chǎn)生一個WM_SYSCHAR或 WM_SYSDEADCHAR消息。TranslateMessage為那些由鍵盤驅(qū)動器映射為ASCll字符的鍵產(chǎn)生WM_CHAR消息。
  如果應(yīng)用程序為其他用途處理虛擬鍵消息,不應(yīng)調(diào)用TranslateMessage。例如,如果件TranslateAccelerator返回一個非零值,應(yīng)用程序不應(yīng)調(diào)用TranslateMessage。
  Windows CE:Windows CE不支持掃描碼或擴展鍵標(biāo)志,因此,不支持由TranslateMessage產(chǎn)生的WM_CHAR消息中的IKeyData參數(shù)(IParam)取值16-24。
  TranslateMessage只能用于轉(zhuǎn)換調(diào)用GetMessage或PeekMessage接收的消息。
 
while (GetMessage(&msg, NULL, 0, 0))
{
  if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
  {
   TranslateMessage(&msg);
   MSG msg1;
   //從這里可以看出,該函數(shù)將WM_KEYDOWN消息轉(zhuǎn)換為WM_CHAR等消息
   //在消息隊列中只有WM_KEYDOWN消息的情況下就將其轉(zhuǎn)換為WM_CHAR了
   if(PeekMessage(&msg1,NULL,WM_CHAR,WM_CHAR,PM_NOREMOVE))
    MessageBox(NULL,"Find WM_CHAR Message","WM_CHAR",MB_OK);
   DispatchMessage(&msg);
  }
 }
 
14.DispatchMessage
函數(shù)功能:該函數(shù)分發(fā)一個消息給窗口程序。通常消息從GetMessage函數(shù)獲得。消息被分發(fā)到回調(diào)函數(shù)(過程函數(shù)),作用是消息傳遞給操作系統(tǒng),然后操作系統(tǒng)去調(diào)用我們的回調(diào)函數(shù),也就是說我們在窗體的過程函數(shù)中處理消息
  函數(shù)原型:LONG DispatchMessage(CONST MSG*lpmsg);
  參數(shù):
  lpmsg:指向含有消息的MSG結(jié)構(gòu)的指針。
  返回值:返回值是窗口程序返回的值。盡管返回值的含義依賴于被調(diào)度的消息,但返回值通常被忽略。
  備注:MSG結(jié)構(gòu)必須包含有效的消息值。如果參數(shù)lpmsg指向一個WM_TIMER消息,并且WM_TIMER消息的參數(shù)IParam不為NULL,則調(diào)用IParam指向的函數(shù),而不是調(diào)用窗口程序。
  速查:Windows NT:3.1及以上版本;Windows:95及以上版本;Windows CE:1.0及以上版本;頭文件:winuser.h;輸入庫:user32.lib;Unicode:在Windows NT環(huán)境下以Unicode和ANSI方式實現(xiàn)。
 
WM_NOTIF在WIN32中得到大量的應(yīng)用,同時也是隨著CommControl的出現(xiàn)WM_NOTIFY成為了CommControl的基本消息??梢赃@樣說CommControl的所有的新增特性都通過WM_NOTIFY來表達(dá)。同時WM_NOTIFY也為CommControl的操作帶來了一致性。 
WM_NOTIFY消息中的參數(shù)如下: 
idCtrl = (int) wParam; 
pnmh = (LPNMHDR) lParam; 其中l(wèi)Param為一個
typedef struct tagNMHDR 
{
HWND hwndFrom; //Window handle of Control Window
UINT idFrom;  //Control ID of Control Window

UINT code;  //Notification code
} NMHDR; 結(jié)構(gòu)指針
從消息的參數(shù)我們已經(jīng)可以分辯出消息的來源,但是這些信息還不足以分辯出消息的具體含義。所以我們需要更多的數(shù)據(jù)來得到更多的信息。MS的做法是對每種不同用途的通知消息都定義另一種結(jié)構(gòu)來表示,同時這中結(jié)構(gòu)里包含了struct tagNMHDR,所以你只要進(jìn)行一下類型轉(zhuǎn)換就可以得到數(shù)據(jù)指針。例如對于LVN_COLUMNCLICK消息(用于在ListCtrl的列表頭有鼠標(biāo)點擊是進(jìn)行通知),結(jié)構(gòu)為;
typedef struct tagNMLISTVIEW{
NMHDR hdr;
int iItem;
int iSubItem;
UINT uNewState;
UINT uOldState;
UINT uChanged;
POINT ptAction;
LPARAM lParam;
} NMLISTVIEW, FAR *LPNMLISTVIEW;
在這個結(jié)構(gòu)的最開始也就包含了struct tagNMHDR,所以在不損失數(shù)據(jù)和產(chǎn)生錯誤的情況下向處理消息的進(jìn)程提供了更多的信息。 
此外通過WM_NOTIFY我們可以一種完全一樣的方式進(jìn)行消息映射,如同在前幾章中所見到的一樣。 
使用如下形式:ON_NOTIFY( wNotifyCode, id, memberFxn )。 
處理函數(shù)也有統(tǒng)一的原型:afx_msg void memberFxn( NMHDR * pNotifyStruct, LRESULT * result ); 
在MFC消息映射的內(nèi)部將根據(jù)定義消息映射時所使用的wNotifyCode和WM_NOTIFY中參數(shù)中pnmh->code(pnmh = (LPNMHDR) lParam)進(jìn)行匹配,然后調(diào)用相應(yīng)的處理函數(shù)。 
還有一點是利用WM_NOTIFY/ON_NOTIFY_REFLECT可以在窗口內(nèi)部處理一些消息,從而建立可重用的控件。
ON_NOTIFY( LVN_KEYDOWN, IDC_LIST1, OnKeydownList1 )

在上面的例子里,ClassWizard提供的函數(shù)是:

void CMessageReflectionDlg::OnKeydownList1(NMHDR* pNMHDR, LRESULT* pResult)
{
LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR;
// TODO: Add your control notification handler
// code here

*pResult = 0;
}

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    丝袜诱惑一区二区三区| 亚洲国产日韩欧美三级| 91播色在线免费播放| 清纯少妇被捅到高潮免费观看| 麻豆视传媒短视频免费观看| 日韩免费国产91在线| 国产精品推荐在线一区| 高清欧美大片免费在线观看| 少妇人妻精品一区二区三区| 黄色国产自拍在线观看| 中文字幕一二区在线观看| 欧美国产在线观看精品| 91人人妻人人爽人人狠狠| 国产中文字幕久久黄色片| 色好吊视频这里只有精| 殴美女美女大码性淫生活在线播放| 最新日韩精品一推荐日韩精品| 午夜福利视频偷拍91| 蜜桃臀欧美日韩国产精品| 国产亚洲视频香蕉一区| 福利新区一区二区人口| 91亚洲人人在字幕国产| 亚洲av又爽又色又色| 欧美一区二区日韩一区二区| 成人精品日韩专区在线观看| 日韩一区二区免费在线观看 | 青青操日老女人的穴穴| 久热99中文字幕视频在线 | 欧美日韩国产欧美日韩| 91插插插外国一区二区| 精品少妇一区二区视频| 一二区中文字幕在线观看| 成人亚洲国产精品一区不卡| 日韩欧美中文字幕av| 精品一区二区三区三级视频| 伊人久久青草地综合婷婷| 又黄又硬又爽又色的视频 | 三级高清有码在线观看| 国产一级二级三级观看| 日本欧美三级中文字幕| 九九蜜桃视频香蕉视频|