C# 擁有豐富的類別庫,但涉及底層視窗繪圖、螢幕擷取等作業時,仍需透過 P/Invoke 呼叫 Windows API。本文詳細說明如何使用 GDI32.dll 的 BitBlt 函數,結合 System.Drawing 命名空間,實作一個完整的螢幕截圖工具。
System.Runtime.InteropServices、System.Drawing、System.Windows.FormsBitBlt 為 GDI 核心位元區塊傳輸函數,簽名如下:
[DllImport("gdi32.dll")]
private static extern bool BitBlt(
IntPtr hdcDest, // 目標裝置內容控制代碼
int nXDest, // 目標矩形左上角 X
int nYDest, // 目標矩形左上角 Y
int nWidth, // 寬度
int nHeight, // 高度
IntPtr hdcSrc, // 來源裝置內容控制代碼
int nXSrc, // 來源矩形左上角 X
int nYSrc, // 來源矩形左上角 Y
int dwRop // 光柵操作代碼(SRCCOPY = 13369376)
);
Rectangle rect = Screen.GetWorkingArea(this);
int width = rect.Width;
int height = rect.Height;
Graphics gScreen = this.CreateGraphics();
Image screenImage = new Bitmap(width, height, gScreen);
Graphics gBitmap = Graphics.FromImage(screenImage);
IntPtr hdcSrc = gScreen.GetHdc(); // 螢幕 DC
IntPtr hdcDest = gBitmap.GetHdc(); // Bitmap DC
BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, 13369376); // SRCCOPY
gScreen.ReleaseHdc(hdcSrc);
gBitmap.ReleaseHdc(hdcDest);
screenImage.Save(@"C:\Capture.jpg", ImageFormat.Jpeg);
// 亦可改為 ImageFormat.Bmp、ImageFormat.Gif、ImageFormat.Png 等
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
using System.Runtime.InteropServices;
public class ScreenCaptureForm : Form
{
private Button btnCapture;
[DllImport("gdi32.dll")]
private static extern bool BitBlt(
IntPtr hdcDest, int nXDest, int nYDest,
int nWidth, int nHeight,
IntPtr hdcSrc, int nXSrc, int nYSrc,
int dwRop);
public ScreenCaptureForm()
{
InitializeComponent();
}
private void InitializeComponent()
{
btnCapture = new Button
{
Location = new Point(64, 40),
Size = new Size(80, 32),
Text = "擷取螢幕",
TabIndex = 0
};
btnCapture.Click += BtnCapture_Click;
ClientSize = new Size(216, 125);
Controls.Add(btnCapture);
Text = "C# 螢幕截圖示範";
MaximizeBox = false;
MinimizeBox = false;
}
private void BtnCapture_Click(object sender, EventArgs e)
{
Rectangle rect = Screen.GetWorkingArea(this);
using (Graphics gScreen = this.CreateGraphics())
using (Image img = new Bitmap(rect.Width, rect.Height, gScreen))
using (Graphics gBitmap = Graphics.FromImage(img))
{
IntPtr hdcSrc = gScreen.GetHdc();
IntPtr hdcDest = gBitmap.GetHdc();
try
{
BitBlt(hdcDest, 0, 0, rect.Width, rect.Height, hdcSrc, 0, 0, 13369376);
}
finally
{
gScreen.ReleaseHdc(hdcSrc);
gBitmap.ReleaseHdc(hdcDest);
}
string path = @"C:\Capture.jpg";
img.Save(path, ImageFormat.Jpeg);
MessageBox.Show($"螢幕已儲存至 {path}");
}
}
[STAThread]
static void Main() => Application.Run(new ScreenCaptureForm());
}
Screen.AllScreens 列舉所有螢幕,計算虛擬桌面總範圍。SetProcessDpiAwareness 避免縮放模糊。Desktop Duplication API (Windows 8+) 或 DirectX。Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)。透過 BitBlt 結合 GDI+,C# 即可輕鬆實作螢幕截圖。關鍵在於正確管理 HDC 生命週期(GetHdc/ReleaseHdc 配對),並善用 using 區塊確保資源釋放。此技術同樣適用於視窗截圖、遊戲畫面擷取等進階場景。