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 onThisOutlookSession
- 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.
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...
ReplyDeleteHey Jason, I added an update that should work better. Thanks for your feedback. Let me know how everything works out.
DeleteWorked perfectly. Thank you, thank you, thank you. This was driving me crazy.
ReplyDeleteWorks great so far. Thanks Kyle
ReplyDeleteThis is really good thanks.
ReplyDeleteJust 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
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.
DeleteI 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:
Delete'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
Thanks! This is a great quick fix. I've updated the post to include these changes.
DeleteYour 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.
ReplyDelete1. 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?
Hi JB,
DeleteFor 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.
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).
DeleteThis works well however if reminder has come up and the reminder window then minmised, additional reminders don't bring the window up again.
ReplyDeleteI 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!
DeleteHey, 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.
ReplyDeleteJust wanted to give you a big THANK YOU for this!!!
ReplyDeleteThank you!!!!! I was missing meetings after installing Outlook 2013.
ReplyDeleteThis 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.
ReplyDeleteDid the same as jeff suggested with a limit of 20, also its for OL 2013 ( 'n Reminder(s)' )
ReplyDeletehere 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
Perfect
ReplyDeleteThe 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 ?...
ReplyDeleteIt works perfectly woth Office 2010. Can anyone help me please?
Cheers
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.
ReplyDeleteThe original code would be modified to:
ReminderWindow = FindWindowA("#32770", vbNullString)
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!
ReplyDeleteThanks,
Brad
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.
DeleteMy 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.
ReplyDeletePrivate 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
Thanks, works really well
ReplyDeleteThank 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!
ReplyDeleteThis worked like a Gem! Thank you!
ReplyDeleteIf you are using office 2013, you can create the digital certificate by executing the below command from start icon
ReplyDeleteC:\Program Files\Microsoft Office 15\root\office15\SELFCERT.EXE
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. In this course, you will get to learn about managing and structuring the data with the use of the modern technologies. cursos de ti
ReplyDeleteHotmail.com On this subject internet page, you'll see my best information, be sure to look over this level of detail.
ReplyDeleteI have bookmarked your blog, the articles are way better than other similar blogs.. thanks for a great blog! budget tracking template
ReplyDeleteMany 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Đặt vé tại phòng vé Aivivu, tham khảo
ReplyDeletevé máy bay đi Mỹ tháng nào rẻ nhất
vé máy bay vinh sài gòn tháng 3
vé máy bay từ nha trang về hà nội
lịch bay hà nội đà lạt
vé máy bay giá rẻ đi Huế
thuê xe đi sân bay nội bài
combo hà nội đà nẵng