Jump to content

Embed RDP in GUI


lod3n
 Share

Recommended Posts

AndyDLD, here is an update which hopefully will sort it out for everyone. That ATL control is tricky little bastard: you can't guess what class name it will have next! So I'm instead enumerating all of the controls, and picking out the ATL one no matter what it's named.

This update also allows you to change the GUI size easily, and shuts down the GUI when you disconnect. Let me know how it works for you, and if you give it the thumbs up, I will modify the original post.

Thanks for your feedback.

#include <GUIConstants.au3>

$width = 1024
$height = 768
$oRDP = ObjCreate("MsTscAx.MsTscAx")
$GUI = GUICreate("Embedded RDP control Test", $width+20, $height+20, 0, -1, $WS_OVERLAPPEDWINDOW + $WS_VISIBLE + $WS_CLIPSIBLINGS)
$GUIActiveX = GUICtrlCreateObj($oRDP, 10, 10, $width, $height)
GUICtrlSetResizing ($GUIActiveX,$GUI_DOCKAUTO)

GUISetState()

; connect to the server. if this is not done first, the child controls are not rendered.
; which is a problem, because we have to change their styles to prevent clipping
$oRDP.Server = "server"
$oRDP.Domain = "domain"
$oRDP.UserName = "user"
$oRDP.Connect()

; Determine the class name of the ATL control - it seems to be random from system to system
Opt("WinTitleMatchMode", 4)     ;1=start, 2=subStr, 3=exact, 4=advanced, -1 to -4=Nocase
Opt("WinSearchChildren", 1)     ;0=no, 1=search children also
$sATLClass = ""
$aClasses = StringSplit(WinGetClassList($GUI,""),@LF)
For $i = 1 To $aClasses[0]
    If StringLeft($aClasses[$i],4) = "ATL:" Then
        $sATLClass = $aClasses[$i]
        ExitLoop
    EndIf
Next

; get the handles to the controls that must have their styles modified
$hUIContainerClass = ControlGetHandle($GUI, "", "[CLASS:UIContainerClass]")
$hUIMainClass = ControlGetHandle($GUI, "", "[CLASS:UIMainClass]")
$hATL = ControlGetHandle($GUI, "", "[CLASS:"&$sATLClass&"]")
ConsoleWrite("$hUIContainerClass (should not be 0 or blank):" & $hUIContainerClass & @crlf)
ConsoleWrite("$hUIMainClass (should not be 0 or blank):" & $hUIMainClass & @crlf)
ConsoleWrite("$hATL (should not be 0 or blank):" & $hATL & @crlf)

; modify the styles of the child controls to match those set by the offical client application
; this prevents clipping problems - though, I don't know why
Const $WS_EX_NOPARENTNOTIFY = 0x4
Const $WS_EX_NOINHERITLAYOUT = 0x100000
$hUIContainerClassStyle = BitOR($WS_CHILD, $WS_CLIPCHILDREN, $WS_CLIPSIBLINGS, $WS_VISIBLE) ; 0x56000000
$hUIContainerClassStyleEx = BitOR($WS_EX_NOINHERITLAYOUT, $WS_EX_NOPARENTNOTIFY) ; 0x00100004
$hUIMainClassStyle = BitOR($WS_CHILD, $WS_CLIPCHILDREN, $WS_CLIPSIBLINGS, $WS_SYSMENU, $WS_VISIBLE) ; 0x56080000
$hUIMainClassStyleEx = 0x0
$hATLStyle = BitOR($WS_CHILD, $WS_CLIPCHILDREN, $WS_CLIPSIBLINGS, $WS_VISIBLE) ; 0x56000000
$hATLStyleEx = 0x0
$guiStyle = BitOR($WS_BORDER, $WS_CAPTION, $WS_CLIPCHILDREN, $WS_CLIPSIBLINGS, $WS_DLGFRAME, $WS_GROUP, $WS_MAXIMIZE, $WS_MAXIMIZEBOX, $WS_MINIMIZEBOX, $WS_SYSMENU, $WS_TABSTOP, $WS_THICKFRAME, $WS_VISIBLE) ; 0x17CF0100
$guiStyleEx = $WS_EX_WINDOWEDGE ; 0x00000100
_SetStyle($hUIContainerClass,$hUIContainerClassStyle,$hUIContainerClassStyleEx)
_SetStyle($hUIMainClass,$hUIMainClassStyle,$hUIMainClassStyleEx)
_SetStyle($hATL,$hATLStyle,$hATLStyleEx)
_SetStyle($gui,$guiStyle,$guiStyleEx)
Func _SetStyle($hwnd,$style,$exstyle)
    DllCall("user32.dll", "long", "SetWindowLong", "hwnd", $hwnd, "int", -16, "long", $style)
    DllCall("user32.dll", "long", "SetWindowLong", "hwnd", $hwnd, "int", -20, "long", $exstyle)
EndFunc

; $WS_EX_NOPARENTNOTIFY and $WS_EX_NOINHERITLAYOUT seem to be fairly important
; This may still be important for other projects with similar problems.

AdlibEnable ( "checkconn", 1000)
Func checkconn()
    If $oRDP.Connected = 0 Then
        Exit
    EndIf
EndFunc


While 1
    $msg = GUIGetMsg()
    Select
        Case $msg = $GUI_EVENT_CLOSE
            ExitLoop
    EndSelect
WEnd

GUIDelete()

Exit

[font="Fixedsys"][list][*]All of my AutoIt Example Scripts[*]http://saneasylum.com[/list][/font]

Link to comment
Share on other sites

I looked into it, and the resizing is not straightforward. It seems that you can't set the size mid-connection via the $oRDP object. My theory is that there is an object associated with the ATL control, and that's where you set the size. Acquiring a reference to that object (if it exists) might be pretty tricky.

Until I figure it out, just set the size you want beforehand. Sorry.

[font="Fixedsys"][list][*]All of my AutoIt Example Scripts[*]http://saneasylum.com[/list][/font]

Link to comment
Share on other sites

  • 3 months later...

Can someone please explain why when I set the embedded RDP ActiveX control within a Tabitem control it draws the screen, and then the application locks up?

#include <GUIConstants.au3>

$width = 1024
$height = 768
$oRDP = ObjCreate("MsTscAx.MsTscAx")
$GUI = GUICreate("Embedded RDP control Test", $width+20, $height+20, 0, -1, $WS_OVERLAPPEDWINDOW + $WS_VISIBLE + $WS_CLIPSIBLINGS)
GUICtrlCreateTab(10, 10, $width, $height)
GUICtrlCreateTabItem("Remote Desktop")
$GUIActiveX = GUICtrlCreateObj($oRDP, 20, 35, $width-20, $height-35)
GUICtrlSetResizing ($GUIActiveX,$GUI_DOCKAUTO)
GUICtrlCreateTabItem("")
GUISetState()

; connect to the server. if this is not done first, the child controls are not rendered.
; which is a problem, because we have to change their styles to prevent clipping
$oRDP.Server = "server"
$oRDP.Domain = "domain"
$oRDP.UserName = "user"
$oRDP.Connect()

; Determine the class name of the ATL control - it seems to be random from system to system
Opt("WinTitleMatchMode", 4)     ;1=start, 2=subStr, 3=exact, 4=advanced, -1 to -4=Nocase
Opt("WinSearchChildren", 1)     ;0=no, 1=search children also
$sATLClass = ""
$aClasses = StringSplit(WinGetClassList($GUI,""),@LF)
For $i = 1 To $aClasses[0]
    If StringLeft($aClasses[$i],4) = "ATL:" Then
        $sATLClass = $aClasses[$i]
        ExitLoop
    EndIf
Next

; get the handles to the controls that must have their styles modified
$hUIContainerClass = ControlGetHandle($GUI, "", "[CLASS:UIContainerClass]")
$hUIMainClass = ControlGetHandle($GUI, "", "[CLASS:UIMainClass]")
$hATL = ControlGetHandle($GUI, "", "[CLASS:"&$sATLClass&"]")
ConsoleWrite("$hUIContainerClass (should not be 0 or blank):" & $hUIContainerClass & @crlf)
ConsoleWrite("$hUIMainClass (should not be 0 or blank):" & $hUIMainClass & @crlf)
ConsoleWrite("$hATL (should not be 0 or blank):" & $hATL & @crlf)

; modify the styles of the child controls to match those set by the offical client application
; this prevents clipping problems - though, I don't know why
Const $WS_EX_NOPARENTNOTIFY = 0x4
Const $WS_EX_NOINHERITLAYOUT = 0x100000
$hUIContainerClassStyle = BitOR($WS_CHILD, $WS_CLIPCHILDREN, $WS_CLIPSIBLINGS, $WS_VISIBLE) ; 0x56000000
$hUIContainerClassStyleEx = BitOR($WS_EX_NOINHERITLAYOUT, $WS_EX_NOPARENTNOTIFY) ; 0x00100004
$hUIMainClassStyle = BitOR($WS_CHILD, $WS_CLIPCHILDREN, $WS_CLIPSIBLINGS, $WS_SYSMENU, $WS_VISIBLE) ; 0x56080000
$hUIMainClassStyleEx = 0x0
$hATLStyle = BitOR($WS_CHILD, $WS_CLIPCHILDREN, $WS_CLIPSIBLINGS, $WS_VISIBLE) ; 0x56000000
$hATLStyleEx = 0x0
$guiStyle = BitOR($WS_BORDER, $WS_CAPTION, $WS_CLIPCHILDREN, $WS_CLIPSIBLINGS, $WS_DLGFRAME, $WS_GROUP, $WS_MAXIMIZE, $WS_MAXIMIZEBOX, $WS_MINIMIZEBOX, $WS_SYSMENU, $WS_TABSTOP, $WS_THICKFRAME, $WS_VISIBLE) ; 0x17CF0100
$guiStyleEx = $WS_EX_WINDOWEDGE ; 0x00000100
_SetStyle($hUIContainerClass,$hUIContainerClassStyle,$hUIContainerClassStyleEx)
_SetStyle($hUIMainClass,$hUIMainClassStyle,$hUIMainClassStyleEx)
_SetStyle($hATL,$hATLStyle,$hATLStyleEx)
_SetStyle($gui,$guiStyle,$guiStyleEx)
Func _SetStyle($hwnd,$style,$exstyle)
    DllCall("user32.dll", "long", "SetWindowLong", "hwnd", $hwnd, "int", -16, "long", $style)
    DllCall("user32.dll", "long", "SetWindowLong", "hwnd", $hwnd, "int", -20, "long", $exstyle)
EndFunc

; $WS_EX_NOPARENTNOTIFY and $WS_EX_NOINHERITLAYOUT seem to be fairly important
; This may still be important for other projects with similar problems.

AdlibEnable ( "checkconn", 1000)
Func checkconn()
    If $oRDP.Connected = 0 Then
        Exit
    EndIf
EndFunc


While 1
    $msg = GUIGetMsg()
    Select
        Case $msg = $GUI_EVENT_CLOSE
            ExitLoop
    EndSelect
WEnd

GUIDelete()

Exit
Link to comment
Share on other sites

Using ActiveX controls in AutoIt tabs has always been problematic. I advise against it.

The issue seems to do with the fact that all of the different types of required window messages that certain controls need to use to manage advanced functionality are not being handled by the parent GUI (AutoIt) in the way they require. Additionally, AutoIt only deals with COM via IDispatch, and I know for a fact that IE and RDP controls expect more interfaces to be available, and there is no chance of that happening in AutoIt.

I could be wrong, and I probably am, on one or more points here, but this is the feeling I get after working on issues like these for some time. One thing you could consider doing is find another application that embeds RDP controls in tabs, and determine the window styles applied to the controls in those tabs, and what styles are applied during what application states (on tab activation, on tab deactivation, on tab new, on tab close, etc). We might be able to replicate the styles in that case, and it might not crash.

There also might be a workaround. Try making a tab control appear as a strip at the top, and then hide/show the RDP window controls below the strip depending on which "tab" is active.

[font="Fixedsys"][list][*]All of my AutoIt Example Scripts[*]http://saneasylum.com[/list][/font]

Link to comment
Share on other sites

  • 7 months later...

Thanks for the example. Works great. I had tried to add 2 activex objects for 2 remote desktop connections. When I run it, it starts up ok but after a couple of mouse clicks, one the the remote controls is unable to accept any controls (mouse or keyboard). I just duplicated the code and 1 for each and applied the styles to both

Link to comment
Share on other sites

  • 1 year later...

AndyDLD, here is an update which hopefully will sort it out for everyone. That ATL control is tricky little bastard: you can't guess what class name it will have next! So I'm instead enumerating all of the controls, and picking out the ATL one no matter what it's named.

This update also allows you to change the GUI size easily, and shuts down the GUI when you disconnect. Let me know how it works for you, and if you give it the thumbs up, I will modify the original post.

Thanks for your feedback.

#include <GUIConstants.au3>

$width = 1024
$height = 768
$oRDP = ObjCreate("MsTscAx.MsTscAx")
$GUI = GUICreate("Embedded RDP control Test", $width+20, $height+20, 0, -1, $WS_OVERLAPPEDWINDOW + $WS_VISIBLE + $WS_CLIPSIBLINGS)
$GUIActiveX = GUICtrlCreateObj($oRDP, 10, 10, $width, $height)
GUICtrlSetResizing ($GUIActiveX,$GUI_DOCKAUTO)

GUISetState()

; connect to the server. if this is not done first, the child controls are not rendered.
; which is a problem, because we have to change their styles to prevent clipping
$oRDP.Server = "server"
$oRDP.Domain = "domain"
$oRDP.UserName = "user"
$oRDP.Connect()

; Determine the class name of the ATL control - it seems to be random from system to system
Opt("WinTitleMatchMode", 4)     ;1=start, 2=subStr, 3=exact, 4=advanced, -1 to -4=Nocase
Opt("WinSearchChildren", 1)     ;0=no, 1=search children also
$sATLClass = ""
$aClasses = StringSplit(WinGetClassList($GUI,""),@LF)
For $i = 1 To $aClasses[0]
    If StringLeft($aClasses[$i],4) = "ATL:" Then
        $sATLClass = $aClasses[$i]
        ExitLoop
    EndIf
Next

; get the handles to the controls that must have their styles modified
$hUIContainerClass = ControlGetHandle($GUI, "", "[CLASS:UIContainerClass]")
$hUIMainClass = ControlGetHandle($GUI, "", "[CLASS:UIMainClass]")
$hATL = ControlGetHandle($GUI, "", "[CLASS:"&$sATLClass&"]")
ConsoleWrite("$hUIContainerClass (should not be 0 or blank):" & $hUIContainerClass & @crlf)
ConsoleWrite("$hUIMainClass (should not be 0 or blank):" & $hUIMainClass & @crlf)
ConsoleWrite("$hATL (should not be 0 or blank):" & $hATL & @crlf)

; modify the styles of the child controls to match those set by the offical client application
; this prevents clipping problems - though, I don't know why
Const $WS_EX_NOPARENTNOTIFY = 0x4
Const $WS_EX_NOINHERITLAYOUT = 0x100000
$hUIContainerClassStyle = BitOR($WS_CHILD, $WS_CLIPCHILDREN, $WS_CLIPSIBLINGS, $WS_VISIBLE) ; 0x56000000
$hUIContainerClassStyleEx = BitOR($WS_EX_NOINHERITLAYOUT, $WS_EX_NOPARENTNOTIFY) ; 0x00100004
$hUIMainClassStyle = BitOR($WS_CHILD, $WS_CLIPCHILDREN, $WS_CLIPSIBLINGS, $WS_SYSMENU, $WS_VISIBLE) ; 0x56080000
$hUIMainClassStyleEx = 0x0
$hATLStyle = BitOR($WS_CHILD, $WS_CLIPCHILDREN, $WS_CLIPSIBLINGS, $WS_VISIBLE) ; 0x56000000
$hATLStyleEx = 0x0
$guiStyle = BitOR($WS_BORDER, $WS_CAPTION, $WS_CLIPCHILDREN, $WS_CLIPSIBLINGS, $WS_DLGFRAME, $WS_GROUP, $WS_MAXIMIZE, $WS_MAXIMIZEBOX, $WS_MINIMIZEBOX, $WS_SYSMENU, $WS_TABSTOP, $WS_THICKFRAME, $WS_VISIBLE) ; 0x17CF0100
$guiStyleEx = $WS_EX_WINDOWEDGE ; 0x00000100
_SetStyle($hUIContainerClass,$hUIContainerClassStyle,$hUIContainerClassStyleEx)
_SetStyle($hUIMainClass,$hUIMainClassStyle,$hUIMainClassStyleEx)
_SetStyle($hATL,$hATLStyle,$hATLStyleEx)
_SetStyle($gui,$guiStyle,$guiStyleEx)
Func _SetStyle($hwnd,$style,$exstyle)
    DllCall("user32.dll", "long", "SetWindowLong", "hwnd", $hwnd, "int", -16, "long", $style)
    DllCall("user32.dll", "long", "SetWindowLong", "hwnd", $hwnd, "int", -20, "long", $exstyle)
EndFunc

; $WS_EX_NOPARENTNOTIFY and $WS_EX_NOINHERITLAYOUT seem to be fairly important
; This may still be important for other projects with similar problems.

AdlibEnable ( "checkconn", 1000)
Func checkconn()
    If $oRDP.Connected = 0 Then
        Exit
    EndIf
EndFunc


While 1
    $msg = GUIGetMsg()
    Select
        Case $msg = $GUI_EVENT_CLOSE
            ExitLoop
    EndSelect
WEnd

GUIDelete()

Exit

Sorry to reactive this old post, i've tried your example and it works great. But i want to disable the maximize-button in the window-frame and did found out how to realize it.

Can you help?

Link to comment
Share on other sites

  • 5 months later...

Hello,

is there a way to set up call back events on rdp interface?

$Rdpc = ObjCreate("MsTscAx.MsTscAx")

I have tried both cases

$ObjectEvent = ObjEvent($Rdpc, "prefix_")

and with pointed interface

$ObjectEvent = ObjEvent($RdpClient, "prefix_","IMsTscAxEvents")

Func prefix_OnConnected()

....

But nothing helps :idea:

I don't get any callbacks. May be I missed something important? Did someone already create event callbacks on rdp succesfully? Is that the problem of AutoIt, so it doesn't support ActiveX events widely or what could be the problem?

Is there a way to figure out with help of debugger if there are any callback tries coming from rdp?

Thank you!

Edited by virtman
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...