Page 1 of 2

Using ActiveX Control

Posted: Tue Mar 09, 2010 11:28 pm
by univeda
I try to embed a rdp-client activex-control (mstscax) into my purebasic-app.

Code: Select all

IncludePath "inc\"
XIncludeFile "COMatePLUS.pbi"

Define.COMateObject rdpObject

If OpenWindow(0, 0, 0, 600, 600, "rdpObject", #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget)

  rdpObject = Comate_CreateActiveXControl(0, 0, 600, 600, "mstscax.mstscax") 
  If rdpObject
    rdpObject\SetProperty("DisconnectedText = 'Verbindung wurde getrennt.'")
    rdpObject\SetProperty("ConnectingText = 'Verbindung wird aufgebaut. Bitte warten...'")
    
    rdpObject\SetProperty("Server = 'my_server_hostname'")
    rdpObject\SetProperty("Domain = 'my_server_logondomain")
    rdpObject\SetProperty("UserName = 'my_username'")
    rdpObject\SetProperty("AdvancedSettings2.ClearTextPassword = 'my_password'")
    
    rdpObject\Invoke("Connect()")    

    While WaitWindowEvent() <> #PB_Event_CloseWindow : Wend 
    CloseWindow(0)
    rdpObject\Release()
  Else
    MessageRequester("rdpObject", "Couldn't create the ActiveX object!")
  EndIf
EndIf
This works fine, so far. But the password is not transfered to the rdpObject.

Code: Select all

rdpObject\SetProperty("AdvancedSettings2.ClearTextPassword = 'my_password'")
I'm using this property in other languages like AutoIt and C# without problems.

Anyone with experience in using this kind of ActiveX-Control with PB?

Re: Using ActiveX Control

Posted: Wed Mar 10, 2010 12:39 am
by Kiffi
univeda wrote:

Code: Select all

rdpObject\SetProperty("AdvancedSettings2.ClearTextPassword = 'my_password'")
try this:

Code: Select all

rdpObject\SetProperty("AdvancedSettings2\ClearTextPassword = 'my_password'")
(replace the point with a backslash)

Greetings ... Kiffi

Re: Using ActiveX Control

Posted: Wed Mar 10, 2010 8:30 pm
by univeda
Thanks, Kiffi. This made the job! Works perfect.

Re: Using ActiveX Control

Posted: Mon Mar 15, 2010 8:49 am
by univeda
After fixing the password-problem (thanks, kiffi), there is another one:

When i move my Windows with the embedded rdp-activeX-Control, some parts of the rdp-desktop disappear. It looks like some kind of clipping error. I realized this program already in autoIt, but how can i adapt this code to purebasic?

Code: Select all

modify the styles of the child controls to match those set by the offical client application
; this prevents clipping problems
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
$guiStyle = BitOR($WS_CAPTION, $WS_CLIPCHILDREN, $WS_CLIPSIBLINGS, $WS_GROUP, $WS_MINIMIZEBOX, $WS_SYSMENU, $WS_TABSTOP, $WS_VISIBLE) ; 0x17CF0100
$guiStyleEx = $WS_EX_WINDOWEDGE ; 0x00000100
_SetStyle($hUIContainerClass, $hUIContainerClassStyle, $hUIContainerClassStyleEx)
_SetStyle($hUIMainClass, $hUIMainClassStyle, $hUIMainClassStyleEx)
_SetStyle($hATL, $hATLStyle, $hATLStyleEx)
_SetStyle($GUI, $guiStyle, $guiStyleEx)
$aStyle = GUIGetStyle()
GUISetStyle(BitAND($aStyle[0], BitNOT($WS_MAXIMIZEBOX)))
Is there an easy way to prevent clipping problems with activex-controls?

Re: Using ActiveX Control

Posted: Mon Mar 15, 2010 11:08 am
by srod
ComatePLUS automatically applies the #WS_CLIPCHILDREN style to ActiveX containers. Perhaps it is this which is causing the problems?

Try and find the following line (in the COMate_CreateActiveXControl() function) and commenting it out - see if that makes any difference?

Code: Select all

SetWindowLongPtr_(hWnd, #GWL_STYLE, GetWindowLongPtr_(hWnd, #GWL_STYLE)|#WS_CLIPCHILDREN)

Re: Using ActiveX Control

Posted: Mon Mar 15, 2010 2:09 pm
by univeda
I tried your hint but it looks like it's getting even worse.

Here is my sample code:

Code: Select all

IncludePath "inc\"
XIncludeFile "COMatePLUS.pbi"

Define.COMateObject RdpObject

Define Server.s = "your_server_ip_or_name"
Define Domain.s = "server_logon_domain"
Define UserName.s = "your_username"
Define Password.s = "your_password"
Define RdpWidth.i = 800
Define RdpHeight.i = 600
Define ColorDepth.i = 16

If OpenWindow(0, 0, 0, RdpWidth, RdpHeight, "Extended Terminal Services Client - " + Server, #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget)

  RdpObject = Comate_CreateActiveXControl(0, 0, RdpWidth, RdpHeight, "mstscax.mstscax") 
  
  If RdpObject
    RdpObject\SetProperty("DisconnectedText = 'Verbindung wurde getrennt.'")
    RdpObject\SetProperty("ConnectingText = 'Verbindung wird aufgebaut. Bitte warten...'")
    RdpObject\SetProperty("Server = '" + Server + "'")
    RdpObject\SetProperty("Domain = '" + Domain + "'")
    RdpObject\SetProperty("UserName = '" + UserName + "'")
    RdpObject\SetProperty("AdvancedSettings2\ClearTextPassword = '" + Password + "'")
    RdpObject\SetProperty("DesktopWidth = '" + Str(RdpWidth) + "'")
    RdpObject\SetProperty("DesktopHeight = '" + Str(RdpHeight) + "'")
    RdpObject\SetProperty("ColorDepth = '" + Str(ColorDepth) + "'")
    RdpObject\Invoke("Connect()")    

    While WaitWindowEvent() <> #PB_Event_CloseWindow : Wend 
    CloseWindow(0)
    RdpObject\Release()
  Else
    MessageRequester("ExTSC", "ActiveX Control konnte nicht erstellt werden!")
  EndIf
  
EndIf
Can you try this code and confirm my problem? You just have to move the window around (outside the local desktop) or minimize it.

Thanks
Michael

Re: Using ActiveX Control

Posted: Mon Mar 15, 2010 2:14 pm
by srod
I have no server to connect to so all I get is the disconnected text. With that, everything looks fine.

Re: Using ActiveX Control

Posted: Mon Mar 15, 2010 2:27 pm
by srod
The COMateClass_GetContainerhWnd() function will allow you to retrieve the hWnd of the ATL container. You can use this to set any styles as you see fit (through SetWindowLongPtr_() etc.) Perhaps setting the styles along the lines of those in your code above will do the trick?

Re: Using ActiveX Control

Posted: Mon Mar 15, 2010 2:49 pm
by univeda
I tried to produce the error with my autoIt-Code:

Code: Select all

; modify the styles of the child controls to match those set by the offical client application
; this prevents clipping problems
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
$guiStyle = BitOR($WS_CAPTION, $WS_CLIPCHILDREN, $WS_CLIPSIBLINGS, $WS_GROUP, $WS_MINIMIZEBOX, $WS_SYSMENU, $WS_TABSTOP, $WS_VISIBLE) ; 0x17CF0100
$guiStyleEx = $WS_EX_WINDOWEDGE ; 0x00000100
_SetStyle($hUIContainerClass, $hUIContainerClassStyle, $hUIContainerClassStyleEx)
_SetStyle($hUIMainClass, $hUIMainClassStyle, $hUIMainClassStyleEx)
_SetStyle($hATL, $hATLStyle, $hATLStyleEx)
_SetStyle($GUI, $guiStyle, $guiStyleEx)
$aStyle = GUIGetStyle()
GUISetStyle(BitAND($aStyle[0], BitNOT($WS_MAXIMIZEBOX)))

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   ;==>_SetStyle
When i disable the function _SetStyle the clipping error appears:

Code: Select all

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   ;==>_SetStyle
[/code]

Can you show me how to set the styles in my pb-code like i my autoIt-Script does?

Re: Using ActiveX Control

Posted: Mon Mar 15, 2010 2:58 pm
by srod
Not exactly because I do not know which windows/controls you are directing the function calls at?

You can change the window and extended window styles for your ActiveX container using something like :

Code: Select all

hWnd = RdpObject\GetContainerhWnd()

SetWindowLongPtr_(hWnd, #GWL_STYLE, myStyle)
SetWindowLongPtr_(hWnd, #GWL_EXSTYLE, myExStyle)
myStyle and myExStyle would be appropriate combinations of window styles (e.g. #WS_CLIPSIBLINGS...) and extended window styles (e.g. #WS_EX_CLIENTEDGE...) etc.

Re: Using ActiveX Control

Posted: Mon Mar 15, 2010 5:11 pm
by univeda
I now have tried this:

Code: Select all

#WS_EX_NOPARENTNOTIFY = $4
#WS_EX_NOINHERITLAYOUT = $100000

If OpenWindow(0, 0, 0, RdpWidth, RdpHeight, "Extended Terminal Services Client - " + Server, #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget)

  RdpObject = Comate_CreateActiveXControl(0, 0, RdpWidth, RdpHeight, "mstscax.mstscax") 
  
  If RdpObject
    RdpObject\SetProperty("DisconnectedText = 'Verbindung wurde getrennt.'")
    RdpObject\SetProperty("ConnectingText = 'Verbindung wird aufgebaut. Bitte warten...'")
    RdpObject\SetProperty("Server = '" + Server + "'")
    RdpObject\SetProperty("Domain = '" + Domain + "'")
    RdpObject\SetProperty("UserName = '" + UserName + "'")
    RdpObject\SetProperty("AdvancedSettings2\ClearTextPassword = '" + Password + "'")
    RdpObject\SetProperty("DesktopWidth = '" + Str(RdpWidth) + "'")
    RdpObject\SetProperty("DesktopHeight = '" + Str(RdpHeight) + "'")
    RdpObject\SetProperty("ColorDepth = '" + Str(ColorDepth) + "'")
    RdpObject\Invoke("Connect()")    
    
    hWnd = RdpObject\GetContainerhWnd()
    SetWindowLongPtr_(hWnd, #GWL_STYLE, #WS_CHILD | #WS_CLIPCHILDREN | #WS_CLIPSIBLINGS | #WS_VISIBLE)
    SetWindowLongPtr_(hWnd, #GWL_EXSTYLE, #WS_EX_NOINHERITLAYOUT | #WS_EX_NOPARENTNOTIFY)    

    While WaitWindowEvent() <> #PB_Event_CloseWindow : Wend 
    CloseWindow(0)
    RdpObject\Release()
  Else
    MessageRequester("ExTSC", "ActiveX Control konnte nicht erstellt werden!")
  EndIf
  
EndIf
The clipping-error still occurs.

But as you can see in my autoIt-Code there are also styles for the MainClass and the ATLClass:

Code: Select all

$hUIContainerClass = ControlGetHandle($GUI, "", "[CLASS:UIContainerClass]")
$hUIMainClass = ControlGetHandle($GUI, "", "[CLASS:UIMainClass]")
$hATL = ControlGetHandle($GUI, "", "[CLASS:" & $sATLClass & "]")

$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
How can i set the style for the MainClass and the ATLClass as i did for the ContainerClass?

Re: Using ActiveX Control

Posted: Mon Mar 15, 2010 7:58 pm
by srod
Try the following and apply the styles (with SetWindowLonPtr_()) as appropriate :

Code: Select all

hUIContainerClass = RdpObject\GetContainerhWnd()
hUIMainClass = GetParent_(hUIContainerClass)
hATL  = FindWindowEx_(hUIContainerClass, 0, 0, 0)
You may need to switch hUIContainerClass and hATL.

Re: Using ActiveX Control

Posted: Mon Mar 15, 2010 10:51 pm
by univeda
Thanks srod for your help. This is my working solution:

Code: Select all

IncludePath "inc\"
XIncludeFile "COMatePLUS.pbi"

Global.COMateObject RdpObject

Define Server.s = "your_servername_or_ipaddress"
Define Domain.s = "your_logon_domain"
Define UserName.s = "your_username"
Define Password.s = "your_password"
Define RdpWidth.i = 800
Define RdpHeight.i = 600
Define ColorDepth.i = 16

Enumeration
#WIN_MAIN
EndEnumeration

Declare SetStyles(COMateObject, hWnd)

#WS_EX_NOPARENTNOTIFY = $4
#WS_EX_NOINHERITLAYOUT = $100000

If OpenWindow(#WIN_MAIN, 10, 10, RdpWidth, RdpHeight, "Extended Terminal Services Client - " + Server, #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget)

  RdpObject = Comate_CreateActiveXControl(5, 5, RdpWidth, RdpHeight, "mstscax.mstscax") 
  
  If RdpObject
    RdpObject\SetProperty("DisconnectedText = 'Verbindung wurde getrennt.'")
    RdpObject\SetProperty("ConnectingText = 'Verbindung wird aufgebaut. Bitte warten...'")
    RdpObject\SetProperty("Server = '" + Server + "'")
    RdpObject\SetProperty("Domain = '" + Domain + "'")
    RdpObject\SetProperty("UserName = '" + UserName + "'")
    RdpObject\SetProperty("AdvancedSettings2\ClearTextPassword = '" + Password + "'")
    RdpObject\SetProperty("DesktopWidth = '" + Str(RdpWidth) + "'")
    RdpObject\SetProperty("DesktopHeight = '" + Str(RdpHeight) + "'")
    RdpObject\SetProperty("ColorDepth = '" + Str(ColorDepth) + "'")
    RdpObject\Invoke("Connect()")
    
    SetStyles(RdpObject, #WIN_MAIN)
    
    While WaitWindowEvent() <> #PB_Event_CloseWindow : Wend 
    CloseWindow(#WIN_MAIN)
    RdpObject\Release()
  Else
    MessageRequester("ExTSC", "ActiveX Control konnte nicht erstellt werden!")
  EndIf
  
EndIf

Procedure SetStyles(COMateObject, hWnd)
;this prevents clipping problems

;ContainerClass
hUIContainerClass = RdpObject\GetContainerhWnd()
SetWindowLongPtr_(hUIContainerClass, #GWL_STYLE, #WS_CHILD | #WS_CLIPCHILDREN | #WS_CLIPSIBLINGS | #WS_VISIBLE)
SetWindowLongPtr_(hUIContainerClass, #GWL_EXSTYLE, #WS_EX_NOINHERITLAYOUT | #WS_EX_NOPARENTNOTIFY)    

;MainClass
hUIMainClass = GetParent_(hUIContainerClass)
SetWindowLongPtr_(hUIMainClass, #GWL_STYLE, #WS_CHILD | #WS_CLIPCHILDREN | #WS_CLIPSIBLINGS | #WS_SYSMENU | #WS_VISIBLE)
SetWindowLongPtr_(hUIMainClass, #GWL_EXSTYLE, $0)

;ATL
hATL = FindWindowEx_(hUIContainerClass, 0, 0, 0)
SetWindowLongPtr_(hATL, #GWL_STYLE, #WS_CHILD | #WS_CLIPCHILDREN | #WS_CLIPSIBLINGS | #WS_VISIBLE)
SetWindowLongPtr_(hATL, #GWL_EXSTYLE, $0)

;Window
hWnd = WindowID(#WIN_MAIN)
SetWindowLongPtr_(hWnd, #GWL_STYLE, #WS_CAPTION | #WS_CLIPCHILDREN | #WS_CLIPSIBLINGS | #WS_GROUP | #WS_MINIMIZEBOX | #WS_SYSMENU | #WS_TABSTOP | #WS_VISIBLE)
SetWindowLongPtr_(hWnd, #GWL_EXSTYLE, #WS_EX_WINDOWEDGE)
EndProcedure
Again, thank you very much!

Re: Using ActiveX Control

Posted: Mon Mar 15, 2010 11:52 pm
by srod
You have some redundancy/repetion here in that hUIMainClass and WindowID(#WinMain) refer to the same window.

Re: Using ActiveX Control

Posted: Tue Mar 16, 2010 8:36 am
by univeda
srod wrote:You have some redundancy/repetion here in that hUIMainClass and WindowID(#WinMain) refer to the same window.
You mean that huiMainClass and #WIN_MAIN is the same? Sorry did not get what you mean.