Using a background thread and Windows API's in Outlook, we can detect when the user has opened the Print tab in the backstage
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[DllImport("user32.dll")] | |
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); | |
[DllImport("user32.dll", SetLastError = true)] | |
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle); | |
/// <summary> | |
/// Startup for Outlook Add-in | |
/// </summary> | |
/// <param name="sender"></param> | |
/// <param name="e"></param> | |
private void ThisAddIn_Startup(object sender, System.EventArgs e) | |
{ | |
// we start by creating a background thread and look for a specific | |
// set of windows to appear, then we know the user clicked print | |
new Thread(() => | |
{ | |
while (true) | |
{ | |
Thread.Sleep(1000); | |
CheckForPrint(); | |
} | |
}).Start(); | |
} | |
/// <summary> | |
/// Checks to see if the user has opened backstage and | |
/// selected the Print tab | |
/// </summary> | |
private void CheckForPrint() | |
{ | |
try | |
{ | |
// depending on whether we have an inspector active, or the explorer | |
// active we will need to get the caption to FindWindow | |
string LstrCaption = ""; | |
if(Application.ActiveWindow() is Outlook.Inspector) | |
{ | |
// Active inspector caption | |
LstrCaption = ((Outlook.Inspector)Application.ActiveWindow()).Caption; | |
} | |
else if(Application.ActiveWindow() is Outlook.Explorer) | |
{ | |
// Active explorer caption | |
LstrCaption = ((Outlook.Explorer)Application.ActiveWindow()).Caption; | |
} | |
// get the window handle | |
IntPtr LintHostHandle = FindWindow(null, LstrCaption); | |
if (LintHostHandle == IntPtr.Zero) return; // if we cannot find it - nevermind | |
// create a list of windows to find (in reverse order) | |
// 4) rctrl_renwnd32 - is the print preview window | |
// 3) NetUICtrlNotifySink - is whole Print options and preview | |
// 2) NetUIHWND - is the the entire print tab | |
// 1) FullpageUIHost - is the backstage page | |
Stack<string> LobjWindowClasses = new Stack<string> ( | |
new string[] { "rctrl_renwnd32", "NetUICtrlNotifySink", "NetUIHWND", "FullpageUIHost" }); | |
// recursive call back to find each window in the stack. | |
// if all of them are found, then present a message to the user | |
if(FindWindowStack(LintHostHandle, LobjWindowClasses)) | |
{ | |
MessageBox.Show("You have clicked on the Print Tab in Outlook."); | |
} | |
} | |
catch { } | |
} | |
/// <summary> | |
/// RECURSIVE | |
/// This function will take the window classnames in the provided stack | |
/// and then find each one in order via recursive calls. If all of them | |
/// are found - we return true = found | |
/// </summary> | |
/// <param name="PintHandle"></param> | |
/// <param name="PobjStack"></param> | |
/// <returns></returns> | |
private bool FindWindowStack(IntPtr PintHandle, Stack<string> PobjStack) | |
{ | |
try | |
{ | |
// get the window with the classname being popped off the stack | |
IntPtr LintNewHandle = FindWindowEx(PintHandle, IntPtr.Zero, PobjStack.Pop(), ""); | |
if(LintNewHandle != IntPtr.Zero && PobjStack.Count == 0) | |
{ | |
return true; // found it | |
} | |
else if(LintNewHandle!= IntPtr.Zero) | |
{ | |
// found a window, but the stack still has items, call next one | |
return FindWindowStack(LintNewHandle, PobjStack); | |
} | |
else | |
{ | |
// did not find it | |
return false; | |
} | |
} | |
catch | |
{ | |
// oops | |
return false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment