Make Access The Active Window

MattS

Crabby Cancerian.....
Local time
Today, 00:14
Joined
Jun 18, 2003
Messages
130
Is this possible?

I'm using the code from rogers access library that allows you to automatically kick users out of a DB. It works on the on_timer event, and in my case opens a form telling them to get out (which closes after 30 seconds), and then exits them after 3 minutes.

This works fine, but some users have a habit of just 'sitting' in the DB. They leave it open in the background whilst working in other applications.

What I want to do is make Access the active window when I open the warning form. I tried making the form modal & pop_up, but this only seems to apply within Access.

Any ideas?

Thanks,

Matt.
 
Check the help files for the AppActivate Statement.

HTH
 
Thanks for the replys guys.

Wayne - wasn't really what I needed this time, but some nice tricks in there I may make use of at a later date.

Ghudson - have tried the AppActivate statement, and it kind of half works. I call it just before I open the warning form, but it doesn't actually make Access the foremost window. It simply makes the shortcut in the Taskbar flash.

I think if I want to make Access the foremost window, I may have to use some kind of API call.

Thanks for your help.

Matt.
 
Thanks for the help so far. Using various of the above suggestions, I currently have the following code included within my on_timer event:

Code:
Dim lngHwnd As LongstrAppTitle As String
    strAppTitle = CurrentDb.Properties("AppTitle") ' Get Database name
    AppActivate strAppTitle ' Make Database active window
    DoCmd.SelectObject acForm, Me.Name ' Set focus onto this form
    lngHwnd = Screen.ActiveForm.Hwnd ' Get this forms Windows handle
    Call apiSetForegroundWindow(lngHwnd) ' Make API call
The API call is:

Code:
Declare Function apiSetForegroundWindow Lib "user32" Alias "SetForegroundWindow" (ByVal Hwnd As Long) As Long
Everything upto the call seems fine, but I'm struggling with the technicalities of the API call (I know ZILCH about them!).

If anybody understands these things your help would be appreciated.

Thanks,

Matt.
 
Here is some code I have used for checking for multiple instances of the application when it is opened, if it is already open it will set focus to the previously opened version. It might help you to do what you require.

Code:
' Module mdlCheckMultipleInstances
' © Graham Mandeno, Alpha Solutions, Auckland, NZ
' [email]graham@alpha.co.nz[/email]
' This code may be used and distributed freely on the condition
'  that the above credit is included unchanged.
 
Private Const cMaxBuffer = 255
 
Private Declare Function apiGetClassName Lib "user32" _
  Alias "GetClassNameA" _
  (ByVal hWnd As Long, _
  ByVal lpClassName As String, _
  ByVal nMaxCount As Long) _
  As Long
    
Private Declare Function apiGetDesktopWindow Lib "user32" _
  Alias "GetDesktopWindow" _
  () As Long
  
Private Declare Function apiGetWindow Lib "user32" _
  Alias "GetWindow" _
  (ByVal hWnd As Long, _
  ByVal wCmd As Long) _
  As Long
  
Private Const GW_CHILD = 5
Private Const GW_HWNDNEXT = 2
 
Private Declare Function apiGetWindowText Lib "user32" _
  Alias "GetWindowTextA" _
  (ByVal hWnd As Long, _
  ByVal lpString As String, _
  ByVal aint As Long) _
  As Long
  
Private Declare Function apiSetActiveWindow Lib "user32" _
  Alias "SetActiveWindow" _
  (ByVal hWnd As Long) _
  As Long
 
Private Declare Function apiIsIconic Lib "user32" _
  Alias "IsIconic" _
  (ByVal hWnd As Long) _
  As Long
 
Private Declare Function apiShowWindowAsync Lib "user32" _
  Alias "ShowWindowAsync" _
  (ByVal hWnd As Long, _
  ByVal nCmdShow As Long) _
  As Long
 
Private Const SW_SHOW = 5
Private Const SW_RESTORE = 9

Public Function winGetClassName(hWnd As Long) As String
Dim sBuffer As String, iLen As Integer
  sBuffer = String$(cMaxBuffer - 1, 0)
  iLen = apiGetClassName(hWnd, sBuffer, cMaxBuffer)
  If iLen > 0 Then
    winGetClassName = Left$(sBuffer, iLen)
  End If
End Function
 
Public Function winGetTitle(hWnd As Long) As String
Dim sBuffer As String, iLen As Integer
  sBuffer = String$(cMaxBuffer - 1, 0)
  iLen = apiGetWindowText(hWnd, sBuffer, cMaxBuffer)
  If iLen > 0 Then
    winGetTitle = Left$(sBuffer, iLen)
  End If
End Function
 
Public Function winGetHWndDB(Optional hWndApp As Long) As Long
Dim hWnd As Long
winGetHWndDB = 0
If hWndApp <> 0 Then
  If winGetClassName(hWndApp) <> "OMain" Then Exit Function
End If
hWnd = winGetHWndMDI(hWndApp)
If hWnd = 0 Then Exit Function
hWnd = apiGetWindow(hWnd, GW_CHILD)
Do Until hWnd = 0
  If winGetClassName(hWnd) = "ODb" Then
    winGetHWndDB = hWnd
    Exit Do
  End If
  hWnd = apiGetWindow(hWnd, GW_HWNDNEXT)
Loop
End Function
 
Public Function winGetHWndMDI(Optional hWndApp As Long) As Long
Dim hWnd As Long
winGetHWndMDI = 0
If hWndApp = 0 Then hWndApp = Application.hWndAccessApp
hWnd = apiGetWindow(hWndApp, GW_CHILD)
Do Until hWnd = 0
  If winGetClassName(hWnd) = "MDIClient" Then
    winGetHWndMDI = hWnd
    Exit Do
  End If
  hWnd = apiGetWindow(hWnd, GW_HWNDNEXT)
Loop
End Function
 
Public Function winCheckMultipleInstances(Optional fConfirm As Boolean = True) As Boolean
Dim fSwitch As Boolean, sMyCaption As String
Dim hWndApp As Long, hWndDb As Long
On Error GoTo ProcErr
  sMyCaption = winGetTitle(winGetHWndDB())
  hWndApp = apiGetWindow(apiGetDesktopWindow(), GW_CHILD)
  Do Until hWndApp = 0
    If hWndApp <> Application.hWndAccessApp Then
      hWndDb = winGetHWndDB(hWndApp)
      If hWndDb <> 0 Then
        If sMyCaption = winGetTitle(hWndDb) Then Exit Do
      End If
    End If
    hWndApp = apiGetWindow(hWndApp, GW_HWNDNEXT)
  Loop
  If hWndApp = 0 Then Exit Function
  If fConfirm Then
    MsgBox sMyCaption & " is already open@" & "Application already opened.  Use other instance.@", vbOKOnly, mbTitle
    'AppActivate "Absence Recorder"
  End If
  apiSetActiveWindow hWndApp
  If apiIsIconic(hWndApp) Then
    apiShowWindowAsync hWndApp, SW_RESTORE
  Else
    apiShowWindowAsync hWndApp, SW_SHOW
  End If
  Application.Quit
ProcEnd:
  Exit Function
ProcErr:
  MsgBox Err.Description
  Resume ProcEnd
End Function
 
Thanks for the code, but from what I can make of it, it's all about which window within Access it shows.

I've attached a (very) simple example of what I'm trying to do. Open the db and after 15 seconds another form opens telling you to get out. This closes after 5 seconds, and the db then closes after another 10. This all works no probs.

If you try again, but this time after opening the db, go into whatever other applications you feel like. If you have the same result as me, all that happens is the caption in the Task Bar starts flashing.

The problem I have is, what's the point of warning a user they're being kicked out when they can't see the warning!! I believe this all to do with the API call.

Any comments appreciated.

Thanks,

Matt.
 

Attachments

The testdb works as follows on my PC, NT 4 with A2K.

If application is behind other windows and is not minimised it will be set to the active window and brought to the front.
If the application is minimised then it just causes the icon to indent on the taskbar but does not bring it to front.

I have changed some details of your code using the code from the Check Multiple Instances and now it will bring the application to the front regardless of whether it is minimised or not.

I have attached the new version.
 

Attachments

Thanks for all your help Antomack.

I still can't get it to work correctly - I got the following results, with Outlook and Internet Explorer also open:

  • TestDB minimised, Outlook as foreground window - OK
  • TestDB minimised, IE as foreground window - OK
  • TestDB maximised, Outlook as foreground window - OK
  • TestDB maximised, IE as foreground window - no change (icon in taskbar flashes)

I also tried it with Excel instead of IE and got the same results. I can't understand why it will make the DB the active window over Outlook, but not the other applications.:confused:

Maybe it's something peculiar to Windows2K?

Like I said, thanks for your help,

Matt
 
I just tried it on W2K myself and as you said all it does is cause the icon on the taskbar to flash, while in NT it will set the application window as the top one.

If you search on MSDN for SetForegroundWindow it details that the flashing cursor is the standard for 98/ME/2000/XP but it can be changed by changing the SystemParametersInfo; this seems to effect all applications then.

A possible 'solution' in W2K would be to use Shell to do a NetSend to the user's screen telling them that they are going to be logged out, etc.. You will need to use API to get the machine id and then can use
Shell ("Net send " & strMchID & " " & strMsg)

where strMchIOD = machine's network ID and strMsg = message you want to appear to the user.
 
Last edited:
Using the Shell command works perfectly.:D Thanks for all your help.

Matt.
 

Users who are viewing this thread

Back
Top Bottom