 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
Sean
Joined: 12 Feb 2007 Posts: 2462
|
Posted: Wed Jun 06, 2007 3:08 am Post subject: |
|
|
| 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 |
|
 |
Joy2DWorld
Joined: 04 Dec 2006 Posts: 561 Location: Galil, Israel
|
Posted: Wed Jun 06, 2007 11:32 pm Post subject: |
|
|
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 |
|
 |
Sean
Joined: 12 Feb 2007 Posts: 2462
|
Posted: Thu Jun 07, 2007 7:21 am Post subject: |
|
|
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 |
|
 |
Dewi Morgan
Joined: 03 Oct 2005 Posts: 186
|
Posted: Mon Jun 25, 2007 5:18 pm Post subject: |
|
|
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 |
|
 |
Sean
Joined: 12 Feb 2007 Posts: 2462
|
Posted: Mon Jun 25, 2007 11:54 pm Post subject: |
|
|
| 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 |
|
 |
Dewi Morgan
Joined: 03 Oct 2005 Posts: 186
|
Posted: Tue Jun 26, 2007 5:13 am Post subject: |
|
|
"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 |
|
 |
FlowPEE
Joined: 28 Feb 2007 Posts: 14
|
Posted: Tue Jun 26, 2007 4:08 pm Post subject: |
|
|
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
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 |
|
 |
Sean
Joined: 12 Feb 2007 Posts: 2462
|
Posted: Wed Jun 27, 2007 12:09 am Post subject: |
|
|
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 |
|
 |
FlowPEE
Joined: 28 Feb 2007 Posts: 14
|
Posted: Wed Jun 27, 2007 9:23 am Post subject: |
|
|
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 |
|
 |
Sean
Joined: 12 Feb 2007 Posts: 2462
|
Posted: Wed Jun 27, 2007 10:31 am Post subject: |
|
|
| 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 |
|
 |
FlowPEE
Joined: 28 Feb 2007 Posts: 14
|
Posted: Wed Jun 27, 2007 11:11 am Post subject: |
|
|
Sean,
that didn't work either
So I guess I have to find a way to talk to Citrix support.
Thanks alot for your help though!
Flo |
|
| Back to top |
|
 |
Sean
Joined: 12 Feb 2007 Posts: 2462
|
Posted: Wed Jun 27, 2007 11:37 am Post subject: |
|
|
| FlowPEE wrote: | that didn't work either  |
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 |
|
 |
erictheturtle
Joined: 27 Jun 2007 Posts: 101 Location: California
|
Posted: Wed Jun 27, 2007 8:08 pm Post subject: |
|
|
Amazing Sean! Not only have you provided support for COM early binding, but also late binding, and all in native AHK!
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.  |
|
| Back to top |
|
 |
Sean
Joined: 12 Feb 2007 Posts: 2462
|
Posted: Thu Jun 28, 2007 12:05 am Post subject: |
|
|
| 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.  |
Thank you and I'm glad to hear that I could be helpful. |
|
| Back to top |
|
 |
ABCyourway Guest
|
Posted: Thu Jun 28, 2007 1:57 am Post subject: |
|
|
| 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?
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 |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|