From: Headache on
Hello,

I'm using a program to drive a GUI. For simple messages such as
LB_SETSEL the PostMessage API works fine. I use SendMessage for
WM_NOTIFY as it takes the address of a local NMITEMACTIVATE structure.
I've tried this with very simple cases. Using Spy++ to obtain the
window handles and to observe the messages I never see the WM_NOTIFY
message neither does my simple handler in my simple client get
invoked. I'm assuming window handles are globally unique. Here is my
code on the testing side:

void CTelusDlg::ClickOnListControl(HWND hWndParent, HWND hWndListCtrl,
int iItem, int iSubItem)
{
NMITEMACTIVATE nmia;
::ZeroMemory(&nmia, sizeof(NMITEMACTIVATE));
// Set up header
nmia.hdr.code = NM_CLICK;
nmia.hdr.hwndFrom = hWndListCtrl;
nmia.hdr.idFrom = ::GetDlgCtrlID(hWndListCtrl); // value is 426
// Setup item and subitem
nmia.iItem = iItem;
nmia.iSubItem = iSubItem;
if ( ! ::SendMessage(hWndParent, WM_NOTIFY, nmia.hdr.idFrom,
(LPARAM)&nmia) )
{
DWORD dwError = ::GetLastError();
LPTSTR lpBuffer;
::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
dwError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
(LPTSTR)&lpBuffer,
0,
NULL);
::AfxMessageBox(lpBuffer);
::LocalFree(lpBuffer);
}
}

Here's the other side:

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
ON_WM_CREATE()
ON_NOTIFY(NM_CLICK, 426, OnClick)
END_MESSAGE_MAP()

void CMainFrame::OnClick(NMHDR *pNMHDR, LRESULT* pResult)
{
::AfxMessageBox(_T("Hurrah!!"));
ASSERT(NM_CLICK == pNMHDR->code);

NMITEMACTIVATE *pNMIA = (NMITEMACTIVATE *)pNMHDR;

*pResult = 1;
}


I'm beginning to think that something chokes WM_NOTIFY messages when
they're sent to windows in different processes. Am I right or has
somebody managed this? Is there a workaround?

From: Scott McPhillips [MVP] on
Headache wrote:
> Hello,
>
> I'm using a program to drive a GUI. For simple messages such as
> LB_SETSEL the PostMessage API works fine. I use SendMessage for
> WM_NOTIFY as it takes the address of a local NMITEMACTIVATE structure.

An address in your process is useless in another process. So even if
the message was passed by Windows it would not contain a valid pointer.
I don't know if Windows suppresses such a cross-process WM_NOTIFY, but
it would be a real good idea if it does.

One option that you could use is to send the WM_COPYDATA message to the
other process. Windows provides support for this message by copying the
passed data into the receiving process' memory.

--
Scott McPhillips [MVP VC++]

From: David Ching on

"Scott McPhillips [MVP]" <org-dot-mvps-at-scottmcp> wrote in message
news:K5adnVn9ws6emhjbnZ2dnUVZ_gCdnZ2d(a)comcast.com...
> Headache wrote:
>> Hello,
>>
>> I'm using a program to drive a GUI. For simple messages such as
>> LB_SETSEL the PostMessage API works fine. I use SendMessage for
>> WM_NOTIFY as it takes the address of a local NMITEMACTIVATE structure.
>
> An address in your process is useless in another process. So even if the
> message was passed by Windows it would not contain a valid pointer. I
> don't know if Windows suppresses such a cross-process WM_NOTIFY, but it
> would be a real good idea if it does.
>
> One option that you could use is to send the WM_COPYDATA message to the
> other process. Windows provides support for this message by copying the
> passed data into the receiving process' memory.
>
> --

To add to Scott's thought that passing fixed addresses to another process is
wrong, see
http://groups.google.com/group/microsoft.public.vc.mfc/browse_frm/thread/40c00794fa444323/291326274362ef36?lnk=st&q=dcsoft+sendmessageremote&rnum=1#291326274362ef36
which discusses my SendMessageRemote() function which sounds ideal for your
situation.

-- David


From: Joseph M. Newcomer on
Really, really Bad Idea. Won't work, don't even try.

You are passing a pointer to some other process, and the pointer is a meaningless integer.

to make this work, you have to have a hook DLL injected into the target, send a customized
message, or do really complicated things to retrieve the data from the other process.

The simplest solution is to assume this is impossible. However, someone else has posted
code that does this by DLL injection so you might check the archives.

Window handles are global but pointers definitely are not, and so you can't send a
WM_NOTIFY as you are trying to do because the pointer is a pointer to some other process.

this is why OLE automation was invented.
joe

On Fri, 29 Jun 2007 03:54:06 -0700, Headache <rquirk(a)tandbergtv.com> wrote:

>Hello,
>
>I'm using a program to drive a GUI. For simple messages such as
>LB_SETSEL the PostMessage API works fine. I use SendMessage for
>WM_NOTIFY as it takes the address of a local NMITEMACTIVATE structure.
>I've tried this with very simple cases. Using Spy++ to obtain the
>window handles and to observe the messages I never see the WM_NOTIFY
>message neither does my simple handler in my simple client get
>invoked. I'm assuming window handles are globally unique. Here is my
>code on the testing side:
>
>void CTelusDlg::ClickOnListControl(HWND hWndParent, HWND hWndListCtrl,
>int iItem, int iSubItem)
>{
> NMITEMACTIVATE nmia;
> ::ZeroMemory(&nmia, sizeof(NMITEMACTIVATE));
> // Set up header
> nmia.hdr.code = NM_CLICK;
> nmia.hdr.hwndFrom = hWndListCtrl;
> nmia.hdr.idFrom = ::GetDlgCtrlID(hWndListCtrl); // value is 426
> // Setup item and subitem
> nmia.iItem = iItem;
> nmia.iSubItem = iSubItem;
> if ( ! ::SendMessage(hWndParent, WM_NOTIFY, nmia.hdr.idFrom,
>(LPARAM)&nmia) )
> {
> DWORD dwError = ::GetLastError();
> LPTSTR lpBuffer;
> ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
>FORMAT_MESSAGE_FROM_SYSTEM,
> NULL,
> dwError,
> MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
> (LPTSTR)&lpBuffer,
> 0,
> NULL);
> ::AfxMessageBox(lpBuffer);
> ::LocalFree(lpBuffer);
> }
>}
>
>Here's the other side:
>
>BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
> ON_WM_CREATE()
> ON_NOTIFY(NM_CLICK, 426, OnClick)
>END_MESSAGE_MAP()
>
>void CMainFrame::OnClick(NMHDR *pNMHDR, LRESULT* pResult)
>{
> ::AfxMessageBox(_T("Hurrah!!"));
> ASSERT(NM_CLICK == pNMHDR->code);
>
> NMITEMACTIVATE *pNMIA = (NMITEMACTIVATE *)pNMHDR;
>
> *pResult = 1;
>}
>
>
>I'm beginning to think that something chokes WM_NOTIFY messages when
>they're sent to windows in different processes. Am I right or has
>somebody managed this? Is there a workaround?
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
From: David Ching on
"Joseph M. Newcomer" <newcomer(a)flounder.com> wrote in message
news:0iae83tncd7dasjl3rq18e67c4v272g38h(a)4ax.com...
> Window handles are global but pointers definitely are not, and so you
> can't send a
> WM_NOTIFY as you are trying to do because the pointer is a pointer to some
> other process.
>
> this is why OLE automation was invented.

I wonder why Windows takes care of marshalling pointers for some messages,
such as WM_GETTEXT, but not for others. For example,
SendMessage(WM_GETTEXT, ...) does work across processes. It seems if they
marshalled some messages they would marshall all of them. I've heard the
rule is messages below WM_USER are marshalled, but not others, but have not
confirmed this.

-- David