Messageprocessing in DLL's

Posted on 1997-11-05
Last Modified: 2013-11-20
I have created DLL used for DLC communication
(a low level network protocol). I want to be able
to load the DLL, start a service thread and post
it messages.

The VC+5.0 environment has a wizard that can create a
DLL template. The produced code gives me a CWinApp derived
object that should be able to receive messages.

However, if I try to start it's CWinThread::Run() method
it terminates since there is no Windows handle assigned
to the DLL (i think).

How do I post a message to a service routine running in a DLL?

Rune.Bundesen @
Question by:puff
  • 2

Expert Comment

ID: 1309395
You use LoadLibrary from an EXE, and the ::Run is called automaticly. the ::Run is instead of DllMain function of a DLL.

Author Comment

ID: 1309396
Thanks for the reply.
Unfortunately it's a little more complex then that I think.
Perhabs im missing something, but here is what I think is
the problem.

I want to load a dll from an exe file (using loadlibrary).
The exe file is a CWinApp itself and lives in the main

After the library is loaded, I want to call a function
from the dll (still inside the main thread), lets call it

Inits function is to start a new thread holding a message pump.
I have tried this.. (CDlcDriverThread is a derrivation of

DWORD CALLBACK InitDlcDriver(HWND hWndReceiver)
 BOOL bRes;

 pDlcDriverThread=new CDlcDriverThread(hWndReceiver);

 if (!bRes) AfxMessageBox("Cannot create DlcDriverThread");
 return pDlcDriverThread->m_nThreadID;

The 'new' operation seems to create a valid object,
but the thread being created shuts down almost immediately.
I have tried to remove the CWinApp object in the dll, since
i thought it could be associated with having two CWinApp's,
but this just causes CreateThread to give an assertion error
[AfxGetApp() returns Null].

I just cant figure out how on earth I can create a
userinterface thread from a function inside a dll!.
Probably a trivial problem once you know the answer,
and I need it to be a userinterface thread since I want
to post the new thread messages (do this, do that, etc.)

thanks for the go Mike ;-), I hope you can clarify things

Accepted Solution

IgorGrebnev earned 300 total points
ID: 1309397
Dear Puff,
You can create new user interface thread in DLL, just like you can do that inside of code of your main exe.
The problem that you mixed the CWinApp object created inside of the DLL with application wizard with creation of new thread. THe application object inside of DLL used for managing of DLL module ( handle of DLL, name of INI file ) but its Run() funciton is never called.

What you need is to create new CWinThread object and call its Run() function. It should be different class from the CWinApp object created in the DLL.
Creating of user interface threads in DLL is not different from creation of threads inside of exe.
For creation of user-interface thread your need to derive class from CWinThread object.
class CMyThread : public CWinThread

{ BOOL InitInstance() { return TRUE; }
YOu should override InitInstance(), because the base implementation return FALSE, thus the thread closed immidiately.
Then you write
CMyThread *pMyThread = new CMyThread;
and the new thread runs and enter message loop. You can send messages to the thread with PostThreadMessage API. You should close the thread by posting WM_QUIT message to the thread, thus the MFC message loop is broken and thread exit. You do not need to call delete on thread object, because the default implementation of MFC do it after calling of ExitInstance() of the thread object.
I worked a lot with user-interface threads and created userful base class "CBaseThread" that used for posting of messages to the thread ( the thread do not have window) closing it and syncronisation. I just copy the source of the the BaseTHread.h and BaseTHread.cpp into the my answer and I can send it to you by mail if you provide the address. Here the source:

// BaseThread.h : header file. Base for all IP threads.
// CBaseThread thread

class CBaseThread : public CWinThread
  CEvent *m_pInitEvent;
  void WaitUntilInit();
  BOOL m_IsInitSucceded;
//------------------- Should not be iverridden by derived classes
  virtual BOOL  InitInstance();
      CBaseThread(); // protected constructor used by derived classes
//--------------- Derived threads should use this function for initialization
  virtual BOOL InitThread() { return TRUE; }  
//----------- Waits until InitInstance is finished
      BOOL CreateIPThread(UINT nStackSize = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL );
//---------------- Should NOT be called from the contents of this thread.
  void CloseThread();
  // Overrides
//------------------ Notification function from WM_IPTHREAD_NOTIFY
//----The value of lParam depends on wParam. In base class do nothing, like pure virtual
  virtual void OnIPThreadMsg( WPARAM, LPARAM ) {}  

      // ClassWizard generated virtual function overrides
      virtual int   ExitInstance();
      virtual BOOL  PreTranslateMessage(MSG* pMsg);

// Implementation
      virtual ~CBaseThread();

      // Generated message map functions
            // NOTE - the ClassWizard will add and remove member functions here.


// BaseThread.cpp : implementation file

#include "stdafx.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;

// CBaseThread



{ m_pInitEvent = new CEvent( FALSE, TRUE );
  m_IsInitSucceded = TRUE;


BOOL CBaseThread::InitInstance()          
{//----------Creates message Que for the threadv and unlock init event
  MSG msg;
  PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE );              
  m_IsInitSucceded = InitThread();
  return TRUE;

int CBaseThread::ExitInstance()
      if ( m_pInitEvent != NULL )
  { delete m_pInitEvent;
      return CWinThread::ExitInstance();

//----------- Waits until InitInstance is finished
void CBaseThread::WaitUntilInit()

{ if ( m_pInitEvent != NULL )
  { m_pInitEvent->Lock();
    if ( m_IsInitSucceded )
    { delete m_pInitEvent;
      m_pInitEvent = NULL;

BEGIN_MESSAGE_MAP(CBaseThread, CWinThread)
            // NOTE - the ClassWizard will add and remove mapping macros here.

// CBaseThread message handlers

BOOL CBaseThread::PreTranslateMessage(MSG* pMsg)
      if ( pMsg->hwnd      == NULL &&  pMsg->message == WM_IPTHREAD_NOTIFY )
  { OnIPThreadMsg( pMsg->wParam, pMsg->lParam );
    return TRUE; // No further processing
      return CWinThread::PreTranslateMessage(pMsg);

BOOL CBaseThread::CreateIPThread( UINT nStackSize, LPSECURITY_ATTRIBUTES lpSecurityAttrs )

{//--------------- Do NOT create suspended thread!!!
  BOOL retVal = CWinThread::CreateThread( 0, nStackSize, lpSecurityAttrs );
  if ( retVal )
  { WaitUntilInit();
    return m_IsInitSucceded;
  return retVal;

void CBaseThread::CloseThread()

{ if ( m_hThread != NULL )
  { HANDLE hThread = m_hThread;
    BOOL result = ::PostThreadMessage( m_nThreadID, WM_QUIT, 0, 0 );
    ASSERT( result );
    WaitForSingleObject( hThread, INFINITE );

BOOL CBaseThread::PostIPMessage( WPARAM wParam, LPARAM lParam  )

{ BOOL retVal = ::PostThreadMessage( m_nThreadID, WM_IPTHREAD_NOTIFY, wParam, lParam );
  ASSERT( retVal );
  return retVal;


Author Comment

ID: 1309398
Thanks for the reply Igor, you hit it right on the spot!
Your solution works fine, so Ill incorporate your class
into my code right away.

Sorry I missed my address, here it is.
Email work:

-Rune Bundesen

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone 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

Suggested Solutions

Title # Comments Views Activity
ASCII Non-Printable characters/codes and their HTML equivalents 6 130
viewing source code from eclipse 13 110
isEverywhere  challenge 19 82
Unix Command -- Challenging  question 7 95
Here is how to use MFC's automatic Radio Button handling in your dialog boxes and forms.  Beginner programmers usually start with a OnClick handler for each radio button and that's just not the right way to go.  MFC has a very cool system for handli…
Introduction: Database storage, where is the exe actually on the disc? Playing a game selected randomly (how to generate random numbers).  Error trapping with try..catch to help the code run even if something goes wrong. Continuing from the seve…
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.
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

789 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