• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 442
  • Last Modified:

OCX that wraps another OCX

I would like to create an OCX control that does some translation and then calls an OCX control to do the work.
for example...
Program uses OCX control to add two scaled numbers
1  Program calls OCX control (Control A).
2  Control A multiplies value by 10 then calls Control B with this value
3  Control B adds 10 to the value then fires an event to Control A.
4  Control A divides this value by 10 then fires an event to the Program

I know how to write the Program and Control B.  Both of these are handled readily by the MFC Wizards.   How do I do Control A?  BTW...What I need to do is actually a lot more complicated,  but I can use the example to do what I need.
0
OleUser
Asked:
OleUser
  • 7
  • 5
1 Solution
 
manfred022897Commented:
From what you wrote, I assume you are using VC4,x/MFC to write your controls. Try this:
- build B with the wizard, as usual.
- build A with the wizard
- when in A, use 'insert/component' and insert B. The wizard will build a wrapper class for B which is now accessible from inside A.
- whenever an instance of A is created, create an instance of B (this is no more than having a variable of type wrapperB and initialize it, using the Create...() functions of wrapperB)
- that's it. you're A functions get called, and you can delegate to B functions as appropriate.
0
 
OleUserAuthor Commented:
Thanks for your response, but...
1)  I assume that I have COCXControlB   ControlB in my class definition file (I made it protected)
1)  I assume that I want to call the Create function inside of Control A's constructor to initialize the control:  ControlB.Create (NULL, WS_OVERLAPPEDWINDOW,  pRect,  this,  IDC_OCX1);
2) I assume that in my method functions I should call ControlB.MtdFunctions
3) What do I do to receive events?  If I was doing a dialog template container,  I would just pick the control.  I tried copying in the code for the BEGIN_EVENTSINK_MAP / END_EVENTSINK_MAP and associated functions, but it would not compile (I changed the parameters for BEGIN_ to ControlA, COleControl instead of Container, CDialog)
0
 
OleUserAuthor Commented:
BTW...If I do a Create in the Contstructor for Control A,  I get an assert error when I try to insert the control into the Program
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
manfred022897Commented:
you are creating your control too early. both controls should be children of one of your windows (usually your view), so passing 'this'==controlA as parent (as you did in your code) is questionable. call control.Create() when your view is alive, not in the constructor.
Perhaps this weekend I'll find time to write some demo code.
0
 
OleUserAuthor Commented:
What I would like to do is to be able to hide ControlB completely from the program...for example,  if they want to use Control A in VB then I would like to have it so that Control B does not have to be added.  Perhaps Control A creates what amounts to an object window in which to place Control B????
0
 
manfred022897Commented:
(back from long weekend...)
what do you mean by 'control B does not have to be added'? You will always have to sell and register bnoth control A and control B, even, if A is a complete wrapper for B and contains an instance of B.
Please tell me once again what you are trying to do (write a control that has the functionality of another, but nobody should know ?? ;) ), and I'll try to get some demo code.

0
 
OleUserAuthor Commented:
Sorry,  I meant to say that I was hoping that Control B did not have to be added to the main program.  I was hoping that the user of my control would not have to do anything with Control B in his program.
If that is not possible,  that is ok.  I realize that I have to sell and register Control B,  but if Control B did not have to be instantiated in the main program,  that would be great.
I am basically trying to write a control that takes a string based format,  then converts it to command(s) to send out to another Control that has already been written (i.e. we are OEMing a control upon which I am trying to place another interface).
Any sample code/demo code would be very helpful.  Thank you for your patience.
0
 
manfred022897Commented:
now, the promised info.

the following will create two controls:
- 'crunch' which can multiply 2 shorts, returning a short
and firing an event in case of overflow;
- 'interface' which will contain 'crunch', squaring a number
by delegating to crunch and handling any events crunch fires.

to use this, you only have to insert 'interface' in an app; crunch' remains invisible.

create ctrlCrunch (std ole wizard)

insert method:

short ctrlCrunch::multiply(short m0, short m1)
{
!      long result = m0 * m1;
!      if(result > 0xffffL) {
!            // tell client we have a numerical problem...
!            FireOverflow(result);
!            result = 0;
!      }
!      return (short) result;
}

insert event: overflow(long val);

-------------------------------------------

create ctrlInterface (std ole wizard)

insert component 'crunch', you get a wrapper class CCrunch;
remember to include the header file ccrunch.h in some sources

insert member 'CCrunch m_crunch' into CCtrlInterface

handle WM_CREATE->

OnCreate(...)
{
      if (COleControl::OnCreate(lpCreateStruct) == -1)
            return -1;

!      // this is very important - we are in a different module!
!      AfxEnableControlContainer();

      // create subcontrol - do not pass something else as parent (must be in permanent wnd map)
!      m_crunch.Create("", WS_CHILD, CRect(0, 0, 1, 1), this, <someID>);

      return 0;

insert method:

short CCtrlInterfaceCtrl::square(short n)
{
!      // delegate to contained control HERE
!      // subcontrol will fire event on overflow and return 0
!      short res = m_crunch.multiply(n, n);
!
!      // just show results of call
!      CString s;
!      s.Format("ctrlInterface: square of %d (as calculated by m_crunch) is %d", n, res);
!      AfxMessageBox(s);
!      return res;
}

event handling:
insert DECLARE_EVENTSINK_MAP() in CCtrlInterface.h

insert event map (easy way: create scratch dialog; insert crunch control; open classwizard, select crunchControl
and write handler for crunch's event; this will insert an eventsink map to the dialog; copy this, changing
the class names and inserting the id you passed in ctrlCrunch.Create())

HTH!

-manfred
0
 
manfred022897Commented:
what about a response??
0
 
OleUserAuthor Commented:
I'll get back with a response as soon as possible,  I am trying out the code now.
0
 
OleUserAuthor Commented:
OK,  I have tried out the code.  The daughter control "crunch" never gets created because the WM_CREATE call is never made in the "Interface" control... Am I missing something?
Thank you for your patience.
0
 
OleUserAuthor Commented:
I have solved the problem if I put the control on a dialog box,  please explain how your method works
0

Featured Post

Vote for the Most Valuable Expert

It’s time to recognize experts that go above and beyond with helpful solutions and engagement on site. Choose from the top experts in the Hall of Fame or on the right rail of your favorite topic page. Look for the blue “Nominate” button on their profile to vote.

  • 7
  • 5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now