Solved

Critique this approach and provide appropriate alternative if needed please

Posted on 2004-08-31
6
284 Views
Last Modified: 2008-02-01
(this might be an MFC question, but I think it's more a C++ design question)

I'm Using VC++ 6.0 and MFC.

I have a class CMoviePage which is derived from CPropertyPage. This contains graphical controls and what not (it's an AVI player embedded in an application). I also have a class CMovieView which contains all of the filter graph and direct draw related stuff. CMovieView also has a message map setup, containing among others, this:

    ON_MESSAGE( WM_GRAPHNOTIFY, HandleGraphEvent )

which is defined in the header:
    #define WM_GRAPHNOTIFY  WM_USER+13

protected:
    afx_msg void HandleGraphEvent(WPARAM wParam, LPARAM lParam);

which my MediaEvent instance is told to watch:
    g_pMediaEvent->SetNotifyWindow((OAHWND)m_hWnd, WM_GRAPHNOTIFY, 0);


HandleGraphEvent looks like this:

void CMovieView::HandleGraphEvent(WPARAM wParam, LPARAM lParam)
{
LONG evCode, evParam1, evParam2;

HRESULT hr;
// Make sure that we don't access the media event interface
// after it has already been released.
if (g_pMediaEvent)
{
   // Process all queued events
   while(SUCCEEDED(g_pMediaEvent->GetEvent(&evCode, (LONG_PTR *) &evParam1, (LONG_PTR *) &evParam2, 0)))
   {

      hr = g_pMediaEvent->FreeEventParams(evCode, evParam1, evParam2);

      switch (evCode)
      {
          case EC_COMPLETE:
             // when done playing, rewind and pause.
             RewindClip();
           XXXXXXX -> UpdateVideoControlUI();

                break;

             // there are others, not relevant..

          }
      }
   }
}


So - what's that XXXXX? for? This is sorta the guts of the question. HandleGraphEvent() is a method within CMovieView.  CMovieView is contained by CMoviePage, which references it via private a member variable:
    CMovieView* pMovieView;

My UpdateVideoControlUI() is implemented by CMoviePage - as that is a UI related function.

So - the question is, I need CMovieView to be able to call "up into it's containing class", the UpdateVideoControlUI() method. My initial thought was to add a private member variable to CMovieView -- CMoviePage* m_pMoviePage  and then have CMovieView pass a 'this' reference into CMoviePage when it's instantiated or apply it via a non constructor method. That way when CMovieView::HandleGraphEvent() executes, it can execute m_pMovePage->UpdateVideoControlUI(), effectively calling a method in it's containing class.

That is in fact what I did, and yes, it works. But I'm not entirely comfortable with this for the following reasons:

1. I don't really like the idea of a class needing to be hard-wired to a specific containing class. While not doing so I believe is a sound design decision in theory for reuse and what not, I'm not sure how relevant it is in this particular situation.

2. I'm not yet fully comfortable enough with C++ to know if there is not a more appropriate mechanism to accomplish this (some kind of callback or MFC mechanism that I just don't know about.)

thougths?

thanks!
-Paul
0
Comment
Question by:PMH4514
  • 2
  • 2
  • 2
6 Comments
 
LVL 86

Expert Comment

by:jkr
Comment Utility
>>I don't really like the idea of a class needing to be hard-wired to a specific containing class

Why not? This is a widely used approach. Just think of e.g. modeling a file system where you need to keep a pointer to the containing directory. If you don't like it, you could still send a message to the main window (available via 'AfxGetMainWnd()') to have it update the UI.
0
 

Author Comment

by:PMH4514
Comment Utility
>>Why not? This is a widely used approach.

good 'nuff! If somebody with your expertise sees nothing wrong with it, then I guess I'm ok with it :-)
0
 
LVL 55

Accepted Solution

by:
Jaime Olivares earned 63 total points
Comment Utility
You can work like old-style WinAPI, create a callback function, to make your view object independent from container.
Define a static function into your page, it will have some strict argument composition, then you can call callback function, passing parent pointer.

static void CYourPage::YourCallBack function(int arg1, float arg2, void *pointer)
{
    CYourPage *thePage = (CYourPage *)pointer;

    thePage->SomeFunc(arg1, arg2);
}

Now you can reuse your view object with any object that complains the same function structure, not only CYourPage.



0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 

Author Comment

by:PMH4514
Comment Utility
jamie - yeah, that's more along the lines of what I was thinking would be appropriate. Either or I guess, both perfectly valid it seems given appropriate arguments pro or con.  it's all in context I guess.

0
 
LVL 55

Expert Comment

by:Jaime Olivares
Comment Utility
Like you, I don't like to make a class dependant from other, because I have troubles when I want to reuse it, since I have many year working for the same contractor, I face this dilemma every day, so I have developed many tricks. The first is the callback, like explained, others are "windows message driven" and even "socket message driven" when working distributed apps.
0
 
LVL 86

Assisted Solution

by:jkr
jkr earned 62 total points
Comment Utility
>> Like you, I don't like to make a class dependant from other

Actually, that's something I'd support, too, if possible. *I* actually would connect the objects in Question using pure abstract interfaces, thus making instatantions be more like

#define interface struct

interface IMediaEvent {

 virtual void FreeEventParams ( LONG, LONG, LONG) = 0;

   // more...
};


interface IVideoControlUI {

  virtual void Update () = 0;

   // more...
};

CMovieView* pmv = new CMovieView ();

IVideoControlUI* pUI = (IVideoControlUI*) this;

pmv->SetConnections ( pUI, (IMediaEvent*) GetTheMediaEventIF());

and have the containing class inherit from these and implement the methods. This keeps it nice, abstract and reusable :o)

Yet, your approach is not something that could not be used.
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Suggested Solutions

Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

744 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

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now