Re: SendMessage WM_NOTIFY across process
I thought Windows might marshall the simple types too. I guess I've
been working too long with COM. However, I tried this in a single
process and still couldn't get it to work. This time I see the message
in Spy++. Looking at the MFC source code it seems to frig WM_NOTIFY
messages. Anyhow here is my source. I send the message in another
thread (as I guess my handler is on the main thread which is blocked
waiting on a SendMessage) and I'm new'ing the structure on the heap
and not even deleting it. I don't get into the MainFrame OnClick
handler even though it is in the message map. It makes me think I'm
missing something simple. Don't ask about where I break out the code
in OnCmdMsg - it was code I wrote while looking at the framework. Once
I get this going I'll have a look at the SendMessageRemote suggestion.
// MainFrm.cpp : implementation of the CMainFrame class
//
#include "stdafx.h"
#include "WmNotify.h"
#include "MainFrm.h"
#include ".\mainfrm.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CMainFrame
IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
ON_WM_CREATE()
ON_NOTIFY(NM_CLICK, 0, OnClick)
ON_COMMAND(ID_EDIT_SENDMESSAGE, OnSendMessage)
END_MESSAGE_MAP()
static UINT indicators[] =
{
ID_SEPARATOR, // status line indicator
ID_INDICATOR_CAPS,
ID_INDICATOR_NUM,
ID_INDICATOR_SCRL,
};
UINT __cdecl SendMessageToMainWnd(LPVOID pParam)
{
NMITEMACTIVATE *pNMIA = new NMITEMACTIVATE;
::ZeroMemory(pNMIA, sizeof(NMITEMACTIVATE));
// Set up header
pNMIA->hdr.code = NM_CLICK;
pNMIA->hdr.hwndFrom = ::AfxGetMainWnd()->GetSafeHwnd();
pNMIA->hdr.idFrom = 426;
// Setup item and subitem
pNMIA->iItem = 1;
pNMIA->iSubItem = 2;
//DWORD dwThreadID = (DWORD)pParam;
::AfxGetMainWnd()->SendMessage(WM_NOTIFY, pNMIA->hdr.idFrom,
(LPARAM)pNMIA);
return 0;
}
// CMainFrame construction/destruction
CMainFrame::CMainFrame()
{
// TODO: add member initialization code here
}
CMainFrame::~CMainFrame()
{
}
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE
| CBRS_TOP
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}
if (!m_wndStatusBar.Create(this) ||
!m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
{
TRACE0("Failed to create status bar\n");
return -1; // fail to create
}
// TODO: Delete these three lines if you don't want the toolbar to be
dockable
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
return 0;
}
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return TRUE;
}
// CMainFrame diagnostics
#ifdef _DEBUG
void CMainFrame::AssertValid() const
{
CFrameWnd::AssertValid();
}
void CMainFrame::Dump(CDumpContext& dc) const
{
CFrameWnd::Dump(dc);
}
#endif //_DEBUG
// CMainFrame message handlers
void CMainFrame::OnClick(NMHDR *pNMHDR, LRESULT* pResult)
{
::AfxMessageBox(_T("Hurrah!!"));
ASSERT(NM_CLICK == pNMHDR->code);
NMITEMACTIVATE *pNMIA = (NMITEMACTIVATE *)pNMHDR;
*pResult = 1;
}
void CMainFrame::OnSendMessage()
{
::AfxBeginThread(SendMessageToMainWnd, (LPVOID)::AfxGetApp()-
m_nThreadID);
}
BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra,
AFX_CMDHANDLERINFO* pHandlerInfo)
{
// TODO: Add your specialized code here and/or call the base class
if ( (HIWORD(nCode) == WM_NOTIFY) && (LOWORD(nCode) == NM_CLICK) )
{
CString str;
str.Format(_T("Msg = %d, nCode = %d\n"), HIWORD(nCode),
LOWORD(nCode));
TRACE(str);
}
return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}