CWinThread message maps - c++

So I'm delving into the world of MFC and in particular, customised use of CWinThread to implement worker threads. I have successfully implemented worker threads other ways, so the main motivation for using CWinThread for a worker thread is to make use of the message map.
For future use I am deriving CWinThread into what will eventually become some form of super class.. See the following declaration..
class WinThreadBase : public CWinThread
{
DECLARE_DYNCREATE(WinThreadBase)
protected:
WinThreadBase(); // protected constructor used by dynamic creation
DECLARE_MESSAGE_MAP()
public:
BOOL isdone_;
};
This is extended and implement by the following
The declaration
class WinThreadImplementation :public WinThreadBase {
DECLARE_DYNCREATE(WinThreadImplementation)
protected:
WinThreadImplementation(); //Declare protected because of dynamic creation
public:
//The following CWinThread methods have to be overriden to complete specfic work.
virtual BOOL InitInstance();
virtual int Run();
private:
CDialog* owner_;
BOOL isinit_;
public:
virtual ~WinThreadImplementation();
void SetOwner( CDialog* pOwner ) { owner_ = pOwner; }
BOOL Isinit() const { return isinit_; }
DECLARE_MESSAGE_MAP()
//Message handler declaration
void OnMyThreadMessage( WPARAM wParam, LPARAM lParam );
void OnQuit( WPARAM wParam, LPARAM lParam );
};
The implemetation
IMPLEMENT_DYNCREATE( WinThreadImplementation, WinThreadBase)
WinThreadImplementation::WinThreadImplementation() {
owner_ = FALSE;
isinit_ = FALSE;
}
WinThreadImplementation::~WinThreadImplementation() {
//........Do some stuff here... //
}
BOOL WinThreadImplementation::InitInstance() {
//Do some initialisation here..
return TRUE; //returning true allows thread start successfully
}
int WinThreadImplementation::Run() {
isinit_ = TRUE;
while( !isdone_ ) {
//Do some work...
//TRACE( "Hello from pat's derived CWinThread" );
Sleep( 1000 ); //Give other threads a chance to run..
}
owner_->PostMessage( WM_QUIT, 0, 0 ); // Tell our parent thread that this thread has finished work
return 0;
}
BEGIN_MESSAGE_MAP(WinThreadImplementation,CWinThread)
//Map messages to handler method here...
//CWinThread messages must be handles like this....
ON_THREAD_MESSAGE(WM_MYTHREADMESSAGE,OnMyThreadMessage)
END_MESSAGE_MAP()
//Put message handlers here...`
void WinThreadImplementation::OnMyThreadMessage( WPARAM wParam, LPARAM lParam ) {
TRACE( "Hello from my message handler\n\r" );
}
Now for actually posting the message
mywinthreadimpl_ = (WinThreadImplementation*)
AfxBeginThread( RUNTIME_CLASS( WinThreadImplementation ), THREAD_PRIORITY_NORMAL,
0, CREATE_SUSPENDED );
mywinthreadimpl_->SetOwner( this );
mywinthreadimpl_->ResumeThread();
while( !mywinthreadimpl_->Isinit() ); //Make sure that the thread has initialised before attempting to post a message
if( PostThreadMessage( mywinthreadimpl_->m_nThreadID, WM_MYTHREADMESSAGE, NULL, NULL ) ) {
TRACE( "message was sent correctly\n" );
}
So the result of this is that it compiles, my CWinThread derivation is working and enters the overriden run function. But I cannot for the life of me receive the message posted by PostThreadMessage.
I have read the following
http://support.microsoft.com/kb/142415?wa=wsignin1.0
and concluded that this does not apply to me since I am using VS 2010.
Can anyone suggest what I may have missed, that would be preventing my CWinThread implementation from receiving the messages?
Thanks

Without using AfxPumpMessage or calling the base class implementation of CWinThread (__super::Run), you will never receive a message!
Don't use isdone_. Instead use PostQuitMessage to terminate thecurrent workerthread too. Just use the base implementation of Run to run the thread and pump the messages.
You can also use OnIdle or other function of CWinThread, to do some work...
Just calling Sleep blocks your thread but the thread isnever interrupted by a windows message

Related

Safe place for an ATL object to release itself

Is there a strategy for safely allowing an ATL object to release itself in response to a Windows message or sink event?
In other words, let's say you have an ATL class that's subclassing some windows (using a message map) and/or sinking events from COM objects (using a sink map). And you'd like the class to release itself given a particular message or event. For example, you might want to release when a particular subclassed window receives WM_CLOSE, or you're sinking DWebBrowserEvents2 and want to release upon DISPID_ONQUIT.
I think the problem is that if you release in the middle of your message or event handler, the ATL framework might still have some processing to do afterward (even if you, say, do something like bHandled = TRUE). And if your object has been released/deleted at that point, then bad things will ensue.
Does anyone know of an approach to solve this? Thanks for any input.
you can do next implementation
class MySubClass : public CWindowImplBaseT<>
{
ULONG dwRefCount = 1;
BEGIN_MSG_MAP(MySubClass)
MESSAGE_HANDLER(WM_CHAR, OnChar)
END_MSG_MAP()
LRESULT OnChar(UINT uMsg, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
{
bHandled = FALSE;
// for instance unsublass when ESC pressed
// but possible do this on any event
if (uMsg == WM_CHAR && wParam == VK_ESCAPE)
{
UnsubclassWindow(FALSE);
}
return 0;
}
virtual void OnFinalMessage(_In_ HWND hWnd)
{
__super::OnFinalMessage(hWnd);
Release();
}
~MySubClass()
{
DbgPrint("%s<%p>\n", __FUNCTION__, this);
}
public:
BOOL SubclassWindow(_In_ HWND hWnd)
{
if (__super::SubclassWindow(hWnd))
{
AddRef();
return TRUE;
}
return FALSE;
}
HWND UnsubclassWindow(_In_ BOOL bForce /*= FALSE*/)
{
if (HWND hwnd = __super::UnsubclassWindow(bForce))
{
// mark window as destroyed
m_dwState |= WINSTATE_DESTROYED;
m_hWnd = hwnd;
return hwnd;
}
return 0;
}
void AddRef()
{
dwRefCount++;
}
void Release()
{
if (!--dwRefCount)
{
delete this;
}
}
};
void DoSubclass(HWND hwnd)
{
if (MySubClass* pObj = new MySubClass)
{
pObj->SubclassWindow(hwnd);
pObj->Release();
}
}
so key points - have reference count on object ( ULONG dwRefCount - here i assume that object will be accessed only from single UI thread, otherwise need use atomic/interlocked operations). delete object inside Release() when dwRefCount became 0. when we subclass window - add additional reference, and in UnsubclassWindow - set WINSTATE_DESTROYED bit in state ( m_dwState |= WINSTATE_DESTROYED ) - as result OnFinalMessage will be called after last message and here we already call Release. or if we not direct unsubclass until window will be destroyed - atl implementation anyway finally call OnFinalMessage where we release self.
According to the documentation for CWindowImpl::OnFinalMessage:
The default implementation of OnFinalMessage does nothing, but you can override this function to handle cleanup before destroying a window. If you want to automatically delete your object upon the window destruction, you can call delete this; in this function.
So that looks like the place to do it.

Ending nested message loop of a custom dialog

I have a dialog class made from dialog template in memory which runs it's own nested message loop (in addition to main app msg loop).
To create a dialog I use CreateDialogIndirectParamW which returns handle to the dialog window,
Since the dialog is completely customized, all the message processing and creation is done manually.
I omitted Dialog procedure, but basically it calls the below relevant message handlers, once the the dialog is closing down.
Note that, we can't use EndDialog function to destroy the dialog and end message loop because for CreateDialogIndirectParamW we must use DestroyWindow explicitly.
I'm looking for efficient way to end the dialog loop.
I tried to implement this loop but problem is that this approach will either consume too much CPU resources since the for loop in the sample code will just run silly until there is a message, or if for is omited then PeekMessage will stop the loop immediately, which is not what I wan't.
Relevant class declaration:
class Dialog :
public ContainerWindow,
public MessageWindow,
public SuperClassWindow
{
// ...
public:
/** Process messages for dialog window */
[[nodiscard]] int RunMessageLoop() override;
protected:
/** Handler for WM_NCDESTROY */
std::uint32_t OnNcDestroy(const UINT& uMsg, const WPARAM& wParam, const LPARAM& lParam) override;
/** Handler for WM_DESTROY */
inline void OnDestroy() const noexcept override;
/** Handler for WM_CLOSE */
inline virtual bool OnClose() noexcept;
// ...
protected:
HWND mhWnd; /** Window handle of derived component */
}
Simplified class definition:
std::uint32_t Dialog::OnNcDestroy(
[[maybe_unused]] const UINT& uMsg,
[[maybe_unused]] const WPARAM& wParam,
[[maybe_unused]] const LPARAM& lParam)
{
// ...
delete this; // note we can't set this pointer to nullptr!
// ...
return count;
}
void Dialog::OnDestroy() const noexcept
{
PostQuitMessage(0);
}
bool Dialog::OnClose() noexcept
{
return DestroyWindow(mhWnd);
}
And here is the message loop for a dialog:
I need to add some checking code into the loop to check if dialog is valid object, that is stop the loop somehow if the Dialog object has been deleted
Once the OnNcDestroy handler is called, IsDialogMessageW bellow will fail, see comment.
Looks like GetMessageW will continue running after WM_NCDESTROY is dispatched, the loop is still waiting for WM_QUIT sent by OnDestroy handler so the msg loop will continue running once the Dialog object is deleted, and that will make IsDialogMessageW(mhWnd, &msg) bellow fail. since mhWnd does not exist any more.
int Dialog::RunMessageLoop()
{
EnableWindow(mhWndParent, FALSE);
MSG msg{ };
BOOL result = FALSE;
while ((result = GetMessageW(&msg, nullptr, 0, 0)) != FALSE)
{
if (result == -1)
{
ShowError(ERR_BOILER); // error checking function.
break;
}
// once OnNcDestroy is called "mhWnd" is invalid memory
// and this will off course cause access violation!
if (!IsDialogMessageW(mhWnd, &msg))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
EnableWindow(mhWndParent, TRUE);
return static_cast<int>(msg.wParam);
}
note that we can't if (this) because this is not nullptr and can't be set to nullptr in OnNcDestroy handler.
OK, after some time experimenting I come out with the following change to the code which makes everything works as it should! (see comments for more info)
btw. I will leave this question open, hopefully there is more efficient way for this, currently IsWindow is called for every message which is maybe a performance issue.
int Dialog::RunMessageLoop()
{
EnableWindow(mhWndParent, FALSE);
MSG msg{ };
BOOL result = FALSE;
// first we save the handle to the window
HWND hwnd = mhWnd;
if (!IsWindow(hwnd)) // make sure the handle is valid dialog window
std::abort();
while ((result = GetMessageW(&msg, nullptr, 0, 0)) != FALSE)
{
if (result == -1)
{
ShowError(ERR_BOILER);
break;
}
// if object is deleted the handle is no longer valid!
// because prior to OnNcDestroy handler DestroyWindow has been called
if (!IsWindow(hwnd))
goto invalid;
if (!IsDialogMessageW(mhWnd, &msg))
{
invalid: // non dialog message processing
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
// NOTE that we removed EnableWindow(mHwndParent) here!
return static_cast<int>(msg.wParam);
}
This on it's own will work but one additional step is to enable owner window (main window) before the dialog is destroyed, so update the handler:
bool Dialog::OnClose() noexcept
{
// otherwise first window in Z order (such as Desktop) will get focus!
EnableWindow(mhWndParent, TRUE);
return DestroyWindow(mhWnd);
}

MFC - Cannot Post Message to a custom class derived from CWnd

I have a custom class derived from CWnd that I would like to post a message to from a worker thread. I am using the PostMessage function to achieve this. The first argument to PostMessage is the HWND type handle to my class, and the next is the message I would like handled. For the first parameter, I generate the handle to my class using GetSafeHwnd() function, and for the second parameter, I use WM_USER+3. Also, I declare a message map inside my class header file, and add an entry for the message handler inside the BEGIN_MESSAGE_MAP and END_MESSAGE_MAP block. However, my handler is not getting called. I have also checked the return value of PostMessage function, it is 1, that means success.
Here is my code :
Inside MyClass.h
class CMyClass : CWnd
{
....
....
public:
void InitHandle();
protected:
afx_msg LRESULT OnMessageReceived(WPARAM wParam, LPARAM lParam);
DECLARE_MESSAGE_MAP()
}
Inside MyClass.cpp
#define WM_MY_MESSAGE WM_USER+3
HWND handleToMyClassWindow;
BEGIN_MESSAGE_MAP(CMyClass, CWnd)
ON_MESSAGE(WM_MY_MESSAGE, OnMessageReceived)
END_MESSAGE_MAP()
LRESULT CMyClass::OnMessageReceived(WPARAM wParam, LPARAM lParam)
{ .... }
void CMyClass::InitHandle()
{
handleToMyClassWindow = GetSafeHwnd();
}
Inside Worker thread
UINT WorkerThreadFunction(LPVOID pParam )
{
....
PostMessage(handleToMyClassWindow, WM_MY_MESSAGE, NULL, NULL);
....
}
My question is, what are the possible reasons for the OnMessageReceived handler to not be called.
P.S.
I take care that the calling object calls the InitHandle() function.
I tried the same technique with the View class (derived from CView) of my program, and it works there, but fails here.
You cannot post to a window if it has not been created. GetSafeHwnd() will return NULL if you have not actually created a window using your class.

Can't get the handle of a Cwnd Class in MFC Windowless Activex?

I have asked two questions earlier about this and for each post there was some solutions i tried them, but the problem still exist.
My first question was : why a windowless Activex does not return the Handle. the suggestion was "change the creation setting an make windowless activate off, i have tried it but still m_hWnd property has returned zero as GetSafeHwnd() method has did.
the second one was the same question this one focused on COleControl class and it's ancestor CWnd. the solution was as this "Create invisible window somewhere in your control initialization code. Handle the messages sent to this window, and call controls methods directly". so i did that but the created class still returns zero handle.
here is my new invisible class source:
// moWind.cpp : implementation file
//
#include "stdafx.h"
#include "PINActive.h"
#include "moWind.h"
#include "include\xfspin.h"
#include <math.h>
// moWind
IMPLEMENT_DYNAMIC(moWind, CWnd)
moWind::moWind(){}
moWind::~moWind(){}
//=============================================================
LRESULT moWind::OnExecuteEvent (WPARAM wParam, LPARAM lParam)
{
WFSRESULT *pResult = (WFSRESULT *)lParam;
CString EK=_T("");
CString str;
int reskey=0;
if (pResult->u.dwEventID=WFS_EXEE_PIN_KEY)
{
LPWFSPINKEY pressedkey;
pressedkey=(LPWFSPINKEY)pResult->lpBuffer;
reskey = log10((double)pressedkey->ulDigit) / log10((double)2);
EK.Format("%d",reskey);
xfsOnKeyEvent->OnKeyRecieved(reskey);
}
else
{
str.Format("ExecuteEvent: ID = %d\r\n", pResult->u.dwEventID);
}
MessageBox("a Execute message Recieved");
return 0;
}
BEGIN_MESSAGE_MAP(moWind, CWnd)
ON_MESSAGE(WFS_EXECUTE_EVENT,OnExecuteEvent)
END_MESSAGE_MAP()
and this is .h file of the class:
// moWind.h
class IXFSEvents
{
protected:
IXFSEvents(){};
virtual ~IXFSEvents(){};
public:
virtual void OnKeyRecieved(int key)=0;
};
class moWind : public CWnd
{
DECLARE_DYNAMIC(moWind)
public:
moWind();
virtual ~moWind();
void Register(IXFSEvents* obj)
{
xfsOnKeyEvent= obj;
}
protected:
IXFSEvents* xfsOnKeyEvent;
LRESULT OnExecuteEvent (WPARAM wParam, LPARAM lParam);
DECLARE_MESSAGE_MAP()
};
and at the end here this the way I've used this class in my Activex:
in the myActivex.h file:
include "moWind.h"
class CmyActivexCtrl : public COleControl, public IXFSEvents
{
...
Class definition
...
protected:
moWind tmpWind;
.
.
};
finally in the creation method of myActivex i have initialized the component callback method an wanted to get it's Handle as this:
CmyActivexCtrl::CmyActivexCtrl()
{
InitializeIIDs(&IID_DmyActivex, &IID_DmyActivexEvents);
tmpWind.Register(this);
myOtherComponent.WindowsHandle=tmpWind.GetSafeHwnd(); //here my Cwnd derived class returns zero
//my other component gets the handle and call an API with it to register
//the given handle and force the API to send the messages to that handle.
}
As you mentioned you need a window handle to be able to receive user messages through it, you always have an option of creating a helper window, such as message only window, see Using CreateWindowEx to Make a Message-Only Window.
For your windowless control it is okay to not have any window handle at all, so you cannot really rely on handle availability unless you own a window yourself.

default WM_DESTROY not properly cleaning up child windows

I have a WTL 8.0 SDI application for Windows Mobile 5. In this contrived example below, I create a view, destroy it, then re-create it. But, when it's re-created assertions in the WM_INITDIALOG handler fail because the control's HWND isn't valid.
I note that I can fix this by handling WM_DESTROY in CMyView and manually destroying every child control. But, I didn't think I should have to. MSDN even says:
This message is sent first to the
window being destroyed and then to the
child windows (if any) as they are
destroyed.
Anybody have an idea as to what's going on?
Edit: If I handle WM_NCDESTROY in CMyView, all of the the child control handles are still valid! (some_control_.IsWindow()==TRUE) That's not how it's supposed to be...
Thanks,
PaulH
class CMyView : public CDialogImpl< CMyView >,
public CWinDataExchange< CMyView >
{
// <snip> Message Map and other standard WTL macros </snip>
LRESULT OnInitDialog( UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/ )
{
DoDataExchange( FALSE );
// assertion fails within the SetWindowText() call
// atlwin.h line 876
// ATLASSERT(::IsWindow(m_hWnd));
some_control_.SetWindowText( _T( "Foo" ) );
return 0;
};
private:
CEdit some_control_;
}; // class CMyView
class CMainFrame : public CFrameWindowImpl< CMainFrame >,
public CUpdateUI< CMainFrame >,
public CMessageFilter,
public CIdleHandler
{
public:
// <snip> Message Map and other standard WTL macros </snip>
BOOL CMainFrame::PreTranslateMessage( MSG* pMsg )
{
if( CFrameWindowImpl< CMainFrame >::PreTranslateMessage( pMsg ) )
return TRUE;
return my_view_.PreTranslateMessage( pMsg );
};
LRESULT OnCreate( UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/ )
{
CMessageLoop* pLoop = _Module.GetMessageLoop();
ATLASSERT( pLoop != NULL );
pLoop->AddMessageFilter( this );
pLoop->AddIdleHandler( this );
m_hWndClient = my_view_.Create( m_hWnd );
my_view_.DestroyWindow();
m_hWndClient = my_view_.Create( m_hWnd );
};
private:
CMyView my_view_;
}; // class CMainFrame
It is not good practice to Create, Destroy and re-Create the same window, you should consider hiding it and reinitializing your contents when showing it again.
Anyhow your code will not ASSERT at re-creation with:
virtual void CMyView::OnFinalMessage(HWND)
{
some_control_.m_hWnd = 0;
}
I'm not a hundred percent sure, but it seems like the some_control_ CEdit control is not registered with the parent window. I think you will need to call some_control_.Create(...) with the parent handle as a parameter.
see msdn article for a documentation of CEdit::Create().