WM_NOTIFY Help - (Noobs stay away! haha) - Printable Version
-Shoutbox (https://shoutbox.menthix.net)
+-- Forum: MsgHelp Archive (/forumdisplay.php?fid=58)
+--- Forum: Messenger Plus! for Live Messenger (/forumdisplay.php?fid=4)
+---- Forum: Scripting (/forumdisplay.php?fid=39)
+----- Thread: WM_NOTIFY Help - (Noobs stay away! haha) (/showthread.php?tid=72467)
WM_NOTIFY Help - (Noobs stay away! haha) by matty on 03-08-2007 at 10:24 PM
Well I have been working on a little project here and it makes use of the Tree View Control. Now since there isn't any built in support for it you have to subclass and receive messages.
Firstly I was using WM_PARENTNOTIFY and the returned value of wParam was WM_LBUTTONDOWN. Now what I need is to be able to use a double click not just a single click. So I did some research and came across website: http://www.codeproject.com/treectrl/treeview.asp.
Now a specific section talks about catching WM_NOTIFY and using the NMHDR structure to get which command :
quote: NM_CLICK ; user has clicked the left mouse button within the control
NM_DBLCLK ; user has Double clicked the left mouse button within the control
NM_RCLICK ; user has clicked the right mouse button within the control
NM_RDBLCLK ; user has Double clicked the left mouse button within the control
Now this is all fine and dandy however I can understand that I can use SendMessageW with WM_NOTIFY and the defined structure will be filled with the information I need however... This message is supposed to be returned in the OnWindowIdEvent_MessageNotification function. So my dilemma is the website example says that lParam is the NMHDR structure however there would be no way to access the members of the structure.
Any ideas?
As well here is the current function in my script.
code: function On_editorEvent_MessageNotification(pPlusWnd, /* Window Object */
nMessage, /* Window Message Received */
wParam, /* wParam field message */
lParam) /* lParam field message */
{
switch (nMessage){
case WM_PARENTNOTIFY:
_sent_notify = true;
Interop.Call('user32', 'SendMessageW', _window.Handle,
WM_NOTIFY,
pPlusWnd.GetControlHandle('tvFiles'),
NMHDR.DataPtr);
break;
case WM_NOTIFY:
_get_item(pPlusWnd);
if (_sent_notify == true){
Interop.Call('kernel32', 'RtlMoveMemory', NMHDR, lParam, 12);
Debug.Trace(NMHDR.ReadDWORD(0));
_sent_notify = false;
}
break;
}
}
RE: WM_NOTIFY Help - (Noobs stay away! haha) by effection on 03-08-2007 at 10:34 PM
code: typedef struct tagNMHDR {
HWND hwndFrom;
UINT_PTR idFrom;
UINT code;
} NMHDR;
now im not sure what size the HWND structure is (i think it is an integer) but UINT_PTR should be a 32bit value and so should UINT, so could you not just read off the DWORDs from the structure?
code: var hwndFrom= nmhdr.ReadDWORD(0);
var idFrom = nmhdr.ReadDWORD(4);
var code = nmhdr.ReadDWORD(8 );
sorry if ive missed something
RE: WM_NOTIFY Help - (Noobs stay away! haha) by deAd on 03-08-2007 at 10:45 PM
This is easy actually, I asked the same question a while back:
code: var pNmhdr = Interop.Allocate(12); // if this is the wrong size sorry
Interop.Call('Kernel32.dll', 'RtlMoveMemory', pNmhdr.DataPtr, lParam, pNmhdr.Size);
// do stuff with pNmhdr
If you want to modify the structure, just call RtlMoveMemory again with the opposite parameters after you're all done modifying it:
code: Interop.Call('Kernel32.dll', 'RtlMoveMemory', lParam, pNmhdr.DataPtr, pNmhdr.Size);
PS: How are you subclassing the control? Dll? or are you just processing the notifications it sends to the parent window?
RE: WM_NOTIFY Help - (Noobs stay away! haha) by matty on 03-08-2007 at 10:50 PM
quote: Originally posted by deAd
code: var pNmhdr = Interop.Allocate(12); // if this is the wrong size sorry
Interop.Call('Kernel32.dll', 'RtlMoveMemory', pNmhdr.DataPtr, lParam, pNmhdr.Size);
// do stuff with pNmhdr
The members of the structure are still 0... I don't see why this isn't working
quote: Originally posted by deAd
PS: How are you subclassing the control? Dll? or are you just processing the notifications it sends to the parent window?
Processing messages to the parent.
RE: RE: WM_NOTIFY Help - (Noobs stay away! haha) by deAd on 03-08-2007 at 10:53 PM
quote: Originally posted by Matty
quote: Originally posted by deAd
PS: How are you subclassing the control? Dll? or are you just processing the notifications it sends to the parent window?
Processing messages to the parent.
Ok, cool Did you get it to work?
RE: WM_NOTIFY Help - (Noobs stay away! haha) by CookieRevised on 03-09-2007 at 12:55 AM
Matty? How did you do it then in SendTo? Doesn't that script use the NMHDR structure or somthing very similar too....?
quote: Originally posted by Matty
quote: Originally posted by deAd
code: var pNmhdr = Interop.Allocate(12); // if this is the wrong size sorry
Interop.Call('Kernel32.dll', 'RtlMoveMemory', pNmhdr.DataPtr, lParam, pNmhdr.Size);
// do stuff with pNmhdr
The members of the structure are still 0... I don't see why this isn't working
Because you've sent the notification message yourself:code: case WM_PARENTNOTIFY:
_sent_notify = true;
Interop.Call('user32', 'SendMessageW', _window.Handle,
WM_NOTIFY,
pPlusWnd.GetControlHandle('tvFiles'),
NMHDR.DataPtr);
but you don't fill the structure with the proper values.
----------------------
quote: Originally posted by Matty
So my dilemma is the website example says that lParam is the NMHDR structure however there would be no way to access the members of the structure.
I could be wrong, but I think you're confusing some things.
Anyways, some stuff about the NMHDR structure when it is send from a control by Windows itself:
lParam points to an _extended_ NMHDR structure. This means, in the OnWndAllContactsEvent_MessageNotification, you need to copy the entire structure in memory to a datablock. This is done with the RtlMoveMemory API, as you already know.
But before you do this, you first need to check several things, so you don't copy unallocated memory (as not every extended structure used by the specific notification messages is the same size). But the basic NMHDR structure is always 12 bytes long of course.
And thus depending on the code member of the structure, the structure will actually be x bytes bigger. The code member is that notification code. (thus of which each uses their own extended NMHDR structures. thus which all begin with the basic NMHDR structure again).
So, from "the top of my head" (almost, as I use this very same code "somewhere" already ):code: function OnWndAllContactsEvent_MessageNotification(pPlusWnd, nMessage, wParam, lParam) {
// Allocate enough memory immediatly for the extended structure we're going to use
var _NMHDR = Interop.Allocate(72);
// Copy only the basic needed members (at first)
// (<= come to think of it, this needs to be fixed in SendTo )
Interop.Call('Kernel32', 'RtlMoveMemory', _NMHDR.DataPtr, lParam, 12);
// Check the code member.
if (_NMHDR.ReadDWORD( 8) === /* LVN_BEGINLABELEDIT */ -175) {
// If it is the correct one, we can copy the rest of the needed bytes safely
Interop.Call('Kernel32', 'RtlMoveMemory', _NMHDR.DataPtr + 12, lParam + 12, 60);
Debug.Trace('0 HWND hwndFrom; ' + _NMHDR.ReadDWORD(0));
Debug.Trace('4 UINT idFrom; ' + _NMHDR.ReadDWORD(4));
Debug.Trace('8 UINT code; ' + _NMHDR.ReadDWORD( 8));
Debug.Trace('12 UINT mask; ' + _NMHDR.ReadDWORD(12));
Debug.Trace('16 int iItem; ' + _NMHDR.ReadDWORD(16));
Debug.Trace('20 int iSubItem; ' + _NMHDR.ReadDWORD(20));
Debug.Trace('24 UINT state; ' + _NMHDR.ReadDWORD(24));
Debug.Trace('28 UINT stateMask; ' + _NMHDR.ReadDWORD(28));
Debug.Trace('32 LPTSTR pszText; ' + _NMHDR.ReadDWORD(32));
Debug.Trace('36 int cchTextMax; ' + _NMHDR.ReadDWORD(36));
Debug.Trace('40 int iImage; ' + _NMHDR.ReadDWORD(40));
Debug.Trace('44 LPARAM lParam; ' + _NMHDR.ReadDWORD(44));
Debug.Trace('48 int iIndent; ' + _NMHDR.ReadDWORD(48));
Debug.Trace('52 int iGroupId; ' + _NMHDR.ReadDWORD(52));
Debug.Trace('56 UINT cColumns; ' + _NMHDR.ReadDWORD(56));
Debug.Trace('60 PUINT puColumns; ' + _NMHDR.ReadDWORD(60));
Debug.Trace('64 int* piColFmt; ' + _NMHDR.ReadDWORD(64));
Debug.Trace('68 int iGroup; ' + _NMHDR.ReadDWORD(68));
}
or in your case (which doesn't actually use an extended NMHDR structure though):code: case WM_NOTIFY:
_get_item(pPlusWnd);
if (_sent_notify == true){
Interop.Call('kernel32', 'RtlMoveMemory', NMHDR, lParam, 12);
Debug.Trace(NMHDR.ReadDWORD(0));
Debug.Trace(NMHDR.ReadDWORD( 8)); // this is your NM_CLICK, NM_DBLCLK, etc notification code
But of course, the members of the structure you read here are filled in by you (or rather, not filled in) so they just return what you've put there: nothing.
-----------
Part 2:
So what do you fill in in that NMHDR structure in the WM_PARENTNOTIFY case? That depends on the values of lparam and wparam. eg: if the low-order word of wParam is WM_LBUTTONDOWN, you should fill he structure with the appropiate handle of the control, the id, and NM_CLICK as code member.
But as far as double clicking goes, this needs to be detected by your own custom code. This means you need to catch two WM_LBUTTONDOWN's in a row in a certain time, and then you could fill in the NMHDR structure with NM_DBLCLK. In other words, if that event occurs, you would have recieved in the WM_NOTIFY case of your code 1 NM_CLICK and milliseconds later (depending on how long you set your timer to detect a doubleclick) one NM_DBLCLK. see WM_LBUTTONDBLCLK.
This brings up the fact that sending your own WM_NOTIFY message is actually useless, as you could just as well handled the double clicking (whatever the effect is you want) directly in the WM_PARENTNOTIFY case.
This said, and this might be a dumb comment, but why don't you use the WM_NOTIFY messages send from the control itself? They will contain all those specific notification messages already. Or aren't they send to the parent window for a TreeView? (I know some stuff for a listview isn't send to the parent either, so I wouldn't be surpised of it actually)...
RE: WM_NOTIFY Help - (Noobs stay away! haha) by Patchou on 03-09-2007 at 06:29 AM
hum.. there'S a lot of stuff here (btw Cookie, did you forget about WM_LBUTTONDBLCLK? ).
so, my first questio nwould be: what do you want to do exactly? because if you simply want to catch notifications sent from the treeview control, all you need to do is to catch WM_NOTIFY messages, cast lParam to a NMHDR structure and check if "code" is equal to NM_CLICK, NM_DBLCLK, etc...
RE: RE: WM_NOTIFY Help - (Noobs stay away! haha) by CookieRevised on 03-09-2007 at 10:45 AM
quote: Originally posted by Patchou
(btw Cookie, did you forget about WM_LBUTTONDBLCLK? ).
yes...
quote: Originally posted by Patchou
so, my first questio nwould be: what do you want to do exactly? because if you simply want to catch notifications sent from the treeview control, all you need to do is to catch WM_NOTIFY messages, cast lParam to a NMHDR structure and check if "code" is equal to NM_CLICK, NM_DBLCLK, etc...
quote: Originally posted by CookieRevised
This said, and this might be a dumb comment, but why don't you use the WM_NOTIFY messages send from the control itself? They will contain all those specific notification messages already.
|