程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> 淺談在應用CRectTracker類的程序中響應WM_LBUTTONUP消息

淺談在應用CRectTracker類的程序中響應WM_LBUTTONUP消息

編輯:關於VC++

本文配套源碼

CRectTracker類也有人稱之為“橡皮筋”類。我們可以通過Windows自帶的畫圖板來了解這個類的作用:用“選定”功能在畫圖區隨意選中一塊兒區域,此時會出現一個由虛線和八個調整標記點組成的矩形選框,我們可通過鼠標點中矩形選框的中心移動其位置,並且能利用調整標記 點來改變其大小……這個矩形選框其實就是一個“橡皮筋選框”。

CRectTracker類的使用並不是什麼新鮮的話題,然而在應用這個類的過程中,我卻發現了一個小問題:我創建了一個對話框程序,希望利用CRectTracker類在對話框上畫出一個“橡皮筋選框 ”,為了使鼠標按下並拖動鼠標的同時出現虛線的選擇框,我在程序中加入了以下代碼:

void CCRectTracker_DemoDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
  // TODO: Add your message handler code here and/or call default
  //當鼠標左鍵按 下時
  CRectTracker temp;
  temp.TrackRubberBand(this,point,TRUE);
   temp.m_rect.NormalizeRect();

  CDialog::OnLButtonDown(nFlags, point);
}

這段代碼確實實現了我所期望的效果。但在程序的另一個地方:

void CCRectTracker_DemoDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
  // TODO: Add your message handler code here and/or call default
  //當鼠標左鍵松開時
   MessageBox("鼠標左鍵松開","松開",NULL);

   CDialog::OnLButtonUp(nFlags, point);
}

OnLButtonUp()事件絲毫不理睬我鼠標的動 作——MessageBox()並沒有執行。仔細一想:TrackRubberBand()是以鼠標左鍵的松開作為結 束標志的,當WM_LBUTTONUP消息發出後,TrackRubberBand()在OnLButtonUp()事件響應前就截獲了該消 息,所以OnLButtonUp()事件就無法正常響應了……想到這裡,腦海中也就浮現了一個解決 這個小問題的辦法,那就是:在TrackRubberBand()後,向程序自身發送一個自己構造的WM_LBUTTONUP消 息。於是將OnLButtonDown()中的代碼改寫成為以下形式:

void CCRectTracker_DemoDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
  // TODO: Add your message handler code here and/or call default
  //當鼠標左鍵按下時
   CRectTracker temp;
  temp.TrackRubberBand(this,point,TRUE);
   temp.m_rect.NormalizeRect();
  //自己構造的WM_LBUTTONUP消息
  this- >SendMessage(WM_LBUTTONUP,NULL,NULL);
  CDialog::OnLButtonDown(nFlags, point);
}

測試後的結果另人滿意,現在我所遇到的問題迎刃而解了。在本文附帶的Demo程序中,程 序分別獲取鼠標左鍵按下和松開時的坐標,然後調用修改後的OnPaint()來畫出“橡皮筋矩形 ”,下面給出Demo中的部分關鍵代碼:

BOOL CCRectTracker_DemoDlg::OnSetCursor (CWnd* pWnd, UINT nHitTest, UINT message)
{
  // TODO: Add your message handler code here and/or call default
  //////////////////////
  //改變光標的形狀
  if (pWnd == this && m_rectTracker.SetCursor(this, nHitTest))
     return TRUE;
  //////////////////////
  else
    return CDialog::OnSetCursor(pWnd, nHitTest, message);
}
void CCRectTracker_DemoDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
  // TODO: Add your message handler code here and/or call default
   ///////////////////////////////////////
  //如鼠標點擊位置不在選框區域內,則構造一 個新選框
  Invalidate(TRUE);
  if(m_rectTracker.HitTest(point)<0)
   {
    IsLButtonDown=TRUE;
    CRectTracker temp;
     temp.TrackRubberBand(this,point,TRUE);
    temp.m_rect.NormalizeRect();

    //鼠標(矩形選框)起始位置
    pt_start=point;
    //鼠標(矩形 選框)結束位置
    GetCursorPos(&pt_end);
    this->SendMessage (WM_LBUTTONUP,NULL,NULL);
  }
  //否則重置選框大小或位置
  else
  {
    m_rectTracker.Track(this,point,TRUE);
     m_rectTracker.m_rect.NormalizeRect();
    this->OnPaint();
  }
   ///////////////////////////////////////

  CDialog::OnLButtonDown(nFlags, point);
}
void CCRectTracker_DemoDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
  // TODO: Add your message handler code here and/or call default
   /////////////////////////////////
  //確保在構造一個新選框時才響應OnLButtonUp,否 則在響應OnLButtonDblClk時會出現錯誤結果
  if(IsLButtonDown==TRUE)
  {
     //MessageBox("鼠標左鍵松開","松開",NULL);

    //由 於GetCursorPos獲得的pt_end是Screen坐標,故用ScreenToClient()進行轉換
     rect.right=pt_end.x;
    rect.bottom=pt_end.y;
    ScreenToClient (&rect);
    pt_end.x=rect.right;
    pt_end.y=rect.bottom;

    //left,top,right,bottom
    m_rectTracker.m_rect.SetRect (pt_start.x,pt_start.y,pt_end.x,pt_end.y);
    m_rectTracker.m_rect.NormalizeRect ();

    this->OnPaint();
    IsLButtonDown=FALSE;
  }
  /////////////////////////////////

  CDialog::OnLButtonUp(nFlags, point);
}
void CCRectTracker_DemoDlg::OnLButtonDblClk(UINT nFlags, CPoint point)
{
  // TODO: Add your message handler code here and/or call default
   ////////////////////////////
  MessageBox("鼠標左鍵雙擊","雙擊 ",NULL);
  ////////////////////////////

   CDialog::OnLButtonDblClk(nFlags, point);
}

由於本人水平所限,關於CRectTracker 類的詳細使用方法請參閱其他資料。謝謝!

附:

以上代碼在Win2000P+SP4/Win98se + VC6+SP6測試通過。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved