News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Why is ASSUME not ASSUMEing?

Started by georgek01, September 06, 2005, 02:46:14 PM

Previous topic - Next topic

georgek01

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?
What we have to learn to do, we learn by doing.

- ARISTOTLE (384-322 BC)

ToutEnMasm

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


georgek01

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.
What we have to learn to do, we learn by doing.

- ARISTOTLE (384-322 BC)

roticv

Maybe you discovered a bug in MASM?  :toothy

P1

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)

QvasiModo

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.

P1

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)

georgek01

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.
What we have to learn to do, we learn by doing.

- ARISTOTLE (384-322 BC)

georgek01

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.
What we have to learn to do, we learn by doing.

- ARISTOTLE (384-322 BC)

ToutEnMasm

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

                               


georgek01

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 lParam 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 - - -
What we have to learn to do, we learn by doing.

- ARISTOTLE (384-322 BC)

georgek01

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?
What we have to learn to do, we learn by doing.

- ARISTOTLE (384-322 BC)

ToutEnMasm

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


georgek01

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.
What we have to learn to do, we learn by doing.

- ARISTOTLE (384-322 BC)