I'm trying to write a little C (C++ is fine, too) utility for spying ActiveX controls. Given some HWND handle of a window I'd like to print
- which properties and which methods are exposed by the ActiveX control for this HWND
- optionally, what interfaces does the control implement
For testing purposes, I'm embedding random ActiveX controls (like, the Microsoft Slider control) into the ActiveX Control Test Container so that I know that the HWND of the control is indeed the window of an ActiveX control. Furthermore, I know what properties/methods the control exposes, so I can开发者_C百科 test my tool.
My current solution for (1) is to use the AccessibleObjectFromWindow function on the HWND to get an IDispatch. It works, but it seems you really always only get an accessible interface back (the IDispatch which is returned is just the IDispatch part of the IAccessible interface). I tried passing the actual CLSID of my sample control as the third argument to AccessibleObjectFromWindow but that didn't help either. Seems that function really lives up to it's name - you always only get the accessibility interface. :-)
Does anybody know whether such an "ActiveX spy" is possible at all? If so, how?
You don't
If you have access to the implementation of the activex control (e.g. in ATL) you can use a lookup table to get back at the control owning the HWND; you could use this in conjunction with the global instance table
As @sehe pointed out, there is no reliable way to discover controls externally, and more to say some ActiveX controls are/might be windowless without their own HWND
s.
However, if you are OK to detect at least some controls out there, you can look for those hosted by popular ATL CAxHostWindow
class. This host will respond to specific window messages letting you obtain both host and control interfaces:
WM_ATLGETHOST
gets youIUnknown
of the control host (site)WM_ATLGETCONTROL
gets youIUnknown
of the control itself
Both message identifiers can be obtained using RegisterWindowMessage
API:
const UINT WM_ATLGETHOST = RegisterWindowMessage(_T("WM_ATLGETHOST"));
const UINT WM_ATLGETCONTROL = RegisterWindowMessage(_T("WM_ATLGETCONTROL"));
Having control's IUnknown
on hands you can move on with doscovery of interfaces and properties requesting IDispatch
, IProvideClassInfo
and other interfaces. However, you need to make it the context of the process hosting the control, which makes enumeration harder: you have to inject your code into the process, e.g. using a hook.
精彩评论