首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

模擬 QQ 截圖功能:全螢幕覆蓋與橡皮筋選取完整實作

     編輯:關於VC++

QQ 的截圖工具體驗極佳:全螢幕半透明遮罩、滑鼠拖曳選取區域、即時顯示座標與尺寸、支援鍵盤微調。本文完整拆解其核心架構,並提供 MFC 對話框為基礎的實作範例。

整體架構:全螢幕無框對話框 + 桌面截圖當背景

  1. 建立無標題、無邊框、置頂的全螢幕對話框,覆蓋整個桌面。
  2. 啟動時截取全螢幕畫面(CopyScreenToBitmap),存在 CBitmap 中。
  3. OnEraseBkgnd 將該位圖繪製到對話框客戶區,使用者看到的彷彿就是真實桌面。
  4. 利用 CRectTracker 繪製「橡皮筋」選取框,並攔截滑鼠/鍵盤訊息實作拖曳、縮放、微調。
  5. 選取完成後,將對應區域的位圖複製到剪貼板或存檔。

關鍵步驟與程式碼重點

1. 初始化:截圖、建立 Tracker、設定游標

CCatchScreenDlg::CCatchScreenDlg()
{
    // 橡皮筋樣式:實線、可內部縮放
    m_rectTracker.m_nStyle = CRectTracker::resizeInside | CRectTracker::solidLine;
    m_rectTracker.m_rect.SetRect(-1, -1, -1, -1);
    m_hCursor = AfxGetApp()->LoadCursor(IDC_CURSOR1);

    // 取得螢幕解析度
    m_xScreen = GetSystemMetrics(SM_CXSCREEN);
    m_yScreen = GetSystemMetrics(SM_CYSCREEN);

    // 截取全螢幕到位圖
    CRect rect(0, 0, m_xScreen, m_yScreen);
    m_pBitmap = CBitmap::FromHandle(CopyScreenToBitmap(&rect));

    // 區域更新用
    m_rgn.CreateRectRgn(0, 0, 50, 50);
}

2. OnInitDialog:設定全螢幕置頂

BOOL CCatchScreenDlg::OnInitDialog()
{
    CDialog::OnInitDialog();
    SetWindowPos(&wndTopMost, 0, 0, m_xScreen, m_yScreen, SWP_SHOWWINDOW);
    // 將提示編輯框移至左上角
    CRect rc; m_tipEdit.GetWindowRect(&rc);
    m_tipEdit.MoveWindow(10, 10, rc.Width(), rc.Height());
    DrawTip(); // 顯示操作提示
    return TRUE;
}

3. OnEraseBkgnd:以桌面位圖填充背景

BOOL CCatchScreenDlg::OnEraseBkgnd(CDC* pDC)
{
    CDC dcMem; dcMem.CreateCompatibleDC(pDC);
    CBitmap* pOld = dcMem.SelectObject(m_pBitmap);
    pDC->BitBlt(0, 0, m_xScreen, m_yScreen, &dcMem, 0, 0, SRCCOPY);
    dcMem.SelectObject(pOld);
    return TRUE; // 已自行處理背景,阻止預設擦除
}

4. 自訂 CTracker 消除虛線框閃爍

繼承 CRectTracker,覆寫 DrawTrackerRect 直接 InvalidateRgn 更新區域,避免預設 XOR 繪圖造成的殘影。

5. 提示視窗 CMyEdit:滑鼠移動時在左右上角切換位置

void CMyEdit::OnMouseMove(UINT nFlags, CPoint point)
{
    CRect rc; GetWindowRect(&rc);
    int xScreen = GetSystemMetrics(SM_CXSCREEN);
    if (m_bMove) { MoveWindow(10, 10, rc.Width(), rc.Height()); m_bMove = FALSE; }
    else         { MoveWindow(xScreen - 180, 10, rc.Width(), rc.Height()); m_bMove = TRUE; }
    CEdit::OnMouseMove(nFlags, point);
}

6. 即時顯示座標與尺寸 DrawMessage

根據滑鼠位置動態計算文字區域,遇到螢幕邊緣自動翻轉,確保資訊框永遠可見。

7. 區域更新 PaintWindow:排除提示框避免閃爍

void CCatchScreenDlg::PaintWindow()
{
    CRect rcDlg, rcTip; GetWindowRect(&rcDlg); m_tipEdit.GetWindowRect(&rcTip);
    CRgn rgnAll, rgnTip, rgnDiff;
    rgnAll.CreateRectRgnIndirect(&rcDlg);
    rgnTip.CreateRectRgnIndirect(&rcTip);
    rgnDiff.CombineRgn(&rgnAll, &rgnTip, RGN_DIFF); // 差集 = 全螢幕 - 提示框
    InvalidateRgn(&rgnDiff);
}

8. 鍵盤微調:ProcessMessageFilter 攔截方向鍵

在 CWinApp 衍生類別中覆寫 ProcessMessageFilter,檢查 WM_KEYDOWN 與 VK_SHIFT 組合,決定移動整個選框或單邊縮放,並呼叫 PaintWindow 重繪。

完成功能清單

  • 全螢幕半透明遮罩效果(實為桌面截圖覆蓋)
  • 滑鼠拖曳選取、八向縮放手柄
  • 即時顯示左上角座標、寬高、滑鼠座標
  • 方向鍵微調位置(Shift+方向鍵 = 縮放單邊)
  • Enter/雙擊確認、Esc/右鍵取消、Ctrl+C 複製到剪貼板
  • 操作提示浮動視窗自動避開滑鼠

原始碼結構說明

專案包含:CCatchScreenApp(訊息過濾)、CCatchScreenDlg(主邏輯)、CTracker(橡皮筋)、CMyEdit(提示框)、CopyScreenToBitmap(螢幕截圖工具函式)。所有繪圖均使用 GDI,無需 DirectX/OpenGL,相容性極佳。

掌握「全螢幕截圖當背景 + 區域更新 + Tracker 選取」這套模式,即可快速開發專業級截圖工具。完整原始碼請參考文章附件。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved