Skip to content

Instantly share code, notes, and snippets.

@davecra
Created June 5, 2020 17:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save davecra/af8ec8f61bc15580c98608ba89a30a4a to your computer and use it in GitHub Desktop.
Save davecra/af8ec8f61bc15580c98608ba89a30a4a to your computer and use it in GitHub Desktop.
Using a background thread and Windows API's in Outlook, we can detect when the user has opened the Print tab in the backstage
[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