Dynamic Creation of Thread-Separated Dialogs Having Only Its Class Name

Introduction

This article describes a way of creating class objects by the name of its classes. This way permits you to create a new class object by calling a function or class method that receives as input parameters a pointer to the CRuntimeClass object. Thus, this method encapsulates the procedure of object creation inside another class or function.

In general, the article demonstrates how to design a mechanism that creates a user-selected dialog window in its own child thread. The child thread class is derived from CWinThread and its InitInstanse method encapsulates the procedure of object creation. A user can choose a type of dialog that is to be created.

The project architecture represented in Figure 1.

Figure 1. Project Architecture

Writing a Dialog Class

For dialog class creation, we can use a standard VC++ wizard. All we need to do is enter class name and choose the class that it is derived from. The first step is to adapt the newly created class to the correct MFC macros DECLARE_DYNAMIC and IMPLEMENT_DYNAMIC to DECLARE_DYNCREATE and IMPLEMENT_DYNCREATE in ".h" and ".cpp" files of class.

Use of the DECLARE_DYNCREATE macro in ".h" and the IMPLEMENT_DYNCREATE macro in ".cpp" permits classes to be created by the framework dynamically at run time.

The class should look like the following:

class CDialog1 : public CDialog
{
   DECLARE_DYNCREATE(CDialog1)

public:
   CDialog1(CWnd* pParent = NULL);   // standard constructor
   virtual ~CDialog1();

// Dialog Data
   enum { IDD = IDD_DIALOG1 };

   DECLARE_MESSAGE_MAP()
public:
   afx_msg void OnClose();
};

It is convenient to add a WM_CLOSE event handler method to notify the thread which dialog is attached to the window that is going to be closed and it is necessary to call the ExitInstanse method. To let the thread know about this intention, the window has to send a WM_QUIT message.

void CDialog1::OnClose()
{
   this->PostMessage( WM_QUIT );

   CDialog::OnClose();
}

Writing a Child Thread Class

We also can create this class with the help of the VC++ class wizard; just set the derived class to CWinThread. It is necessary to repeat the procedure of changing the MFC macros DECLARE_DYNAMIC and IMPLEMENT_DYNAMIC to DECLARE_DYNCREATE and IMPLEMENT_DYNCREATE in the ".h" and ".cpp" files of the class. This class also is to be created dynamically at run time.

Obviously, we need some variables: pointer to dialog, dialog ID, pointer to CRuntimeClass object of attached dialog class.

class CChildThread : public CWinThread
{
   friend class CMainFrame;
   DECLARE_DYNCREATE(CChildThread)

public:
CChildThread( CRuntimeClass* pClass = NULL, UINT id = 0 );
   virtual ~CChildThread();

private:
   CRuntimeClass* m_pClass;
   UINT m_ID;

protected:
   CDialog* m_pDialog;

public:
   virtual BOOL InitInstance();
   virtual int ExitInstance();

   DECLARE_MESSAGE_MAP()
};

The class constructor ought to be modified to get some class variable values from input parameters. We can initialise the pointer to CRuntimeClass and dialog ID.

CChildThread::CChildThread( CRuntimeClass* pClass, UINT id )
{
   m_pClass  = pClass;
   m_ID      = id;
   m_pDialog = NULL;
}

Now, when the thread object already exists, the InitInstanse method might be called. The mechanism of class object creation by name is placed into this function.

BOOL CChildThread::InitInstance()
{
   if ( m_pClass != NULL)
   {
      CObject* pObject = m_pClass->CreateObject();

      if ( pObject->IsKindOf( RUNTIME_CLASS( CDialog ) ) )
      {
         CWnd desktop;
         desktop.Attach( ::GetDesktopWindow() );

         m_pDialog = ( CDialog* )pObject;
         m_pDialog->Create( m_ID, &desktop );

         m_pMainWnd   = m_pDialog;
         m_pActiveWnd = m_pDialog;
         m_pMainWnd->ShowWindow( SW_SHOW );
         m_pMainWnd->UpdateWindow();

         desktop.Detach();
      }
   }

   return TRUE;
}

First, the object will be created by using the CreateObject method of the CRuntimeClass class. Second, we should convince that just-created object is derived from CDialog using the IsKindOf method of the CObject class. And finally, the Create method of the CDialog class might be called.

The ExitInstance method of the class is to be extended. You should process such an operation like destroying the attached dialog.

int CChildThread::ExitInstance()
{
   if ( m_pDialog != NULL)
   {
      m_pDialog->DestroyWindow();
      delete m_pDialog;
      m_pDialog = NULL;
   }

   return CWinThread::ExitInstance();
}

Using a Class of the Child Thread Type

When a user performs actions to create a new dialog window by dialog selecting, we must take care of the handler that catches this event.

void CSampleDlg::OnDialogDialog1()
{
   CChildThread* pThread = new CChildThread(
                 RUNTIME_CLASS( CDialog1 ), IDD_DIALOG1 );
   pThread->CreateThread();

   m_aChildThreads.Add( pThread );
}

All we have to do is dynamically create a new CChildThread object, passing as input parameters to its constructor a pointer to the CRuntimeClass object and to call the CreateThread method of the newly created thread object. For convenience of subsequent destroying, the thread object pointers are to be stored in a special array. This array is useful when the application main window is going to be closed.

void CSampleDlg::OnClose()
{
   for ( int i = 0; i < m_aChildThreads.GetSize(); i++ )
   {
      if ( m_aChildThreads[i]->GetThreadPriority()
           == THREAD_PRIORITY_NORMAL )
      {
         m_aChildThreads[i]->ExitInstance();
         m_aChildThreads[i]->Delete();
      }
   }

   m_aChildThreads.RemoveAll();

   CDialog::OnClose();
}

Conclusion

Thus, it was cleared how to create a class object having only its class name and why this mechanism is needed. This project model is convenient to use when designing a multi thread application with a set of fixed dialog types when each thread has its own message queue. This model permits you to create windows with equal priority of overlapping. Nevertheless, there is an unresolved task to manage a behaviour of such dialogs, to control operations of minimise and restore.

The idea of using one child thread class for all types of dialogs is original. It actually optimises the project architecture when it is used in a thread-separated dialog.



Downloads

Comments

  • How to Send Data to the Dialog

    Posted by GuenniAtWork on 07/21/2005 08:52am

    How can i put data from the Main Dialog to the Thread Dialog?

    Reply
  • Re:G? Posted by gang5310 on 04/06/2004 09:52pm

    Re:G? Reply

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

  • Today's "average" business in general is ever more reliant on technology and the Internet. Mobility is the most often cited business trend that has transformed the way many of us work and communicate. From an IT security perspective, this means that protection methods and tools from even a few years ago are rapidly becoming "unfit for purpose." This guide provides crucial facts to assist you in building a robust business case, meeting the demands of your business, and protecting against threats now and in the …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds