程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> QQ靜態截圖完善實現之改造CRectTracker類

QQ靜態截圖完善實現之改造CRectTracker類

編輯:關於VC++

由於前次寫的代碼過於倉促(相關文章參見:“QQ 靜態截圖程序模擬實現”),還沒仔細修改就投稿了,在這裡向大家表示道歉,可能你覺得這種程序不值的一看,但我本著精益求精的態度,還是把它完善了一下,更重要的是深入了解CRectTracer類的內部機制,以能更靈活和使用該類 ,在此我把MFC的CRectTracker類源碼,提取出來做了小小的改造,有興趣的朋友還可能更深入的增加更 多的功能。

本文主要講述三個問題:

程序中操作提示窗口文本更新閃爍問題;

程序在調整截取矩形大小和位置時,主窗口收不到消息;

CRectTracker類的簡要說明和改造類 CMyTracker;

圖一 示列

一、操作提示窗口是一個編輯框控件,刷新時由 於整個文本刷新,所以會有很難看的閃爍,而其實只有上面的RGB值在變化,那麼就

只要更新RGB 值的文本就可以了,由於CEdit中沒有更改指定文本內容的成員方法,在這裡有一個巧妙的方法來實現, 用CEdit的成員方法 SetSel選中要更改的RGB文本字符,然後用ReplaceSel就可以把選中的文本替換,從 而達到不用更新整個文本,面造極度成閃爍。

程序代碼如下:

void CCatchScreenDlg::ChangeRGB()
{
  //保存舊的RGB值字符串
    static CString strOld("");
  CPoint pt;
  GetCursorPos(&pt);
   //當到當前R,G,B,各像素值
  COLORREF color;
  CClientDC dc(this);
   color=dc.GetPixel(pt);
  BYTE rValue,gValue,bValue;
  rValue=GetRValue (color);
  gValue=GetGValue(color);
  bValue=GetGValue(color);

   //按格式排放字符串
  CString string;
  string.Format("(%d,%d,%d) ",rValue,gValue,bValue);
  //如果當前顏色沒變則不刷新RGB值,以免窗口有更多閃爍
  if(strOld!=string)
  {
    //得到RGB文本那一行的文本長度
     int LineLength=m_tipEdit.LineLength(6);
    //復選RGB值文本,也就是選中 (255,255,255)樣式
    m_tipEdit.SetSel(20,LineLength+6);

    //替換 RGB內容
    m_tipEdit.ReplaceSel(string);
  }
  //保存RGB值字符串
  strOld=string;
}
程序中存在硬編碼,但只要知道就行了!!

二、程序在調整大小和位置時,主窗口收不到消息,這是由於CRectTracker內部處處理了消息,看一下 CRectTracker::TrackHandle的MFC源碼 :

// get messages until capture lost or cancelled/accepted
for (;;)
{
 MSG msg;
 VERIFY (::GetMessage(&msg, NULL, 0, 0));

 if (CWnd::GetCapture() != pWnd)
  break;
 //增加的,把消息派送給窗口
 DispatchMessage(&msg);
 switch (msg.message)
 {
 // handle movement/accept messages
  case WM_LBUTTONUP:
 case WM_MOUSEMOVE:
  rectOld = m_rect;
  // handle resize cases (and part of move)
  if (px != NULL)
   *px = (int) (short)LOWORD(msg.lParam) - xDiff;
  if (py != NULL)
   *py = (int)(short)HIWORD(msg.lParam) - yDiff;
  // handle move case
  if (nHandle == hitMiddle)
  {
   m_rect.right = m_rect.left + nWidth;
   m_rect.bottom = m_rect.top + nHeight;
 }
 // allow caller to adjust the rectangle if necessary
 AdjustRect(nHandle, &m_rect);
 // only redraw and callback if the rect actually changed!
 m_bFinalErase = (msg.message == WM_LBUTTONUP);
  if (!rectOld.EqualRect(&m_rect) || m_bFinalErase)
  {
   if (bMoved)
   {
    m_bErase = TRUE;
    DrawTrackerRect(&rectOld, pWndClipTo, pDrawDC, pWnd);
   }
   OnChangedRect(rectOld);
   if (msg.message != WM_LBUTTONUP)
   {
    bMoved = TRUE;
   }
  }
  if (m_bFinalErase)
    goto ExitLoop;
  if (!rectOld.EqualRect(&m_rect))
   {
    m_bErase = FALSE;
    DrawTrackerRect (&m_rect, pWndClipTo, pDrawDC, pWnd);
   }
   break;
 // handle cancel messages
 case WM_KEYDOWN:
  if (msg.wParam != VK_ESCAPE)
   break;
 case WM_RBUTTONDOWN:
  if (bMoved)
   {
    m_bErase = m_bFinalErase = TRUE;
    //DrawTrackerRect(&m_rect, pWndClipTo, pDrawDC, pWnd);
   }
   m_rect = rectSave;
   goto ExitLoop;
 // just dispatch rest of the messages
 default:
  DispatchMessage(&msg);
  break;
 }
}

我們只要在GetMessage(&msg, NULL, 0, 0)之後調用DispatchMessage(&msg),就可以把消息傳遞到 主窗口,這樣,內部處理和主窗口消息兩不誤,進而為程序為CRectTrakcer不能響應WM_LBUTTONUP和其消 息而不用大改程序了...

三、CRectTracker類的簡要說明和改造類CMyTracker, CMyTracker類中增加 了更改矩形顏色方法,增加StyleFlags的resizeMiddle設置中間位置,增加SetResizeCursor方法用開改 變調整矩形大小和位置時鼠標光標,CRectTracker類中有幾個重要的成員方法,一個是Draw方法負責畫出 當前矩形,在此方法中可能更改矩形顏色,看如下代碼

// draw lines
if ((m_nStyle & (dottedLine|solidLine)) != 0)
{
 if (m_nStyle & dottedLine)
 {
  //改變當前矩形顏色 ,點線
  pOldPen = pDC->SelectObject(CPen::FromHandle(_afxBlackDottedPen));
 }
 else
 {
  //改變當前矩形顏色 ,實線
  //pOldPen = (CPen*)pDC->SelectStockObject(BLACK_PEN);
  pOldPen = pDC- >SelectObject(CPen::FromHandle(_afxBlackSolidPen));
 }
 pOldBrush = (CBrush*)pDC->SelectStockObject(NULL_BRUSH);
 nOldROP = pDC- >SetROP2(R2_COPYPEN);
 rect.InflateRect(+1, +1);  // borders are one pixel outside
 pDC->Rectangle(rect.left, rect.top, rect.right, rect.bottom);
 pDC->SetROP2(nOldROP);
}

其中_afxBlackSolidPen是我增加的全局 畫筆句柄,在初始化時創建,通過增加的SetRectColor方法可以改變顏色, 修改了矩形顏色,當然還得 修改調整矩形手柄了,也就是那八個點,修改代碼處如下:if ((m_nStyle & (resizeInside|resizeOutside)) != 0)
{
 UINT mask = GetHandleMask();
 for (int i = 0; i < 8; ++i)
 {
  GetHandleRect ((TrackerHit)i, &rect);
  //改變當前調整手柄矩形顏色,也就是那八個點
  pDC->FillSolidRect(rect, m_rectColor);
 }
}

其次是Track方法和TrackRubberBand方法,在其內部主要是調用TrackHandle方法,在Tracker方法中 主要是消息捕獲處理,動態調整當前 m_rect 矩形大小,和在調整大小和位置時畫出虛線,當然畫虛線 功能是在DrawTrackerRect方法中實現,在此方法中主要是調用CDC類中的DrawDragRect方法,至使動態 畫虛線時不用刷新窗口.程序中由於不需要畫虛線所以把DrawTrackerRect方法中代碼注釋了,直接更新主窗口,如果需要原來的功能,可能把注釋去掉,在CRectTracker類中還有一些輔助方法,在這就 不一一講說。

四、CMyTracker類從MFC源文件COPY過來,頭文件在AFXEXT.H中,實現文件為 TRCKRECT.CPP,COPY時去掉了一些調試信息,類的無參數構造

函數定義為內聯函數,是在 AFXEXT.INL中實現,在構造函數中調用類中初始化函數Construct(),可以直接在實現文件中加入無參數 構造函

的實現,直接調用函數Construct(),其實這些簡單的功能只要直接修改MFC源代碼,程序 調試完成後再改回來,但這樣不能很好的通用,有些朋友認為微軟的MFC源碼神聖不可侵犯,但是為了程 序的性能和功能,就要不擇手段。

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