Jump to content


Photo

COM Standard Library


  • Please log in to reply
655 replies to this topic

#1 Sean

Sean
  • Members
  • 2462 posts

Posted 08 September 2007 - 01:10 AM

This is a standard library COM.ahk.
It requires at least AHK build 1.0.47.00.
Before downloading, please read first about Standard Library.

DOWNLOAD: COM.zip or COM_L.zip (for AutoHotkey_L) or AutoHotkey32/64 (COM is built into).

PREREQUISITE: ComCall via DllCall (Allowing Function Pointer in DllCall)

The usage of COM_Invoke():

If it has the form in VBS-like scripts as
value = Object.Function(param1, param2, ...) ; [color=red]Method, PropertyGet[/color]
it'll be translated like
value := COM_Invoke(Object, "Function", param1, param2, ...)

And, if
Object.Function(param1, param2, ...) = value ; [color=red]PropertyPut, PropertyPutRef[/color]
then similarly with the above
COM_Invoke(Object, "Function", param1, param2, ..., value)
However, there exist occasions the above simple form becomes ambiguous. In those cases, can force it to use PropertyPut by appending to the function name the artificial suffix "=" like:
COM_Invoke(Object, "Function[color=red]=[/color]", param1, param2, ..., value)

There are some occasions where another COM Object ObjPrm should be a parameter. In that case, prefix it with "+" like:
COM_Invoke(Object, "Function", ..., "[color=red]+[/color]" . ObjPrm , ...) ; never directly prefix it like +ObjPrm.
As a consequence, "+0" will play the role of VBS Nothing.

And, "-0" will represent VBS missing parameter. For eample
Object.Function(..., param1, , param3, ...)
in VBS-like scripts can be written as
COM_Invoke(Object, "Function", ..., param1, "[color=red]-0[/color]" , param3, ...)

Finally, to control the error message pop-up of COM Library, call
COM_Error(b) ; b := 0/1 for off/on

REF. If like to use dot syntax, can use ez_invoke() and/or COM_InvokeDeep().

PS. The last updated time is the last edited time of this post.

#2 majkinetor

majkinetor
  • Fellows
  • 4511 posts

Posted 08 September 2007 - 09:57 AM

Thx, it was about time to sort COM funcs out.

#3 Sean

Sean
  • Members
  • 2462 posts

Posted 08 September 2007 - 11:53 AM

Thx, it was about time to sort COM funcs out.

Thanks. Here are the function lists. I'll include it in the COM.zip in the next update. Those in italic are optional parameters.

COM_Invoke(pdisp, sName, arg1, ...) ; Optional arg up to 9.
COM_Invoke_(pdisp, sName, type1, arg1, ...) ; Optional type & arg up to 9.
COM_CoInitialize()
COM_CoUninitialize()
COM_ActiveXObject(ProgID)
COM_CreateObject(CLSID, IID)
COM_ConnectObject(psource, prefix, DIID)
COM_GetObject(Moniker)
COM_GetActiveObject(ProgID)
COM_Release(ppv)
COM_AddRef(ppv)
COM_QueryInterface(ppv, IID)
COM_QueryService(ppv, SID, IID)
COM_VTable(ppv, idx)
COM_AtlAxWinInit(Version)
COM_AtlAxWinTerm(Version)
COM_AtlAxGetControl(hWnd, Version)
COM_AtlAxAttachControl(pdsp, hWnd, Version)
COM_AtlAxCreateControl(hWnd, Name, Version)
COM_AtlAxCreateContainer(hWnd, l, t, w, h, Name, Version)
COM_AtlAxGetContainer(pdsp)
COM_DispGetParam(pDispParams, Position, vtType)
COM_Ansi4Unicode(pString, nSize)
COM_Unicode4Ansi(ByRef wString, sString, nSize)
COM_Ansi2Unicode(ByRef sString, ByRef wString, nSize)
COM_Unicode2Ansi(ByRef wString, ByRef sString, nSize)
COM_CLSID4ProgID(ByRef CLSID, sProgID, nOffset = 0)
COM_GUID4String(ByRef CLSID, sString, nOffset = 0)
COM_ProgID4CLSID(pCLSID)
COM_String4GUID(pGUID)
COM_SysAllocString(sString)
COM_SysFreeString(bstr)
COM_SysStringLen(bstr)
COM_SafeArrayDestroy(psa)
COM_VariantClear(pvarg)
COM_CoTaskMemAlloc(cb)
COM_CoTaskMemFree(pv)
COM_CoCreateGuid()
COM_OleInitialize()
COM_OleUninitialize()
COM_IsEqualGUID(pGUID1, pGUID2)
COM_FindConnectionPoint(pdp, DIID)
COM_GetConnectionInterface(pcp)
COM_Advise(pcp, psink)
COM_Unadvise(pcp, nCookie)
COM_DispInterface()
COM_CreateIDispatch()
COM_GetDefaultInterface()
COM_GetDefaultEvents()
COM_GetGuidOfName()
COM_GetTypeInfoOfGuid()



#4 daonlyfreez

daonlyfreez
  • Members
  • 995 posts

Posted 08 September 2007 - 12:20 PM

Excellent!

Though I understand not even half of it, this is invaluable for advanced options in AHK.

:)

#5 polyethene

polyethene

    Administrator

  • Administrators
  • 5473 posts

Posted 08 September 2007 - 12:29 PM

Small error...

COM.ahk (120) : ==> Call to nonexistent function.
     Specifically: Release(NumGet(this+16)) . Release(NumGet(this+8)) . COM_CoTaskMemFree(this)

btw. what's the difference between Unicode4Ansi and Unicode2Ansi?

#6 Sean

Sean
  • Members
  • 2462 posts

Posted 08 September 2007 - 02:28 PM

Small error...

Oops, sorry. I updated it.

btw. what's the difference between Unicode4Ansi and Unicode2Ansi?

Here, 2 means To and 4 means From or For. So,

Unicode4Ansi(ByRef wString, sString) obtains (ByRef) Unicode wString From provided (ByVal) ANSI sString.
Unicode2Ansi(ByRef wString, ByRef sString) converts provided (ByRef) Unicode wString To (ByRef) ANSI sString.
Ansi2Unicode(ByRef sString, ByRef wString) converts provided (ByRef) ANSI sString To (ByRef) Unicode wString.
Ansi4Unicode(pString) converts the Unicode string at address pString to ANSI string and returns it.

I introduced these 4 functions, in addition to the already existed 2 functions, to reduce the usage of ByRef parameters.
My original plan was to ditch 2 in favor of 4, but these 2 also have their own merit, I finally decided to leave them too.

#7 corrupt

corrupt
  • Members
  • 2558 posts

Posted 08 September 2007 - 10:45 PM

I uploaded standard library COM.ahk.

Thanks :)

Those in italic are optional parameters.

Italic is really hard to distinguish here.

#8 Sean

Sean
  • Members
  • 2462 posts

Posted 08 September 2007 - 11:55 PM

Those in italic are optional parameters.

Italic is really hard to distinguish here.

Yeh, I first planned to use them in the code box, but italic didn't work in code box, so quoted them instead. I included the text file in this format in COM.zip.

#9 Sean

Sean
  • Members
  • 2462 posts

Posted 09 September 2007 - 02:01 PM

I was playing a little more with the standard library thing, more precisely with Lib subdirectory. If want to use still CoHelper.ahk, rather than altering the existing scripts to adapt to COM.ahk, you may put CoHelper.ahk to Lib subdirectory after adding a dummy function to it:

CoHelper_Init()
{
}
Then, remove #Include CoHelper.ahk, and call instead CoHelper_Init() at the start of the script.
BTW, what I'm actually using is:

CoHelper_Init()
{
	CoInitialize()
}

CoHelper_Term()
{
	CoUninitialize()
}
and call them instead of CoInitialize() and CoUninitialize().

OK, it may not be really different with #Include, but the pro of it is that the included file can reside in the constant place, the Lib subdirectory. The con is that the dummy function can't be placed in an arbitrary position in the script, it should be called before any other functions in the included file.

Just a tip for the users who aren't aware of it yet.

#10 Joy2DWorld

Joy2DWorld
  • Members
  • 562 posts

Posted 09 September 2007 - 03:06 PM

not sure if this is helpful, likely obvious, but just in case.. simple formatting suggestion example for helpfile text/post help text type thing..
COM_Invoke(pdisp, sName, [arg1], ...) ; Optional arg up to 9.

COM_Invoke_(pdisp, sName, [type1], [arg1], ...) ; Optional type & arg up to 9.

COM_DispGetParam(pDispParams, [Position], [vtType])

COM_AtlAxWinInit([Version])

COM_AtlAxWinTerm([Version])

COM_AtlAxGetControl(hWnd, [Version])

COM_AtlAxAttachControl(pdsp, hWnd, [Version])

COM_AtlAxCreateControl(hWnd, Name, [Version])

COM_AtlAxCreateContainer(hWnd, l, t, w, h, [Name], [Version])

COM_AtlAxGetContainer(pdsp)

COM_CoInitialize()

COM_CoUninitialize()

COM_ActiveXObject(ProgID)

COM_CreateObject(CLSID, [IID])

COM_ConnectObject(psource, [prefix], [DIID])

COM_GetObject(Moniker)

COM_GetActiveObject(ProgID)

COM_Release(ppv)

COM_AddRef(ppv)

COM_QueryInterface(ppv, IID)

COM_QueryService(ppv, SID, IID)

COM_VTable(ppv, idx)

COM_Ansi2Unicode(ByRef sString, ByRef wString, [nSize])

COM_Unicode2Ansi(ByRef wString, ByRef sString, [nSize])

COM_Unicode4Ansi(ByRef wString, sString, [nSize])

COM_Ansi4Unicode(pString, [nSize])



#11 corrupt

corrupt
  • Members
  • 2558 posts

Posted 09 September 2007 - 03:54 PM

If want to use still CoHelper.ahk, rather than altering the existing scripts to adapt to COM.ahk, you may put CoHelper.ahk to Lib subdirectory after adding a dummy function to it:

Another alternative could be to rename CoHelper.ahk to CoInitialize.ahk and remove the #Include line.

#12 Joy2DWorld

Joy2DWorld
  • Members
  • 562 posts

Posted 09 September 2007 - 05:08 PM

Another alternative could be to rename CoHelper.ahk to CoInitialize.ahk and remove the #Include line.


or, on same line of thought, but avoids confusion over the CoHelper.ahk file name

simply add a CoInitialize.ahk to the lib that contains #Include CoHelper.ahk

#13 BoBo¨

BoBo¨
  • Guests

Posted 13 September 2007 - 09:13 AM

Hi. I wasn't successfull with identifying mandatory details to extract from the code below, to be used with one of those/your functions. :(
Target is to get the Artist (Track/Duration/Album) name of the currently playing track in Windows Media Player (WMP).
Hope you can help me & thx for listening. :)
#define _ATL_APARTMENT_THREADED

#include <atlbase.h>
#include <atlcom.h>
#include <atlwin.h>
#include <initguid.h>
#include "RemoteHost.h"

CComModule _Module;

BEGIN_OBJECT_MAP(ObjectMap)
END_OBJECT_MAP()

int PrintCurrSong()
{
HRESULT hr = S_OK;
RECT rcClient;
CComPtr<IObjectWithSite> spHostObject;
CComPtr<IAxWinHostWindow> spHost;
CComObject<CRemoteHost> *pRemoteHost = NULL;
CComPtr<IWMPPlayer4> m_spPlayer;


// Create an ActiveX control container
AtlAxWinInit();
CAxWindow *m_pView = new CAxWindow();
if(!m_pView)
{
hr = E_OUTOFMEMORY;
}

if(SUCCEEDED(hr))
{
m_pView->Create(NULL, rcClient, NULL, WS_VISIBLE , WS_EX_CLIENTEDGE);

if(::IsWindow(m_pView->m_hWnd))
{
hr = m_pView->QueryHost(IID_IObjectWithSite, (void **)&spHostObject);
if(!spHostObject.p)
{
hr = E_POINTER;
}
}
}

// Create remote host which implements IServiceProvider and IWMPRemoteMediaServices
if(SUCCEEDED(hr))
{
hr = CComObject<CRemoteHost>::CreateInstance(&pRemoteHost);
if(pRemoteHost)
{
pRemoteHost->AddRef();
}
else
{
hr = E_POINTER;
}
}

// Set site to the remote host
if(SUCCEEDED(hr))
{
hr = spHostObject->SetSite((IWMPRemoteMediaServices *)pRemoteHost);
}

if(SUCCEEDED(hr))
{
hr = m_pView->QueryHost(&spHost);
if(!spHost.p)
{
hr = E_NOINTERFACE;
}
}

// Create WMP Control here

if(SUCCEEDED(hr))
{
hr = spHost->CreateControl(CComBSTR(L"{6BF52A52-394A-11d3-B153-00C04F79FAA6}"), m_pView->m_hWnd, NULL);
}

if(SUCCEEDED(hr))
{
hr = m_pView->QueryControl(&m_spPlayer);
if(!m_spPlayer.p)
{
hr = E_NOINTERFACE;
}
IWMPMedia *media;
m_spPlayer->get_currentMedia(&media);
CComBSTR str;
media->get_name(&str);
CW2A printstr(str);
printf("%s\n", printstr);
}

// Release remote host object
if(pRemoteHost)
{
pRemoteHost->Release();
}
return 1; // Let the system set the focus
}

int _tmain()
{
HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);

HRESULT hRes = CoInitialize(NULL);

_ASSERTE(SUCCEEDED(hRes));
_Module.Init(ObjectMap, hInstance, &LIBID_ATLLib);

hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER,
REGCLS_MULTIPLEUSE);

_ASSERTE(SUCCEEDED(hRes));

PrintCurrSong();
_Module.RevokeClassObjects();
_Module.Term();
CoUninitialize();
return 0;
}


#14 majkinetor

majkinetor
  • Fellows
  • 4511 posts

Posted 13 September 2007 - 09:38 AM

he he :D

Maybe you shoud practice a bit more, I will send you adequate tunes for inspiration :p

#15 Sean

Sean
  • Members
  • 2462 posts

Posted 13 September 2007 - 10:19 AM

Target is to get the Artist (Track/Duration/Album) name of the currently playing track in Windows Media Player (WMP).

Exactly from where are you trying to get the infos?
The code you attached has nothing to do with wmplayer.exe, it's about how to create container object using ATL library and then to host the WMPlayer.OCX control.
I'm not aware of any COM way to retrieve the infos from the running wmplayer.exe.