1、我之前的做法是,用API的方式创建WORDAPP,然后创建Document,然后API查找句柄,然后嵌入到WINFORM窗体。这种方法比较麻烦。
2、下面的Host方法,很简单,可以考虑考虑:
There is no OLE container control in .NET, but Microsoft's suggestion is that you use the WebBrowser control to embed Excel, Word and Powerpoint documents in Windows Forms applications.
This works surprisingly well on my system. Using Visual Studio 2005, drop a WebBrowser control on a form, and write one line of code to navigate to a Word document:
webBrowser1.Navigate("c:/test/test.doc");
You get a prompt (I haven't investigated how or whether this can be disabled), and the Word document opens in the WebBrowser control, very fast on my system.
However, someone asked in the dotnet newsgroups how to get a reference to the hosted Word document. The WebBrowser control has a Document property, but it is of type HtmlDocument. In the underlying ActiveX control, and in the COM wrapper you get if you import the WebBrowser control directly rather than using the official .NET control, the Document property is an object which you can cast to whatever type of document is actually being hosted.
A possible solution is to use the WebBrowser's ActiveXInstance property to get a reference to the underlying ActiveX WebBrowser control. Not that you are not meant to do this: the docs say: "This property supports the .NET Framework infrastructure and is not intended to be used directly from your code."
[Aside]I always find this annoying: if it is not meant to be used, why is it public? If there are things that can only be achieved via this property, why is it not meant to be used?]
Anyway, I tried the following code in VB, in a handler for DocumentComplete, and it works fine. Note that I also set a reference to Microsoft.Office.Interop.Word:
Private Sub WebBrowser1_DocumentCompleted(ByVal sender As System.Object, ByVal e As System.Windows.Forms.WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted Dim doc As Microsoft.Office.Interop.Word.Document Dim docobj As Object docobj = Me.WebBrowser1.ActiveXInstance.document If TypeOf (docobj) Is Microsoft.Office.Interop.Word.Document Then doc = docobj MessageBox.Show("Got a word doc: " + doc.Name) End If End Sub
Very handy. But what is the C# equivalent? I tried:
object doc; doc = webBrowser1.ActiveXInstance.GetType().GetProperty("Document"); //update - this can't work. GetProperty returns PropertyInfo - metadata //about the property, not an instance value. However, calling GetValue //on this doesn't work either - the type is simply System.__ComObject //which does not have a Document property. It must be cast to the right //interface. if (doc is Microsoft.Office.Interop.Word.Document) { //... }
...but that doesn't seem to work. The if statement always evaluates false. If it works in VB there must be a way.
Update
This works in C#. First, set a reference to SHDocVw. Then:
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { //get ref to Word doc Microsoft.Office.Interop.Word.Document worddoc; object doc; SHDocVw.WebBrowser wb; wb = (SHDocVw.WebBrowser)webBrowser1.ActiveXInstance; doc = wb.Document; if (doc is Microsoft.Office.Interop.Word.Document) { worddoc = (Microsoft.Office.Interop.Word.Document)doc; MessageBox.Show("Got a word document: " + worddoc.Name); } }