Tuesday, March 4, 2014

Open MS Office documents within a desktop application

Have you ever had to develop an application where you had to open MS office documents within your desktop form (as a child form)? If yes, you would have found that it almost seems to be an impossible task. A long time back, I too had a similar problem. I do not know with newer technology and versions of Windows and VS, maybe there is an easy way to get it done. But at that time, I had a tough time figuring how to get it done.

What I had to do was
- open a office document
- position the office document as a child window within another windows form so that I can control the parent windows form for closing it, positioning it, etc

If you have already searched the internet, you would see various suggestions like using activex controls and some other solutions that his own issues and limitations.

The way I finally got it done was using Windows API. This worked in Windows XP and I think there must be similar APIs for Windows 7 (may even be the same). I am sorry, but I haven't tried whether it works on it or not on Windows 8.

const UInt32 WS_OVERLAPPED = 0x0;
const UInt32 WS_POPUP = 0x80000000;
const UInt32 WS_CHILD = 0x40000000;
const UInt32 WS_MINIMIZE = 0x20000000;
const UInt32 WS_VISIBLE = 0x10000000;
const UInt32 WS_DISABLED = 0x8000000;
const UInt32 WS_CLIPSIBLINGS = 0x4000000;
const UInt32 WS_CLIPCHILDREN = 0x2000000;
const UInt32 WS_MAXIMIZE = 0x1000000;
const UInt32 WS_CAPTION = 0xC00000; //'/* WS_BORDER | WS_DLGFRAME */
const UInt32 WS_BORDER = 0x800000;
const UInt32 WS_DLGFRAME = 0x400000;
const UInt32 WS_VSCROLL = 0x200000;
const UInt32 WS_HSCROLL = 0x100000;
const UInt32 WS_SYSMENU = 0x80000;
const UInt32 WS_THICKFRAME = 0x40000;
const UInt32 WS_GROUP = 0x20000;
const UInt32 WS_TABSTOP = 0x10000;
const UInt32 WS_MINIMIZEBOX = 0x20000;
const UInt32 WS_MAXIMIZEBOX = 0x10000;

[DllImport("user32.dll", SetLastError = true)] static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent); 
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong); 
[DllImport("user32.dll", SetLastError = true)]
static extern int GetWindowLong(IntPtr hWnd, int nIndex); 
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName); 
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
 
[DllImport("user32.dll")]
private static extern int ShowWindow(IntPtr hwnd, uint command); 
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter,
string className, string windowTitle);

[DllImport("user32.dll")]
private static extern IntPtr FindWindowEx(
IntPtr parentHwnd,
IntPtr childAfterHwnd,
IntPtr className,
string windowText); 
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni); 
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam); 
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
        [StructLayout(LayoutKind.Sequential)]
public struct RECT
{public int Left;
public int Top;
public int Right; 
public int Bottom;
} 
public static void InitializeWindow(IntPtr pProcessHandle, IntPtr pCurrentHandle, int pLeft, int pTop, int pWidth, int pHeight) //, bool bRepaint)
{  //postion the window
   MoveWindow(pProcessHandle, pLeft, pTop, pWidth, pHeight, true);
   //set the parent as current application
   SetParent(pProcessHandle, pCurrentHandle)    
   int lStyle = GetWindowLong(pProcessHandle, GWL_STYLE); 
   lStyle = lStyle - (int)(WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
   // Put the modified style back:
   SetWindowLong(pProcessHandle, GWL_STYLE, lStyle);
}
Call "InitializeWindow" to position and setup the application's (MS office application) window as a child window of the current form
 using System.Diagnostics;ProcessStartInfo psInfo = new ProcessStartInfo(FilePath of the MS document);
psInfo.WindowStyle = ProcessWindowStyle.Normal;
 //open the external application
Process ApplicationProcess = Process.Start(psInfo);
ApplicationProcess.WaitForInputIdle(1000);//Initialize the application window
InitializeWindow(ApplicationProcess.MainWindowHandle, this.Handle, 100, 0, 300, 200, true);
 
 

No comments:

Post a Comment