Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations wOOdy-Soft on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Controlling Application Attributes 3

Status
Not open for further replies.

SteveJR

Programmer
Aug 13, 2001
72
GB
Hi,

Does anyone know if there is a way to control application attributes? For example:

If I use the Shell command in say an Access form to start a Notepad session, is there a way to resize the Notepad application window, move the window etc

Any help would be much appreciated.

Thanks,

Steve
 
Private Declare Function MoveWindow Lib "user32" (ByVal hwnd As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal bRepaint As Long) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

Private Sub Form_Load()
Dim WinWnd As Long

'launch Notepad with Normal Focus so FindWindow can see it
Ret = Shell("Notepad", vbNormalFocus)

'Use FindWindow to get the handle to the Notepad window
WinWnd = FindWindow(vbNullString, "Untitled - Notepad")

'Move and size the window
MoveWindow WinWnd, 0, 0, 100, 100, 1

End Sub


*note that if the user happens to have an "Untitled - Notepad" already open than it will use this one instead of the new one... research EnumWindows if this is an issue.


 
As Hardkor says, one of the problems with FindWindow is that it cannot discriminate between 'your' just-launched app and any already running instances. What would be nice would be if there was some version of the Shell function that returned the hWnd of the application you launch rather than the hProcess.

Over in the VB5 & 6 forum I provided one potential solution to this in thread222-153621. Whilst that solution is specifically tailored towards launching the program through the Createprocess API (and hence has a lot of extraneous code) I mention that the same technique can be used for other methods of launching programs. Here's a minor rewrite that works with the Shell command. Just drop it into a code module:
[tt]
Option Explicit
Private Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As Long, lpdwProcessId As Long) As Long
Private Declare Function WaitForInputIdle Lib "user32" (ByVal hProcess As Long, ByVal dwMilliseconds As Long) As Long

Private Const INFINITE = &HFFFF
Public hWndApp As Long

Private Function EnumWindowsProc(ByVal hWnd As Long, ByVal lParam As Long) As Long
Dim hInstance As Long

EnumWindowsProc = True

GetWindowThreadProcessId hWnd, hInstance
If lParam = hInstance Then
hWndApp = hWnd
EnumWindowsProc = False ' End enumeration
End If

End Function

Public Function ShellAndGetWindowHandle(Pathname As String, Optional WindowStyle As VbAppWinStyle = vbMinimizedFocus) As Long

Dim hProcess As Long

hWndApp = 0
hProcess = Shell(Pathname, WindowStyle)
WaitForInputIdle hProcess, INFINITE 'Let it initialise properly

Call EnumWindows(AddressOf EnumWindowsProc, hProcess)

ShellAndGetWindowHandle = hWndApp
End Function
 
Mike/Hardcor1001110,

Thanks for the above. I was trying to use the ShellEx command last night as I noticed it returned a lot more params but I still couldn't get it to work!

Mike - I have added your code into a module in Access but it has an error on the AddressOf statement. Is there a way round this as I can't see anything in the help manual.

Thanks again for the above.

Steve
 
Ah! Sadly Access VBA doesn't support the AddressOf operator, so you can't use the callback enumerator. You will need to implement your own windows enumerator using FindFirstWindow and then (repeatedly) FindWindow. You only need to enumerate top-level windows.
 
Mike,

Not wanting to be a major pain but have you got any examples of what I need to do?

Thanks,

Steve
 
Steve,

If I get enough free time to put together the necessary code I'll do so. Apparantly, however, my employers would quite like me to spend my time producing code for them...

Mike
 
Cheers Mike.

I didn't think employers expected their employees to do 'proper' work on a Friday!

Anything that you could supply would be much appreciated for a newbie to VB!

Thanks,

Steve
email SJRichards_1@Hotmail.Com
 
Cheers Mike.

I didn't think employers expected their employees to do 'proper' work on a Friday!

Anything that you could supply would be much appreciated by a newbie to VB!

Thanks,

Steve
email SJRichards_1@Hotmail.Com
 
OK, add the following to the previous code:
[tt]
Private Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function GetTopWindow Lib "user32" (ByVal hwnd As Long) As Long

Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
Private Const GW_HWNDFIRST = 0
Private Const GW_HWNDNEXT = 2



Public Function myEnumWindows(lParam As Long) As Long
Dim hWndNext As Long
Dim EnumerationInProgress As Boolean

EnumerationInProgress = True
hWndNext = GetTopWindow(GetDesktopWindow())
hWndNext = GetWindow(hWndNext, GW_HWNDFIRST)
Do While hWndNext <> 0 And EnumWindowsProc(hWndNext, lParam) <> 0
hWndNext = GetWindow(hWndNext, GW_HWNDNEXT)
Loop

End Function
[/tt]
and replace

[tt]Call EnumWindows(AddressOf EnumWindowsProc, hProcess)[/tt]
in the ShellAndGetWindowHandle function with
[tt]
Call myEnumWindows(hProcess)

 
Mike,

Not too sure what is happening here. I have placed the code above into a module. After it has executed and returned an application handle I am using the MoveWindow function but it is not doing anything!

Any suggestions?

Steve
 
Works fine here with the returned window handle. I guess we'd need to see some of your code to progress this any further.
 
it's probably something simple. some suggestions: try using MoveWindow with an Hwnd you know is correct, like Form1.Hwnd, check your returned handles to make sure they're not Null, if you are launching Notepad as vbMinimizedFocus which is the default you would also have this problem.

btw, you're going to run into some other quirks that you probably didn't expect. when a user clicks on your Access app, notepad will loose foreground focus and disappear. Users will experience other little inconsistencies. It will depend on their skill level as to how much of an issue this really is.

to curb some of the inconsistencies you may have some luck with SetParent, which will turn the notepad into a child of your Access app. This will keep it from disappearing and keep it attached to your window. This might help a little but may have some problems as well, you just have to try it and see... Here you go...

Declare Function SetParent Lib &quot;user32&quot; Alias &quot;SetParent&quot; (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long
 
Mike/HardKor1001110,

Found the problem - it was as HardKor said. I changed the call to the Shell command to pass a windows value of 1(VBNormalFocused) and all works ok now. It causes the screen to flicker slightly as the application is started and resized but I can live with that!

Thank you both for your help and the code you provided. I might just be able to get to grips with VB!

Thanks again,

Steve
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top