?
Solved

ActiveX control inside same ActiveX control

Posted on 1999-06-25
10
Medium Priority
?
497 Views
Last Modified: 2013-11-20
I have an ActiveX Controls created using the AppControl Wizard
provided by Visual C++ 6. I want to create one instance of the control
inside another instance of the same control.

When I
create the internal instance I get an assertion in Wincore.cpp in
CWnd::Attach saying that the window is already mapped (was attached
already).

When inserting a control of another class, there is no problem.
0
Comment
Question by:mco
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 4
10 Comments
 
LVL 1

Expert Comment

by:SergioL
ID: 1307902
How make a MSFlexGrid Control inside a ActiveX Control in VC++ 6
by SergioL

1) Crear el Nuevo Control (CC)
En la función InitInstance agregar

BOOL CCCApp::InitInstance()
{
      BOOL bInit = COleControlModule::InitInstance();

      if (bInit)
      {
            // TODO: Add your own module initialization code here.
            AfxEnableControlContainer();
      }

      return bInit;
}

en el constructor del Control nuevo:

CCCCtrl::CCCCtrl()
{
      InitializeIIDs(&IID_DCC, &IID_DCCEvents);

      // TODO: Initialize your control's instance data here.
      EnableSimpleFrame();

}

class CCCCtrl : public COleControl
{
      DECLARE_DYNCREATE(CCCCtrl)

// Constructor
public:
      CCCCtrl();
      CMSFlexGrid m_grilla;  
            // en este ejemplo uso una Flex Grid!!
...

en la func. OnCreate (Mapear WM_CREATE)
int CCCCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
      if (COleControl::OnCreate(lpCreateStruct) == -1)
            return -1;
      
      CRect rect;
      m_grilla.Create(0,WS_VISIBLE,rect,this,101);
      return 0;
}


2) Propiedades

en el header del nuevo control y en el codigo de la libreria de tipos(con add property):

protected:
...
// Dispatch maps
      //{{AFX_DISPATCH(CCCCtrl)
      long m_filas;
      afx_msg void OnFilasChanged();  
      //}}AFX_DISPATCH
      DECLARE_DISPATCH_MAP()
...

en la func. DoPropExchange:

void CCCCtrl::DoPropExchange(CPropExchange* pPX)
{
      ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
      COleControl::DoPropExchange(pPX);

      // TODO: Call PX_ functions for each persistent custom property.
      PX_Long (pPX, _T("Filas"), m_filas, 2);

           //... Por cada propiedad a tratar desde la App Cliente!!
}

en el evento que se produce al modificar la propiedad:
void CCCCtrl::OnFilasChanged()
{
      // TODO: Add notification handler code

      m_grilla.SetRows(m_filas);
      SetModifiedFlag();
}

y si desea que el control ocupe toda el area cliente (del nuevo control)
void CCCCtrl::OnSize(UINT nType, int cx, int cy)
{
      COleControl::OnSize(nType, cx, cy);
      
      m_grilla.SetWindowPos(0,0,0,cx,cy,0);      
}


1) Crear el Nuevo Control (for example : CC)  
En la función InitInstance agregar  
1) Make a new activex control (for example: CC)    
In the function InitInstance add    
 
en el constructor del Control nuevo:  
in the contructor of new control:  
 
CMSFlexGrid m_grilla;    
            // en este ejemplo uso una Flex Grid!!  
CMSFlexGrid m_grilla;      
            // in this example I use the Flex Grid!!  
 
en la func. OnCreate (Mapear WM_CREATE)  
in the func. OnCreate (Map WM_CREATE)    
 
2) Propiedades  
2) Properties (of the ocx)  
 
en el header del nuevo control y en el codigo de la libreria de tipos(con add property):  
in the header of the new control and on the code of types library(with add property):    
 
en la func. DoPropExchange:  
in the func. DoPropExchange:    
 
           //... Por cada propiedad a tratar desde la App Cliente!!  
           //... For each properties to handle from the client application!!    
 
en el evento que se produce al modificar la propiedad:  
in the event that takes place when modifying the property:    
 
y si desea que el control ocupe toda el area cliente (del nuevo control)  
and if you wants that the control occupies the whole area client (of the new control)    
 
I hope this helps you.  
SergioL  

0
 
LVL 1

Author Comment

by:mco
ID: 1307903
It seems you did not read the question carefully.
The containing and contained ActiveX control have to be instances
of the SAME control.

0
 
LVL 4

Expert Comment

by:mandhjo
ID: 1307904
How are you creating the internal control?  Did you add a wrapper class to your project or are you using CWnd::CreateWindow?
0
Will your db performance match your db growth?

In Percona’s white paper “Performance at Scale: Keeping Your Database on Its Toes,” we take a high-level approach to what you need to think about when planning for database scalability.

 
LVL 1

Author Comment

by:mco
ID: 1307905
CWnd:CreateControl
0
 
LVL 4

Expert Comment

by:mandhjo
ID: 1307906
That's what I meant.  Oops.  I've got a slow day today, so I'm going to fool around with this problem.  I'll let you know what I find.
0
 
LVL 4

Expert Comment

by:mandhjo
ID: 1307907
Can I see the code where you create the control?  I think allocating the CWnd object on the heap is the way to go.
0
 
LVL 1

Author Comment

by:mco
ID: 1307908
You can't see the code for a number of reasons, major one being I won't be at work for a few days.
Anyway, it is allocate on the heap.
The problem has to do with the fact that since it is another instance
of the same OCX, the InitInstance of the OCX is called only once.
That is why (indirectly) something is being attached twice.

0
 
LVL 4

Expert Comment

by:mandhjo
ID: 1307909
OK -- I have experienced your pain first-hand.  The problem is that the contained control and the control itself are forced to share the same OleClientSite (perhaps because they are the same window class).

I believe this to be a shortcoming of MFC, but I'm not going to proclaim that to the world as I don't have much to back it up.  I think I've heard of someone doing this in ATL, but I don't know that for sure, so I'll be quiet about it.

A potential work around which you have probably already considered is presented below.

ActiveX Control A - The one you already have developed which is unable to contain a control of it's same type.  Modify it to dynamically create an instance of ActiveX Control B (described below) where you had hoped to create another instance of ActiveX Control A.

ActiveX Control B - A control who's only purpose in life is to wrap ActiveX Control A.  In OnCreate, you do a CWnd::CreateControl of ActiveX ControlA and you destroy it in the OnDestroy method.

It's important to note that as far as the user is concerned, they are seeing an instance of a control within an instance of the same control.  Since it's possible to have one OCX file contain more than one ActiveX control, it looks even more like one control containing itself.

I implemented this solution with success.  Control A is called AXTest.  Control B is called AXContainTest.

AXTest displays a CButton object (top 1/5 of the client area) which when clicked creates an instance of AXContainTest which fills the rest of the client area (bottom 4/5).

AXContainTest is very simple.  OnCreate, OnDestroy, and OnSize, are the only functions I have implemented (you may need more I suppose).  I implemented OnSize simply so I could re-position the contained instance of AXTest.

I used the ActiveX Control Test Container to create an instance of AXTest and clicked the button.  This created AXContaintTest in the remaining client area of the control.  AXContainTest contains another instance of AXTest which fills the entire area of AXContainTest (that is, the bottom 4/5 of the initial instance of AXTest).  I could then repeatedly click the bottom most button and more and more instances of AXContainTest (and AXTest with it) were created.

It should be pointed out that AXContainTest could be generalized to contain any control based on a given ProgID.  The challenge would be communicating that ProgID to AXContainTest from AXTest.  I suppose AXContainTest could be created and it wouldn't create the control to be contained until some method was called that set the ProgID.

Hope this helps.  If you'd like, I could email you the controls I created.

Mark
0
 
LVL 1

Author Comment

by:mco
ID: 1307910
mandhjo, great stuff
Post and answer and you shall be rewarded

0
 
LVL 4

Accepted Solution

by:
mandhjo earned 800 total points
ID: 1307911
Glad I could help.

MJ
0

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This is to be the first in a series of articles demonstrating the development of a complete windows based application using the MFC classes.  I’ll try to keep each article focused on one (or a couple) of the tasks that one may meet.   Introductio…
Have you tried to learn about Unicode, UTF-8, and multibyte text encoding and all the articles are just too "academic" or too technical? This article aims to make the whole topic easy for just about anyone to understand.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
This tutorial will teach you the special effect of super speed similar to the fictional character Wally West aka "The Flash" After Shake : http://www.videocopilot.net/presets/after_shake/ All lightning effects with instructions : http://www.mediaf…

719 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question