在office上選取物件利用ctrl+c複製物件到clipboard內,
並在picturebox控制項上利用ctrl+v將物件從clipboard取出,
並以圖片形式顯示在picturebox上,
最後將picturebox上的image存成圖片檔。
首先先記錄一下如何判斷鍵盤的組合鍵,如下:
private void Form1_KeyDown(object sender, KeyEventArgs e) { switch (e.KeyData) { case (Keys.Control | Keys.V): // do something break; } }
接下來的重點是從clipboard內取出物件時必須知道它支援那些格式,
我們可以利用下面的方式知道該物件所支援的格式有那些:
foreach (string format in Clipboard.GetDataObject().GetFormats()) { // do something }也有一些簡便的方式,例如Clipboard.ContainsText()或Clipboard.ContainsImage()等可以判斷。
再來我們準備一些method來從clipboard中取出office中大部份常見的格式。
Bitmap格式的物件,我們都能用下面的方式取得image:
public void CatchBitmap() { this.pictureBox1.Image = (Bitmap)Clipboard.GetImage(); }
這裡遇到比較麻煩的困難點是EnhancedMetafile格式,
必須要用win32裡的API去取得系統的clipboard來使用,方式如下:
public const uint CF_METAFILEPICT = 3; public const uint CF_ENHMETAFILE = 14; [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] public static extern bool OpenClipboard(IntPtr hWndNewOwner); [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] public static extern bool CloseClipboard(); [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] public static extern IntPtr GetClipboardData(uint format); [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] public static extern bool IsClipboardFormatAvailable(uint format); public void CatchEMF() { if (OpenClipboard(this.Handle)) { if (IsClipboardFormatAvailable(CF_ENHMETAFILE)) { IntPtr ptr = GetClipboardData(CF_ENHMETAFILE); if (!ptr.Equals(new IntPtr(0))) { Metafile metafile = new Metafile(ptr, true); //Set the Image Property of PictureBox this.pictureBox1.Image = metafile; } } CloseClipboard(); } }
再來如果copy放進clipboard內的是純文字物件的話,
就必須要用Graphics來drawing string才能產生圖檔,如下:
public void DrawString() { String sImageText = Clipboard.GetText(); Bitmap objBmpImage = new Bitmap(1, 1); int intWidth = 0; int intHeight = 0; // Create the Font object for the image text drawing. Font objFont = new Font("Arial", 20, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Pixel); // Create a graphics object to measure the text's width and height. Graphics objGraphics = Graphics.FromImage(objBmpImage); // This is where the bitmap size is determined. intWidth = (int)objGraphics.MeasureString(sImageText, objFont).Width; intHeight = (int)objGraphics.MeasureString(sImageText, objFont).Height; // Create the bmpImage again with the correct size for the text and font. objBmpImage = new Bitmap(objBmpImage, new Size(intWidth, intHeight)); // Add the colors to the new bitmap. objGraphics = Graphics.FromImage(objBmpImage); // Set Background color objGraphics.Clear(Color.White); objGraphics.SmoothingMode = SmoothingMode.AntiAlias; objGraphics.TextRenderingHint = TextRenderingHint.AntiAlias; objGraphics.DrawString(sImageText, objFont, new SolidBrush(Color.FromArgb(102, 102, 102)), 0, 0); objGraphics.Flush(); this.pictureBox1.Image = objBmpImage; }
接下來下面要講解的功能是如何把在excel內選取的cells自動轉換成對應的chart圖,
基本上複製的cells放進clipboard本身就支援Bitmap格式,
但直接取用會直接像剪貼那樣,如果要轉換成對應的chart圖則必須再行判斷,
這裡是利用Microsoft.Office.Interop.Excel來轉換,範例碼如下:
public void Convert() { IDataObject iData = Clipboard.GetDataObject(); String cellArea = (String)iData.GetData(DataFormats.Text); String[] rows = cellArea.Split(new Char[] { '\n' }); Excel.Application xlApp; Excel.Workbook xlWorkBook; Excel.Worksheet xlWorkSheet; object misValue = System.Reflection.Missing.Value; xlApp = new Excel.ApplicationClass(); xlWorkBook = xlApp.Workbooks.Add(misValue); xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1); int rowLength = rows.Length; int rowCount = 1; int cellCount = 1; int maxCellCount = 1; foreach (String line in rows) { if (rowCount == rowLength) { break; } String[] cells = line.Split(null); int cellLength = cells.Length; foreach (String cell in cells) { if (cellCount == cellLength) { break; } if (cellCount > maxCellCount) { maxCellCount++; } xlWorkSheet.Cells[rowCount, cellCount] = cell; cellCount++; } rowCount++; cellCount = 1; } Excel.Range chartRange; Excel.ChartObjects xlCharts = (Excel.ChartObjects)xlWorkSheet.ChartObjects(Type.Missing); Excel.ChartObject myChart = (Excel.ChartObject)xlCharts.Add(10, 80, 300, 250); Excel.Chart chartPage = myChart.Chart; rowCount--; maxCellCount--; String endCorner = map.ElementAt(maxCellCount).Value; endCorner = endCorner + rowCount.ToString(); // endCorner的格式例如:c7,就是cells右下角的範圍邊界點 chartRange = xlWorkSheet.get_Range("A1", endCorner); chartPage.SetSourceData(chartRange, misValue); // 設定繪製的chart圖型式 chartPage.ChartType = Excel.XlChartType.xlColumnClustered; chartPage.CopyPicture(Excel.XlPictureAppearance.xlScreen, Excel.XlCopyPictureFormat.xlBitmap, Excel.XlPictureAppearance.xlScreen); xlWorkBook.Close(false, false, misValue); }產生的chart圖會利用copy放進clipboard內。
使用畫面如下,紅色框部份就是被選取的cells,當在picturebox上按下ctrl+v時,
就會利用office元件繪製chart圖:
最後就是整理一些條件判斷式,來處理當遇到什樣格式時要執行那一個method比較恰當:
// 一般的圖檔 if (this.formatList.Contains("Bitmap") && !this.formatList.Contains("Text")) { CatchBitmap(); } // excel的cells欄位集合 else if (this.formatList.Contains("Bitmap") && this.formatList.Contains("Text")) { // if want to create chart Convert(); // offic 2003 CatchBitmap(); // offic 2007 CatchEMF(); } // 純粹選取文字 else if (!this.formatList.Contains("Bitmap") && this.formatList.Contains("Text")) { DrawString(); } // excel2003的chart,只有emf格式,最後再處理 else if (this.formatList.Contains("EnhancedMetafile")) { CatchEMF(); }