0

Я разрабатываю диалог пользовательских адресов для Outlook 2010, следуя образец Helmut Оберданна опубликованным здесьOutlook 2010 плагина неправильно 32770 окна

http://www.codeproject.com/Articles/21288/Customize-the-built-in-Outlook-Select-Names-dialog

Я мигрировал проект в VS2015 с каркасом 4.5, но У меня проблема с функцией findwindow

IntPtr hBuiltInDialog = WinApiProvider.FindWindow ("# 32770", "");

на каком-то компьютере (мой) хорошо работает и на каком-то другом (заказчике) его нет. Кажется, что функция находит другое окно 32770, которое не является Outlook, я попытался перечислить все окна 32770, но когда активирована функция InspectorWrapper_Deactivate, мое окно 32770 отсутствует в списке. Возникает странное поведение, если я помещаю сообщение в функцию дезактивации, оно появляется дважды, а после второго раза попадает правое окно и открывается пользовательский диалог.

Вот функция InspectorWrapper_Deactivate

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; 
    } 
} 

любое предложение будет действительно оценить. Благодаря Флавио

После Дмитрия внушения , но до сих пор не в состоянии найти 32770 окно, потому что она имеет пустое имя окна (даже если он существует)

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; 
        } 
       } 
      } 
     } 
    } 

+0

Это довольно типичный код codeproject.com, это только когда-либо работает правильно совершенно случайно. Тебе придется выбросить его. Используйте пространство имен System.Windows.Automation, есть немного кривая обучения, но инвестиции хорошо стоят и в будущем окупится. –

ответ

0

После нескольких дней тестирования и попыток решение (предложенное Microsoft) состояло в том, чтобы вставить отдельный поток, начатый с инспектора и автоматически завершенный при обнаружении окна.

Внутри 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(); 
    } 

и внутри нити

public Worker(Outlook.Inspector insp) 
    { 
     Inspector = insp; 
     _shouldStop = false; 
    } 

    public void DoWork() 
    { 
     while (!_shouldStop) 
     { 
      SubstituteWindow(); 
     } 
    } 

0

Вместо использования FindWindow, вы будете нужно найти окно Outlook, в котором находится этот элемент управления (листинг Inspector для IOleWindow и cal lIOelWindow.GetWindow), затем найдите дочерний элемент этого окна (EnumChildWindows) с заданным именем класса/заголовком/и т. д. Если несколько окон с этим class name, вам может потребоваться использовать уникальную комбинацию окон родителя/дочернего/однорангового узла, чтобы убедиться, что у вас есть правильный.

+0

Привет, Дмитрий, спасибо за ответ, я выполнил ваши инструкции, но цикл в списке не нашел правильного окна, название кажется пустым, я собираюсь проверить функцию имени окна get –

+0

Играть с Сначала Spy ++, чтобы увидеть правильную иерархию окон. –

+0

Использование Spy ++ Я вижу, что окно, которое я ищу, находится под управлением рабочего стола. Проблема заключается в том, что при вызове функции дезактивации инспектора окно по-прежнему отсутствует в списке –

Смежные вопросы