Prev: Runtime error-help plz.
Next: uafxcw.lib(dllmodul.obj) : error LNK2005: _DllMain@12 already defined
From: Joseph M. Newcomer on 2 Jul 2007 11:10 You should not be sending Windows messages from another thread. This would be a serious error in design. If you need to do something from another thread, you should use PostMessage of a user-defined message. Note that in the PostMessage/SendMessage debate, it is still erroneous to SendMessage a Windows message unless you truly know what you are doing. From what I see here, there is no reason at all to send a WM_NOTIFY, so you should be using a user-defined message. joe On Mon, 02 Jul 2007 01:31:13 -0700, Headache <rquirk(a)tandbergtv.com> wrote: >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; ***** Because you are using 'SendMessage' there is no need to use 'new'. Note also that you are missing the corresponding 'delete'. So you have a memory leak. Presumably this is a static method, so it is usually good practice to add the 'static' keyword to it as a comment, e.g., /* static */ UINT CDECL SendMessageToMainWnd(LPVOID pParam) If it is not static, there would be a serious problem. ***** > ::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) ***** Is the control in question a child control of the mainframe? If it isn't, this code is in the wrong place and should be moved. ***** >{ > ::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) **** I presume that this is here just for debugging purposes **** >{ > // 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); >} Joseph M. Newcomer [MVP] email: newcomer(a)flounder.com Web: http://www.flounder.com MVP Tips: http://www.flounder.com/mvp_tips.htm
From: Joseph M. Newcomer on 2 Jul 2007 21:09 WHile it seems reasonable that this should be done, the truth is that it is not done. Life would be a lot easier for all of us if it had been done. joe On Sun, 01 Jul 2007 20:31:04 GMT, "David Ching" <dc(a)remove-this.dcsoft.com> wrote: >"Joseph M. Newcomer" <newcomer(a)flounder.com> wrote in message >news:eb3g835kcr8bfllckal6ihe85m28da8gv2(a)4ax.com... >> This was handled as a special case because of its importance, particularly >> because a huge >> number of programs depended on being able to get window captions. It is >> one of the very, >> very, very, very few messages that actually works this way. > >I repeat: It seems if they marshalled some messages they would marshall all >of them. > >Who's to say that getting a foreign process's window caption is important >but not the state of a toolbar button within that window? I need to do >both, that's why I created SendMessageRemote(), but it shouldn't have been >necessary. > >-- David > Joseph M. Newcomer [MVP] email: newcomer(a)flounder.com Web: http://www.flounder.com MVP Tips: http://www.flounder.com/mvp_tips.htm
From: Headache on 5 Jul 2007 03:46 I make no apologies for the tattiness of my code I just wanted the mechanism to work and tried lot's of things out. Anyhow, I decided to redouble my efforts and have found out exactly why this doesn't work. Examining the call stack you can see that CWnd::OnNotify the first parameter has value 0x000001aa. This is the window's ID (426 decimal). In the next call to CMainFrame this has morphed into an nID parameter of 0x00003c38. > mfc71d.dll!AfxFindMessageEntry(const AFX_MSGMAP_ENTRY * lpEntry=0x00426028, unsigned int nMsg=0x0000004e, unsigned int nCode=0x0000fffe, unsigned int nID=0x00003c38) Line 1659 C++ mfc71d.dll!CCmdTarget::OnCmdMsg(unsigned int nID=0x00003c38, int nCode=0x0000fffe, void * pExtra=0x0013fb74, AFX_CMDHANDLERINFO * pHandlerInfo=0x00000000) Line 383 + 0x18 C++ mfc71d.dll!CFrameWnd::OnCmdMsg(unsigned int nID=0x00003c38, int nCode=0x004efffe, void * pExtra=0x0013fb74, AFX_CMDHANDLERINFO * pHandlerInfo=0x00000000) Line 897 + 0x18 C++ WmNotify.exe!CMainFrame::OnCmdMsg(unsigned int nID=0x00003c38, int nCode=0x004efffe, void * pExtra=0x0013fb74, AFX_CMDHANDLERINFO * pHandlerInfo=0x00000000) Line 170 C++ mfc71d.dll!CWnd::OnNotify(unsigned int __formal=0x000001aa, long lParam=0x00037970, long * pResult=0x0013fc70) Line 2576 C++ mfc71d.dll!CWnd::OnWndMsg(unsigned int message=0x0000004e, unsigned int wParam=0x000001aa, long lParam=0x00037970, long * pResult=0x0013fca4) Line 1771 + 0x28 C++ mfc71d.dll!CWnd::WindowProc(unsigned int message=0x0000004e, unsigned int wParam=0x000001aa, long lParam=0x00037970) Line 1745 + 0x1e C++ This is the reason why: BOOL CWnd::OnNotify(WPARAM, LPARAM lParam, LRESULT* pResult) { ASSERT(pResult != NULL); NMHDR* pNMHDR = (NMHDR*)lParam; HWND hWndCtrl = pNMHDR->hwndFrom; // get the child ID from the window itself UINT_PTR nID = _AfxGetDlgCtrlID(hWndCtrl); OnNotify ignores the NMHDR.idFrom field and instead recalculates it from _AfxGetDlgCtrlID(hWndCtrl). Now the hWndFrom that I passed was from my MainFrame window so the ID becomes that of my MainFrame window and not the control. I think some of you hinted at this. The HWND and ID should both tie up. Breaking out a WM_NOTIFY message in the command map looks like this: BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo) { TRACE(_T("HIWORD(nCode) = %x\n"), HIWORD(nCode)); TRACE(_T("LOWORD(nCode) = %x\n"), LOWORD(nCode)); TRACE(_T("WM_NOTIFY = %x\n"), WM_NOTIFY); TRACE(_T("NM_CLICK = %x\n"), NM_CLICK); // TODO: Add your specialized code here and/or call the base class if ( (HIWORD(nCode) == WM_NOTIFY) && (LOWORD(nCode) == LOWORD(NM_CLICK)) ) { CString str; str.Format(_T("nID = %ld, nCode = %ld\n"), nID, nCode); TRACE(str); } return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo); } You have to do LOWORD(nCode) == LOWORD(NM_CLICK) because only the low word of NM_CLICK (defined as 0xFFFFFFFE) is placed into nCode. As an aside it appears impossible to write a program where the mainframe notifies itself (*VIA STATIC MAP ENTRIES*) as the Mainframe's ID is decided at run- time. Well, I said I was trying something arcane out. Now to get back to looking at RemoteSendMessage API or whatever it's called.
First
|
Prev
|
Pages: 1 2 3 4 Prev: Runtime error-help plz. Next: uafxcw.lib(dllmodul.obj) : error LNK2005: _DllMain@12 already defined |