Tuesday, November 22, 2005

Hidden MessageBox and VSTO

When trying to display a Message box from VSTO code, the message box is some times hidden in the background. MessageBox's Show method takes a "owner" parameter of type IWin32Window, this makes the Message box to be displayed in front of the IWin32Window passed. Below is a code snippet from gotdotnet site to get the IWin32Window of the foreground window.


// Stephen Toub
// stoub@microsoft.com
//
// ActiveWindow.cs v1.0.0
// 8/28/02
//
// Implements IWin32Window where Handle returns the handle of the system's foreground window.
// Can be used with MessageBox to display the box in front of the active window, such as:
// MessageBox.Show(ActiveWindow.Active, "Hello, World!");
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace Toub.Windows.Forms
{
/// Used to get an IWin32Window for the active window.
public class ActiveWindow : IWin32Window
{
#region Private Members
/// Static instance to use for factory pattern.
private static ActiveWindow _window = new ActiveWindow();
#endregion
#region Construction
/// Prevent external instantiation.
private ActiveWindow() {}
#endregion
#region Public Properties
/// Gets an IWin32Window for the active window.
public static IWin32Window Active { get { return _window; } }
#endregion
#region Private Functions
/// Finds the frontmost window using the Win32 API.
[DllImport("user32.dll")]
private static extern int GetForegroundWindow();
/// Gets a handle to the active window.
System.IntPtr IWin32Window.Handle
{
get { return new System.IntPtr(GetForegroundWindow()); }
}
#endregion
}
}

Tuesday, November 08, 2005

How to Retrieve XML data from MS Word form fields using VSTO.

MS word has this cool feature where you can attach an XML schema to the document and tag the form fields with XML elements in the schema. When you save the document as XML, the form field values are stored as XML data. Unfortunately saving XML data does not work with Check box and Drop down form fields. So, if you need to save the data from Check box and Drop down form fields you have to walk through all the XML nodes and retrive the data. Below is a C# code snippet to walk through the XML nodes and write it as XML.


private string BuildWordDocumentXmlData(XMLNode xmlNode)
{
object oRef = 1;
object missing = Missing.Value;
Range range;
StringBuilder xmlString = new StringBuilder();
xmlString.Append("");
if(!xmlNode.HasChildNodes)
{
xmlString.Append("<" + xmlNode.BaseName + ">");
range = xmlNode.Range;
if (range.FormFields.Count > 0)
{
FormField formField = range.FormFields.get_Item(ref oRef);
if (formField.Type == WdFieldType.wdFieldFormCheckBox)
{
if (formField.Result.CompareTo("1") == 0)
{
xmlString.Append("true");
}
else
{
xmlString.Append("false");
}
}
else if (formField.Type == WdFieldType.wdFieldFormTextInput)
{
if (formField.Result != null)
{
xmlString.Append(formField.Result);
}
}
}
else
{
xmlString.Append(xmlNode.Text);
}
xmlString.Append("");
}
else
{
string returnString;
xmlString.Append("<" + xmlNode.BaseName + ">\n");
foreach(XMLNode childXmlNode in xmlNode.ChildNodes)
{
returnString = BuildWordDocumentXmlData(childXmlNode);
xmlString.Append(returnString + "\n");
}
xmlString.Append("");
}
return xmlString.ToString();
}
public void SaveWordDocumentXmlData(string xmlFileName)
{
Application.ScreenUpdating = false;
string xml;
try
{
xml = BuildWordDocumentXmlData(ActiveDocument.XMLNodes[1]);
using (StreamWriter sw = new StreamWriter(xmlFileName))
{
sw.Write(xml);
}
}
catch(Exception exp)
{
Trace.WriteLine(exp.ToString());
}
Application.ScreenUpdating = true;
}