Making Sure Outlook Calendar Reminders Actually Pop-up in Windows 7

Introduction

In Windows 7, MS Outlook seems to be horribly bad at popping up calendar reminders when outlook doesn’t have focus. This can cause a series of problems from minor annoyances to missed meetings. As discussed in this StackExchange question, there are some relatively easy work arounds to this issue that I’ll elaborate on here. If you’ve never used Outlook’s VBA editor to extend it’s capabilities before, this article will take you through how to set up everything you’ll need to do, start to finish. If you’re already familiar with using VBA in Outlook, then you can just skip to Step 5 and paste in the code and you’ll be all set.

Step By Step

  • 1) Hit the Windows Key and type “certificate”
  • 2) Select Digital Certificate for VBA Projects and type in a name for your certificate and hit OK
  • 3) Open Outlook 2010 and Hit Alt + F11 to start the VBA editor
  • 4) In the Project Pane on the left, Expand Project1 > Microsoft Outlook Objects > and double click on ThisOutlookSession
  • 5) Paste in the following code exactly:
'ensures all reminder notices receive focus
Private Sub Application_Reminder(ByVal Item As Object)
    If TypeOf Item Is AppointmentItem Then
        Application.ActiveWindow.Activate
    End If
End Sub

Edit: Added New Better Code Below:

'Declare Functions From User32 Library  
Private Declare PtrSafe Function FindWindowA Lib "user32" _  
        (ByVal lpClassName As String, _  
         ByVal lpWindowName As String) As Long  
Private Declare PtrSafe Function SetWindowPos Lib "user32" _  
        (ByVal hwnd As Long, _  
         ByVal hWndInsertAfter As Long, _  
         ByVal X As Long, _  
         ByVal Y As Long, _  
         ByVal cx As Long, _  
         ByVal cy As Long, _  
         ByVal wFlags As Long) As Long  

'Declare Constants  
Private Const SWP_NOSIZE = &H1  
Private Const SWP_NOMOVE = &H2  
Private Const FLAGS As Long = SWP_NOMOVE Or SWP_NOSIZE  
Private Const HWND_TOPMOST = -1  

'Only show the message the first time  
Private messageAlreadyShown As Boolean  

'Finds Reminder Window and Brings to TopMost position  
Private Sub Application_Reminder(ByVal Item As Object)  
    On Error Resume Next  

    'show message box for first reminder  
    If Not messageAlreadyShown Then  
        MsgBox "First Reminder", vbSystemModal, ""  
        messageAlreadyShown = True  
    End If  

    'find reminder window  
    ReminderWindow = FindWindowA(vbNullString, "1 Reminder")  
    'bring reminder window to front  
    SetWindowPos ReminderWindow, HWND_TOPMOST, 0, 0, 0, 0, FLAGS  
End Sub 
  • 6) Sign the Macro by going to Tools > Digital Signature and clicking Choose
  • 7) Select the certificate you created earlier and hit OK
  • 8) Select OK again, hit Ctrl + S to save and exit the VBA window
  • 9) To Enable Macros, Go to File > Options and select Trust Center from the left window
  • 10) Run the Trust center by clicking the Trust Center Settings button on the right.
  • 11) From the Trust Center, select Macro Settings, and select “Notifications for digitally signed macros, all other macros disabled” and hit OK
  • 12) Exit Outlook - It will ask you if you want to save the project, click Yes
  • 13) Start Outlook - It will give you a security notice. Select “Trust all documents from this publisher” (You can first confirm that you are the publisher by selecting “Show Signature Details”)
  • 14) That’s it! You’re all set. You never have to touch any of that code again or miss another meeting (unintentionally)

UPDATE!

I’ve update the code to use ActiveWindow instead of ActiveExplorer, which returns nothing “if no explorer is active.” Thanks to CW for the impetus to update my code.

34 comments:

  1. Is anything special needed in order to enable this feature to work. I followed the instructions exactly, and the reminder still does not pop up on top of other windows...

    ReplyDelete
    Replies
    1. Hey Jason, I added an update that should work better. Thanks for your feedback. Let me know how everything works out.

      Delete
  2. Worked perfectly. Thank you, thank you, thank you. This was driving me crazy.

    ReplyDelete
  3. This is really good thanks.
    Just one question it does not seem to work on the first reminder after the PC has been booted. Once the first reminder has been accepted all subsequent reminders work just fine. I have temporally resolved this issue by setting a daily reminder early each morning so it pops up when I start outlook, this is Ok but a bit ugly, is there anyway of modifying the code to resolve this nice & neatly
    Gary

    ReplyDelete
    Replies
    1. Gary, great work around. Nothing that I've found so far. I'll post any better solutions if I stumble across them. Please let me know if you find something as well and I'll post it here.

      Delete
    2. I have found another workaround for this; albeit slightly ugly. It essentially pops up a message box for the first reminder of the session, which somehow forces the first activation to work. I wouldn't deploy this accross an organization, but the crude fix works for my own computer. Thanks Kyle for posting this, it works great:

      'Delcare Functions From User32 Library
      Private Declare PtrSafe Function FindWindowA Lib "user32" _
      (ByVal lpClassName As String, _
      ByVal lpWindowName As String) As Long
      Private Declare PtrSafe Function SetWindowPos Lib "user32" _
      (ByVal hwnd As Long, _
      ByVal hWndInsertAfter As Long, _
      ByVal X As Long, _
      ByVal Y As Long, _
      ByVal cx As Long, _
      ByVal cy As Long, _
      ByVal wFlags As Long) As Long

      'Declare Constants
      Private Const SWP_NOSIZE = &H1
      Private Const SWP_NOMOVE = &H2
      Private Const FLAGS As Long = SWP_NOMOVE Or SWP_NOSIZE
      Private Const HWND_TOPMOST = -1

      'Only show the message the first time
      Private messageAlreadyShown As Boolean

      'Finds Reminder Window and Brings to TopMost position
      Private Sub Application_Reminder(ByVal Item As Object)
      On Error Resume Next

      If Not messageAlreadyShown Then
      MsgBox "First Reminder", vbSystemModal, ""
      End If
      messageAlreadyShown = True

      ReminderWindow = FindWindowA(vbNullString, "1 Reminder")
      SetWindowPos ReminderWindow, HWND_TOPMOST, 0, 0, 0, 0, FLAGS
      End Sub

      Delete
    3. Thanks! This is a great quick fix. I've updated the post to include these changes.

      Delete
  4. Your code in step 5 worked for me, thanks. The longer recommended code did not work. I did have a few issues I was hoping you could comment on.

    1. This code opens up Outlook, rather than the reminder window. Is there any way to open up the reminder window itself? Another possibility is to use the code from the StackExchange thread you referenced to replace your 'Application.ActiveWindow.Activate' with a message box.

    Downside of this is that it is just a generic message.

    2. I know the main concern is appointments, but how would you modify the code to take all reminders into account? For example, what if you added a reminder directly to a message in your inbox?

    ReplyDelete
    Replies
    1. Hi JB,
      For 1), the last resort is to just display a message box. It's boring and dull, but it forces the application to receive focus in order to display the message box, which in turn, allows the reminder message to display. However this isn't maximally convenient because you then have to close two messages every time a reminder pops up and the point of this code was to get things to work correctly the first time as you'd expect they should. For anyone reading, just use this in your reminder event:

      MsgBox "Message text", vbSystemModal, "Message title"

      For 2), If you wanted it to work will all reminder items (AppointmentItem, MailItem, ContactItem, and TaskItem as per per Reminder Event, then you can just remove the following IF Block from the handling and it will fire for every event, although typically Appointment Items bear the most pertinent information.

      If TypeOf Item Is AppointmentItem Then

      I'm afraid I've been unable to fine tune it past what code I have so far. There's only so much to do to override what Windows is trying really hard to force upon the user.

      Delete
    2. Thanks Kyle - By the way, your write-up was excellent. I did a lot of research on this topic, and this is the only article that pulls everything together so that anyone benefit from it (even non-coders like me).

      Delete
  5. This works well however if reminder has come up and the reminder window then minmised, additional reminders don't bring the window up again.

    ReplyDelete
    Replies
    1. I get the same issue as this, I guess the workaround is to make sure you close it everytime and not just minimise which is easier said than done!

      Delete
  6. Hey, i am using outlook2007 and the above code is not working for me. It gives me an compliation error for ptrsafe function. It states that function or sub-function expected. Can you please help me.

    ReplyDelete
  7. Just wanted to give you a big THANK YOU for this!!!

    ReplyDelete
  8. Thank you!!!!! I was missing meetings after installing Outlook 2013.

    ReplyDelete
  9. This only works if there is only 1 reminder, because the Window name changes every time. If there is more than 1, then subsequent reminders don't pop on top. I made a loop that goes through 1-10, until it finds one. Probably a much way of doing this, but I'd don't really code stuff like this anymore.

    ReplyDelete
  10. Did the same as jeff suggested with a limit of 20, also its for OL 2013 ( 'n Reminder(s)' )

    here is the code:

    Private Declare PtrSafe Function FindWindowA Lib "user32" _
    (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

    Private Declare PtrSafe Function SetWindowPos Lib "user32" ( _
    ByVal hwnd As Long, ByVal hWndInsertAfter As Long, _
    ByVal X As Long, ByVal Y As Long, ByVal cx As Long, _
    ByVal cy As Long, ByVal wFlags As Long) As Long

    Private Const SWP_NOSIZE = &H1
    Private Const SWP_NOMOVE = &H2
    Private Const FLAGS As Long = SWP_NOMOVE Or SWP_NOSIZE
    Private Const HWND_TOPMOST = -1

    Private Sub Application_Reminder(ByVal Item As Object)
    Dim ReminderWindowHWnd As Variant
    Dim cnt As Long
    On Error Resume Next
    cnt = 1
    Do Until (cnt > 20 Or ReminderWindowHWnd <> 0)
    ReminderWindowHWnd = FindWindowA(vbNullString, cnt & " Reminder(s)")
    cnt = cnt + 1
    Loop
    SetWindowPos ReminderWindowHWnd, HWND_TOPMOST, 0, 0, 0, 0, FLAGS
    End Sub

    ReplyDelete
  11. The new code won't work on my Outlook 2007 (running on Win7 64bit). The output was "compile error". The new code seem not working with old 32 bit ?...
    It works perfectly woth Office 2010. Can anyone help me please?
    Cheers

    ReplyDelete
  12. You can use AutoIt from autohotkey to inspect the window and it appears that the class name for Outlook 2013 is #32770 for the reminder windows. This way you don't have to go through a loop and inspect the window title. It will also make the code work in other languages. Of course, the class may be different for different versions or service packs of Outlook.

    The original code would be modified to:
    ReminderWindow = FindWindowA("#32770", vbNullString)

    ReplyDelete
  13. For those who are having trouble with the other solutions mentioned here, you can go to www.radaker.com and download Outlook Reminders On Top. It's a quick and easy download. It just runs in your system tray, and it automatically pops up any Outlook reminder window above all other windows. And it will not steal the focus away from the application you're currently working in when it does it. Frankly it's the way Microsoft should have made it work to begin with!

    Thanks,
    Brad

    ReplyDelete
    Replies
    1. I was using the macro suggested initially, but when my company upgraded to Office 365 the macro doesn't seem to be behaving the same. I can't yet tell when/why reminders would be on top or in the background. I went ahead and tried Brad's suggestion of www.radaker.com and it appears to be the solution I was looking for all along.

      Delete
  14. My final code, has the popup for the first reminder but then behaves like the old reminder window from that point forward until you exit that session of Outlook. If you normally have more than 20 reminders in your window you may want to increase the loop count size.

    Private Declare PtrSafe Function FindWindowA Lib "user32" _
    (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

    Private Declare PtrSafe Function SetWindowPos Lib "user32" ( _
    ByVal hwnd As Long, ByVal hWndInsertAfter As Long, _
    ByVal X As Long, ByVal Y As Long, ByVal cx As Long, _
    ByVal cy As Long, ByVal wFlags As Long) As Long

    Private Const SWP_NOSIZE = &H1
    Private Const SWP_NOMOVE = &H2
    Private Const FLAGS As Long = SWP_NOMOVE Or SWP_NOSIZE
    Private Const HWND_TOPMOST = -1
    'Only show the message the first time
    Private messageAlreadyShown As Boolean

    Private Sub Application_Reminder(ByVal Item As Object)
    Dim ReminderWindowHWnd As Variant
    Dim cnt As Long
    On Error Resume Next

    'show message box for first reminder
    If Not messageAlreadyShown Then
    MsgBox "First Reminder", vbSystemModal, ""
    messageAlreadyShown = True
    'find reminder window
    ReminderWindow = FindWindowA(vbNullString, "1 Reminder")
    'bring reminder window to front
    SetWindowPos ReminderWindow, HWND_TOPMOST, 0, 0, 0, 0, FLAGS
    Exit Sub
    End If




    cnt = 1
    Do Until (cnt > 20 Or ReminderWindowHWnd <> 0)
    ReminderWindowHWnd = FindWindowA(vbNullString, cnt & " Reminder(s)")
    cnt = cnt + 1
    Loop
    SetWindowPos ReminderWindowHWnd, HWND_TOPMOST, 0, 0, 0, 0, FLAGS
    End Sub

    ReplyDelete
  15. Thank you, this worked like a charm. At my workplace no any additional software can be downloaded, so a solution must use what's already there. Which yours did, to perfection. Thanks again!

    ReplyDelete
  16. This worked like a Gem! Thank you!

    ReplyDelete
  17. If you are using office 2013, you can create the digital certificate by executing the below command from start icon

    C:\Program Files\Microsoft Office 15\root\office15\SELFCERT.EXE

    ReplyDelete
  18. This issue has been a constant irritation and I have missed or been late to a number of appointments and reminders due to it. Just installed this in Outlook and it works perfectly!! Thanks for the great code piece on this issue and providing it on the net. Best..

    ReplyDelete
  19. . In this course, you will get to learn about managing and structuring the data with the use of the modern technologies. cursos de ti

    ReplyDelete
  20. Hotmail.com On this subject internet page, you'll see my best information, be sure to look over this level of detail.

    ReplyDelete
  21. I have bookmarked your blog, the articles are way better than other similar blogs.. thanks for a great blog! budget tracking template

    ReplyDelete
  22. Many may have fallen victims of this chancy button - "reply all" without intending to send the mail to everyone tagged. You might want to double check whether or not the mail is intended for everyone in your company or just selected few - there is no undoing this, so you better be careful. [pii_email_37f47c404649338129d6]

    ReplyDelete