怎樣將GIS圖形複製到Windows剪貼簿,粘貼到Word中
很久沒寫隨筆了,有點想關了這個部落格,不再更新,但還是沒有下定決心。趁這些天比較閑,發一個以前寫著玩的功能吧。
複製、粘貼功能是一件很簡單的事情,但怎樣將GIS圖形粘貼到word中呢?最簡單的思路還是將GIS圖形儲存為Image形式,發送到剪貼簿,再粘貼到Word。但如果Image格式採用柵格的格式,如BMP或JPEG,則粘貼後在Word中展開時,效果會受到影響,比較合適的格式是採用WMF或EMF這種向量的格式。將Visio格式複製到Word中時,可以看到就是這種效果,而且文字還是可以編輯的。好,下面我們就看看怎樣實現這個功能。
第一步當然是將圖形複製為一個MetaFile對象:
public Metafile GetGeometryMetafile(ISymbol pSymbol, IGeometry pGeometry)
{
//先擷取一個IDisplayTransformation對象
IDisplayTransformation pDisTrans = new DisplayTransformationClass();
IEnvelope pEnv = pGeometry.Envelope;
Rectangle rect = new Rectangle(0, 0, 500, 500);
tagRECT r;
r.left = rect.Left;
r.right = rect.Right;
r.bottom = rect.Bottom;
r.top = rect.Top;
pDisTrans.set_DeviceFrame(ref r);
pDisTrans.Bounds = pEnv;
pDisTrans.Resolution = 72;
pDisTrans.ReferenceScale = 1.0;
pDisTrans.ScaleRatio = 1;
//建立WMF
MemoryStream ms = new MemoryStream();
Graphics g = CreateGraphics();
IntPtr hdc = g.GetHdc();
Metafile mf = new Metafile(ms, hdc, new Rectangle(0,0,500,500),MetafileFrameUnit.Pixel, EmfType.EmfPlusDual);
g.ReleaseHdc(hdc);
g.Dispose();
g = Graphics.FromImage(mf);
g.FillRectangle(new SolidBrush(Color.White), new Rectangle(0, 0, 500, 500));
pSymbol.SetupDC((int)g.GetHdc(), pDisTrans);
pSymbol.Draw(pGeometry);
pSymbol.ResetDC();
g.ReleaseHdc();
g.DrawString("by watson", this.Font, new SolidBrush(Color.Blue), new PointF(20, 20));
g.Save();
g.Dispose();
return mf;
}
第二步:發送到剪貼簿:
IDataObject data = new DataObject();
data.SetData(DataFormats.MetafilePict, mf);
Clipboard.SetDataObject(data, true);
測試 .... 什麼,不成功??
估計是.net不支援將metafile格式複製到剪貼簿吧。
於是,用於搜尋引擎,搜尋一翻,在某國外論壇找到解決方案:
public class ClipboardMetafileHelper
{
[DllImport("user32.dll")]
static extern bool OpenClipboard(IntPtr hWndNewOwner);
[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);
// Metafile mf is set to an invalid state inside this function
static public bool PutEnhMetafileOnClipboard(IntPtr hWnd, Metafile mf)
{
bool bResult = false;
IntPtr hEMF, hEMF2;
hEMF = mf.GetHenhmetafile(); // invalidates mf
if (!hEMF.Equals(new IntPtr(0)))
{
hEMF2 = CopyEnhMetaFile(hEMF, new IntPtr(0));
if (!hEMF2.Equals(new IntPtr(0)))
{
if (OpenClipboard(hWnd))
{
if (EmptyClipboard())
{
IntPtr hRes = SetClipboardData(14 /**//*CF_ENHMETAFILE*/, hEMF2);
bResult = hRes.Equals(hEMF2);
CloseClipboard();
}
}
}
DeleteEnhMetaFile(hEMF);
}
return bResult;
}
}
調用PutEnhMetafileOnClipboard方法就可以了,
再測試....大功告成!
再看一看PutEnhMetafileOnClipboard中的代碼,比較特別的是CopyEnhMetaFile函數,將MetaFile在記憶體中複製一份,看來是.net中的metafile與Windows中的metafile格式有一定出入,windows剪貼簿不認識的緣故吧
來自:http://www.cnblogs.com/watsonyin/archive/2007/11/22/968651.html