Hi there,
I'm trying to get the lParam member from the TVITEM structure. This structure is pointed to by the NM_TREEVIEW message that gets sent via WM_NOTIFY.
From WIN32 API:
NM_TREEVIEW:
typedef struct _NM_TREEVIEW { nmtv
NMHDR hdr;
UINT action;
TV_ITEM itemOld;
TV_ITEM itemNew;
POINT ptDrag;
} NM_TREEVIEW;
typedef NM_TREEVIEW FAR *LPNM_TREEVIEW;
TVITEM:
typedef struct _TV_ITEM { tvi
UINT mask;
HTREEITEM hItem;
UINT state;
UINT stateMask;
LPSTR pszText;
int cchTextMax;
int iImage;
int iSelectedImage;
int cChildren;
LPARAM lParam;
} TV_ITEM, FAR *LPTV_ITEM;
I'm able to get the NM_DBLCLK value from [NM_TREEVIEW.hdr.code] using:
mov edi, lParam
assume edi:ptr NM_TREEVIEW
.if [edi].hdr.code == NM_DBLCLK
; something happens here
.endif
assume edi:NOTHING
Then, if the value == NM_DBCLICK I want to check the [NM_TREEVIEW.itemNew.lParam] value using:
mov edi, lParam
assume edi:ptr NM_TREEVIEW
.if [edi].hdr.code == NM_DBLCLK
assume edi:NOTHING
mov edi,lParam
assume edi:ptr NM_TREEVIEW
.if [edi].itemNew.lParam == 99d
; do something
.endif
.endif
assume edi:NOTHING
But this does not work.
The lParam value was assigned during TVM_INSERTITEM, I know this because I can successfully test for it using:
mov edi,lParam
assume edi:ptr NM_TREEVIEW
.if [edi].itemNew.lParam == 99d
; something does happen here
.else
; nothing happens here
.endif
assume edi:NOTHING
Why after using ASSUME for the second time does EDI not "take on" the ASSUME?
Hello,
The suit of messages is perhaps not complete.
First
.elseif uMsg == WM_NOTIFY
mov ebx, lParam ; Get pointer to NMHDR
mov eax, (NMHDR ptr [ebx]).code ;ex:TTN_NEEDTEXT ou EN_SELCHANGE
mov edx,(NMHDR ptr [ebx]).hwndFrom
second
.if eax == SomeMessage (that is said pointing on NM_TREEVIEW by winhelp)
(TVN_BEGINDRAG for example)
mov ecx,( NM_TREEVIEW ptr [ebx]).itemNew.lParam
ToutEnMasm
I replaced my code with:
mov ebx, lParam
mov eax, (NMHDR ptr [ebx]).code
.if eax == NM_DBLCLK
mov ecx,( NM_TREEVIEW ptr [ebx]).itemNew.lParam
.if ecx == 99d
; this does not work...
.endif
.endif
But this does not work either.
Maybe you discovered a bug in MASM? :toothy
Notification Messages in Win32 from MSDN Library
For controls that existed in Windows 3.1, the Win32 API uses most of the notification messages that were used in Windows 3.x. However, Win32 also adds a number of sophisticated, complex controls to those supported in Windows 3.x. Frequently, these controls need to send additional data with their notification messages. Rather than adding a new WM_* message for each new notification that needs additional data, the designers of the Win32 API chose to add just one message, WM_NOTIFY, which can pass any amount of additional data in a standardized fashion.
WM_NOTIFY messages contain the ID of the control sending the message in wParam and a pointer to a structure in lParam. This structure is either an NMHDR structure or some larger structure that has an NMHDR structure as its first member. Note that since the NMHDR member is first, a pointer to this structure can be used as either a pointer to an NMHDR or as a pointer to the larger structure depending on how you cast it.
In most cases, the pointer will point to a larger structure and you'll need to cast it when you use it. In only a few notifications, such as the common notifications (whose names start with NM_) and the tool tip control's TTN_SHOW and TTN_POP notifications, is an NMHDR structure actually used.
Just a guess, I don't see where you check for the ID in wParam. So how do you know this message is from this control versus another?
Note the Casting comment because of the conditional response of the passed structure.
Regards, P1 :8)
Hi :)
What is exactly the problem, is the code not assembling, or not running properly?
If it's not assembling it may help to show us what error code is MASM giving you.
If it's not running properly then the problem is not within MASM's "assume" directive. There could be a problem somewhere else, like P1 mentioned maybe you just forgot to check for the correct control ID.
Snipped from C:\Masm32\EXAMPLE7\TREEDEMO: Does not need the Assume statement.
.elseif wMsg == WM_NOTIFY
.if wParam == 44 ; Treeview
mov eax, lParam
mov ebx, (NM_TREEVIEW ptr [eax]).hdr.code
mov ecx, (NM_TREEVIEW ptr [eax]).itemNew.hItem
Hope this helps.
There is also another Treeview example in: C:\Masm32\ICZTUTES\TUTE19, which does use the Assume statement.
Regards, P1 :8)
QvasiModo,
The code does assemble - no errors.
With WM_NOTIFY, lParam points to the NM_TREEVIEW structure. Within this, the hdr member points to the NMHDR structure - from this I get NM_DBLCLK (code member). I test for this successfully.
Then I want to test for the lParam value. The NM_TREEVIEW member itemNew points to a TVITEM structure. This has the lParam member that I populate when I create the tree. This is the value I want to lastly test for.
If I ONLY test for either of these all works fine, but when I first test for NM_DBLCLK, I'm unable to get lParam value from TVITEM - it's as if the value was never populated.
I'm using lParam from the TVITEM structure to "hold" information about the tree node (similar to the TAG property in VB). Only specific tree nodes will be of interest, hence I want to check the value.
P1,
QuoteHope this helps.
Yes and no.
This code works:
.elseif uMsg == WM_NOTIFY
mov eax,lParam
mov ebx, (NM_TREEVIEW ptr [eax]).hdr.code
.if ebx == NM_DBLCLK
;mov eax, lParam
;mov ecx,( NM_TREEVIEW ptr [eax]).itemNew.lParam
;.if ecx == 99d
invoke MessageBox,hDlg,addr szReady, addr szReady,MB_OK
; message box appears only on double click
;.endif
.endif
This code works:
.elseif uMsg == WM_NOTIFY
;mov eax,lParam
;mov ebx, (NM_TREEVIEW ptr [eax]).hdr.code
;.if ebx == NM_DBLCLK
mov eax, lParam
mov ecx,( NM_TREEVIEW ptr [eax]).itemNew.lParam
.if ecx == 99d
invoke MessageBox,hDlg,addr szReady, addr szReady,MB_OK
; the message box appears twice - for key up and key down
.else
; code executes here correctly if lParam was not pupulated with 99d
.endif
;.endif
This does not work:
.elseif uMsg == WM_NOTIFY
mov eax,lParam
mov ebx, (NM_TREEVIEW ptr [eax]).hdr.code
.if ebx == NM_DBLCLK
mov eax, lParam
mov ecx,( NM_TREEVIEW ptr [eax]).itemNew.lParam
.if ecx == 99d
invoke MessageBox,hDlg,addr szReady, addr szReady,MB_OK
.else
; code executes here, even though lParam was populated with 99d
.endif
.endif
Testing each structure individually works fine, but when I combined them, it does not work as expected.
Hello,
Verifying the NM_DBLCLK with winhelp , I read
NM_DBLCLK
pnmh = (NMHDR FAR *) lParam;
The NM_DBLCLK provide only a pointer on NMHDR only,read the description of the message in winhelp,your code couldn't work .
Note:If you can put the litteral message in your code instead of it's numeric value,you can search more easily in winhelp and see the pointed structure.
ToutEnMasm
That's right:
http://msdn.microsoft.com/library/en-us/shellcc/platform/commctls/treeview/notifications/nm_dblclk_treeview.asp?frame=true
http://msdn.microsoft.com/library/en-us/shellcc/platform/commctls/treeview/notifications/nm_return_treeview.asp?frame=true
You'll have to deduce the item the user clicked on by sending a TVM_HITTEST message:
http://msdn.microsoft.com/library/en-us/shellcc/platform/commctls/treeview/messages/tvm_hittest.asp?frame=true
BTW, for the notification messages that send a TV_ITEM structure in it, always check the imask member to see if the data is really there.
ToutEnMasm,
Will this successfully test for
NM_DBLCLK?
.elseif uMsg == WM_NOTIFY
.if wParam == IDC_TREE
mov eax,lParam
mov ebx, (NM_TREEVIEW ptr [eax]).hdr.code
.if ebx == NM_DBLCLK
QuoteIf you can put the litteral message in your code instead of it's numeric value...
I'm not with you on this one. Numeric value? If you referring to the
99d, that's the value I give to l
Param when I create the node...
mov tvinsert.hParent,eax
mov tvinsert.hInsertAfter,TVI_LAST
mov tvinsert.item.imask, [b]TVIF_PARAM[/b] or TVIF_IMAGE or TVIF_SELECTEDIMAGE or TVIF_TEXT
[b]mov eax, 99d
mov tvinsert.item.lParam, eax[/b]
mov eax, ico
mov tvinsert.item.iImage,eax
mov tvinsert.item.iSelectedImage,eax
mov tvinsert.item.pszText, offset myIncident
invoke SendMessage,hTrv,TVM_INSERTITEM,0,addr tvinsert
...or am I misunderstanding you completely?
QvasiModo,
How does
TVM_HITTEST help me get to the value (in this case 99d) I assigned to
lParam during
TVM_INSERTITEM? Should I be using the
hItem member from
TV_HITTESTINFO?
Quote...always check the imask member to see if the data is really there
As per my code above, I set the
TVIF_PARAM flag indicating I want
lParam to be available.
Win32 API:
typedef struct _NM_TREEVIEW { nmtv
NMHDR hdr;
UINT action;
TV_ITEM itemOld;
TV_ITEM itemNew;
POINT ptDrag;
} NM_TREEVIEW;
typedef NM_TREEVIEW FAR *LPNM_TREEVIEW;
I should be able to get to all the infrmation in this structure during
WM_NOTIFY, and all the information pointed to by the pointers in this structure.
I am able to seperately test for
NM_DBLCLK and I am able to test for the value I assigned during
TVM_INSERTITEM - but when I combined the two tests, it does not test for the value I assigned duing
TVM_INSERTITEM.
All I want is after the user double clicked a tree node, to know if the lParam of the clicked node == 99d (or anything else I decide to assign it).
- - - If I'm frustrating you it must be because I'm frustrated myself! Thank you for the assistance. :U - - -
Once I've check for TVN_SELCHANGED, the code works fine, but not once I've check for NM_DBLCLK.
.elseif uMsg == WM_NOTIFY
.if wParam == IDC_TREE
; check which node was selected
mov eax,lParam
mov ebx, (NM_TREEVIEW ptr [eax]).hdr.code
.if ebx == NM_DBLCLK
mov eax, lParam
mov ecx,(NM_TREEVIEW ptr [eax]).itemNew.lParam
.if ecx == 99d ; - - - this does not work!!
invoke MessageBox,hDlg,addr szReady, addr szReady,MB_OK
.endif
.elseif ebx == TVN_SELCHANGED
mov eax, lParam
mov ecx,(NM_TREEVIEW ptr [eax]).itemNew.lParam
.if ecx == 99d ; - - - this works fine!
invoke MessageBox,hDlg,addr szReady, addr szReady,MB_OK
.endif
.elseif ebx == TVN_ITEMEXPANDED
;...
.endif
.endif
So, this tells me my code works fine - only thing is I need to check after a double click. Any guesses why I'm able to get information from the TV_ITEM structure after a selection change but not a double click?
Hello,
I can try to say you the same thing than my two others mails in another way.
The windows message WM_NOTIFY grant you a pointer To NMHDR.
Messages provided by NMHDR.code grant you nothing more.
You must read winhelp to know the additionnal structures for a particular message.
Perhaps, there is more than NMHDR , perhaps not,only winhelp can answer.
If you haven't winhelp , search this site for a link (it's also on my site)
ToutEnMasm
ToutEnMasm,
As you suggested I looked at the Win32 API documentation regarding treeview messages.
QuoteMessages provided by NMHDR.code grant you nothing more.
Yes, this member gives me what I want, nl NM_DBLCLK.
I'm working with two structures, nl NMHDR and TV_ITEM - both found in NM_TREEVIEW.
After I successully test for NM_DBLCLK, I want to look at one of the other members/structure of NM_TREEVIEW, nl itemNew.
WM_NOTIFY (lParam) points to NM_TREEVIEW.
typedef struct _NM_TREEVIEW { nmtv
NMHDR hdr;
UINT action;
TV_ITEM itemOld;
TV_ITEM itemNew;
POINT ptDrag;
} NM_TREEVIEW;
typedef NM_TREEVIEW FAR *LPNM_TREEVIEW;
NMHDR is a member of NM_TREEVIEW that points to the following structure:
typedef struct tagNMHDR {
HWND hwndFrom;
UINT idFrom;
UINT code;
} NMHDR;
From WIN32API:
Quote
code
Specifies the notification code. This member can be a control-specific notification code, or it can be one of the following common notification values:
...
NM_DBLCLK The user has double-clicked the left mouse button within the control.
...
I successfully test for NM_DBLCLK.
Now I want to look at the itemNew member of NM_TREEVIEW, just as I checked for NM_DBLCLK.
The structure looks like this:
typedef struct _TV_ITEM { tvi
UINT mask;
HTREEITEM hItem;
UINT state;
UINT stateMask;
LPSTR pszText;
int cchTextMax;
int iImage;
int iSelectedImage;
int cChildren;
LPARAM lParam;
} TV_ITEM, FAR *LPTV_ITEM;
From Win32API:
Quote
lParam
A 32-bit value to associate with the item.
This member I fill when I create the tree node. Ultimately, this is what I'm after.
I can get to it if I first test for TVN_SELCHANGED, but not when I first test for NM_DBLCLK.
Quote from: georgek01 on September 08, 2005, 02:32:22 PM
WM_NOTIFY (lParam) points to NM_TREEVIEW.
What ToutEnMasm is trying to tell you is that when a WM_NOTIFY message arrives and NMHDR.code is NM_DBLCLK, the lParam parameter
doesn't point to a NM_TREEVIEW structure, but only to an NMHDR one. You can't access the "other members" of NM_TREEVIEW because
what you're reading is not an NM_TREEVIEW structure.
Oh!!! :red
ToutEnMasm, I apologise profusely!
Seems I'll have to live with TRV_SELCHANGED only.
Thanks for all the assistance!
Quote from: georgek01 on September 08, 2005, 05:45:41 AM
How does TVM_HITTEST help me get to the value (in this case 99d) I assigned to lParam during TVM_INSERTITEM? Should I be using the hItem member from TV_HITTESTINFO?
Since NM_DBLCLK doesn't give you any more info, you can try to deduce on what item has the user clicked from the mouse coordinates. The TVM_HITTEST message takes the mouse coordinates as a parameter and returns the item.
Quote from: georgek01 on September 08, 2005, 05:45:41 AM
Quote...always check the imask member to see if the data is really there
As per my code above, I set the TVIF_PARAM flag indicating I want lParam to be available.
Sorry, I should have been more specific. I meant that when you get an NM_TREEVIEW structure you should read the imask member to see which members of iItem were set by the system.
Hope this helps! :U
Thanks, I'll give it a try!
Quote from: georgek01 on September 08, 2005, 07:09:21 AM
Once I've check for TVN_SELCHANGED, the code works fine, but not once I've check for NM_DBLCLK. ...Any guesses why I'm able to get information from the TV_ITEM structure after a selection change but not a double click?
Another, roundabout idea to detect a double-click might be detecting single-clicks while waiting for a timer. Something like this:
mov doubleclk,0
; single-click detected here
.if doubleclk==1
; double-click detected here
.else
mov doubleclk,1 ; flag as clicked once
invoke SetTimer,hWnd,111,1000 ; 1 second
.elseif eax==WM_TIMER ; timer expire routine
mov eax,wParam
.if eax==111
mov doubleclk,0 ; reset flag when timer expires
invoke KillTimer,hWnd,111
.endif
.endif
Double clicks are not just two clicks in a short time, they also have to happen within certain a distance. Well, actually the system uses a rectangle, but you get the idea :wink two quick clicks anywhere on the screen do not always make a double click.
In any case the problem is not that doubleclicks are not being detected, but that the NM_DBLCLK notification doesn't contain all the information we'd like. So we have to deduce some information from the mouse position instead. :)
Try this..
[attachment deleted by admin]
Ted, may I call you genius? :U Thanks dude!
:red hehe
No problem :U