Solved

Shell as child of MDI

Posted on 1998-12-22
11
484 Views
Last Modified: 2012-08-13
I have a program that from an MDI form the file menu lets you start a program that will come up in a shell and gain focus.  What I want is that shell to be a child of the MDI form so that you will be able to run both the shell program and the vb program.
0
Comment
Question by:zaq
  • 3
  • 3
  • 3
  • +2
11 Comments
 
LVL 13

Expert Comment

by:Mirkwood
ID: 1451965
As an MDI child window is impossible. An MDI window needs to contain more information than a regular window.
It is possible to make the application a child window using the SetParent api.
You first have to get the window handle of the launched application and then make it your child using the SetParent API.

One trick that is often used is to change the style of the child window and remove all borders and caption. Now create a MDI form and make the launched application a child of this MDI form. This works ok for 80%. The problem is that accelerator keys do not work and that the TAB key does not work anymore.
0
 

Author Comment

by:zaq
ID: 1451966
how do I do this?  How do get the window handle of the application?
0
 
LVL 13

Expert Comment

by:Mirkwood
ID: 1451967
Using the findwindow api for example

Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long

Private Sub Command1_Click()
    Dim pmHwnd As Long
    Dim dvHwnd As Long
    Dim lvHwnd As Long
    pmHwnd = FindWindowEx(0, 0, "Progman", "Program Manager")
    dvHwnd = FindWindowEx(pmHwnd, 0, "SHELLDLL_DefView", "")
    lvHwnd = FindWindowEx(dvHwnd, 0, "SysListView32", "")
    MsgBox lvHwnd
End Sub

-- Another example
  hwndexpl = FindWindow("IEFrame", 0)   ' Find Internet Explorer
    hwndsizerebar = FindWindowEx(hwndexpl, 0,   "SizableReBar", "")    ' Find the sizable rebar toolbar control
    hwndrebar = FindWindowEx(hwndsizerebar, 0, "ReBarWindow32", "") ' Find the rebar toolbar control
    hwndcomboex = FindWindowEx(hwndrebar, 0, "ComboBoxEx32", "")  ' Find the extended combobox control on the toolbar
    hwndcombo = FindWindowEx(hwndcomboex, 0, "ComboBox", "")  ' Find the combobox control with the extended combo
    hwndedit = FindWindowEx(hwndcombo, 0, "Edit", "") 'Find the editbox within the combobox

0
Live: Real-Time Solutions, Start Here

Receive instant 1:1 support from technology experts, using our real-time conversation and whiteboard interface. Your first 5 minutes are always free.

 
LVL 3

Expert Comment

by:jjmartin
ID: 1451968
It is possible to bring it up and force it to be a child of the MDI form.  I need to find my code on this.  I will get back to you.
0
 
LVL 3

Expert Comment

by:jjmartin
ID: 1451969
Post your email address, and I will send you a project that will show you how to force other applictions to be Children of your MDI form. It is much to long to post here.
0
 
LVL 13

Expert Comment

by:Mirkwood
ID: 1451970
JJMartin: Does it integrate well when you maximize the child window. And what is the principe it work on. Is it like I described and are you experiencing the problems I described?
0
 
LVL 3

Expert Comment

by:jjmartin
ID: 1451971
Using the hwnd and task id, it literally makes the shelled application a child of your MDI.  It minimizes within the MDI form, and the MDI form has the control to kill the child window.  Howver, you still have the same limitations you would have with any shelled appliction.  I am still working on a problem with the MDI taking the child windows menu bar though.
0
 

Author Comment

by:zaq
ID: 1451972
my email address is trolli@ctc.com
0
 
LVL 4

Expert Comment

by:idcanada
ID: 1451973
0
 

Author Comment

by:zaq
ID: 1451974
The people that left comments already mentioned that same file and emailed it to me, that you mentioned idcanada.  Therefore I believe the credit should go to them.  Sorry.
0
 
LVL 1

Accepted Solution

by:
mathies earned 350 total points
ID: 1451975
You have to find the handle of the application you start from shell command using  the description of the window.  A application have always the same Description, but not the same handle.

You can use these 3 function to retrieve the handle by description.
Note: You window should be in top level list to be able to find it.

Private Function GetBaseName$(ByVal Source$)
' If source$ is a path, this function retrieves the
' basename, or filename sans path
' source$ MUST be a valid filename
'

On Error GoTo ErrorHandle

    Do While InStr(Source$, "\") <> 0
        Source$ = Mid$(Source$, InStr(Source$, "\") + 1)
    Loop
    If InStr(Source$, ":") <> 0 Then
        Source$ = Mid$(Source$, InStr(Source$, ":") + 1)
    End If
    GetBaseName$ = Source$

    Exit Function

ErrorHandle:
    MsgErr
    Resume Next

End Function
'******************************************************************


'******************************************************************
Private Function GetWindowDesc$(ByVal hwnd)
'   Builds a string descrbing the window in format
'   handle, source application, class
'   seperated by tabs
'

    Dim Desc$
    Dim tbuf$

   Dim inst As Long
   Dim dummy As Long
   
On Error GoTo ErrorHandle

    ' Include the windows handle first
    Desc$ = "&H" + Hex$(hwnd) + Chr$(9)

    ' Get name of source app
    tbuf$ = String$(256, 0) ' Predefine string length
    ' Get instance for window
    inst = GetWindowWord(hwnd, GWW_HINSTANCE)
   
    ' Get the module filename
    dummy = GetModuleFileName(inst, tbuf$, 255)
    tbuf$ = GetBaseName$(tbuf$)
   

    ' The following two lines are equivalent
    'tbuf$ = agGetStringFromLPSTR$(tbuf$)
    ' If InStr(tbuf$, Chr$(0)) Then tbuf$ = Left$(tbuf$, InStr(tbuf$, Chr$(0)) - 1)
   
    ' And add it to the description
    Desc$ = Desc$ + tbuf$ + Chr$(9)

    ' Finally, add the class name
    tbuf$ = String$(256, 0) ' Initialize space again
    dummy = GetClassName(hwnd, tbuf$, 255)
    'tbuf$ = agGetStringFromLPSTR(tbuf$)
    If InStr(tbuf$, Chr$(0)) Then tbuf$ = Left$(tbuf$, InStr(tbuf$, Chr$(0)) - 1)

    Desc$ = Desc$ + tbuf$

    ' And return the description
    GetWindowDesc$ = Desc$

    Exit Function

ErrorHandle:
    MsgErr
    Resume Next

End Function

'******************************************************************
Private Function GetWindowhWnd$(ByVal hwnd)
'   Builds a string descrbing the window in format
'   handle, source application, class
'   seperated by tabs
'
   Dim Desc$
   Dim tbuf$
   Dim inst As Long
   Dim dummy As Long

On Error GoTo ErrorHandle

    ' Include the windows handle first
    Desc$ = "&H" + Hex$(hwnd) + Chr$(9)

    ' Get name of source app
    tbuf$ = String$(256, 0) ' Predefine string length
    ' Get instance for window
    inst = GetWindowWord(hwnd, GWW_HINSTANCE)
   
    ' Get the module filename
    dummy = GetModuleFileName(inst, tbuf$, 255)
    tbuf$ = GetBaseName$(tbuf$)
   

    ' Finally, add the class name
    tbuf$ = String$(256, 0) ' Initialize space again
    dummy = GetClassName(hwnd, tbuf$, 255)
   
    ' And return the description
    GetWindowhWnd$ = Desc$

    Exit Function

ErrorHandle:
    MsgErr
    Resume Next

End Function
'******************************************************************


'******************************************************************
Private Function GetWindowName$(ByVal hwnd)
'   Builds a string descrbing the window in format
'   handle, source application, class
'   seperated by tabs
'
    Dim Desc$
    Dim tbuf$
   
    #If Win32 Then
        Dim inst As Long
        Dim dummy As Long
    #Else
        Dim inst As Integer
        Dim dummy As Integer
    #End If

On Error GoTo ErrorHandle


    ' Include the windows handle first
    Desc$ = "&H" + Hex$(hwnd) + Chr$(9)

    ' Get name of source app
    tbuf$ = String$(256, 0) ' Predefine string length
    ' Get instance for window
    inst = GetWindowWord(hwnd, GWW_HINSTANCE)
   
    ' Get the module filename
    dummy = GetModuleFileName(inst, tbuf$, 255)
    tbuf$ = GetBaseName$(tbuf$)
   

    ' The following two lines are equivalent
    'tbuf$ = agGetStringFromLPSTR(tbuf$)
    ' If InStr(tbuf$, Chr$(0)) Then tbuf$ = Left$(tbuf$, InStr(tbuf$, Chr$(0)) - 1)
   
    ' And add it to the description
    Desc$ = Desc$ + tbuf$ + Chr$(9)

    ' Finally, add the class name
    tbuf$ = String$(256, 0) ' Initialize space again
    dummy = GetClassName(hwnd, tbuf$, 255)
    'tbuf$ = agGetStringFromLPSTR(tbuf$)
    If InStr(tbuf$, Chr$(0)) Then tbuf$ = Left$(tbuf$, InStr(tbuf$, Chr$(0)) - 1)
   
    Desc$ = tbuf$

    ' And return the description
    GetWindowName$ = Desc$

    Exit Function

ErrorHandle:
    MsgErr
    Resume Next

End Function
'******************************************************************


After yo have just to change the attribute to your window to transform this window child of the window you want


Public Sub AddChild(strDescription As String, objParent As Object, Optional blnLike As Boolean = False)
'************************************************************************
'PURPOSE    This function loop in all top level window and search for   *
'           the windows description match with strDescription parameter *
'INPUT:     String to compare with window description                   *
'************************************************************************
'Note Chaine = TACTICIAN if you search for Tactician description
 
   Dim lngCurrHwnd As Long
   Dim lngParentHwnd As Long
   Dim lngChildHwnd As Long
   Dim lngDesktopHwnd As Long
   Dim lngTmpHwnd As Long
   
On Error GoTo ErrorHandle
       
   
    ' The desktop is the highest window
    lngDesktopHwnd = GetDesktopWindow()
   
    'Initialisation
    lngParentHwnd = objParent.hwnd
   
    ' It's first child is the 1st top level window
    lngCurrHwnd = GetWindow(lngDesktopHwnd, GW_CHILD)

    ' Now LOOP all top level windows
    Do
      'If description match with request string
      If blnLike Then
         If UCase(GetWindowName$(lngCurrHwnd)) Like UCase(strDescription) Then
         
            'Window search found
            lngChildHwnd = GetWindowhWnd$(lngCurrHwnd)
           
            'Make this window a child window
            lngTmpHwnd = GetWindowLong(lngChildHwnd, GWL_STYLE)
            lngTmpHwnd = SetWindowLong(lngChildHwnd, GWL_STYLE, lngTmpHwnd + WS_CHILD)
           
            'Set the parent of the window
            lngTmpHwnd = SetParent(lngChildHwnd, lngParentHwnd)
           
            'Don't notify parent if child close
            lngTmpHwnd = GetWindowLong(lngChildHwnd, GWL_EXSTYLE)
            lngTmpHwnd = SetWindowLong(lngChildHwnd, GWL_EXSTYLE, lngTmpHwnd + WS_EX_NOPARENTNOTIFY)
           
            'Hide child window
            lngTmpHwnd = ShowWindow(lngChildHwnd, SW_HIDE)
            lngTmpHwnd = ShowWindow(lngChildHwnd, SW_SHOW)
           
            Exit Do
           
         End If
      Else
         If UCase(GetWindowName$(lngCurrHwnd)) = UCase(strDescription) Then
         
            'Window search found
            lngChildHwnd = GetWindowhWnd$(lngCurrHwnd)
           
            'Make this window a child window
            lngTmpHwnd = GetWindowLong(lngChildHwnd, GWL_STYLE)
            lngTmpHwnd = SetWindowLong(lngChildHwnd, GWL_STYLE, lngTmpHwnd + WS_CHILD)
           
            'Set the parent of the window
            lngTmpHwnd = SetParent(lngChildHwnd, lngParentHwnd)
           
            'Don't notify parent if child close
            lngTmpHwnd = GetWindowLong(lngChildHwnd, GWL_EXSTYLE)
            lngTmpHwnd = SetWindowLong(lngChildHwnd, GWL_EXSTYLE, lngTmpHwnd + WS_EX_NOPARENTNOTIFY)
           
            'Hide child window
            lngTmpHwnd = ShowWindow(lngChildHwnd, SW_HIDE)
           
            Exit Do
           
         End If
      End If
     
      'get the net window
      lngCurrHwnd = GetWindow(lngCurrHwnd, GW_HWNDNEXT)

    Loop While lngCurrHwnd <> 0
   
   
    Exit Sub

ErrorHandle:
    MsgErr
    Resume Next

End Sub






0

Featured Post

Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Introduction While answering a recent question about filtering a custom class collection, I realized that this could be accomplished with very little code by using the ScriptControl (SC) library.  This article will introduce you to the SC library a…
The debugging module of the VB 6 IDE can be accessed by way of the Debug menu item. That menu item can normally be found in the IDE's main menu line as shown in this picture.   There is also a companion Debug Toolbar that looks like the followin…
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…

813 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now