Die Community zu .NET und Classic VB.
Menü

VB 5/6-Tipp 0489: Fremde Fenster in eigenes Fenster einbinden

 von 

Beschreibung 

Mit diesem Tipp kann man fremde Anwendungen wie z.B. Notepad "kidnappen" und in sein eigenes Fenster einbinden.

Schwierigkeitsgrad:

Schwierigkeitsgrad 3

Verwendete API-Aufrufe:

FindWindowA (FindWindow), GetDesktopWindow (GetDeskTopWindow), MoveWindow, SetParent, SetWindowTextA (SetWindowText), ShowWindow

Download:

Download des Beispielprojektes [2,66 KB]

'Dieser Quellcode stammt von http://www.activevb.de
'und kann frei verwendet werden. Für eventuelle Schäden
'wird nicht gehaftet.

'Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum.
'Ansonsten viel Spaß und Erfolg mit diesem Source!

'------------ Anfang Projektdatei Kidnapper.vbp  ------------
'--------- Anfang Formular "Form1" alias Form1.frm  ---------
' Steuerelement: Schaltfläche "Command2"
' Steuerelement: Schaltfläche "Command1"
'
' ---------------------------------------------------------

' Achtung! Man muss das fremde Programm auf jeden Fall
' beenden oder wieder ins Desktop setzen bevor das eigene
' Fenster geschlossen wird.

' Um dieses Beispiel einfach zu halten, wurde auf Shellexecute
' OpenProcess und TerminateProcess (siehe Tip 147) verzichtet.

' Autor: K. Langbein (E-Mail: Klaus@ActiveVB)

Option Explicit

Private Declare Function SetParent Lib "user32" (ByVal hWndChild As Long, _
    ByVal hWndNewParent As Long) As Long
    
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" ( _
    ByVal lpClassName As String, ByVal lpWindowName As String) As Long
    
Private Declare Function MoveWindow Lib "user32" (ByVal hwnd As Long, _
    ByVal X As Long, ByVal y As Long, ByVal nWidth As Long, _
    ByVal nHeight As Long, ByVal bRepaint As Long) As Long
    
Private Declare Function ShowWindow Lib "user32" (ByVal hwnd As Long, _
    ByVal nCmdShow As Long) As Long
    
Private Declare Function SetWindowText Lib "user32" Alias "SetWindowTextA" ( _
    ByVal hwnd As Long, ByVal lpString As String) As Long
    
Private Declare Function GetDeskTopWindow Lib "user32" _
    Alias "GetDesktopWindow" () As Long

Private lhwnd As Long
Private ret As Long
        
Private Sub Command1_Click()
    Dim ltop As Long
    Dim lleft As Long
    Dim lwidth As Long
    Dim lheight As Long
  
    ' Notepad starten
    Call Shell("notepad", vbHide)
    
    ' Warten bis vollstaendig geladen
    Call pause(0.2)
   
    ' Handle des neuen Notepad-Fensters feststellen
    lhwnd = FindWindow("Notepad", vbNullString)
    
    If lhwnd <> 0 Then
        Command1.Enabled = False
        Command2.Enabled = True
        
        ' Jetzt wird das Fenster geklaut
        Call SetParent(lhwnd, Me.hwnd)
        
        ' Ausmasse festlegen (Scalemode von Form1 muss Pixel sein)
        ltop = Command1.Top + Command1.Height
        lleft = 0
        lwidth = Me.ScaleWidth
        lheight = Me.ScaleHeight - ltop
        
        ' Neue Ausmasse setzen
        Call MoveWindow(lhwnd, lleft, ltop, lwidth, lheight, 1)
        
        ' Caption zuweisen
        ret = SetWindowText(lhwnd, "Kidnapped Notepad")
        
        ' Sichtbar machen
        ret = ShowWindow(lhwnd, 1)
        
    End If
    
End Sub

Sub pause(ByVal pause As Single)
    Dim t As Single
    t = Timer
    
    Do
        DoEvents
    Loop Until (Timer - t) >= pause
End Sub

Private Sub Command2_Click()
    Dim dh As Long
    
    ' Handle des Desktop bestimmen
    dh = GetDeskTopWindow()
    
    ' Programm wieder in den Desktop setzen.
    Call SetParent(lhwnd, dh)
    
    Command1.Enabled = True
    Command2.Enabled = False
End Sub

Private Sub Form_Unload(Cancel As Integer)
    Call Command2_Click
End Sub
'---------- Ende Formular "Form1" alias Form1.frm  ----------
'------------- Ende Projektdatei Kidnapper.vbp  -------------

Tipp-Kompatibilität:

Windows/VB-VersionWin32sWin95Win98WinMEWinNT4Win2000WinXP
VB4
VB5
VB6

Hat dieser Tipp auf Ihrem Betriebsystem und mit Ihrer VB-Version funktioniert?

Ja, funktioniert!

Nein, funktioniert nicht bei mir!

VB-Version:

Windows-Version:

Ihre Meinung  

Falls Sie Fragen zu diesem Artikel haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.

Archivierte Nutzerkommentare 

Klicken Sie diesen Text an, wenn Sie die 15 archivierten Kommentare ansehen möchten.
Diese stammen noch von der Zeit, als es noch keine direkte Forenunterstützung für Fragen und Kommentare zu einzelnen Artikeln gab.
Aus Gründen der Vollständigkeit können Sie sich die ausgeblendeten Kommentare zu diesem Artikel aber gerne weiterhin ansehen.

Kommentar von Jojo am 27.10.2010 um 22:59

Ich habe mal eine Frage:

Ich versuche schon einige Zeit den explorer in den Code einzubauen. Leider klappt das nie....... Hat jemand eine Lösung wie ich statt notepad den explorer einbinde?


Vielen Dank

Kommentar von Tilman am 08.08.2008 um 00:58

Funzt (dank diesem Code hier) auch in Delphi: http://www.delphi-forum.de/viewtopic.php?t=85516

@Wolfram Glitzer: das liegt daran dass die programme dann nicht mehr als eigenständige Anwendungen gefundne werden. Und wenn ein Programm verhindern will dass es sich selbst zweimal startet, dann prüft es zu beginn ob es bereits ein Formular mit dem selben Namen gibt - in diesem Fall ist das ja nicht mehr der Fall. Lösung: Man müsste beim Fangen einfach ein (unsichtbares) neues Formular mit dem selben namen wie dem gefangenen erstellen. Dieses Formular muss aber als eigenständige Anwendung erkannt werden (ka. obs reicht handle = getDesktopWindow zu setzen).

Grüße
Tilman

Kommentar von Stefan Massopust am 07.06.2008 um 14:42

Hallo,

Kann es sein, daß der Tipp nicht bei Vista funktioniert?

Kommentar von Olaf Böhm am 14.07.2006 um 22:54

Von der Idee her, ist das ganze ja recht nett, aber praktisch ist sowas kaum zu gebrauchen (mal von nem Quick'n'Dirty-Tool mal abgesehen). Hat sich mal jemand angeschaut, was dabei rauskommt, wenn man das Elternfenster durch ein anderes Fenster überlappt und dann mal auf den "Kidnapped Notepad" klickt? Die Fenster bleiben beide hinter dem verdeckendem Fenster! Auch der Umbau zu einer MDI-Version ändert daran nichts. Erst wenn man auf das Elternfenster klickt, kommt dieses wieder in den Vordergrund. Ich hab mich schon dumm und dämlich danach gesucht, wie man es besser machen könnte - herausgekommen ist leider nichts, sonst hätte ich dieses Wissen gerne mit euch geteilt. Falls jemand 'ne Idee hat, wie man echte MDI-Childs aus einer externen Anwendung macht... - Echte MDI-Fenster holen die Elternform mit in den Vordergrund, wenn man draufklickt, echte MDI-Fenster übergeben ihr Menü an das Elternfenster, echte MDI-Fenster tragen sich in die Fensterliste ein... 2B continued... - Laßt mich nicht dumm sterben!

Kommentar von Heike Unger am 02.07.2006 um 19:02

Gibt es zu diesem Source auch eine Variante für .NET (vb 2005)? Die automatische Konvertierung von vb6 nach vb2005 funktioniert hier leider nicht! Nach Behebung aller syntaktischen Fehler erhalte ich beim Aufruf der mittels Declare Anweisung aufgenommenen Funktionen immer "PInvokeStackImbalance wurde erkannt". Der Code wird dann zwar scheinbar ausgeführt, allerdings wird das Notepad-Fenster nicht "gefangen".

Kommentar von Andreas Ressel am 24.08.2004 um 15:09

Funktioniert sehr gut. Für nicht MS-Anwendungen die ProcessID ermitteln (siehe Tips) und das RetVal bestimmen und in hwnd setzen >> gefangen.
Für MDI: Einfach in diesem Beispiel Form1 durch MDIForm ersetzen (Routinen übernehmen) und voila >> gefangen. Da es dann keinen Sinn macht, das gekidnappte Prog zurück an den Desktop zu übergeben: Einfach unter "kill" den hwnd nicht auf Desktop setzen sonder mit SendMessage (siehe Tips) schließen.

Kommentar von Wolfram Glitzner am 13.07.2004 um 19:43

Hallo

funktioniert im wesentlichen ganz Klasse :-), ist jedoch die
'gekidnappte Anwendung' eine Anwendung die sich normalerweise nur einmal starten läßt, läßt sie sich nun mehr sowohl in der der gidnappte Form als auch als normale
EXE starten. :-(
Hat jemand eine Idee, womit sich diese kleine Problem lösen läßt ?

Kommentar von Markus am 04.06.2004 um 21:12

Hallo,

dieser tipp ist zwar klasse.. allerdings hätte ich da eine frage zu.
wie kann man fenster klauen, die in einer anderen sitzung laufen (terminalserver)?

Kommentar von Rainbird am 04.05.2004 um 21:06

Ganz große Klasse!

Kommentar von Simeon am 06.01.2004 um 09:46

Könnte man damit auch den Desktop in eine Form einbinden?

Kommentar von Jens Iggena am 07.10.2003 um 21:02

wenn man über SetWindowLong Notepad als Child-Style-Window definieren würde, würde dann das Focus Problem evtl. nicht verschwinden?

Kommentar von Buchholz am 16.08.2003 um 17:38

Tipp 0489 mag ja mit Nodetpad funktionieren, aber nicht mit anderer externer Anwendung die nicht von Microsoft ist

Kommentar von Daniel Pramel am 16.06.2003 um 10:12

Ziemlich nützlich um GUIs seiner ActiveX-dll-plugins in der hostanwendung anzuzeigen :-)
Danke

Kommentar von Mabuse am 29.10.2002 um 18:10

Kann man dem gefangenen Fenster auch irgendwie den Style MDICHILD verpassen, damit sich das Fenster dann wie ein echtes MDI-Child-Form verhält (z.B. das die Anwendung den Fokus nicht verliert, wenn das gefangene Fenster aktiv ist)?

Kommentar von Möglichkeit am 09.10.2002 um 13:33

hm, meiner Meinung nach kann man das auch mit einer MDI Form und einer Browser Form erreichen... die BrwfORM läuft dann auch nur in der MDI - Form

gruss E-T