none
Outlook window getting the keyboard focus instead of user created Form Window during Outlook Startup RRS feed

  • Question

  • This MAPILogonComplete method involves creating a Form Window to show "What's New" of a certain Addin version (DisplayWhatsNewDialog() in the code):

    private void _outlook_MAPILogonComplete() { _logger.Info("_outlook_MAPILogonComplete"); try { if (_timerForm != null) { _timerForm.Timer.Stop(); _timerForm.Timer.Dispose(); } } catch (Exception ex2) { _logger.Error(ex2.Message, ex2); } try { if (Globals.BJNSettings.showWhatsNew) { Globals.BJNSettings.showWhatsNew = false; UIHelper.DisplayWhatsNewDialog(false); } Ol.Inspector insp = null; if (_inspectors.Count > 0) { for (int i = _inspectors.Count; i >= 1; i--) { insp = _inspectors[i]; WrapInspector(insp); insp = null; } } Ol.Explorer expl = null; if (_explorers.Count > 0) { for (int i = _explorers.Count; i >= 1; i--) { expl = _explorers[i]; WrapExplorer(expl); expl = null; } } GetAddinsList();

    Thread logSystemInfoThread = new Thread(new ThreadStart(LogSystemInformation)); logSystemInfoThread.TrySetApartmentState(ApartmentState.STA); logSystemInfoThread.IsBackground = true; logSystemInfoThread.Start(); try { Ol.NameSpace ns = _outlook.GetNamespace("MAPI"); _calFolder = ns.GetDefaultFolder(Ol.OlDefaultFolders.olFolderCalendar) as Ol.Folder; _calFolder.BeforeItemMove += new Ol.MAPIFolderEvents_12_BeforeItemMoveEventHandler(_calFolder_BeforeItemMove); _delFolder = ns.GetDefaultFolder(Ol.OlDefaultFolders.olFolderDeletedItems) as Ol.Folder; Marshal.ReleaseComObject(ns); ns = null; } catch (Exception ex) { _logger.Error(ex.Message, ex); } UIHelper.WriteDoNotDisableKeyToRegistry(); Globals.AppointmentsToProcess = new List<string>(); _timerForm.ProcessTimer.Interval = 3000; _timerForm.ProcessTimer.Start(); } catch (Exception ex) { _logger.Error(ex.Message, ex); } }


    DisplayWhatsNewDialog() has this signature:

    public static void DisplayWhatsNewDialog(bool modal)
    
        {
            try
            {
         
                string defaultWhatsNewFile = Globals.BJN_APP_BASE_DIRECTORY + "WhatsNew.txt";
    
            
                string localISOLanguageName = Languages.GetTwoLetterISOLanguageName();
                
                string localizedWhatsNewFile = Languages.GetInstalledLocalizedFilePath(localISOLanguageName, "WhatsNew.txt");
    
                if (String.IsNullOrEmpty(localizedWhatsNewFile)) 
                {
                    localizedWhatsNewFile = defaultWhatsNewFile;
                }
    
                if (File.Exists(localizedWhatsNewFile))
                {
                    BJNWhatsNew whatsNew = new BJNWhatsNew(localizedWhatsNewFile);
    
                    if (modal)
                    {
                        whatsNew.ShowDialog();
                        whatsNew.Dispose();
                    }
                    else
                    {
                        whatsNew.TopMost = true;
                        whatsNew.Show();                  
                    }
    
                    whatsNew = null;
                }
            }
            catch (Exception ex)
            {
                _logger.Error(ex.Message, ex);
            }
        }


    The problem is if the Window is made modal, it blocks the Outlook to launch and also goes back of the Outlook loading window (Whats New window will not be having keyboard focus). And if the Window is made non-modal (passing false to DisplayWhatsNewDialog()), Outlook launches properly and What's New window comes at the top but will not be having keyboard focus; instead the launched Outlook window will be having the keyboard focus. May anyone please suggest a way to make the What's New window to be always having the keyboard focus? Structure of form window class BJNWhatsNew is given below:

    public partial class BJNWhatsNew : Form
        {
            private static ILog _logger = LogManager.GetLogger(typeof(BJNWhatsNew));
    
            public BJNWhatsNew(string whatsNewTextFileName)
            {
                InitializeComponent();
    
                InitLabels();
                InitEventHandlers();
                InitWhatsNew(whatsNewTextFileName);
            }
    
            private void InitLabels()
            {
                try
                {
                   
                    this.Text = Properties.Resources.bjn_version_info_caption;
                   
                    this.buttonClose.Text = Properties.Resources.ok_hotkey;
    
                    this.labelBJNAddin.Text = Properties.Resources.bjn_version_ol_addin;
    
                    this.labelVersion.Text = String.Format(Properties.Resources.version_format, Assembly.GetExecutingAssembly().GetName().Version.ToString(3));
    
                  
                    Assembly assembly = Assembly.GetExecutingAssembly();
                    FileInfo fileInfo = new FileInfo(assembly.Location);
                    DateTime buildDate = fileInfo.LastWriteTime;
    
                    string formatString = "d MMM, yyyy";
                    this.labelReleaseDate.Text = String.Format(Properties.Resources.bjn_version_release_date, buildDate.ToString(formatString));
                    
                }
                catch (Exception ex)
                {
                    _logger.Error(ex.Message, ex);
                }
            }
    
            private void InitEventHandlers()
            {
                this.buttonClose.Click += new EventHandler(buttonClose_Click);
            }
    
            private void InitWhatsNew(string whatsNewTextFileName)
            {
                try
                {
                    if (File.Exists(whatsNewTextFileName))
                    {
                        StreamReader sr = new StreamReader(whatsNewTextFileName);
                        string whatsNew = sr.ReadToEnd();
                        sr.Close();
    
                        this.richTextBox1.Text = whatsNew;
                        this.richTextBox1.SelectionLength = 0;
                        this.buttonClose.Select();
    
                        
                        this.buttonClose.Focus();  
                    }
                }
                catch (Exception ex)
                {
                    _logger.Error(ex.Message, ex);
                }
            }
    
            void buttonClose_Click(object sender, EventArgs e)
            {
                this.Close();
            }
        }


    • Edited by Prasad U S Wednesday, January 7, 2015 5:28 PM
    Wednesday, January 7, 2015 5:24 PM

Answers

  • Hello Prasad,

    The ShowDialog method will block the current thread. If you want to continue working with Outlook objects you need to use the Show method instead. The key fact is that both methods (Show and ShowDialog) accepts an instance of the IWin32Window interface which allows to specify the parent window handle. Specifying the parent window handle (Outlook Explorer window) to the Show method you can make your window shown on top of Outlook all the time.

    To get the HWND of an Outlook explorer  object (e.g. Application.ActiveExplorer), cast it to IOleWindow and call IOleWindow.GetWindow(). Also you may find the How to get the IWin32Window for Outlook article helpful.

    Thursday, January 8, 2015 6:30 AM
  • Yes Eugene. Thanks a lot for your help. Its working correctly now. I am using ShowDialog() and passing the IWin32Window of Outlook.

    Cheers,

    Prasad

    Thursday, January 8, 2015 5:21 PM

All replies

  • Hello Prasad,

    The ShowDialog method will block the current thread. If you want to continue working with Outlook objects you need to use the Show method instead. The key fact is that both methods (Show and ShowDialog) accepts an instance of the IWin32Window interface which allows to specify the parent window handle. Specifying the parent window handle (Outlook Explorer window) to the Show method you can make your window shown on top of Outlook all the time.

    To get the HWND of an Outlook explorer  object (e.g. Application.ActiveExplorer), cast it to IOleWindow and call IOleWindow.GetWindow(). Also you may find the How to get the IWin32Window for Outlook article helpful.

    Thursday, January 8, 2015 6:30 AM
  • If I use Show() or ShowDialog() (for this case, I made TopMost = true;), the Window is at the top, but the problem is with the keyboard focus. I have given an OK button which user has to click or hit enter. That's the issue. I am losing the keyboard focus always. Rather, it will be with main Outlook UI. At least when I use ShowDialog(), if the keyboard focus falls on my custom window, its enough for my use case.

    Thanks

    Prasad

    Thursday, January 8, 2015 12:20 PM
  • Prasad,

    Did you try to specify the parent window handle?

    Thursday, January 8, 2015 12:42 PM
  • Yes Eugene. Thanks a lot for your help. Its working correctly now. I am using ShowDialog() and passing the IWin32Window of Outlook.

    Cheers,

    Prasad

    Thursday, January 8, 2015 5:21 PM