Maximize other application from VBA

G

Guest

How do I maximize an already running - but minimized - application from
Access VBA?

I want db1.mde to activate and maximize db2.mde, where both db1 and db2 are
applications in Access2K saved as .mde files
 
G

Guest

You can use the sendkeys method to do a lot of things in other databases.
Try playing around with that.
 
N

Nikos Yannacopoulos

How do you do this with SendKeys? For instance, how do you know how many
Alt+Tab 's to activate the target window?

SendKeys is one of Access's big dont's. If I had my way with Access
product development in Microsoft, I would (a) fire whoever came up with
SendKeys, and (b) make sure it never appears again in a future version.
It is notorious for doing anything but what it was intended to, nine
times out of ten or more - and for a good reason too: it just sends
keystrokes without being able to check its environment or their results,
nor does it seem to care!
For whatever one might try to accomplish with SendKeys, there is a
better, much more robust way (in your case, check out Alex's answer),
and any developer out there will advise you to exhaust all other
possibilities before you decide to resort to SendKeys.

HTH,
Nikos
 
A

Alex White MCDBA MCSE

Yep, if it can break it will, I personally never use SendKeys I have always
found a way round it, now that I have said that I will have to use it
today!!!!
 
G

Guest

Thanks for the link. But how do I declare the functions in the User32.dll?

I can not reference it in my VBA module, so I have to make it in a specific
statement.
 
A

Alex White MCDBA MCSE

Hi Diane,

create a module (you should always put code like in a module of its own) and
copy all the code below this line until the rem **** STOP ****

Declare Function EnumWindows Lib "user32" (ByVal wndenmprc As Long, ByVal
lParam As Long) As Long
Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal
hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd
As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Declare Function BringWindowToTop Lib "user32" (ByVal hwnd As Long) As Long
Public Const WM_SYSCOMMAND = &H112
Public Const SC_MAXIMIZE = &HF030&

Private Target As String
' Check a returned task to see if we should
' maximize it.
Public Function EnumCallback(ByVal app_hWnd As Long, ByVal param As Long) As
Long
Dim buf As String * 256
Dim title As String
Dim length As Long

' Get the window's title.
length = GetWindowText(app_hWnd, buf, Len(buf))
title = Left$(buf, length)

' See if this is the target window.
If InStr(title, Target) <> 0 Then
' Maximize the window.
SendMessage app_hWnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0
BringWindowToTop app_hWnd

' Stop searching.
EnumCallback = 0
Else
' Continue searching.
EnumCallback = 1
End If
End Function

' Ask Windows for the list of tasks.
Public Sub MaximizeTask(app_name As String)
Target = app_name
EnumWindows AddressOf EnumCallback, 0
End Sub

rem **** STOP ****

this is not my code it is taken from the same place that I pointed you to in
the earler post, but it should do what you want.

any problems post back here.
 
G

Guest

Hi Alex,

The sample code works - but it is not very stable. I can make db1 detect and
activate db2 - but sometimes it does not work. And now the code gives a "DDE
Server Window: MSACCESS.EXE - Application Error" and crashes completely.

Is there a simpler way to identify an already running application - since I
know the name, there should be no need to loop trough all active applications
- but just go to the one I want.
 
A

Alex White MCDBA MCSE

Hi Diane,

if you can the hWnd (internal windows handle) of each of the windows then if
you run

Application.hWndAccessApp

in the other mdb's it returns the window handle for itself, couple of ways
we can solve this either write the current hWnd into a registry key or a
database record for the other (controlling) database to read.

by calling MaxhWnd( with the window handle it should work )

Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd
As Long, ByVal wMsg As Long, ByVal wParam As Long,lParam As Any) As Long
Declare Function BringWindowToTop Lib "user32" (ByVal hwnd As Long) As Long
Public Const WM_SYSCOMMAND = &H112
Public Const SC_MAXIMIZE = &HF030&

public sub MaxhWnd(lnghWnd as long)
SendMessage lnghWnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0
BringWindowToTop lnghWnd
end sub

If you continue to have stability problems post back and I will do some
testing for you.
 
G

Guest

oh - one more detail

If I communicate a handle - how do I then know that the application is still
active?

This is all about preventing duplicate instances of one application - so I
want to check if db2 is currently running minimized - and if so, then
maximize it - otherwise open a new instance of db2.
 
G

Guest

Now that works!

Only detail is then that I have to communicate the handle. The really cool
solution was to have a function that returns the handle of the application
with a given title.

Then I could have db1 get the handle of db2 and then maiximize it.
 
A

Alex White MCDBA MCSE

Hi Diane,

It sounds to me like you are already running the other two databases to me
the best solution is they 'advertise' their hWnd handles to the registry or
db, see how much code has been stripped away because we don't have to go
trrough the windows handle list checking for captions, also this system is
more reliable as you can change the caption of either of the other two
databases and it will still work

look into 2 commands

getsettings

savesettings

for reading and writing to the registry.
 
G

Guest

Hi Alex
Thanks for your patience...

Now the registry works as a way to communicate the handle.

I still have a problem:
If the PC lost power and is tarted up again, the registry still holds the
old handle of db2 - and then db1 tries to activate an application that doesnt
run any more - and in that case it should start db2 (not just maximize it).

In other words db1 is the "starter" of db2, and in case db2 is minimized (by
accident) it just maximizes it - but id db2 is not running at all - it starts
it.

So I still need to find out whether db2 is in fact running or not. Checking
on .ldb is not good enough - because in case of a power loss the .ldb files
are not cleaned up, and then this would incorrectly indicate db2 still
running.

Any ideas on how to see if a handle actually still runs?
 
A

Alex White MCDBA MCSE

Hi Diane,

I have to ask, what is the chance of the PC loosing power, also if the PC
lost power you could clear the entries in the registry as a startup process,
e.g.
allways make sure you run the 'controlling' mdb first, as is startup
procedure, it clears the registry settings, then run the other 2 mdb's they
then need to write the new entries to the registry.

The other thing to do is if the routine that maximizes the mdb fails then
shell a process to run that database then try to maximize it again,
something like

Shell "Start c:\db1.mdb" should do the trick.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top