Toon posts:

[vb.net] externe applicatie 'docken'

Pagina: 1
Acties:
  • 150 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
Goeiemiddag,

Ik ben bezig met een applicatie maar loop nu tegen een ding aan. Weet niet zeker of het wel mogelijk is maar het is de bedoeling dat ik een exe applicatie run (wat wel lukt) maar deze in mijn applicatie wil 'docken'

Is dit zo en zo mogelijk en zo ja kan iemand mij op weg helpen ?

Got search Google search en codeproject gaven mij geen duwtje in de rug

Alvast bedankt

  • user109731
  • Registratie: Maart 2004
  • Niet online
Ja dat is mogelijk met api-functies.

Zie bijvoorbeeld het volgende voorbeeld:
Visual Basic .NET:
1
2
3
4
5
6
7
8
    Public Declare Function SetParent Lib "user32" (ByVal hWndChild As Integer, ByVal hWndNewParent As Integer) As Integer

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim p As Process = Process.Start("C:\windows\system32\notepad.exe")
        p.WaitForInputIdle()
        Dim handle As Long = p.MainWindowHandle
        SetParent(handle, Me.PictureBox1.Handle)
    End Sub

Dit zorgt ervoor dat kladblok gestart word en in je picturebox word gezet. Undocken kan door de parent weer naar 'desktop' te zetten. Je kan eventueel nog het window moven naar 0,0 en de grootte aanpassen, zodatie precies past. De titelbalk kun je er afslopen door de goede message te sturen.

Verwijderd

Topicstarter
Dit lukt helemaal prima met notepad. Maar met vncviewer.exe en met mstsc.exe lukt dit helaas niet :(

Enig idee ?

  • user109731
  • Registratie: Maart 2004
  • Niet online
Sorry voor de lange lap code, maar deze werkt wel met mstsc.exe iig.
Probleem was bij de vorige code dat de MainWindowHandle niet altijd verwijst naar het window wat je ziet (bijvoorbeeld naar een onzichtbaar achtergrondwindow). Onderstaande code pakt gewoon de foregroundwindow, wat in vrijwel alle gevallen goed werkt. Het kan wel netter natuurlijk, maar dat moet met veel meer code dan.

Nu word het child-window ook geresized (als je de anchor-property van de picturebox instelt bijv.) en weer 'losgelaten' zodra je je window sluit.
Nadeel is wel dat een app als mstsc.exe een vaste window grootte heeft, dat kun je eventueel weer oplossen in de resize code.
Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
Imports System.Runtime.Interopservices

Public Class Form1
    Private Declare Function SetParent Lib "user32" (ByVal hWndChild As Integer, ByVal hWndNewParent As Integer) As Integer
    Private Declare Function MoveWindow Lib "user32" (ByVal hWnd As IntPtr, ByVal X As Integer, ByVal Y As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal bRepaint As Boolean) As Boolean
    Private Declare Auto Function SetWindowLong Lib "User32.Dll" (ByVal hWnd As IntPtr, ByVal nIndex As Integer, ByVal dwNewLong As Integer) As Integer

    <DllImport("user32.dll", EntryPoint:="GetWindowLong")> _
    Private Shared Function GetWindowLong32(ByVal hWnd As IntPtr, ByVal nIndex As Integer) As Integer
    End Function

    <DllImport("user32.dll", EntryPoint:="GetWindowLongPtr")> _
    Private Shared Function GetWindowLongPtr64(ByVal hWnd As IntPtr, ByVal nIndex As Integer) As IntPtr
    End Function
    <DllImport("user32.dll", SetLastError:=True)> _
    Private Shared Function GetForegroundWindow() As IntPtr
    End Function

    Private childHandle As Long
    Private oldStyle As Long

    Private Const SM_CYBORDER = 6
    Private Const SM_CYCAPTION = 4
    Private Const GWL_STYLE = (-16)
    Private Const WS_CAPTION = &HC00000  'WS_BORDER Or WS_DLGFRAME 
    Private Const WS_DLGFRAME = &H400000
    Private Const WS_BORDER = &H800000

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim p As Process = Process.Start("mstsc.exe")
        p.WaitForInputIdle()
        childHandle = GetForegroundWindow()
        SetParent(childHandle, Me.PictureBox1.Handle)
        RemoveCaptionBar(childHandle)
        resizeChild()
    End Sub

    Private Sub PictureBox1_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles PictureBox1.Resize
        resizeChild()
    End Sub

    Private Sub resizeChild()
        If (childHandle > 0) Then
            MoveWindow(childHandle, 0, 0, Me.PictureBox1.Width, Me.PictureBox1.Height, True)
        End If
    End Sub

    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        If (childHandle > 0) Then
            AddCaptionBar(childHandle)
            SetParent(childHandle, 0)
        End If
    End Sub

    Public Shared Function GetWindowLongPtr(ByVal hWnd As Long, ByVal nIndex As Integer) As IntPtr
        If IntPtr.Size = 8 Then
            Return GetWindowLongPtr64(hWnd, nIndex)
        Else
            Return New IntPtr(GetWindowLong32(hWnd, nIndex))
        End If
    End Function

    Private Sub RemoveCaptionBar(ByVal hwnd As Long)
        oldStyle = GetWindowLongPtr(hwnd, GWL_STYLE)
        Dim NewStyle As Long = oldStyle And Not WS_CAPTION
        SetWindowLong(hwnd, GWL_STYLE, NewStyle)
    End Sub

    Private Sub AddCaptionBar(ByVal hwnd As Long)
        SetWindowLong(hwnd, GWL_STYLE, oldStyle)
    End Sub
End Class

[ Voor 12% gewijzigd door user109731 op 16-05-2006 20:02 . Reden: yeahh, de parser werkt weer :) ]


Verwijderd

Topicstarter
Bedankt voor je reactie. Het loginscherm komt inderdaad prima in het pictureboxje terecht. maar de rdp sessie zelf komt niet in de picturebox.

Dit is allemaal volkomen nieuw voor me.
Kan je me nog een beetje op weg helpen ?

Alvast bedankt

Verwijderd

Topicstarter
:(

Modbreak: Ik begrijp het dat je het vervelend vindt als je met je probleem blijft zitten, maar zo'n boze smiley wekt ook niet bepaald sympathie op. ;) Als je je topic omhoog wil schoppen kun je beter een regeltje plaatsen als "Ik zit nog steeds met dit probleem. Heeft iemand nog suggesties?" Dat staat wat netter en je wekt er een betere indruk mee, waardoor je sneller geholpen wordt. :)

[ Voor 100% gewijzigd door NMe op 16-05-2006 21:25 ]


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

probeer eens met Spy++ het gedrag van de vensters te achterhalen.

De kans is groot dat na inloggen het voorgrond venster wijzigt en je dus met een oude form zit.

ASSUME makes an ASS out of U and ME


  • MisterData
  • Registratie: September 2001
  • Laatst online: 11-02 08:33
Probeer met Spy++ de WindowClass en titel te achterhalen en gebruik dat met FindWindowEx... dan heb je vrijwel altijd het goede venster te pakken (en er is vast nog een methode om te checken of het gevonden venster bij het gestartte proces hoort :))

Als je trouwens een terminal-client (mstsc) wil embedden: dat kan ook gewoon met de RDP ActiveX-control? Lijkt me iets makkelijker en scheelt je een hoop gekloot met SendMessage als je ook maar iets méer wil doen dan alleen 'docken' :)

[ Voor 33% gewijzigd door MisterData op 16-05-2006 19:51 ]


  • user109731
  • Registratie: Maart 2004
  • Niet online
Met reactie hierboven.

Het probleem is btw niet dat het voorgrond venster verandert, maar dat er gewoon een nieuw venster geopend word.
Visual Basic .NET:
1
2
3
4
5
6
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function FindWindowEx(ByVal parentHandle As IntPtr, _
                      ByVal childAfter As IntPtr, _
                      ByVal lclassName As String, _
                      ByVal windowTitle As tring) As IntPtr
End Function

Dit is de FindWindowEx declaratie voor vb.net. (van www.pinvoke.net onder user32, erg handig :))
Wat je kunt doen is die met een timer automatisch laten checken of de te-docken-app een nog-niet-gedockt venster open heeft staan, en zo ja die automatisch docken.

Als je meer vensters tegelijkertijd wil docken word het wat lastiger met mijn bovenstaande code. Misschien moet je voordat je een nieuw venster dockt eerst alle vensters vrijgeven, zodat je telkens maximaal 1 venster gedockt heb staan. Dit om problemen met handles ed te voorkomen.

Als je er niet uitkomt horen we het wel, succes ermee :)

Verwijderd

Topicstarter
Verwijderd schreef op dinsdag 16 mei 2006 @ 17:21:
:(

Modbreak: Ik begrijp het dat je het vervelend vindt als je met je probleem blijft zitten, maar zo'n boze smiley wekt ook niet bepaald sympathie op. ;) Als je je topic omhoog wil schoppen kun je beter een regeltje plaatsen als "Ik zit nog steeds met dit probleem. Heeft iemand nog suggesties?" Dat staat wat netter en je wekt er een betere indruk mee, waardoor je sneller geholpen wordt. :)
Hij komt mischien boos over maar zo bedoelde ik het niet. Vind het eerder jammer dat ik niet verder kom ;) maar je heb gelijk.

  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 13-02 20:06

Gerco

Professional Newbie

Als je mstsc wilt embedden, ben je misschien beter geholpen met de Remote Desktop Web Connection ActiveX control, zoals die door MS zelf gebruikt wordt in Remote Desktop Web Connection. Dat is een control die je in webpaginas kunt embedden voor terminal services toegang. Ik neem aan dat je hem dan ook wel in een applicatie kunt embedden...

[ Voor 10% gewijzigd door Gerco op 17-05-2006 11:02 ]

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!

Pagina: 1