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 bkrike on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Controlling third party apps within VB

Status
Not open for further replies.

coboldave

MIS
Dec 20, 2001
41
US
I was very lucky being able to find this free source code at The program allows me to start any executable program (I use COBOL) from within. What makes it different from Winexec and other methods is that the third party app does not appear in the task bar while running and when minimized it goes to the lower left hand corner, not to the taskbar. This works well for those who wish to create a Visual Basic frontend for console programs or to include notepad or others.

The one problem that I find with it is, that it does not work on an MDI child form. I'm sure I'm missing something, I just don't know what. VB6, and Win98.


Option Explicit

Private Const GW_HWNDNEXT = 2

Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Private Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As Long, ByVal lpWindowName As Long) As Long
Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Private Declare Function SetParent Lib "user32" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long

Private old_parent As Long
Private child_hwnd As Long

' Return the window handle for an instance handle.
Private Function InstanceToWnd(ByVal target_pid As Long) As Long
Dim test_hwnd As Long
Dim test_pid As Long
Dim test_thread_id As Long

' Get the first window handle.
test_hwnd = FindWindow(ByVal 0&, ByVal 0&)

' Loop until we find the target or we run out
' of windows.
Do While test_hwnd <> 0
' See if this window has a parent. If not,
' it is a top-level window.
If GetParent(test_hwnd) = 0 Then
' This is a top-level window. See if
' it has the target instance handle.
test_thread_id = GetWindowThreadProcessId(test_hwnd, test_pid)

If test_pid = target_pid Then
' This is the target.
InstanceToWnd = test_hwnd
Exit Do
End If
End If

' Examine the next window.
test_hwnd = GetWindow(test_hwnd, GW_HWNDNEXT)
Loop
End Function

Private Sub cmdFree_Click()
SetParent child_hwnd, old_parent

cmdRun.Enabled = True
cmdFree.Enabled = False
End Sub

Private Sub cmdRun_Click()
Dim pid As Long
Dim buf As String
Dim buf_len As Long

' Start the program.
pid = Shell(txtProgram.Text, vbNormalFocus)
If pid = 0 Then
MsgBox &quot;Error starting program&quot;
Exit Sub
End If

' Get the window handle.
child_hwnd = InstanceToWnd(pid)

' Reparent the program so it lies inside
' the PictureBox.
old_parent = SetParent(child_hwnd, picChild.hwnd)

cmdRun.Enabled = False
cmdFree.Enabled = True
End Sub

Private Sub Form_Resize()
Dim hgt As Single

hgt = ScaleHeight - picChild.Top
If hgt < 120 Then hgt = 120

picChild.Move 0, picChild.Top, ScaleWidth, hgt
End Sub
 
Dave,

Can't give you the exact code at the mo, I'm a bit busy, but it looks like you're setting the wrong hDC or hwnd.

When you run the code in a standalone form, the API calls 'link'(Very bad description!) your new process to the desktop because it's the form's &quot;parent&quot;, so it works fine.

When you place the code into an MDIchild, the parent is now the MDIform, not the Desktop, so the process 'links' to the MDIform rather than the Desktop, and it doesn't behave as expected.

All you need to do is examine the code and replace the hwnd's for the MDIform (or Parent) with the hwnd for the desktop.. You can get the function to extract the desktop's hwnd from allapi.

Hope that was clear enough to at least point you in the right direction.

Let us know how you get on!
 
Actually I,m stalled here. I don't know where to begin to fix it.
 
In what way doesn't it work?

I jusy copied and pasted your code into exactly the same setup (VB6, W98), and it works fine on an MDI child.
 
strongm,

I found that running from a 'standalone' form allowed the launched app to minimize to the systray while seeming to run standalone, however, when running the code from the MDI child form, the app launches as child process to the MDIform, staying whithin and minimizing within the MDIform.

I think that coboldave is trying to get the MDIchild to launch his app as a separate process being able to drop to the systray, much like a Service.

dave, is that right or have I got the wrong end of the stick?

and strongm, what results did you get?
 
Hmm.
I'm away from any of my development boxes today, so I won't have a chance to look at this again until tonight...
 
I am wanting to run the app from the MDI child and minimize within the MDIform.

For me, it runs fine as a standalone but as a MDI child it runs in the background. Pressing Ctrl+Del, I can see the app (runcobol.exe).

Running the code I provided are any of you having to create a picture box on the form?

What changes in the naming structure did you have to make?

VB is very new but intriguing *<|:),
I must conquer VB!
::)
 
Weird. If that's what you're after, it should work fine!

Yes, you need a PictureBox called picChild
Also two Command buttons: cmdFree and cmdRun
Lastly a textbox called txtProgram.

Start a new Project.
Remove the default form
Add an MDIform.
Add a (big) PictureBox to the MDIform
* MDIforms can only accept controls with hDC's so...
Add the controls into your picturebox.

Run the code, type your program name into the textbox and hit cmdRun... all should run fine. You'll probably have to type the full path. I just tested with 'notepad.exe'...

The only 'funny' I found was when moving the app by it's caption bar the co-ordinates where a little bit out, but I think that was the way I'd laid out the buttons and textbox.
Anyway, It shouldn't take too much correction.

Yes, the app shows in the task list. I did see somewhere some sourcecode to run your app as a hidden process (Service), but I can't remember where. I'm unsure if that's what you're after... If it is, a quick search should point you in the right direction!

To further extend the app you could also...
*Instead of one PictureBox, use two, one called PicHeading (thin) to store your controls, one called picChild to run the app in.
*add some code to the resize event to ensure your picChild takes up the fully available client area of the MDIform.


HTH
 
If it doesn't work-start over.

That's what I did, and it worked! I really didn't want to redo my menu's for that form but it's now worth it.

Instead of using the Run command button, I changed the Shell=(txtProgram.Text, vbNormalFocus)to Shell=(&quot;c:\cobol\runcobol.exe objectfile&quot;, vbNormalFocus)Later I'll work on the path thing.

The one problem is that if I close the MDI child while the cobol app is open I get a fatal error and have to reboot. How do I close the app at the same time as I close the MDI child window?

How can I prevent two of the same objects from being able to run at the same time?
 
dave,

Ahh, those halcyon days of Cobol2 and Level II !!
(THAT'S how long it's been since I touched COBOL!!)

Why the cobol is failing, I'd have no idea. It maybe the app itself not unloading nicely, or something in the child form is acting up. If it needs a re-boot, though, it's gotta be fairly serious!

Maybe you could pass a parameter to the Cobol App to close it down before the form closes? In the unload event or something?

point 2...
You CAN use API calls to test whether or the app is running, but I'd reckon it would be easier to just set a flag and check it like...

If Not(booAppRunning) Then
Shell=(&quot;c:\cobol\runcobol.exe objectfile&quot;, vbNormalFocus)
booAppRunning = True
End If

(However, this'll obviously fail if you've two MDI instances running, so it looks like it's back to the API - There's an FAQ somewhere)

Let us know how you get on.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top