none
AppointmentItem.Display Method leaves a blank window in behind RRS feed

  • Question

  • I am using AppointmentItem.Display method to display my appointment item as modal dialog. It is working fine. but when the modal window get closes it leaves skeletal structure of the blank window in behind. How to get rid of this blank window?

    This is piece of code i am using to show appointment as modal window.

    AppointmentItem.Display(true);
    AppointmentItem.Save();

    Thanks a lot for your help and time.


    http://www.selvaonline.com - Live a Happy & Balanced Life


    • Edited by SelvaOnline Wednesday, February 12, 2014 3:53 PM
    Wednesday, February 12, 2014 3:52 PM

Answers

  • That sort of "ghost" window is common when displaying Outlook Inspectors modally. If possible display the item non-modally.

    Where I have to get rid of an artifact window like that I get the window handle and use a pinvoke of PostMessage() with a message of WM_CLOSE.

    The Inspector window can be cast as an IOleWindow object and then you can call its GetWindow() method to get a hWnd for that window. This is the declaration you'd use for IOleWindow:

            [ComImport]
            [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
            [Guid("00000114-0000-0000-C000-000000000046")]
            internal interface IOleWindow { void GetWindow(out System.IntPtr phwnd); void ContextSensitiveHelp([In] bool fEnterMode);}

    This is what would be used for PostMessage() and WM_CLOSE:

            [DllImport("user32", SetLastError = true)]
            [return: MarshalAs(UnmanagedType.Bool)]
            internal static extern bool PostMessage(IntPtr hWnd, uint wMsg, IntPtr wParam, IntPtr lParam);

           internal const int WM_CLOSE = 0x10;


    Ken Slovak MVP - Outlook

    • Proposed as answer by Eugene Astafiev Wednesday, February 12, 2014 8:34 PM
    • Marked as answer by SelvaOnline Thursday, February 13, 2014 3:17 AM
    Wednesday, February 12, 2014 4:09 PM
    Moderator
  • Inspector.Close() closes the window. It does not release any references. If your Inspector is "insp" and your AppointmentItem is "appt", this would release the references:

    Marshal.ReleaseComObject(appt);

    appt = null;

    Marshal.ReleaseComObject(insp);

    insp = null;


    Ken Slovak MVP - Outlook

    • Marked as answer by SelvaOnline Thursday, February 13, 2014 10:41 PM
    Thursday, February 13, 2014 9:29 PM
    Moderator
  • Declare a class something like this:

    using System.Runtime.InteropServices;

        public class Win32UI
        {
                public Win32UI()
            {
            }

            [ComImport]
            [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
            [Guid("00000114-0000-0000-C000-000000000046")]
            internal interface IOleWindow { void GetWindow(out System.IntPtr phwnd); void ContextSensitiveHelp([In] bool fEnterMode);}
        }

    Then if your Inspector is "insp" you can get the handle this way, where "pointer" is the window handle:

     Win32UI.IOleWindow win = insp as Win32UI.IOleWindow;

     IntPtr pointer = IntPtr.Zero;

     win.GetWindow(out pointer);


    Ken Slovak MVP - Outlook

    • Marked as answer by SelvaOnline Thursday, February 13, 2014 3:17 AM
    Wednesday, February 12, 2014 10:03 PM
    Moderator

All replies

  • That sort of "ghost" window is common when displaying Outlook Inspectors modally. If possible display the item non-modally.

    Where I have to get rid of an artifact window like that I get the window handle and use a pinvoke of PostMessage() with a message of WM_CLOSE.

    The Inspector window can be cast as an IOleWindow object and then you can call its GetWindow() method to get a hWnd for that window. This is the declaration you'd use for IOleWindow:

            [ComImport]
            [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
            [Guid("00000114-0000-0000-C000-000000000046")]
            internal interface IOleWindow { void GetWindow(out System.IntPtr phwnd); void ContextSensitiveHelp([In] bool fEnterMode);}

    This is what would be used for PostMessage() and WM_CLOSE:

            [DllImport("user32", SetLastError = true)]
            [return: MarshalAs(UnmanagedType.Bool)]
            internal static extern bool PostMessage(IntPtr hWnd, uint wMsg, IntPtr wParam, IntPtr lParam);

           internal const int WM_CLOSE = 0x10;


    Ken Slovak MVP - Outlook

    • Proposed as answer by Eugene Astafiev Wednesday, February 12, 2014 8:34 PM
    • Marked as answer by SelvaOnline Thursday, February 13, 2014 3:17 AM
    Wednesday, February 12, 2014 4:09 PM
    Moderator
  • If possible display the item non-modally.

    Yes I can. Do we have any method to do this?

    I am getting the error when i use your above code snippet in my code.

      [ComImport]   // ; expected

       [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] //InterfaceType is not exist in current context
        [Guid("00000114-0000-0000-C000-000000000046")]  //error
            internal interface IOleWindow { void GetWindow(out System.IntPtr phwnd); void ContextSensitiveHelp([In] bool fEnterMode);}

    Do i need to refer any dll to use your code?


    http://www.selvaonline.com - Live a Happy & Balanced Life


    • Edited by SelvaOnline Wednesday, February 12, 2014 8:35 PM
    Wednesday, February 12, 2014 8:34 PM
  • To display it non-modally use an argument of false for the Display() method:

    AppointmentItem.Display(false);

    Use this in the class for the IOleWindow declaration:

    using System.Runtime.InteropServices;


    Ken Slovak MVP - Outlook

    Wednesday, February 12, 2014 8:50 PM
    Moderator
  • Thank you. I am able to declare. I need modal window only.

    AppointmentItem.Display(true);

    i am not sure how to cast the modal window to IOleWindow object?

    The Inspector window can be cast as an IOleWindow object and then you can call its GetWindow() method to get a hWnd for that window.


    http://www.selvaonline.com - Live a Happy & Balanced Life

    Wednesday, February 12, 2014 9:40 PM
  • Declare a class something like this:

    using System.Runtime.InteropServices;

        public class Win32UI
        {
                public Win32UI()
            {
            }

            [ComImport]
            [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
            [Guid("00000114-0000-0000-C000-000000000046")]
            internal interface IOleWindow { void GetWindow(out System.IntPtr phwnd); void ContextSensitiveHelp([In] bool fEnterMode);}
        }

    Then if your Inspector is "insp" you can get the handle this way, where "pointer" is the window handle:

     Win32UI.IOleWindow win = insp as Win32UI.IOleWindow;

     IntPtr pointer = IntPtr.Zero;

     win.GetWindow(out pointer);


    Ken Slovak MVP - Outlook

    • Marked as answer by SelvaOnline Thursday, February 13, 2014 3:17 AM
    Wednesday, February 12, 2014 10:03 PM
    Moderator
  • Thanks a lot Ken for your time and help. It worked me in a perfect way.

    http://www.selvaonline.com - Live a Happy & Balanced Life

    Thursday, February 13, 2014 4:34 AM
  • Ken,

    I have an issue on this thread.

    I am getting "A dialog box is open. Close it and try again." error stacktrace at Microsoft.Office.Interop.Outlook._AppointmentItem.Display(Object Modal).

    I believe we have already closed the modal window and why this is occured again? Kindly help me.


    http://www.selvaonline.com - Live a Happy & Balanced Life

    Thursday, February 13, 2014 7:26 PM
  • Have you completely released all references to the original item and its Inspector? That error is usually when there are hanging references to a modal item.

    It would really be best if you did not have to display the item modally. Outlook items displayed modally have never functioned correctly in all aspects.


    Ken Slovak MVP - Outlook

    Thursday, February 13, 2014 7:33 PM
    Moderator
  • Inspector.Close() method is not working. What is the best way to release all references to the original item and inspector?

    http://www.selvaonline.com - Live a Happy & Balanced Life

    Thursday, February 13, 2014 9:03 PM
  • Inspector.Close() closes the window. It does not release any references. If your Inspector is "insp" and your AppointmentItem is "appt", this would release the references:

    Marshal.ReleaseComObject(appt);

    appt = null;

    Marshal.ReleaseComObject(insp);

    insp = null;


    Ken Slovak MVP - Outlook

    • Marked as answer by SelvaOnline Thursday, February 13, 2014 10:41 PM
    Thursday, February 13, 2014 9:29 PM
    Moderator
  • This really helps me. Thanks again !!

    http://www.selvaonline.com - Live a Happy & Balanced Life

    Thursday, February 13, 2014 10:41 PM
  • Hi Ken,

    The above fix works fine for very first time when i open a meeting item in the modal window and close the same. If i want to do it more than one modal windows, the first modal window refernce still exist and i am getting "a dialog box is open close it and try again" message when i am trying to open the second modal window.

    Kindly help.

    Regards,

    Selva


    http://www.selvaonline.com - Live a Happy & Balanced Life

    Wednesday, February 19, 2014 8:24 PM
  • That means that you haven't released all your references. You need to check your code to make sure that all references are released.

    Also, my recommendation still stands. Modal Inspector windows are a lot of trouble and are not something I recommend using at all.


    Ken Slovak MVP - Outlook

    Wednesday, February 19, 2014 8:37 PM
    Moderator