How to subclass a dialog-based ActiveX control

How to subclass a dialog-based ActiveX control

Post by Samuel Whit » Thu, 11 Apr 2002 21:45:04



I'm doing this in ATL (WTL) but question 2 below is very general. In any
case, I want to subclass a dialog-based ActiveX control in order to trap
messages in my own self-contained C++ class. The goal is to create a member
variable in the dialog class itself and then hook it up to the ActiveX
control in the WM_INITDIALOG handler (standard stuff). All messages should
be routed through this class's message map however, NOT the dialog's. So:

1) For ATL developers: Is it more appropriate to derive my class from
"CWindowImpl" or "CContainedWindow". I think the latter is primarily for
routing messages through the contained window's message map which doesn't
apply here (since I don't want to route through the dialog window's message
map). I will call "SubclassWindow()" in the WM_INITDIALOG handler
accordingly.
2) In general, how do you get hold of the actual window handle to subclass.
If you simply subclass the return value of "GetDlgItem()", that returns the
ActiveX control's container window if I'm not mistaken. You need to subclass
the ActiveX control window itself however which is a child of the latter
window I believe. I'm a little fuzzy on the window relationships here
however. What is the formal way of getting hold of this window then?

Thanks.

 
 
 

How to subclass a dialog-based ActiveX control

Post by Igor Tandetni » Thu, 11 Apr 2002 23:23:26


1) CWindowImpl makes more sense to me.

2) I don't understand the question. You seem to want to subclass the
window you get full control over. So you have your HWND readily
available.

Or are you asking how to subclass the window of third-party ActiveX
control you are hosting? It is not recommended - you are supposed to
manipulate the control using its public interface. In case you really
need to do this for some reason, query the control for IOleWindow and
call IOleWindow::GetWindow. Naturally, that does not work on windowless
controls.
--
With best wishes,
    Igor Tandetnik

"For every complex problem, there is a solution that is simple, neat,
and wrong." H.L. Mencken


Quote:> I'm doing this in ATL (WTL) but question 2 below is very general. In
any
> case, I want to subclass a dialog-based ActiveX control in order to
trap
> messages in my own self-contained C++ class. The goal is to create a
member
> variable in the dialog class itself and then hook it up to the ActiveX
> control in the WM_INITDIALOG handler (standard stuff). All messages
should
> be routed through this class's message map however, NOT the dialog's.
So:

> 1) For ATL developers: Is it more appropriate to derive my class from
> "CWindowImpl" or "CContainedWindow". I think the latter is primarily
for
> routing messages through the contained window's message map which
doesn't
> apply here (since I don't want to route through the dialog window's
message
> map). I will call "SubclassWindow()" in the WM_INITDIALOG handler
> accordingly.
> 2) In general, how do you get hold of the actual window handle to
subclass.
> If you simply subclass the return value of "GetDlgItem()", that
returns the
> ActiveX control's container window if I'm not mistaken. You need to
subclass
> the ActiveX control window itself however which is a child of the
latter
> window I believe. I'm a little fuzzy on the window relationships here
> however. What is the formal way of getting hold of this window then?

> Thanks.


 
 
 

How to subclass a dialog-based ActiveX control

Post by Samuel Whit » Fri, 12 Apr 2002 00:13:40


Thanks.

Quote:> 1) CWindowImpl makes more sense to me.

Turns out that you can't use either "CWindowImpl" or "CContainedWindow". I
wanted a class that looked something like this for instance:

class C3rdPartyControl : public CAxWindowT<CWindowImpl<C3rdPartyControl> >

This would give my class both a message map and access to
"SubclassWindow()". I could then subclass the control's window and route its
messages through my class. The default constructor for "CAxWindowT" takes an
HWND however and passes it to its base class "CWindowImpl". The latter class
has no such constructor however (neither does "CContainedWindow") so a
compiler error results (C2664). I guess they never expected anyone to
subclass an ActiveX control - either that or the design is flawed. Instead,
I simply inherited from "CAxWindow" directly (the normal route) and created
a "CContainedWindow" member variable. I then subclass that member and route
its messages through the message map of my class. Somewhat ugly but I'm open
to better suggestions.

Quote:

> 2) ... Or are you asking how to subclass the window of third-party ActiveX
> control you are hosting? It is not recommended - you are supposed to
> manipulate the control using its public interface. In case you really
> need to do this for some reason, query the control for IOleWindow and
> call IOleWindow::GetWindow. Naturally, that does not work on windowless
> controls.

Yes, that's what I'm after. I'm manipulating the control normally but need
to trap WM_KILLFOCUS. I'm wondering if most controls don't provide an event
for this. The one I'm using ("VSFlexGrid" - fairly well known) doesn't
provide it. I'd therefore like to trap it and pass it to the parent window
(dialog) as a (customized) control notification message (say, VN_KILLFOCUS).
The control would then behave consistently with the standard Windows
controls. Any comments? Thanks again.
 
 
 

How to subclass a dialog-based ActiveX control

Post by Igor Tandetni » Fri, 12 Apr 2002 02:07:27


1) I must admit you lost me there. Can you sketch what exactly you
intend to do with such a class? BTW, if you need CWindowImpl that also
has methods of CAxWindow, try

class C3rdPartyControl : public CWindowImpl<C3rdPartyControl, CAxWindow>

That produces the correct inheritance hierarchy. It's unclear to me why
you would ever want such a thing though.

2) The control calls IOleControlSite::OnFocus when it gains or loses
focus. Unfortunately, ATL implementation does nothing there and it is
difficult to customize it. There are two ways - simple but hackish and
correct but complicated. Simple way is to copy <atlhost.h> header into
your project directory, call it something else and include this copy
where you would otherwise inclue atlhost.h. Then you simply make any
change you want to OnFocus implementation, e.g. send a message to parent
window. Of course the moment you upgrade your compiler and want to use
updated ATL headers, you'll have to repeat this procedure (unless ATL
hosting support is considerably improved in this new version).

Another way is to aggregate client site implementation. You create a COM
object that supports some of the interfaces you want to override (e.g.
IOleControlSite). In FinalConstruct of this object you can use this code
to create AxHostWindow (taken from <atlhost.h> line 2474 and slightly
modified):

 hr = CAxHostWindow::_CreatorClass::CreateInstance(this, IID_IUnknown,
(void**)&spUnkContainer);

The first parameter is the outer unknown (NULL in the original code).
spUnkContainer will become your inner unknown. Use
COM_INTERFACE_ENTRY_AGGREGATE_BLIND at the end of your interface map to
forward all interfaces you don't explicitly override to this inner
unknown. You can also forward calls to it on a per-method basis.

To actually host a control in this contraption, use
IAxWinHostWindow::CreateControl or CreateControlEx. You'll need to pass
an HWND to it - any will do, e.g. a static control of suitable size.
CAxHostWindow subclasses it.

This mechanism only works with controls you create dynamically at
run-time. It cannot be used if you want to place controls on the dialog
using Dialog Editor.
--
With best wishes,
    Igor Tandetnik

"For every complex problem, there is a solution that is simple, neat,
and wrong." H.L. Mencken


Quote:> Thanks.

> > 1) CWindowImpl makes more sense to me.

> Turns out that you can't use either "CWindowImpl" or

"CContainedWindow". I
Quote:> wanted a class that looked something like this for instance:

> class C3rdPartyControl : public

CAxWindowT<CWindowImpl<C3rdPartyControl> >
Quote:

> This would give my class both a message map and access to
> "SubclassWindow()". I could then subclass the control's window and
route its
> messages through my class. The default constructor for "CAxWindowT"
takes an
> HWND however and passes it to its base class "CWindowImpl". The latter
class
> has no such constructor however (neither does "CContainedWindow") so a
> compiler error results (C2664). I guess they never expected anyone to
> subclass an ActiveX control - either that or the design is flawed.
Instead,
> I simply inherited from "CAxWindow" directly (the normal route) and
created
> a "CContainedWindow" member variable. I then subclass that member and
route
> its messages through the message map of my class. Somewhat ugly but
I'm open
> to better suggestions.

> > 2) ... Or are you asking how to subclass the window of third-party
ActiveX
> > control you are hosting? It is not recommended - you are supposed to
> > manipulate the control using its public interface. In case you
really
> > need to do this for some reason, query the control for IOleWindow
and
> > call IOleWindow::GetWindow. Naturally, that does not work on
windowless
> > controls.

> Yes, that's what I'm after. I'm manipulating the control normally but
need
> to trap WM_KILLFOCUS. I'm wondering if most controls don't provide an
event
> for this. The one I'm using ("VSFlexGrid" - fairly well known) doesn't
> provide it. I'd therefore like to trap it and pass it to the parent
window
> (dialog) as a (customized) control notification message (say,
VN_KILLFOCUS).
> The control would then behave consistently with the standard Windows
> controls. Any comments? Thanks again.

 
 
 

How to subclass a dialog-based ActiveX control

Post by Samuel Whit » Fri, 12 Apr 2002 03:20:30


Quote:> 1) I must admit you lost me there. Can you sketch what exactly you
> intend to do with such a class? BTW, if you need CWindowImpl that also
> has methods of CAxWindow, try

> class C3rdPartyControl : public CWindowImpl<C3rdPartyControl, CAxWindow>

I appreciate your help. I'm new to a lot of the ATL Window classes. Don't
want to bog you down so what follows if relatively easy. I'm trying to wrap
the control (a grid) in my own class. Don't want to create it dynamically
since it's easier to manipulate with the resource editor. My class now looks
like this based on assistance from your last post (stripped down for
brevity -  I believe it now works though):

class CGrid : public CAxWindow
{
public:
     // ...

     CGrid() : m_GridWindow(this)
     {
     }

     BEGIN_MSG_MAP(CGrid)
          MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus)
     END_MSG_MAP()

     virtual LRESULT OnKillFocus(UINT, WPARAM wParam, LPARAM, BOOL
&bHandled);

     void Init(UINT uID, CWindow *pParent)
     {
          // Step 1
          Attach(pParent->GetDlgItem(uID));

          // Step 2
          QueryControl(&m_spGrid);

          // Step 3 (based on your last post)
          IOleWindowPtr spOleWindow;
          m_spGrid.QueryInterface(__uuidof(IOleWindow), &spOleWindow);
          HWND hGridWindow;
          spOleWindow->GetWindow(&hGridWindow);
          m_GridWindow.SubclassWindow(hGridWindow));
     }

private:
     IVSFlexGridPtr m_spGrid; // Using #import
     CContainedWindow m_GridWindow;

Quote:};

I simply call the above from WM_INITDIALOG for each grid on the dialog,
passing the control ID ("uID") and dialog window ("pParent") accordingly. I
can now add member functions and invoke the real methods via "m_spGrid"
accordingly. I can also trap WM_KILLFOCUS. However, it seems cleaner to
simply invoke "SubclassWindow()" inside "Init()". "CAxWindow" has no such
function however. If I use the hieararchy you suggested in your last post,

> That produces the correct inheritance hierarchy. It's unclear to me why
> you would ever want such a thing though.

> 2) The control calls IOleControlSite::OnFocus when it gains or loses
> focus. Unfortunately, ATL implementation does nothing there and it is
> difficult to customize it. There are two ways - simple but hackish and
> correct but complicated. Simple way is to copy <atlhost.h> header into
> your project directory, call it something else and include this copy
> where you would otherwise inclue atlhost.h. Then you simply make any
> change you want to OnFocus implementation, e.g. send a message to parent
> window. Of course the moment you upgrade your compiler and want to use
> updated ATL headers, you'll have to repeat this procedure (unless ATL
> hosting support is considerably improved in this new version).

> Another way is to aggregate client site implementation. You create a COM
> object that supports some of the interfaces you want to override (e.g.
> IOleControlSite). In FinalConstruct of this object you can use this code
> to create AxHostWindow (taken from <atlhost.h> line 2474 and slightly
> modified):

>  hr = CAxHostWindow::_CreatorClass::CreateInstance(this, IID_IUnknown,
> (void**)&spUnkContainer);

> The first parameter is the outer unknown (NULL in the original code).
> spUnkContainer will become your inner unknown. Use
> COM_INTERFACE_ENTRY_AGGREGATE_BLIND at the end of your interface map to
> forward all interfaces you don't explicitly override to this inner
> unknown. You can also forward calls to it on a per-method basis.

> To actually host a control in this contraption, use
> IAxWinHostWindow::CreateControl or CreateControlEx. You'll need to pass
> an HWND to it - any will do, e.g. a static control of suitable size.
> CAxHostWindow subclasses it.

> This mechanism only works with controls you create dynamically at
> run-time. It cannot be used if you want to place controls on the dialog
> using Dialog Editor.
> --
> With best wishes,
>     Igor Tandetnik

> "For every complex problem, there is a solution that is simple, neat,
> and wrong." H.L. Mencken



> > Thanks.

> > > 1) CWindowImpl makes more sense to me.

> > Turns out that you can't use either "CWindowImpl" or
> "CContainedWindow". I
> > wanted a class that looked something like this for instance:

> > class C3rdPartyControl : public
> CAxWindowT<CWindowImpl<C3rdPartyControl> >

> > This would give my class both a message map and access to
> > "SubclassWindow()". I could then subclass the control's window and
> route its
> > messages through my class. The default constructor for "CAxWindowT"
> takes an
> > HWND however and passes it to its base class "CWindowImpl". The latter
> class
> > has no such constructor however (neither does "CContainedWindow") so a
> > compiler error results (C2664). I guess they never expected anyone to
> > subclass an ActiveX control - either that or the design is flawed.
> Instead,
> > I simply inherited from "CAxWindow" directly (the normal route) and
> created
> > a "CContainedWindow" member variable. I then subclass that member and
> route
> > its messages through the message map of my class. Somewhat ugly but
> I'm open
> > to better suggestions.

> > > 2) ... Or are you asking how to subclass the window of third-party
> ActiveX
> > > control you are hosting? It is not recommended - you are supposed to
> > > manipulate the control using its public interface. In case you
> really
> > > need to do this for some reason, query the control for IOleWindow
> and
> > > call IOleWindow::GetWindow. Naturally, that does not work on
> windowless
> > > controls.

> > Yes, that's what I'm after. I'm manipulating the control normally but
> need
> > to trap WM_KILLFOCUS. I'm wondering if most controls don't provide an
> event
> > for this. The one I'm using ("VSFlexGrid" - fairly well known) doesn't
> > provide it. I'd therefore like to trap it and pass it to the parent
> window
> > (dialog) as a (customized) control notification message (say,
> VN_KILLFOCUS).
> > The control would then behave consistently with the standard Windows
> > controls. Any comments? Thanks again.

 
 
 

How to subclass a dialog-based ActiveX control

Post by Samuel Whit » Fri, 12 Apr 2002 03:27:02


Igor:

Ignore the post I just sent if still present - tried to cancel it. Was a
work in progress when my machine went nuts (don't ask). Will re-post
shortly.


> 1) I must admit you lost me there. Can you sketch what exactly you
> intend to do with such a class? BTW, if you need CWindowImpl that also
> has methods of CAxWindow, try

> class C3rdPartyControl : public CWindowImpl<C3rdPartyControl, CAxWindow>

> That produces the correct inheritance hierarchy. It's unclear to me why
> you would ever want such a thing though.

> 2) The control calls IOleControlSite::OnFocus when it gains or loses
> focus. Unfortunately, ATL implementation does nothing there and it is
> difficult to customize it. There are two ways - simple but hackish and
> correct but complicated. Simple way is to copy <atlhost.h> header into
> your project directory, call it something else and include this copy
> where you would otherwise inclue atlhost.h. Then you simply make any
> change you want to OnFocus implementation, e.g. send a message to parent
> window. Of course the moment you upgrade your compiler and want to use
> updated ATL headers, you'll have to repeat this procedure (unless ATL
> hosting support is considerably improved in this new version).

> Another way is to aggregate client site implementation. You create a COM
> object that supports some of the interfaces you want to override (e.g.
> IOleControlSite). In FinalConstruct of this object you can use this code
> to create AxHostWindow (taken from <atlhost.h> line 2474 and slightly
> modified):

>  hr = CAxHostWindow::_CreatorClass::CreateInstance(this, IID_IUnknown,
> (void**)&spUnkContainer);

> The first parameter is the outer unknown (NULL in the original code).
> spUnkContainer will become your inner unknown. Use
> COM_INTERFACE_ENTRY_AGGREGATE_BLIND at the end of your interface map to
> forward all interfaces you don't explicitly override to this inner
> unknown. You can also forward calls to it on a per-method basis.

> To actually host a control in this contraption, use
> IAxWinHostWindow::CreateControl or CreateControlEx. You'll need to pass
> an HWND to it - any will do, e.g. a static control of suitable size.
> CAxHostWindow subclasses it.

> This mechanism only works with controls you create dynamically at
> run-time. It cannot be used if you want to place controls on the dialog
> using Dialog Editor.
> --
> With best wishes,
>     Igor Tandetnik

> "For every complex problem, there is a solution that is simple, neat,
> and wrong." H.L. Mencken



> > Thanks.

> > > 1) CWindowImpl makes more sense to me.

> > Turns out that you can't use either "CWindowImpl" or
> "CContainedWindow". I
> > wanted a class that looked something like this for instance:

> > class C3rdPartyControl : public
> CAxWindowT<CWindowImpl<C3rdPartyControl> >

> > This would give my class both a message map and access to
> > "SubclassWindow()". I could then subclass the control's window and
> route its
> > messages through my class. The default constructor for "CAxWindowT"
> takes an
> > HWND however and passes it to its base class "CWindowImpl". The latter
> class
> > has no such constructor however (neither does "CContainedWindow") so a
> > compiler error results (C2664). I guess they never expected anyone to
> > subclass an ActiveX control - either that or the design is flawed.
> Instead,
> > I simply inherited from "CAxWindow" directly (the normal route) and
> created
> > a "CContainedWindow" member variable. I then subclass that member and
> route
> > its messages through the message map of my class. Somewhat ugly but
> I'm open
> > to better suggestions.

> > > 2) ... Or are you asking how to subclass the window of third-party
> ActiveX
> > > control you are hosting? It is not recommended - you are supposed to
> > > manipulate the control using its public interface. In case you
> really
> > > need to do this for some reason, query the control for IOleWindow
> and
> > > call IOleWindow::GetWindow. Naturally, that does not work on
> windowless
> > > controls.

> > Yes, that's what I'm after. I'm manipulating the control normally but
> need
> > to trap WM_KILLFOCUS. I'm wondering if most controls don't provide an
> event
> > for this. The one I'm using ("VSFlexGrid" - fairly well known) doesn't
> > provide it. I'd therefore like to trap it and pass it to the parent
> window
> > (dialog) as a (customized) control notification message (say,
> VN_KILLFOCUS).
> > The control would then behave consistently with the standard Windows
> > controls. Any comments? Thanks again.

 
 
 

How to subclass a dialog-based ActiveX control

Post by Samuel Whit » Fri, 12 Apr 2002 03:43:00


Quote:> 1) I must admit you lost me there. Can you sketch what exactly you
> intend to do with such a class? BTW, if you need CWindowImpl that also
> has methods of CAxWindow, try

> class C3rdPartyControl : public CWindowImpl<C3rdPartyControl, CAxWindow>

I appreciate your help Igor. I'm new to a lot of the ActiveX stuff. Don't
want to bog you down so what follows if relatively easy. I'm trying to wrap
the control (a grid) in my own class. Don't want to create it dynamically
since it's easier to manipulate with the resource editor. My class now looks
like this based on assistance from your last post (stripped down for
brevity -  I believe it now works though):

class CGrid : public CAxWindow, public CMessageMap
{
public:
     // ...

     CGrid() : m_GridWindow(this)
     {
     }

     BEGIN_MSG_MAP(CGrid)
          MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus)
     END_MSG_MAP()

     virtual LRESULT OnKillFocus(UINT, WPARAM wParam, LPARAM, BOOL
&bHandled);

     void Init(UINT uID, CWindow *pParent)
     {
          // Step 1 (would prefer "SubclassWindow()" however)
          Attach(pParent->GetDlgItem(uID));

          // Step 2
          QueryControl(&m_spGrid);

          // Step 3 (based on your last post)
          IOleWindowPtr spOleWindow;
          m_spGrid.QueryInterface(__uuidof(IOleWindow), &spOleWindow);
          HWND hGridWindow;
          spOleWindow->GetWindow(&hGridWindow);
          m_GridWindow.SubclassWindow(hGridWindow));
     }

private:
     IVSFlexGridPtr m_spGrid; // Using #import
     CContainedWindow m_GridWindow;

Quote:};

I simply call the above from WM_INITDIALOG for each grid on the dialog,
passing the control ID ("uID") and dialog window ("pParent") accordingly.
Using the above class I can now add member (wrapper) functions and invoke
the real methods via "m_spGrid" accordingly. I can also trap WM_KILLFOCUS.
However, it seems cleaner to eliminate the "m_GridWindow" nonsense
altogether and simply invoke "SubclassWindow()" inside "Init()" (instead of
using "Attach()" as seen). If I use the hieararchy suggested in your last
post, it now compiles cleanly and I have access to "SubclassWindow()". What
changes would I then make in "Init()"? That is, as seen above, the handle
passed to "SubclassWindow()" is obtained using "m_spGrid" which was
retrieved using "QueryControl()". The latter function requires "m_hWnd" to
work however but that won't be available if I kill the call to "Attach()"
above (since I'm now going to rely on "SubclassWindow()"). It's a chicken
and egg scenario. I could detach at that point and then call
"SubclassWindow()" but what's your opinion on this entire scenario anyway.
It seems a reasonably clean approach to me (if you have the patience to
follow it all). Thanks.
 
 
 

How to subclass a dialog-based ActiveX control

Post by Igor Tandetni » Fri, 12 Apr 2002 04:02:38


You don't need CAxWindow at all here. You are only using it for
QueryControl. You can use CWindow::GetDlgControl instead:

class CGrid : public CWindowImpl
{
public:
     void Init(UINT uID, CWindow *pParent)
     {
           CComPtr<IUnknown> spUnk;
           pParent->GetDlgControl(uID, &spUnk);
           spUnk->QueryInterface(&m_spGrid);

          // Step 3
          IOleWindowPtr spOleWindow;
          m_spGrid.QueryInterface(__uuidof(IOleWindow), &spOleWindow);
          HWND hGridWindow;
          spOleWindow->GetWindow(&hGridWindow);
          SubclassWindow(hGridWindow);
     }

Quote:};

See also AtlAxGetControl. Both CWindow::GetDlgControl and
CAxWindow::QueryControl end up calling it.
--
With best wishes,
    Igor Tandetnik

"For every complex problem, there is a solution that is simple, neat,
and wrong." H.L. Mencken


Quote:> > 1) I must admit you lost me there. Can you sketch what exactly you
> > intend to do with such a class? BTW, if you need CWindowImpl that
also
> > has methods of CAxWindow, try

> > class C3rdPartyControl : public CWindowImpl<C3rdPartyControl,
CAxWindow>

> I appreciate your help Igor. I'm new to a lot of the ActiveX stuff.
Don't
> want to bog you down so what follows if relatively easy. I'm trying to
wrap
> the control (a grid) in my own class. Don't want to create it
dynamically
> since it's easier to manipulate with the resource editor. My class now
looks
> like this based on assistance from your last post (stripped down for
> brevity -  I believe it now works though):

> class CGrid : public CAxWindow, public CMessageMap
> {
> public:
>      // ...

>      CGrid() : m_GridWindow(this)
>      {
>      }

>      BEGIN_MSG_MAP(CGrid)
>           MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus)
>      END_MSG_MAP()

>      virtual LRESULT OnKillFocus(UINT, WPARAM wParam, LPARAM, BOOL
> &bHandled);

>      void Init(UINT uID, CWindow *pParent)
>      {
>           // Step 1 (would prefer "SubclassWindow()" however)
>           Attach(pParent->GetDlgItem(uID));

>           // Step 2
>           QueryControl(&m_spGrid);

>           // Step 3 (based on your last post)
>           IOleWindowPtr spOleWindow;
>           m_spGrid.QueryInterface(__uuidof(IOleWindow), &spOleWindow);
>           HWND hGridWindow;
>           spOleWindow->GetWindow(&hGridWindow);
>           m_GridWindow.SubclassWindow(hGridWindow));
>      }

> private:
>      IVSFlexGridPtr m_spGrid; // Using #import
>      CContainedWindow m_GridWindow;
> };

> I simply call the above from WM_INITDIALOG for each grid on the
dialog,
> passing the control ID ("uID") and dialog window ("pParent")
accordingly.
> Using the above class I can now add member (wrapper) functions and
invoke
> the real methods via "m_spGrid" accordingly. I can also trap
WM_KILLFOCUS.
> However, it seems cleaner to eliminate the "m_GridWindow" nonsense
> altogether and simply invoke "SubclassWindow()" inside "Init()"
(instead of
> using "Attach()" as seen). If I use the hieararchy suggested in your
last
> post, it now compiles cleanly and I have access to "SubclassWindow()".
What
> changes would I then make in "Init()"? That is, as seen above, the
handle
> passed to "SubclassWindow()" is obtained using "m_spGrid" which was
> retrieved using "QueryControl()". The latter function requires
"m_hWnd" to
> work however but that won't be available if I kill the call to
"Attach()"
> above (since I'm now going to rely on "SubclassWindow()"). It's a
chicken
> and egg scenario. I could detach at that point and then call
> "SubclassWindow()" but what's your opinion on this entire scenario
anyway.
> It seems a reasonably clean approach to me (if you have the patience
to
> follow it all). Thanks.

 
 
 

How to subclass a dialog-based ActiveX control

Post by Samuel Whit » Fri, 12 Apr 2002 04:16:49


Fantastic! I'll look into it further. I only used "CAxWindow" because some
documentation I read did things this way (without trapping messages
however). Don't normally follow advice blindly but am still feeling my way
around. Thanks again. You've been a big help!


> You don't need CAxWindow at all here. You are only using it for
> QueryControl. You can use CWindow::GetDlgControl instead:

> class CGrid : public CWindowImpl
> {
> public:
>      void Init(UINT uID, CWindow *pParent)
>      {
>            CComPtr<IUnknown> spUnk;
>            pParent->GetDlgControl(uID, &spUnk);
>            spUnk->QueryInterface(&m_spGrid);

>           // Step 3
>           IOleWindowPtr spOleWindow;
>           m_spGrid.QueryInterface(__uuidof(IOleWindow), &spOleWindow);
>           HWND hGridWindow;
>           spOleWindow->GetWindow(&hGridWindow);
>           SubclassWindow(hGridWindow);
>      }
> };

> See also AtlAxGetControl. Both CWindow::GetDlgControl and
> CAxWindow::QueryControl end up calling it.
> --
> With best wishes,
>     Igor Tandetnik

> "For every complex problem, there is a solution that is simple, neat,
> and wrong." H.L. Mencken



> > > 1) I must admit you lost me there. Can you sketch what exactly you
> > > intend to do with such a class? BTW, if you need CWindowImpl that
> also
> > > has methods of CAxWindow, try

> > > class C3rdPartyControl : public CWindowImpl<C3rdPartyControl,
> CAxWindow>

> > I appreciate your help Igor. I'm new to a lot of the ActiveX stuff.
> Don't
> > want to bog you down so what follows if relatively easy. I'm trying to
> wrap
> > the control (a grid) in my own class. Don't want to create it
> dynamically
> > since it's easier to manipulate with the resource editor. My class now
> looks
> > like this based on assistance from your last post (stripped down for
> > brevity -  I believe it now works though):

> > class CGrid : public CAxWindow, public CMessageMap
> > {
> > public:
> >      // ...

> >      CGrid() : m_GridWindow(this)
> >      {
> >      }

> >      BEGIN_MSG_MAP(CGrid)
> >           MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus)
> >      END_MSG_MAP()

> >      virtual LRESULT OnKillFocus(UINT, WPARAM wParam, LPARAM, BOOL
> > &bHandled);

> >      void Init(UINT uID, CWindow *pParent)
> >      {
> >           // Step 1 (would prefer "SubclassWindow()" however)
> >           Attach(pParent->GetDlgItem(uID));

> >           // Step 2
> >           QueryControl(&m_spGrid);

> >           // Step 3 (based on your last post)
> >           IOleWindowPtr spOleWindow;
> >           m_spGrid.QueryInterface(__uuidof(IOleWindow), &spOleWindow);
> >           HWND hGridWindow;
> >           spOleWindow->GetWindow(&hGridWindow);
> >           m_GridWindow.SubclassWindow(hGridWindow));
> >      }

> > private:
> >      IVSFlexGridPtr m_spGrid; // Using #import
> >      CContainedWindow m_GridWindow;
> > };

> > I simply call the above from WM_INITDIALOG for each grid on the
> dialog,
> > passing the control ID ("uID") and dialog window ("pParent")
> accordingly.
> > Using the above class I can now add member (wrapper) functions and
> invoke
> > the real methods via "m_spGrid" accordingly. I can also trap
> WM_KILLFOCUS.
> > However, it seems cleaner to eliminate the "m_GridWindow" nonsense
> > altogether and simply invoke "SubclassWindow()" inside "Init()"
> (instead of
> > using "Attach()" as seen). If I use the hieararchy suggested in your
> last
> > post, it now compiles cleanly and I have access to "SubclassWindow()".
> What
> > changes would I then make in "Init()"? That is, as seen above, the
> handle
> > passed to "SubclassWindow()" is obtained using "m_spGrid" which was
> > retrieved using "QueryControl()". The latter function requires
> "m_hWnd" to
> > work however but that won't be available if I kill the call to
> "Attach()"
> > above (since I'm now going to rely on "SubclassWindow()"). It's a
> chicken
> > and egg scenario. I could detach at that point and then call
> > "SubclassWindow()" but what's your opinion on this entire scenario
> anyway.
> > It seems a reasonably clean approach to me (if you have the patience
> to
> > follow it all). Thanks.

 
 
 

1. Handling notification messages from contained subclassed activex control inside dialog class

I have a dialog hosting one activex control, which subclasses a windows tree
control. I am interested in handling some regular windows messages and other
notification messages (like the reflected sel_change message), which I
usually can handle inside my activex control class to be handled inside my
dialog.
Can somebody suggest how I can send the reflected notification messages
normally received and handled by the activex control to be sent and handled
inside my dialog class. (Somehow controlling the reflector window, maybe??)
I donot want to create a new event for each notification message in my
activex control.

2. Pilot Wireless Communications

3. ActiveX control under ATL, using Dialog base, How?

4. We have taken the Hassles out of the net

5. activex control based on MFC control class

6. default email

7. ATL and dialog-based COM control

8. GPO problems under win2000SP2

9. Remote Control Dialog-based App via OLE Automation

10. I found an article in the Internet, is subclass a in ActiveX Control this simple?

11. Subclassed SysListView32 ActiveX Control

12. Finding base class name of a subclassed control