I'm trying to make an app that previews mails in Outlook 2007. The thing is that when I try to capture the Inspector with the email, the graphics aren't yet fully loaded and I need to add a delay to the capture function. For that I use Thread.Sleep. Now my problem is that even though the Inspector is an Outlook process it freezes as well. I'm sure of this because when I use Thread.Sleep(15000) in my app and try to manually interact with the Inspector (move, select text, resize), it's frozen. Only after I'm done with it in the app (just after the capture process took place) I can access it. Here is my code:
private static void HandleOutlookMail(string EntryIDCollection)
{
// Get the incoming M开发者_StackOverflow中文版ailItem based on ID.
NameSpace outlookNS = outLookApp.GetNamespace("MAPI");
MAPIFolder mFolder =
outLookApp.Session.GetDefaultFolder(OlDefaultFolders.olFolderInbox);
newMail = (MailItem)
outlookNS.GetItemFromID(EntryIDCollection, mFolder.StoreID);
// Now show mail.
i = newMail.GetInspector;
//Make inspector big enough to show entire email
i.Height=2000;
//Activate inspector in order to avoid black screen capture
((_Inspector)i).Activate();
// Dispatch event for the screen capture to take place
OnNewOutlookMail();
}
Now when the event is fired above the following handler is called:
private void TakeScreen()
{
IntPtr hwnd = new IntPtr();
Process[] processes = Process.GetProcessesByName("OUTLOOK");
foreach (Process p in processes)
{
if (p.MainWindowTitle == iOutlook.newMail.GetInspector.Caption)
{
hwnd = p.MainWindowHandle;
Debug.WriteLine("Found " + p.MainWindowTitle);
break;
}
}
iOutlook.releaseInspector();
//Give time to Inspector to finish loading - useless since it freezes and doesn't update
Thread.Sleep(15000);
//Save the image to disk
System.Drawing.Image img = (System.Drawing.Image)CaptureWindow(hwnd);
img.Save("t.png", ImageFormat.Png);
//Because I added the releaseInspector call to try to unfreeze the inspector I can't use:
//iOutlook.i.Close(Microsoft.Office.Interop.Outlook.OlInspectorClose.olDiscard);
}
The code for the 2 functions used above is:
public static void releaseInspector()
{
Marshal.ReleaseComObject(i);
Marshal.ReleaseComObject(newMail);
i = null;
newMail = null;
GC.Collect();
GC.WaitForPendingFinalizers();
Debug.WriteLine("Released?");
}
and
public System.Drawing.Bitmap CaptureWindow(IntPtr hWnd)
{
System.Drawing.Rectangle rctForm = System.Drawing.Rectangle.Empty;
using (System.Drawing.Graphics grfx = System.Drawing.Graphics.FromHdc(GetWindowDC(hWnd)))
{
rctForm = System.Drawing.Rectangle.Round(grfx.VisibleClipBounds);
}
System.Drawing.Bitmap pImage = new System.Drawing.Bitmap(rctForm.Width, rctForm.Height);
System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(pImage);
IntPtr hDC = graphics.GetHdc();
//paint control onto graphics using provided options
try
{
PrintWindow(hWnd, hDC, (uint)0);
}
finally
{
graphics.ReleaseHdc(hDC);
}
return pImage;
}
Any ideas? Any help is much appreciated. Thanks in advance.
Ok, I got the answer from the MSDN forums. The thing is that Outlook waits (synchronously) for my handler to return. The key was to start another thread in the handler that would run TakeScreen and put the Thread.Sleep there. This way my handler would return before the screenshot is made and so the Inspector would have time to update/ load graphics.
精彩评论