2009年10月17日 星期六

小心使用.NET的Clipboard物件

clipboard

最近在開發電子書的時候,因為用了Adobe的OLE元件,所以也看了許多這方面的SDK資料。前兩天我一直在測試一個功能,就是將Adobe擷取出來的screenshot,複製到clipboard(就是剪貼簿啦),舊程式都是可以用的,可是我自己開了一個新的Console專案之後,發現這一段程式總是會出現exception。

Acrobat.CAcroPDPage page = doc.AcquirePage(pagenumber);
Acrobat.CAcroRect rect = new Acrobat.AcroRectClass();
Acrobat.AcroPoint pt = (Acrobat.AcroPoint)page.GetSize();

rect.Top = 0;
rect.Left = 0;
rect.right = pt.x;
rect.bottom = pt.y;

page.CopyToClipboard(rect, 0, 0, 100);

Bitmap bmp = (Bitmap)Clipboard.GetImage();
string imgName = saveImgDir + "\\" + pagenumber.ToString() + ".jpeg";
bmp.Save(imgName, System.Drawing.Imaging.ImageFormat.Jpeg);
bmp.Dispose();

照理說執行完這段程式,應該會出現一個jpg檔,而這個檔案的內容就是PDF的screenshot,可是我發現卻沒有產生這個jpg檔,找半天都找不到原因,看了一下這段程式碼也沒什麼邏輯上的問題,只好一行一行開始debug了。

當我執行到第10行的時候,PDF的screenshot確實是有複製到clipboard。證實方法很簡單,就是執行完這行之後,直接開啟繪圖軟體,按下ctrl+v,就會出現PDF的screenshot了。可是當我執行到第12行的時候,卻出現exception。這真是讓我百思不解呀!!!因為相同的程式,在舊專案可以跑,在我這個新專案就不行跑,de了半天都找不出問題,害我原本還跟perry說星期一一定交的出來 = =。

後來我不知道是發什麼神經,居然在第11行插入Clipboard.Clear(),然後就出現了一個不一樣的exception,就是ThreadStateException,於是我又查了一些相關資料,發現我沒有加上STAThread啦!!!

STAThread是在寫WinForm程式一定要加的一個屬性,而Clipboard因為是引用System.Windows.Forms,所以在用Clipboard這個物件的時候,一定要加上STAThread,要不然會造成程式運作異常。看吧,我就是因為這個問題,結果出現異常了啦。好險最後解決了問題,明天也應該可以給perry一個交待了。

參考資料:
Clipboard.Clear 方法 (System.Windows.Forms)
ThreadStateException 類別 (System.Threading)
請以 STAThread 標記 Windows Form 進入點

沒有留言: