I'm developing a custom address dialog for Outlook 2010, following the sample of Helmut Oberdan published here
http://www.codeproject.com/Articles/21288/Customize-the-built-in-Outlook-Select-Names-dialog
I've migrated the project to VS2015 with framework 4.5 but I'm in trouble with the findwindow function
IntPtr hBuiltInDialog = WinApiProvider.FindWindow("#32770", "");
on some computer (mine) works well and on some other (customer) it doesn't. It seems that the function finds another 32770 window that is not the Outlook's one, I've tryed to enumerate all the 32770 windows but when the InspectorWrapper_Deactivate function fires up, my 32770 window is not present in the list. A strange behavior occurs, if I put a messagebox in the deactivate function it pops up twice and after the second time the right window gets catched and my custom dialog opens.
Here is the InspectorWrapper_Deactivate function
void InspectorWrapper_Deactivate()
{
_showOwnDialogOnActivate = false;
// If there is an invisible ghost Window out there - close it
if (_hWndInvisibleWindow != IntPtr.Zero) WinApiProvider.SendMessage(_hWndInvisibleWindow, WinApiProvider.WM_SYSCOMMAND, WinApiProvider.SC_CLOSE, 0);
IntPtr hBuiltInDialog = WinApiProvider.FindWindow("#32770", "");
if (hBuiltInDialog != IntPtr.Zero)
{
// ok, found one
// let's see what childwindows are there
List<IntPtr> childWindows = WinApiProvider.EnumChildWindows(hBuiltInDialog);
// Let's get a list of captions for the child windows
List<string> childWindowNames = WinApiProvider.GetWindowNames(childWindows);
//MessageBox.Show("Contact");
// now check some criteria to identify the build in dialog..
int languageId = Inspector.Application.LanguageSettings.get_LanguageID(Microsoft.Office.Core.MsoAppLanguageID.msoLanguageIDUI);
switch (languageId)
{
case 1031:
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!! This part is only valid for German Outlook 2007 Version !!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if (!childWindowNames.Contains("Nur N&ame")) return;
if (!childWindowNames.Contains("&Mehr Spalten")) return;
if (!childWindowNames.Contains("A&dressbuch")) return;
// you can even check more criteria
break;
case 1033:
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!! This part is only valid for english Outlook 2007 Version !!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if (!childWindowNames.Contains("&Name only")) return;
if (!childWindowNames.Contains("Mo&re columns")) return;
if (!childWindowNames.Contains("A&ddress Book")) return;
break;
case 1040:
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!! This part is only valid for italian Outlook 2007 Version !!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if (!childWindowNames.Contains("Solo n&ome")) return;
if (!childWindowNames.Contains("Altre &colonne")) return;
if (!childWindowNames.Contains("R&ubrica")) return;
break;
// TODO: place your language here....
default:
return;
}
// OK - we have the built in Recipient Dialog
// Create a new invisible window
_hWndInvisibleWindow = WinApiProvider.CreateWindowEx(0, "Static", "BriaSOFT", 0, 0, 0, 0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
// use this window as new Parent for the original Dialog
WinApiProvider.SetParent(hBuiltInDialog, _hWndInvisibleWindow);
WinApiProvider.SendMessage(hBuiltInDialog, WinApiProvider.WM_SYSCOMMAND, WinApiProvider.SC_CLOSE, 0);
// When our INspector becomes active again, we should show our own Dialog
_showOwnDialogOnActivate = true;
}
}
any suggestion will be really appreciate. Thanks Flavio
Following Dmitry suggestion but still not able to find the 32770 window, because it has empty window name (even if it exists)
string windowName;
IntPtr outlookHandle = (IntPtr)0;
IOleWindow window = Inspector as IOleWindow;
if (window != null)
{
window.GetWindow(out outlookHandle);
List<IntPtr> subWindows = WinApiProvider.EnumChildWindows(outlookHandle);
foreach (IntPtr hand in subWindows)
{
StringBuilder ClassName = new StringBuilder(256);
int nRet = WinApiProvider.GetClassName(hand, ClassName, ClassName.Capacity);
if (nRet != 0)
{
if (ClassName.ToString().Contains("#32770"))
{
windowName = WinApiProvider.GetWindowName(hand);
if (windowName.Contains("Seleziona nomi"))
{
hBuiltInDialog = hand;
break;
}
}
}
}
}
After days of test and tryes the solution (suggested by Microsoft) has been to insert a separate thread, started from the inspector and auto terminated when the window is found.
Inside the inspector_deactivate
if (workerThread.ThreadState == ThreadState.Unstarted)
{
// Start the worker thread.
workerThread.Start();
while (!workerThread.IsAlive) ;
// Put the main thread to sleep for 1 millisecond to
// allow the worker thread to do some work:
Thread.Sleep(1);
}
else if (!workerThread.IsAlive)
{
workerObject = new Worker(Inspector);
workerThread = new Thread(workerObject.DoWork);
workerThread.Start();
}
and inside the thread
public Worker(Outlook.Inspector insp)
{
Inspector = insp;
_shouldStop = false;
}
public void DoWork()
{
while (!_shouldStop)
{
SubstituteWindow();
}
}