none
How do I get MailItem.PropertyChange event to fire? RRS feed

  • Question

  • I have a custom button on the Ribbon that passes the email address on the "To" line to a service.  The process works fine except for one instance.

    If you type the email address and perhaps click somewhere else, or hit the Tab key the "PropertyChange" event will fire and the the "To" property of the MailItem object will be set.

    However, if you were to type a value on the "To" line then (without taking any other mouse or keyboard action) Click a Custom button, the "PropertyChange" event doesn't fire and the "To" property of the MailItem will not be set.

    I'm guessing I may need to simulate some sort of KeyClick, or maybe even a CheckNames action in order to force the value in the "To" field to either be checked, or Resolved, or whatever the process may be called that gets the "PropertyChange" event to fire.

    Not sure how to force this.
    • Edited by GermanEZI Thursday, April 27, 2017 1:47 AM Clarification
    Wednesday, April 26, 2017 6:23 PM

Answers

  • Pardon the code.   This is just a "proof of concept" and not the final version.  All the elements are here.

    The biggest part was just finding that "To" edit window control.  Once I did, the rest was easy. 

    I retrieved the value from the "To" edit window control then set the "To" property of the MailItem object to the value I retrieved from the window and this would cause the PropertyChange event to fire.
     

        class Win32
        {
            [DllImport("user32.dll", SetLastError = true)]
            public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

            [DllImport("user32.dll")]
            public static extern IntPtr GetActiveWindow();

            [DllImport("user32.dll")]
            public static extern int GetWindowText(IntPtr hWnd, System.Text.StringBuilder text, int count);

            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, [Out] System.Text.StringBuilder lParam);

        }

    public static string GetTextFromControl() { IntPtr hWnd = Win32.GetActiveWindow(); IntPtr hWndChild = IntPtr.Zero; IntPtr hWndFound = IntPtr.Zero; if( hWnd != IntPtr.Zero) { hWndChild = Win32.FindWindowEx(hWnd, IntPtr.Zero, "AfxWndW", null); if (hWndChild != IntPtr.Zero) { IntPtr level1 = Win32.FindWindowEx(hWndChild, IntPtr.Zero, "AfxWndW", null); if (level1 != IntPtr.Zero) { IntPtr level2 = Win32.FindWindowEx(level1, IntPtr.Zero, "#32770", null); if (level2 != IntPtr.Zero) { hWndFound = Win32.FindWindowEx(level2, IntPtr.Zero, "RichEdit20WPT", null); } } } } int iCount = 0; System.Text.StringBuilder sb=null; //int iResult = Win32.GetWindowText(hWndFound, sb, iCount); int length = (int)Win32.SendMessage(hWndFound, /*WM_GETTEXTLENGTH*/ 0x000E, IntPtr.Zero, sb); sb = new System.Text.StringBuilder(length + 1); Win32.SendMessage(hWndFound, /*WM_GETTEXT*/ 0x000D, (IntPtr)sb.Capacity, sb); return sb.ToString(); if( iCount > 0 ) { return sb.ToString(); } else { return string.Empty; } }




    • Marked as answer by GermanEZI Friday, April 28, 2017 9:54 PM
    • Edited by GermanEZI Wednesday, May 17, 2017 8:43 PM correction
    Friday, April 28, 2017 9:54 PM

All replies

  • Try to call the Save method of the MailItem class or just move the focus to another field in the Outlook window using the SetFocus function (Windows API).  

    profile for Eugene Astafiev at Stack Overflow, Q&A for professional and enthusiast programmers

    Wednesday, April 26, 2017 7:46 PM
  • Not a bad idea.  I'll give it a shot and get back to you.
    Wednesday, April 26, 2017 8:24 PM
  • You got me on the right track.  Here's what I found.

    Once the "To" field loses focus, the PropertyChange event will eventually fire.

    I thought I would need to send a "SetFocus" call, but I won't have to.  The fact that the Custom Button is being clicked is enough.  Clicking the button causes the "To" field to lose focus (which in turn will cause the "PropertyChange" event to fire).

    What I will need to do is check if the Window (the "To" edit) is Indeed empty.  If it really is empty I will pop-up a window that reminds the user that they need to enter at least one recipient.

    If the "To" edit box is not empty, then I'll simply let the framework send the "PropertyChange" event, and my code will take over.

    I'll need to tweak the logic a bit to handle this, but it should work.

    I'll set it up and let you know.

    Friday, April 28, 2017 5:16 PM
  • Pardon the code.   This is just a "proof of concept" and not the final version.  All the elements are here.

    The biggest part was just finding that "To" edit window control.  Once I did, the rest was easy. 

    I retrieved the value from the "To" edit window control then set the "To" property of the MailItem object to the value I retrieved from the window and this would cause the PropertyChange event to fire.
     

        class Win32
        {
            [DllImport("user32.dll", SetLastError = true)]
            public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

            [DllImport("user32.dll")]
            public static extern IntPtr GetActiveWindow();

            [DllImport("user32.dll")]
            public static extern int GetWindowText(IntPtr hWnd, System.Text.StringBuilder text, int count);

            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, [Out] System.Text.StringBuilder lParam);

        }

    public static string GetTextFromControl() { IntPtr hWnd = Win32.GetActiveWindow(); IntPtr hWndChild = IntPtr.Zero; IntPtr hWndFound = IntPtr.Zero; if( hWnd != IntPtr.Zero) { hWndChild = Win32.FindWindowEx(hWnd, IntPtr.Zero, "AfxWndW", null); if (hWndChild != IntPtr.Zero) { IntPtr level1 = Win32.FindWindowEx(hWndChild, IntPtr.Zero, "AfxWndW", null); if (level1 != IntPtr.Zero) { IntPtr level2 = Win32.FindWindowEx(level1, IntPtr.Zero, "#32770", null); if (level2 != IntPtr.Zero) { hWndFound = Win32.FindWindowEx(level2, IntPtr.Zero, "RichEdit20WPT", null); } } } } int iCount = 0; System.Text.StringBuilder sb=null; //int iResult = Win32.GetWindowText(hWndFound, sb, iCount); int length = (int)Win32.SendMessage(hWndFound, /*WM_GETTEXTLENGTH*/ 0x000E, IntPtr.Zero, sb); sb = new System.Text.StringBuilder(length + 1); Win32.SendMessage(hWndFound, /*WM_GETTEXT*/ 0x000D, (IntPtr)sb.Capacity, sb); return sb.ToString(); if( iCount > 0 ) { return sb.ToString(); } else { return string.Empty; } }




    • Marked as answer by GermanEZI Friday, April 28, 2017 9:54 PM
    • Edited by GermanEZI Wednesday, May 17, 2017 8:43 PM correction
    Friday, April 28, 2017 9:54 PM