AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

COM Helper
Goto page Previous  1, 2, 3 ... 6, 7, 8, 9, 10, 11  Next
 
This topic is locked: you cannot edit posts or make replies.    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
Sean



Joined: 12 Feb 2007
Posts: 2462

PostPosted: Wed Jun 06, 2007 3:08 am    Post subject: Reply with quote

Joy2DWorld wrote:
any help/guidance appreciated, streaming feed to the html from var seems like a valueable function... anyhow...

Although I may implement it if there are urgent demands, this function would become redundant once DOM is supported, which is more elegant way to do it, IMO.
Back to top
View user's profile Send private message
Joy2DWorld



Joined: 04 Dec 2006
Posts: 561
Location: Galil, Israel

PostPosted: Wed Jun 06, 2007 11:32 pm    Post subject: Reply with quote

ok, i'll add it to *my* project list... and hopefully you'll give me some guidance in those areas where my skull is too thick...
_________________
Joyce Jamce
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 2462

PostPosted: Thu Jun 07, 2007 7:21 am    Post subject: Reply with quote

I added one more function, ActiveXObject, to CoHelper.ahk.
Although this function may not be as accurate as CreateObject(), I suppose it is the closest to VBScript's CreateObject() or JScript's ActiveXObject().

For example, in ZipFolder script, may replace

Code:
   CLSID_Shell := "{13709620-C279-11CE-A49E-444553540000}"
    IID_IShell := "{D8F015C0-C278-11CE-A49E-444553540000}"
   psh := CreateObject(CLSID_Shell, IID_IShell)

with

Code:
   psh := ActiveXObject("Shell.Application")
Back to top
View user's profile Send private message
Dewi Morgan



Joined: 03 Oct 2005
Posts: 186

PostPosted: Mon Jun 25, 2007 5:18 pm    Post subject: Reply with quote

In another thread I am trying to intercept drag/drop operations. I am disabled by the fact that I have never done any COM programming before.

In order to do this, I need to (from MSDN's page on the topic):


  • "initialize COM with OleInitialize, not CoInitialize." [CoHelper can do this: the OleInitialize() function]

  • "expose an IDropTarget interface." [I do not know if this is possible in AHK]

  • "register with the system by calling RegisterDragDrop." - and passing it a pointer to the object that exposes the IDropTarget interface. [Though CoHelper can call the function, I do not know what DLL it is in, nor whether I can create a pointer to an interface in AHK]

  • Create the functions IDropTarget::DragEnter(), IDropTarget::DragOver(), IDropTarget::DragLeave() and IDropTarget::Drop() to be called by the system. [While I can create them as AHK functions, I suspect this is not good enough, and they need to be real functions with memory addresses and stuff.]

  • Accept a pointer to a data object as a parameter to DragEnter() [Pointers in AHK? I don't know if possible.]

  • Use that pointer to obtain the information from the IDataObject that is being dragged. [I am unsure of object manipulation is possible in AHK.]


So, I have questions :)

Is all the above possible in AHK?

Is there a lower level at which I could hook into drag/drop, so that I wouldn't need to place a window under the mouse in order to capture the IDataObject?

Am I using the wrong tool, needlessly hobbling myself using AHK? Should I instead download a C compiler and learn to program the Windows API in that?

Can you offer any other advice?
_________________
Yet another hotkeyer.
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 2462

PostPosted: Mon Jun 25, 2007 11:54 pm    Post subject: Reply with quote

Dewi Morgan wrote:
Is all the above possible in AHK?

Basically, I would say yes, now officially, using RegisterCallback.
Moreover, I think it's highly likely as IDropTarget interface is relatively simple.

I once did a similar job:
http://www.autohotkey.com/forum/viewtopic.php?t=19475

There, I'm still feeling that I was very lucky as I had to implement the corresponding AHK's procedure for only one member function. In principle, however, you have to implement its own (AHK's) procedure for each member functions.

Quote:
Should I instead download a C compiler and learn to program the Windows API in that?

You can also use C, even (in-line) ASM, inside AHK. See this breath-taking post by Laszlo:
http://www.autohotkey.com/forum/topic18713.html
Back to top
View user's profile Send private message
Dewi Morgan



Joined: 03 Oct 2005
Posts: 186

PostPosted: Tue Jun 26, 2007 5:13 am    Post subject: Reply with quote

"relatively simple" he says! Way to scare me away from Windows programming! :P

But thank you - that is awesomely helpful, and I seems to be exactly what I needed.
_________________
Yet another hotkeyer.
Back to top
View user's profile Send private message
FlowPEE



Joined: 28 Feb 2007
Posts: 14

PostPosted: Tue Jun 26, 2007 4:08 pm    Post subject: Reply with quote

Hi Sean + others,

very helpful script you wrote accessing COM.
I have some problems, maybe you can give me a hint
on how to solve my problem.

I am trying to communicate with the Citrix API through the ICA client.
I am new to this topic but I have to figure out how I can send
keystrokes and maybe also mouseclicks to a citrix application.

I tried to use PostMessage but this won't work on a Citrix window.

So now I am using cohelper.ahk to use the wfica.ocx.
I managed to login through citrix but now I get stuck on how to use
the keyboard.

Alright. Now some information.

I use
Code:
piT := ActiveXObject("Citrix.ICAClient")
to connect to the API and piT contains a valid identifier. Then I am able to set some properties and to pass them.
For instance:

Code:

Ctrx_SetProp(ByRef piT, propName, propVal)
{
   pName := SysAllocString(propName)
   pStr := SysAllocString(propVal)
   ret := DllCall(VTable(piT, 16), "Uint", piT, "Uint", pName, "Uint", pStr)
   
   SysFreeString(pName)
   SysFreeString(pStr)

   return ret
}


Ctrx_SetProp(piT,"Username",user)
Ctrx_SetProp(piT,"Password",Pwd)


Now the problem. As I can see from the typelib browser, there are differten CLSIDs and IIDs but I don't know, how to use different than
the ICAClient

Code:

' ****************************************************************************************
' ProgIDs (Program identifiers)
' ****************************************************************************************

$PROGID_CitrixICAClient25 = "Citrix.ICAClient.2.5"
$PROGID_CitrixICAClientProp24 = "Citrix.ICAClientProp.2.4"

' ****************************************************************************************
' ClsIDs (Class identifiers)
' ****************************************************************************************

$CLSID_ICAClient = GUID$("{238F6F83-B8B4-11CF-8771-00A024541EE3}")
$CLSID_ICAClientProp = GUID$("{238F6F85-B8B4-11CF-8771-00A024541EE3}")
$CLSID_Keyboard = GUID$("{B5D6ED13-EDAA-4C2C-B2E2-26FD9BC1C710}")
$CLSID_Mouse = GUID$("{901591F7-7ACA-477A-9119-C75198E74F72}")
$CLSID_ScreenShot = GUID$("{1F26DF05-9E90-4156-B58B-44632B0DC461}")
$CLSID_Session = GUID$("{1DA5FBD9-3ED4-4617-9A95-334789A2B52A}")
$CLSID_window = GUID$("{CBC0A3C6-7F47-4F70-B0FC-307688E5EAB2}")
$CLSID_Windows = GUID$("{30DBF909-6147-46C8-B02C-96B460712ED3}")

' ****************************************************************************************
' IIDs (Interface identifiers)
' ****************************************************************************************

$IID_IICAClient = GUID$("{238F6F81-B8B4-11CF-8771-00A024541EE3}")
$IID_IKeyboard = GUID$("{17BFCA0A-C42E-4AC9-A693-29473FF9BA6C}")
$IID_IMouse = GUID$("{02093274-7B69-4FEB-B7FD-3A010561A5F3}")
$IID_IScreenShot = GUID$("{8F2D9E63-D224-47E4-8111-32DBB016A4C6}")
$IID_ISession = GUID$("{4A502C16-CFAE-4BB0-B1F9-93ACADDA57BB}")
$IID_IWindow = GUID$("{4D5D2139-29E2-4CDC-8020-429B35999BE6}")
$IID_IWindows = GUID$("{9B371833-5E4F-4B72-A8F6-CB8E762999F4}")
$IID__IICAClientEvents = GUID$("{238F6F82-B8B4-11CF-8771-00A024541EE3}")
$IID__IKeyboardEvents = GUID$("{8A5961DF-314E-4B7C-B57F-AAF35EA33079}")
$IID__IMouseEvents = GUID$("{24013613-FF51-4B50-9832-37FA561594ED}")
$IID__IScreenShotEvents = GUID$("{785A16E9-4E42-4C87-84AD-BFB4A60570A3}")
$IID__ISessionEvents = GUID$("{24FD31DB-3560-4C78-8950-30F03352D830}")
$IID__IWindowEvents = GUID$("{49813E6D-17FF-41A1-9A7B-95C3D5B44185}")


I tried the following to send a keystroke:
Code:

   GUID4String(CLSID_Keyboard, "{B5D6ED13-EDAA-4C2C-B2E2-26FD9BC1C710}")
   GUID4String(IID_IKeyboard, "{17BFCA0A-C42E-4AC9-A693-29473FF9BA6C}")

   puh := CreateObject(CLSID_Keyboard, IID_IKeyboard)
   VK = 65
   DllCall(VTable(piT, 7), "Uint", piT, "Long", VK, "Long")


But the puh variable always contains 0 instead of a valid identifiert.
What am I missing and what do I wrong?

I read through many articles containg cohelper and got that far but no further Sad


here is the original function as revealed with TypeLib browser
Code:

' ****************************************************************************************
' SendKeyUp method
' Interface name = IKeyboard
' method SendKeyUp
' VTable offset = 32 [&H20]
' DispID = 101 [&H00000065]
' ****************************************************************************************
FUNCTION CitrixIKeyboard_SendKeyUp ALIAS "CitrixIKeyboard_SendKeyUp" ( _
    BYVAL pthis AS DWORD PTR _                          ' %VT_DISPATCH <dispinterface>
  , BYVAL keyId AS LONG _                               ' %VT_I4 <LONG> [in]
    ) EXPORT AS LONG                                    ' %VT_HRESULT <LONG>

    LOCAL HRESULT AS LONG
    IF pthis = 0 THEN FUNCTION = %E_POINTER : EXIT FUNCTION
    CALL DWORD @@pthis[8] USING CitrixIKeyboard_SendKeyUp(pthis, keyId) TO HRESULT
    FUNCTION = HRESULT

END FUNCTION


Any help is appreciated!

n/b: I never used cohelper nor Citrix before. So both is new to me.

Thanks alot,
FlowPEE
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 2462

PostPosted: Wed Jun 27, 2007 12:09 am    Post subject: Reply with quote

I don't use citrix, but I got the typelib of it. Try the following.
If still not working, tell me the ErrorLevel and A_LastError.
And, make sure there exists a registry key HKEY_CLASSES_ROOT\CLSID\{B5D6ED13-EDAA-4C2C-B2E2-26FD9BC1C710}.

Code:
#Include CoHelper.ahk

CoInitialize()
pica := ActiveXObject("Citrix.ICAClient")

If !Invoke(pica, "IsKeyboardInputEnabled")
    Invoke(pica, "EnableKeyboardInput")

GUID4String(CLSID_Keyboard, "{B5D6ED13-EDAA-4C2C-B2E2-26FD9BC1C710}")
GUID4String( IID_IKeyboard, "{17BFCA0A-C42E-4AC9-A693-29473FF9BA6C}")

pkey := CreateObject(CLSID_Keyboard, IID_IKeyboard)
;MsgBox, % ErrorLevel . " | " . A_LastError
VK = 65
DllCall(VTable(pkey, 7), "Uint", pkey, "int", VK)
/*
VarSetCapacity(var, 16, 0)
NumPut( 3, var, 0)
NumPut(VK, var, 8)
Invoke(pkey, "SendKeyDown", var)
*/

Release(pkey)
Release(pica)
CoUninitialize()


PS. I updated CoHelper.ahk, so please recopy it. And, it needs AHK 1.0.47.00.
Back to top
View user's profile Send private message
FlowPEE



Joined: 28 Feb 2007
Posts: 14

PostPosted: Wed Jun 27, 2007 9:23 am    Post subject: Reply with quote

Sean,

thanks for your reply !

Unfortuanetely, that is not working.
ErrorLevel contains 0 and A_LastError contains 1008.

The reg key does NOT exist. Maybe there is the/a problem?
Why is the CLSID not registered and do I have a chance to
add it to the registry?

I tried your script with the new cohelper.ahk and the new AHK.

Do you need something else from me to support you?

Thanks for your help,

Florian

EDIT: btw, when I do e.g.
Code:

bla := Invoke(pica, "GetScreenWidth")
MsgBox %bla%

I do successfully get a result, namely 1280
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 2462

PostPosted: Wed Jun 27, 2007 10:31 am    Post subject: Reply with quote

FlowPEE wrote:
The reg key does NOT exist. Maybe there is the/a problem?
Why is the CLSID not registered and do I have a chance to
add it to the registry?

I see. Actually that's what I suspected from the lack of the corresponding ProgIDs.
Then, the following is the only remained one I can think of.
If it doesn't work, you may have to consult the support service of Citrix.

Code:
#Include CoHelper.ahk
CoInitialize()
pica := ActiveXObject("Citrix.ICAClient")
pssn := Invoke(pica, "Session")
pkey := Invoke(pssn, "Keyboard")

VK = 65
VarSetCapacity(var, 16, 0), NumPut(3, var, 0), NumPut(VK, var, 8)
Invoke(pkey, "SendKeyDown", var) ; Invoke(pkey, "SendKeyUp", var)

Release(pkey)
Release(pssn)
Release(pica)
CoUninitialize()

PS. May need to add the following after pica:

Code:
If !Invoke(pica, "IsKeyboardInputEnabled")
    Invoke(pica, "EnableKeyboardInput")
Back to top
View user's profile Send private message
FlowPEE



Joined: 28 Feb 2007
Posts: 14

PostPosted: Wed Jun 27, 2007 11:11 am    Post subject: Reply with quote

Sean,

that didn't work either Sad

So I guess I have to find a way to talk to Citrix support.
Thanks alot for your help though!

Flo
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 2462

PostPosted: Wed Jun 27, 2007 11:37 am    Post subject: Reply with quote

FlowPEE wrote:
that didn't work either Sad

Sorry to hear that...
BTW, exactly which step not worked? pssn or pkey?
Anyway, if you find a working script in any language like VBS, that could be of help.
Back to top
View user's profile Send private message
erictheturtle



Joined: 27 Jun 2007
Posts: 101
Location: California

PostPosted: Wed Jun 27, 2007 8:08 pm    Post subject: Reply with quote

Amazing Sean! Not only have you provided support for COM early binding, but also late binding, and all in native AHK! Shocked

I've attempted to do a similar thing with another scripting language I use, but my high expectations turned it into a gross mess (I didn't want to require the API user to understand/deal with VARIANTs).

I owe you much for your posts because it helped me understand enough of the raw workings of COM to finally use it myself.

For the longest time I've wanted a super easy method to work with COM in my scripting languages. I assumed it was complicated, so I thought it would be nice if someone could at least make a small DLL to handle the dirty work. It has surprised me that no one ever has (or have they?).

Now that I know enough to do so, I'm putting together a DLL to do that very thing. It meets my needs well since I can use it in any language that loads DLLs. Plus, writing COM in C++ (or even C) is ridiculously easier than in a scripting language.

Since I have wanted this for so long, I'm curious if there's any other interest in a DLL like this.

Simple API usage example:
Code:

;; Required
hModule := DllCall("LoadLibrary", "str", "easycom.dll") 

;;; Set spVoice = CreateObject("SAPI.SpVoice")
spVoice := DllCall("easycom.dll\CreateObject", "str", "SAPI.SpVoice")

;;; iRet = spVoice.Speak("hello there", 0)
DllCall("easycom.dll\BeginMemberCall")
DllCall("easycom.dll\AddArgument", "int", TYPE_STR, "str", "hello there")
DllCall("easycom.dll\AddArgument", "int", TYPE_INT, "int", 0)
DllCall("easycom.dll\InvokeMethod", "int", spVoice, "str", "Speak")
iRet := DllCall("easycom.dll\GetReturn", "*int")
DllCall("easycom.dll\EndMemberCall")

;;; Set spVoice = Nothing
DllCall("easycom.dll\ReleaseObject", "int", spVoice)

DllCall("FreeLibrary", "UInt", hModule)

Still kinda messy I know, but at least there is no need to poke around in memory.

And after adding a few wrapper functions, down to 6 lines!
Code:

#include EasyCOM.ahk
LoadEasyCOM()

;;; Set spVoice = CreateObject("SAPI.SpVoice")
spVoice = CreateObject("SAPI.SpVoice")

;;; iRet = spVoice.Speak("hello there", 0)
iRet := Method(spVoice, "Speak", TYPE_STR, "hello there", TYPE_INT, 0)

;;; Set spVoice = Nothing
ReleaseObject(spVoice)

UnloadEasyCOM()


This small amount of code will be fully flexible for any class, any method/property, with any amount/types of arguments. And easycom.dll will likely be only around 100k.

If nothing else, thank you Sean for your input into this community. I'm really happy to finally have this available. Smile
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 2462

PostPosted: Thu Jun 28, 2007 12:05 am    Post subject: Reply with quote

erictheturtle wrote:
This small amount of code will be fully flexible for any class, any method/property, with any amount/types of arguments. And easycom.dll will likely be only around 100k.

Very interesting!
Does it care for the optional parameters too, I mean, if an user omits optional parameters then the dll fills them instead?
It would be quite helpful in some cases like Excel, where some functions expect lots of parameters and most of them are indeed optional.

Quote:
If nothing else, thank you Sean for your input into this community. I'm really happy to finally have this available. Smile

Thank you and I'm glad to hear that I could be helpful.
Back to top
View user's profile Send private message
ABCyourway
Guest





PostPosted: Thu Jun 28, 2007 1:57 am    Post subject: Reply with quote

Quote:
Since I have wanted this for so long,

Maybe most of people here have!

Quote:
I'm curious if there's any other interest in a DLL like this.


Do you really have to be curious? Very Happy
From what I have seen from this thread, there is no quesiton about people being eager to have your EASYCOM.DLL

Personally I don't understand most of the details about raw COM object disscussed here, but I know some others and I want it!
Back to top
Display posts from previous:   
This topic is locked: you cannot edit posts or make replies.    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page Previous  1, 2, 3 ... 6, 7, 8, 9, 10, 11  Next
Page 7 of 11

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group