none
External program window running within Windows Form Panel (VB.NET) RRS feed

  • Question

  • Hi All, 

    I'm trying to get an external program window to display within a windows form panel for a proof of concept project I'm working on for a single user desktop (idea is to do it properly with ActiveX or rebuilding the external program in a browser if we get approval/resource to go ahead). 

    The code below works for Chrome providing the user doesn't already have an instance open but I have two issues:

    1) the content is not scaling to the panel size (though things like Wordpad or Notepad do)
    2) Any program that takes a while to load or has a splash screen or multiple windows isn't working and just opens outside of my form

    What I have tried:

    Hide   Copy Code
    Option Strict On
    Option Explicit On
    Imports System.Threading
    Public Class Form1
        Declare Auto Function SetParent Lib "user32.dll" (ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As Integer
        Declare Auto Function SendMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
        Private Const WM_SYSCOMMAND As Integer = 274
        Private Const SC_MAXIMIZE As Integer = 61488
        Dim proc As Process
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            proc = Process.Start("Chrome.exe")
            proc.WaitForInputIdle()
            proc.WaitForExit(1000)
            SetParent(proc.MainWindowHandle, Panel1.Handle)
            SendMessage(proc.MainWindowHandle, WM_SYSCOMMAND, SC_MAXIMIZE, 0)
        End Sub
    End Class

    • Edited by flak_jack Monday, May 20, 2019 8:30 AM
    Sunday, May 19, 2019 4:42 PM

All replies

  • You must add the WS_CHILD style before calling SetParent (see the Remarks section)

    (I just tested on Windows 10)

    For the second problem, you probably don't use the right window handle.

    And to embed applications like Office, MS recommends to use the WebBrowser control

    (How to use the WebBrowser control in Visual Basic to open an Office document)

    (it works fine on Windows 10)

    Sunday, May 19, 2019 5:24 PM
  • Thank you very much for a quick and helpful reply. 

    I've had a look at the window handle options and you're right, adding a timed delay before checking for the window handle seems to have part-resolved the issue.  

    How would you define the WS_Child in this context? I'm still very new to Windows Coding.  


    Monday, May 20, 2019 6:36 AM
  • You change the style with SetWindowLong

    But the behaviour is different for each application...

    For example :

    Dim nStyle As Integer = GetWindowLong(proc.MainWindowHandle, GWL_STYLE)
    If (nStyle And WS_CHILD) = 0 Then
        nStyle += WS_CHILD
    End If
    
    ' For Notepad
    If (nStyle And WS_CAPTION) <> 0 Then
        nStyle -= WS_CAPTION
    End If
    
    SetWindowLong(proc.MainWindowHandle, GWL_STYLE, nStyle)

    with declarations :

       Public Const WS_OVERLAPPED = &H0
        Public Const WS_POPUP = &H80000000
        Public Const WS_CHILD = &H40000000
        Public Const WS_MINIMIZE = &H20000000
        Public Const WS_VISIBLE = &H10000000
        Public Const WS_DISABLED = &H8000000
        Public Const WS_CLIPSIBLINGS = &H4000000
        Public Const WS_CLIPCHILDREN = &H2000000
        Public Const WS_MAXIMIZE = &H1000000
        Public Const WS_CAPTION = &HC00000    ' WS_BORDER | WS_DLGFRAME 
        Public Const WS_DLGFRAME = &H400000
        Public Const WS_VSCROLL = &H200000
        Public Const WS_HSCROLL = &H100000
        Public Const WS_SYSMENU = &H80000
        Public Const WS_THICKFRAME = &H40000
        Public Const WS_GROUP = &H20000
        Public Const WS_TABSTOP = &H10000
    
        Public Const WS_MINIMIZEBOX = &H20000
        Public Const WS_MAXIMIZEBOX = &H10000
    
        Public Const GWL_STYLE As Integer = (-16)
        Public Const GWL_EXSTYLE As Integer = (-20)
    
        Public Shared Function SetWindowLong(hWnd As IntPtr, nIndex As Integer, dwNewLong As Long) As Integer
            If IntPtr.Size = 4 Then
                Return SetWindowLongPtr32(hWnd, nIndex, CInt(dwNewLong))
            End If
            Return SetWindowLongPtr64(hWnd, nIndex, dwNewLong)
        End Function
    
        <DllImport("user32.dll", EntryPoint:="SetWindowLong")>
        Private Shared Function SetWindowLongPtr32(ByVal hWnd As IntPtr, <MarshalAs(UnmanagedType.I4)> nIndex As Integer, ByVal dwNewLong As Integer) As Integer
        End Function
    
        <DllImport("user32.dll", CharSet:=CharSet.Auto, EntryPoint:="SetWindowLongPtr")>
        Public Shared Function SetWindowLongPtr64(hWnd As IntPtr, nIndex As Integer, dwNewLong As Long) As Integer
        End Function
    
        Public Shared Function GetWindowLong(hWnd As IntPtr, nIndex As Integer) As Integer
            If IntPtr.Size = 4 Then
                Return GetWindowLong32(hWnd, nIndex)
            End If
            Return GetWindowLongPtr64(hWnd, nIndex)
        End Function
    
        <DllImport("User32.dll", EntryPoint:="GetWindowLong", CharSet:=CharSet.Auto)>
        Private Shared Function GetWindowLong32(hWnd As IntPtr, nIndex As Integer) As Integer
        End Function
    
        <DllImport("User32.dll", EntryPoint:="GetWindowLongPtr", CharSet:=CharSet.Auto)>
        Private Shared Function GetWindowLongPtr64(hWnd As IntPtr, nIndex As Integer) As Integer
        End Function



    • Edited by Castorix31 Monday, May 20, 2019 7:24 AM
    Monday, May 20, 2019 7:21 AM

  • Must admit I don't understand it yet and I'm not currently sure where to put it all, but I will once I put the time in.

    Amazing response, thank you. 

    Monday, May 20, 2019 9:07 AM

  • Must admit I don't understand it yet and I'm not currently sure where to put it all, but I will once I put the time in.

    Amazing response, thank you. 

    Hi,

    I made a demo,

    Imports System.Runtime.InteropServices
    
    Public Class Form1
        <DllImport("user32")>
        Private Shared Function FindWindow(ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
        End Function
        <DllImport("user32")>
        Private Shared Function SetParent(ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As IntPtr
        End Function
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim hDeskTop As IntPtr = FindWindow(Nothing, "TestForm")
            SetParent(hDeskTop, Me.Handle)
        End Sub
    End Class
    

    Best Regards,

    Alex


    MSDN Community Support Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, May 24, 2019 3:12 AM