Solved

Shell as child of MDI

Posted on 1998-12-22
11
488 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
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
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

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Introduction I needed to skip over some file processing within a For...Next loop in some old production code and wished that VB (classic) had a statement that would drop down to the end of the current iteration, bypassing the statements that were c…
Enums (shorthand for ‘enumerations’) are not often used by programmers but they can be quite valuable when they are.  What are they? An Enum is just a type of variable like a string or an Integer, but in this case one that you create that contains…
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
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…

809 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