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

WinForms 控制項匯出矢量圖完整指南:EMF 格式與 GDI+ 繪圖表面實戰

     編輯:關於.NET

為什麼需要矢量圖?

Control.DrawToBitmap 僅能產生點陣圖,缺點明顯:檔案大、放大失真、難編輯。Windows Metafile (WMF/EMF) 記錄 GDI 命令序列,重播即可無損重建,適合文檔嵌入、報表輸出、設計編輯。

核心步驟:建立 EMF 繪圖表面

// 1. 取得螢幕 DC 建立 EMF 檔案
Graphics g1 = control.CreateGraphics();
IntPtr hdc = g1.GetHdc();
Metafile mf = new Metafile(hdc,
    new Rectangle(0, 0, control.Width, control.Height),
    MetafileFrameUnit.Pixel, EmfType.EmfOnly);
g1.ReleaseHdc(hdc);
g1.Dispose();

// 2. 從 EMF 建立 Graphics 物件
Graphics g2 = Graphics.FromImage(mf);

關鍵技術:WM_PRINT 訊息列印控制項樹

WinForms 控制項透過 OnPaint 繪製。使用 SendMessage 發送 WM_PRINT 讓控制項及其子控制項繪製到指定 Graphics(即 EMF 表面)。

const int WM_PRINT = 0x0317;
const int PRF_CHILDREN = 0x10, PRF_CLIENT = 0x04, 
          PRF_ERASEBKGND = 0x08, PRF_NONCLIENT = 0x02;

[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(HandleRef hWnd, int msg, IntPtr wParam, IntPtr lParam);

public static void DrawControl(Control control, Graphics g) {
    if (!control.Created) control.CreateControl();
    IntPtr hDc = g.GetHdc();
    SendMessage(new HandleRef(control, control.Handle), WM_PRINT, hDc,
        (IntPtr)(PRF_CHILDREN | PRF_CLIENT | PRF_ERASEBKGND | PRF_NONCLIENT));
    g.ReleaseHdc(hDc);
}

進階:將 EMF 複製到剪貼簿

支援直接貼上到 Word、Excel、CorelDRAW 等軟體編輯:

[DllImport("user32.dll")] static extern bool OpenClipboard(IntPtr hWnd);
[DllImport("user32.dll")] static extern bool EmptyClipboard();
[DllImport("user32.dll")] static extern IntPtr SetClipboardData(uint uFormat, IntPtr hMem);
[DllImport("user32.dll")] static extern bool CloseClipboard();
[DllImport("gdi32.dll")] static extern IntPtr CopyEnhMetaFile(IntPtr hemfSrc, IntPtr hNULL);
[DllImport("gdi32.dll")] static extern bool DeleteEnhMetaFile(IntPtr hemf);

public static bool PutEnhMetafileOnClipboard(IntPtr hWnd, Metafile mf) {
    IntPtr hEMF = mf.GetHenhmetafile(); // 使 mf 失效
    IntPtr hEMF2 = CopyEnhMetaFile(hEMF, IntPtr.Zero);
    bool result = false;
    if (OpenClipboard(hWnd)) {
        if (EmptyClipboard()) {
            IntPtr hRes = SetClipboardData(14 /*CF_ENHMETAFILE*/, hEMF2);
            result = hRes == hEMF2;
            CloseClipboard();
        }
    }
    DeleteEnhMetaFile(hEMF);
    return result;
}

實際效果

  • 無限放大不失真
  • 文字可編輯、可搜尋
  • 檔案體積遠小於高解析度點陣圖

此技術適用於報表產生器、UI 文檔自動化、設計工具整合等場景,讓 WinForms 介面無縫融入矢量工作流。

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