简体   繁体   中英

How do I get a COM interface given a HWND of an ActiveX control?

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

  1. which properties and which methods are exposed by the ActiveX control for this HWND
  2. 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 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?

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 you IUnknown of the control host (site)
  • WM_ATLGETCONTROL gets you IUnknown 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, eg using a hook.

You don't

If you have access to the implementation of the activex control (eg 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM