MFC Window程式設計(第二版)精華濃縮筆記(三) (轉)

worldblog發表於2007-12-12
MFC Window程式設計(第二版)精華濃縮筆記(三) (轉)[@more@]

第三章、鍵盤和滑鼠

精華濃縮:

  鍵盤和滑鼠恐怕是用的人摸的最多的兩樣東西(當然,DIYer們除外),也正因為有很直觀的印象,要理解它們並不難。
  在中,鍵盤和滑鼠輸入是以訊息的形式出現的。首先,裝置接收並處理滑鼠和鍵盤中斷,透過中斷處理(ISR)把最初的電脈衝訊號轉換為識別的事件通知(就是訊息)放入系統訊息佇列中。核心有一個專門的執行緒(應該就是user32.dll)來系統訊息佇列,透過它把訊息分發到各應用程式執行緒訊息佇列中。以後,就是應用程式對訊息的檢索處理,在MFC開發中,就是第一章講到的訊息對映機制了。
  學習如何響應鍵盤和滑鼠的輸入關鍵是要了解該處理哪個訊息以及和處理相關的一些MFC和。
  滑鼠訊息首先分為兩大類,即客戶區訊息和非客戶區訊息。再按不同輸入動作,又細分為左(右、中)鍵單擊、雙擊和按下、彈起以及滑鼠移動訊息等。例如WM_LBUTTONDOWN, 表示這是客戶區滑鼠左鍵按下訊息,而WM_NCMBUTTONUP, 則表示這是非客戶區(Not Client)滑鼠中鍵彈起訊息。滑鼠事件和對應訊息的詳情可參考MSDN 。

  在MFC中,客戶區滑鼠訊息處理函式的原型為:
  afx_msg void OnMsgName(UINT nFlags,CPoint point)
其中,point指示當前游標位置,這個位置座標是以相對於視窗客戶區左上角的裝置座標而言的。如有必要,可用CDC::DPtoLP()將其轉換為邏輯座標。nFlags引數指出訊息生成時滑鼠鍵以及Shift和Ctrl的狀態。通常用於判斷滑鼠或鍵盤狀態,如 if(nFlags & MK_LBUTTON) ...。
  非客戶區訊息的處理函式原型為:
  afx_msg void OnMsgName(UINT nHitTest,CPoint point)
其中,point指示事件在視窗中發生的位置,但這個位置是螢幕座標。可用CWnd::ScreenToClient()把螢幕座標轉換為客戶區座標。nHitTest引數包含標識視窗非客戶區事件發生地方的命中測試碼。如HTCAPTION、HTCLOSE、HTSYSMENU等。可在WM_NCHITTEST或CWnd::OnNcHitTest()的幫助文件中找到完整的命中測試碼列表。實際應用與nFlags類似。
  滑鼠游標是滑鼠與之間的介面。我們知道,每個視窗都有相應的WNDCLASS, 其特性在WNDCLASS結構中定義。其中的hCursor欄位儲存了視窗型別游標的控制程式碼,該游標就是在視窗客戶區上的圖象。在滑鼠移動時,windows透過重畫游標的背景把游標從舊位置上清除。然後,它給游標下的視窗傳送包含命中測試碼的WM_SETCURSOR訊息。對此訊息系統的預設響應是::SetCursor()API函式。如果命中測試碼是HTCLIENT(即在客戶區中),則顯示設定的型別游標,否則顯示預設箭頭游標。游標將根據滑鼠移動時週期的捕獲命中測試碼自動。這個技巧也可以應用到其他圖象處理過程中。
  設定游標的方法總結:
  1.註冊WNDCLASS(如何註冊,在後面知識點部分有總結),並指定希望的游標型別為視窗類游標;
  2.或在OnSetCursor訊息處理函式中呼叫API函式::SetCursor()響應WM_SETCURSOR訊息。
 
  windows應用程式瞭解鍵盤事件的方式與瞭解滑鼠事件相同:都是透過訊息。鍵盤訊息只有三種,即
  WM_KEYDOWN  鍵盤按下
  WM_KEYUP  鍵盤抬起
  WM_CHAR  可列印字元鍵按下或抬起(這是為了簡化字元處理過程)
 
  windows總是把鍵盤訊息送到擁有輸入焦點的視窗。它用WM_SETFOCUS和WM_KILLFOCUS訊息通知即將通知接收或失去輸入焦點的視窗。CWnd::SetFocus()把輸入焦點轉移到另一個視窗;CWnd::GetFocus()用於找到當前用於輸入焦點的視窗,它的返回型別為CWnd。
  一個鍵盤處理函式會接收很多有關擊鍵的訊息,其中包括一個程式碼用來標識被按下或釋放的鍵值。原型如下:
  afx_msg void OnMsgName(UINT nChar,UINT nRepCnt,UINT nFlags)
 其中,nChar是被按下或釋放的鍵的虛擬鍵值,nRepCnt是重複次數,通常為1。nFlags引數包含鍵的掃描碼以及一些位標誌(詳情可參考MSDN)。
  和滑鼠與游標關聯一樣,與鍵盤有關的系統資源是插入符。但游標是全域性共享資源,而插入符是單執行緒共享資源,它被執行在同一執行緒上的所有視窗共享。
  插入符的使用有一些簡單規則:
  1.插入符應在接收到輸入焦點時建立,在失去輸入焦點時“銷燬”。相關函式有CreateCaret、CreateGrayCaret、::DestroyCaret等;
  2.直到呼叫ShowCaret才能使建立的插入符可見,而呼叫HCaret可將使其隱藏;
  3.呼叫SetCaretPos來移動插入符,永遠記住,控制插入符的移動是你自己的工作。對插入符位置的檢索可用GetCaretPos。
 

一些知識點:
1.自定義視窗型別:在MFC中,可以用全域性函式AfxRigisterWndClass註冊視窗型別。這需要初始化WNDCLASS結構中的欄位。AfxRigisterWndClass已為你自動填充了大多數字段,你一般只需要關心4個值。AfxRigisterWndClass的函式原型為:
  LPCTSTR AfxRigisterWndClass(UINT nClassStyle,HCURSOR hCursor=0,HBRUSH hbrBackground=0,HICON hIcon=0)
其中,nClassStyle指定視窗型別樣式(不是顯示型別),而是視窗允許的某種操作特性。如CS_OWNDC,表示由WNDCLASS建立的視窗均有自己的裝置描述表(DC);hCursor為由WNDCLASS建立的視窗標識“型別游標”。可透過AfxGetApp()->LoadStandardCursor(IDC_XXX)獲得;hbrBackground引數定義了視窗的預設背景顏色;最後一個引數hIcon指定windows用來在桌面上、工作列等地方代表應用程式的大、小圖示。
  在MFC中,呼叫此函式通常透過覆蓋PreCreateWindow虛擬函式完成。

2.一些非主流的滑鼠訊息:
1)WM_NCHITTEST訊息:視窗在接受一個客戶區或非客戶區滑鼠訊息之前,首先接收到游標的螢幕座標和WM_NCHITTEST訊息。windows一般預設處理它。一個使用OnNcHitTest處理函式的技巧是用HTCAPTION命中測試碼代替HTCLIENT,以建立一個可在客戶區拖動的視窗:
  UINT CMainWindow::OnNcHitTest(CPoint point)
  {
  UINT nHitTest = CFrameWnd::OnNcHitTest(point);
  if(nHitTest == HTCLIENT)
  nHitTest=HICAPTION;
  return nHitTest;
  }
2)WM_MOUSELEAVE和WM_MOUSEHOVER訊息:這兩個訊息可以使你知道滑鼠何時進入視窗或在視窗中移動了。與此相關的API函式是::TrackMouseEvent(),透過它,一個程式可以註冊,當游標離開視窗時接收WM_MOUSELEAVE訊息,而游標在視窗中停滯時接收WM_MOUSEHOVER訊息。::TrackMouseEvent()函式只有一個引數,是一個指向TRACKMOUSEEVENT結構的指標。
3)WM_MOUSEWHEEL訊息: windows的ON_WM_MOUSEWHEEL宏將WM_MOUSEWHEEL訊息對映到訊息處理函式OnMouseWheel,其原型為:
  BOOL OnMouseWheel(UINT nFlags,short zDelta,CPoint point)
其中,nFlags和point與其他滑鼠處理函式意義相同,zDelta的值等於WHEEL_DELTA(向前滾動一個增量)或-WHEEL_DELTA(向後滾動一個增量)。

3.滑鼠的捕獲:這通常用於“橡皮筋”畫圖操作中。用CWnd::SetCapture捕獲滑鼠,相應的用::ReleaseCapture釋放它。

 

 
 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-991561/,如需轉載,請註明出處,否則將追究法律責任。

相關文章