Set Global Address Dialog as ForeGroundWindow

hatman

Well-known Member
Joined
Apr 8, 2005
Messages
2,664
My code works well for computer with and without Outlook INstalled. Provided an Outlook Session is already running, then this whole thing works fine, however, if not, then the SetForeGroundWindow is not able to bring the dialog to the foreground. My users are the brightest bulbs, and a blinking Outlook icon in the Taskbar is not adequate to alert them that a dialog is waiting for them. As soon as teh .Display method is invoked, XL waits for the Dialog to be dismissed by the user. Until that point, there is no visible window for the SetForeGroundWindow function to grab hold of...

Please Help.

Code:
Option Explicit
Private Declare Function FindWindow Lib "user32" _
    Alias "FindWindowA" _
    (ByVal lpClassName As String, _
    ByVal lpWindowName As String) As Long
    
Private Declare Function SetForegroundWindow Lib "user32" _
    (ByVal hwnd As Long) As Long
 

Public Function ShowOnlyContacts(Optional ByVal vstrContacts As String = "") As String
  
    Const c_strOutlook_Class As String = "rctrl_renwnd32"
    
    #If Development Then
  
        Dim olApp As Outlook.Application
        Dim oAL As Outlook.AddressList
        Dim oDialog As Outlook.SelectNamesDialog
        Dim oMsg As Outlook.MailItem
  
    #Else
  
        Dim olApp As Object
        Dim oAL As Object
        Dim oDialog As Object
        Dim oMsg As Object
  
    #End If
  
    Dim strRecipients As String
    Dim arrRecipient() As String
    Dim intIndex As Integer
    Dim lngHWND As Long
    Dim blnCreated_Outlook As Boolean
  
  
    DoEvents
    
    On Error Resume Next
    
    Set olApp = GetObject(, "Outlook.Application")
    
    If olApp Is Nothing Then
  
          #If Development Then
        
              Set olApp = VBA.CreateObject("Outlook.Application")
        
          #Else
        
              Set olApp = New Outlook.Application
              
          #End If
          
          blnCreated_Outlook = True
          
    End If
    
    On Error GoTo 0
    
    If olApp Is Nothing Then
    
'        MsgBox "Please install Microsoft Outlook on this machine and try again.", vbOKOnly +vbCritical , "OOPS"
    
        Exit Function
        
    End If
    
    lngHWND = FindWindow(c_strOutlook_Class, vbNullString)
    SetForegroundWindow lngHWND
    
    Set oMsg = olApp.CreateItem(olMailItem)
    
    Set oDialog = olApp.Session.GetSelectNamesDialog
  
    arrRecipient = Split(vstrContacts, ";")
  
    For intIndex = 0 To UBound(arrRecipient)
        
        oMsg.Recipients.Add arrRecipient(intIndex)
  
    Next intIndex
    
    Set oAL = olApp.GetNamespace("MAPI").AddressLists("Global Address List")
  
    With oDialog
        .InitialAddressList = oAL
        .ShowOnlyInitialAddressList = True
        .Recipients = oMsg.Recipients
        .NumberOfRecipientSelectors = olShowTo
        .Display
        DoEvents
    End With
 
    strRecipients = ""
    
    For intIndex = 1 To oMsg.Recipients.Count
    
        strRecipients = strRecipients & "; " & oMsg.Recipients(intIndex)
        
    Next
    
    ShowOnlyContacts = Mid(strRecipients, 2)
  
    SetForegroundWindow Application.hwnd
    
    Set oDialog = Nothing
    Set oAL = Nothing
    Set oMsg = Nothing
    
    If blnCreated_Outlook Then
    
        olApp.Quit
        
    End If
    
    Set olApp = Nothing
  
End Function
 

Excel Facts

Remove leading & trailing spaces
Save as CSV to remove all leading and trailing spaces. It is faster than using TRIM().
RESOLVED (i think): Set Global Address Dialog as ForeGroundWindow

So I guess I would need to better understand the difference between SetForeGroundWindow and SetActiveWindow. The MSDN documentation is too obscure for me to use in explaining the solution or the behaviour. The long and short is I added a SetActiveWindow just before I display the dialog (SetForeGroundWindow at this point in teh code did nothing), and when the window become visible, it becomes the top/active window, as desired. I figured at that point that the earlier invocation of the SetForeGroundWindow was redundant, so I remove dit. As expected, it didn't make a difference when Outlook was instantiated by the code. However, when grabbing an instance that is already running, the code failed to bring teh dialog to the foreground. So I re-inserted the SetForeGroundWindow into teh code to bring the main Outlook window to teh front first (if it's visible). This seems to work under both scenarios, at least on my machine. Several more test cases to go, but it looks promising. Any explanation about this behaviour would be appreciated.

Final Code (well, before beta-testing and complete debugging):
Code:
Option Explicit
Private Declare Function SetForegroundWindow Lib "user32" _
    (ByVal hwnd As Long) As Long

Private Declare Function FindWindow Lib "user32" _
    Alias "FindWindowA" _
    (ByVal lpClassName As String, _
    ByVal lpWindowName As String) As Long
Private Declare Function SetActiveWindow Lib "user32.dll" _
    (ByVal hwnd As Long) As Long

Public Function ShowOnlyContacts(Optional ByVal vstrContacts As String = "") As String
  
    Const c_strOutlook_Class As String = "rctrl_renwnd32"
    
    #If Development Then
  
        Dim olApp As Outlook.Application
        Dim oAL As Outlook.AddressList
        Dim oDialog As Outlook.SelectNamesDialog
        Dim oMsg As Outlook.MailItem
  
    #Else
  
        Dim olApp As Object
        Dim oAL As Object
        Dim oDialog As Object
        Dim oMsg As Object
  
    #End If
  
    Dim strRecipients As String
    Dim arrRecipient() As String
    Dim intIndex As Integer
    Dim lngHWND As Long
    Dim blnCreated_Outlook As Boolean
  
  
    DoEvents
    
    On Error Resume Next
    
    Set olApp = GetObject(, "Outlook.Application")
    
    If olApp Is Nothing Then
  
          #If Development Then
        
              Set olApp = VBA.CreateObject("Outlook.Application")
        
          #Else
        
              Set olApp = New Outlook.Application
              
          #End If
          
          blnCreated_Outlook = True
          
    End If
    
    On Error GoTo 0
    
    If olApp Is Nothing Then
    
'        MsgBox "Please install Microsoft Outlook on this machine and try again.", vbOKOnly +vbCritical , "OOPS"
    
        Exit Function
        
    End If
    
    lngHWND = FindWindow(c_strOutlook_Class, vbNullString)
    SetForegroundWindow lngHWND
    
    Set oMsg = olApp.CreateItem(olMailItem)
    
    Set oDialog = olApp.Session.GetSelectNamesDialog
  
    arrRecipient = Split(vstrContacts, ";")
  
    For intIndex = 0 To UBound(arrRecipient)
        
        oMsg.Recipients.Add arrRecipient(intIndex)
  
    Next intIndex
    
    Set oAL = olApp.GetNamespace("MAPI").AddressLists("Global Address List")
  
    
    With oDialog
        .InitialAddressList = oAL
        .ShowOnlyInitialAddressList = True
        .Recipients = oMsg.Recipients
        .NumberOfRecipientSelectors = olShowTo
        
        lngHWND = FindWindow(vbNullString, "Select Names: Global Address List")
        SetActiveWindow lngHWND
        
        .Display
        DoEvents
    End With
 
    strRecipients = ""
    
    For intIndex = 1 To oMsg.Recipients.Count
    
        strRecipients = strRecipients & "; " & oMsg.Recipients(intIndex)
        
    Next
    
    ShowOnlyContacts = Mid(strRecipients, 2)
  
    SetForegroundWindow Application.hwnd
    
    Set oDialog = Nothing
    Set oAL = Nothing
    Set oMsg = Nothing
    
    If blnCreated_Outlook Then
    
        olApp.Quit
        
    End If
    
    Set olApp = Nothing
  
End Function
 
Upvote 0
Re: RESOLVED (i think): Set Global Address Dialog as ForeGroundWindow

Hmm, not as much as I thought. Turns out, with additional testing, this was not consistantly bringing teh GAL Dialog to teh foreground, when Outlook was not already running. And on laptops connecting the network via wireless, instantiating a new Outlook session could take several minutes. Further, we actually have some machines with Outlook installed that IT has firewalled out of the MAPI network, which I woul dneed to test to see what happens when a session gets instrantiated but no account is set up, and no connectiosn are available. I ended simply displaying a message box telling the user to start up Outlook before trying again, then exit the function... not as robust as I would like, but on a Friday afternoon, an hour before I leave and go home to play at being a Blueberry Farmer, it seems like the right and proper decision.
 
Upvote 0

Forum statistics

Threads
1,215,372
Messages
6,124,542
Members
449,169
Latest member
mm424

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top