Link to home
Start Free TrialLog in
Avatar of SkyWalker
SkyWalker

asked on

Extrating Tree view data using win32api, HELP!!!

trying to retrieve nodes' text in a tree view object from a different application. I have manage to get the window handle of the object but do not know how to get the data in the tree view, class found is systreeview32.
Avatar of SkyWalker
SkyWalker

ASKER

I would like to thank you very very much in advance, this thing has been giving me problem for the past few weeks.

Thanks again and regards...
There are no direct API-calls for doing this. You'll have to
send messages to the control. Here's are messages, the constants and the Type you need (it's not in the API textviewer, I directly translated it from the C++ header).

const TV_FIRST      &h1100
const TVM_GETITEMA (TV_FIRST + 12)
const TVM_GETITEM  TVM_GETITEMA
const TVM_GETNEXTITEM    (TV_FIRST + 10)
const TVGN_ROOT               &h0000
const TVGN_NEXT               &h0001
const TVGN_PREVIOUS           &h0002
const TVGN_PARENT             &h0003
const TVGN_CHILD              &h0004
const TVGN_FIRSTVISIBLE       &h0005
const TVGN_NEXTVISIBLE        &h0006
const TVGN_PREVIOUSVISIBLE    &h0007
const TVGN_DROPHILITE         &h0008
const TVGN_CARET              &h0009

const TVIF_TEXT               &h0001
const TVIF_IMAGE              &h0002
const TVIF_PARAM              &h0004
const TVIF_STATE              &h0008
const TVIF_HANDLE             &h0010
const TVIF_SELECTEDIMAGE      &h0020
const TVIF_CHILDREN           &h0040

const I_CHILDRENCALLBACK  (-1)


Type TV_ITEM      'Maybe the Integers should also be Longs...
    mask as Long
    hItem as Long
    state as Long
    stateMask as Long
    pszText as String
    cchTextMax as Integer
    iImage as Integer
    iSelectedImage as Integer
    cChildren as Integer
    lParam as Long
End Type


TVM_GETNEXTITEM
wparam = flag   'See above, all that begin with TVGN
lParam = hItem  'See below. It's a long

Use it with TVGN_ROOT to get the root item (set hItem to Null). It retruns an hItem which you can use with subsequent calls to TVM_GETNEXTITEM.


TVM_GETITEM
wParam = 0
lParam = pitem  (TV_ITEM Type)
This message returns TRUE if succesfull, FALSE otherwise. Below a copy of microsofts reference about TV_ITEM.

The TV_ITEM structure specifies or receives attributes of a tree-view item.

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;
 

MEMBERS
***********************
mask

Array of flags that indicate which of the other structure members contain valid data. When this structure is used with the TVM_GETITEM message, the mask member indicates the item attributes to retrieve. This member can be a combination of the following values:
 
TVIF_CHILDREN  The cChildren member is valid.
 
TVIF_HANDLE  The hItem member is valid.
 
TVIF_IMAGE  The iImage member is valid.
 
TVIF_PARAM  The lParam member is valid.
 
TVIF_SELECTEDIMAGE  The iSelectedImage member is valid.
 
TVIF_STATE  The state and stateMask members are valid.
 
TVIF_TEXT  The pszText and cchTextMax members are valid.
 


hItem
Identifies the item to which this structure refers.

state
A set of bit flags and image list indexes that indicate the item’s state. For a list of item state bit flags, see Tree-View Item States. For information about the state image and overlay image indexes, see Tree-View Image Lists.
When setting the state of an item, the stateMask member indicates the bits of the state member that are valid. When retrieving the state of an item, the state member returns the current state for the bits indicated in the stateMask member.

stateMask
Specifies the bits of the state member that are valid.

pszText
Pointer to a null-terminated string that contains the item text if the structure specifies item attributes. If this member is the LPSTR_TEXTCALLBACK value, the parent window is responsible for storing the name. In this case, the tree-view control sends the parent window a TVN_GETDISPINFO notification message when it needs the item text for displaying, sorting, or editing, and a TVN_SETDISPINFO notification message when the item text changes.
If the structure is receiving item attributes, this member is the pointer to the buffer that receives the item text.

cchTextMax
Size of the buffer pointed to by the pszText member if the structure is receiving item attributes. If the structure specifies item attributes, this member is ignored.

iImage
Index in the tree-view control’s image list of the icon image to use when the item is in the non-selected state.
If this member is the I_IMAGECALLBACK value, the parent window is responsible for storing the index. In this case, the tree-view control sends the parent a TVN_GETDISPINFO notification message to get the index when it needs to display the image.

iSelectedImage
Index in the tree-view control’s image list of the icon image to use when the item is in the selected state.
If this member is the I_IMAGECALLBACK value, the parent window is responsible for storing the index. In this case, the tree-view control sends the parent a TVN_GETDISPINFO notification message to get the index when it needs to display the image.

cChildren
Flag that indicates whether the item has associated child items. This member is one of the following values:

zero  The item has no child items.
 
1  The item has one or more child items.
 
I_CHILDRENCALLBACK  The parent window keeps track of whether the item has child items. In this case, when the tree-view control needs to display the item, the control sends the parent a TVN_GETDISPINFO notification message to determine whether the item has child items.
 
If the tree-view control has the TVS_HASBUTTONS style, it uses this member to determine whether to display the button indicating the presence of child items. You can use this member to force the control to display the button even though the item does not have any child items inserted. This allows you to display the button while minimizing the control’s memory usage by inserting child items only when the item is visible or expanded.


lParam
A 32-bit value to associate with the item.


********************************
REMARKS
This structure is used with the TVM_GETITEM, TVM_SETITEM, and TVM_INSERTITEM messages. It is also included with many of the notification messages. When the structure is used to retrieve item information, only the structure members indicated by mask contain valid data. All other members are invalid.



*************************************
*************************************
Use SendMessage when you try these things. If you have trouble implementing it, post your comments, and I'll try to help you further.

Regards, Abel

BTW, I'm not completely sure if you can retrieve the properties of an item with TV_GETITEM from withing VB. The TV_ITEM is a far pointer, and I don't know how VB handles that. Unfnortunately, this is the only way to get to the text and other properties of a treeview's item.
Good luck! (you'll need it. Doing these things is much easier in C++)
ASKER CERTIFIED SOLUTION
Avatar of abel
abel
Flag of Netherlands image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Also as comment?????
Oops, this way it's getting a really long thread... :-)
Sorry. (not my fault)
Abel, thanks very much for your reply. I've tried the codes but I couldn't get it working in VB, I didn't get any error though. I was trying to sendmessage to the window handle with TVM_GETITEM as the message, pitem (Dim type TV_ITEM) as lparam, the return I got was "0". I don't know if it is too much to ask for the portion of codes in VB.

I am not so farmiliar with C++, but I wouldn't mind using it if I can get more help from you. Never mind, forget it, I'm going to take too much of your time. Thanks again and regards...
Abel, thanks very much for your reply. I've tried the codes but I couldn't get it working in VB, I didn't get any error though. I was trying to sendmessage to the window handle with TVM_GETITEM as the message, pitem (Dim type TV_ITEM) as lparam, the return I got was "0". I don't know if it is too much to ask for the portion of codes in VB.

I am not so farmiliar with C++, but I wouldn't mind using it if I can get more help from you. Never mind, forget it, I'm going to take too much of your time. Thanks again and regards...
Somewhere I must have these things already implemented in C++. I can look it up and post it here when I find it. What C++ package do you have? I've used C++ 5 with MFC to do the trick.
You say you can't get it to work, but did you first call TVM_GETNEXTITEM? You must use it to get a handle to the root item. You also have to use it every time you browse to the next item in the treeview. The handle you get from TVM_GETNEXTITEM must be used with TVM_GETITEM, which retrieves the properties of the item (like the text) for you.

Let me know if you want me to help you further (that's why I'm here, ain't I?)

Regards, Abel
Dear Abel, I have tried it again but still couldn't get it work. Here's the code I have.

    hwnd = FindWindow(vbNullString, "Tree View")
    nChildHandle = GetWindow(hwnd, 5)
    nLong = SendMessage(nChildHandle, TVM_GETNEXTITEM, TVGN_ROOT, 0)
    pItem.hItem = nLong
    pItem.mask = TVIF_TEXT
    nLong = SendMessage(nChildHandle, TVM_GETITEM, 0, pItem)
    MsgBox nLong
    MsgBox pItem.pszText

I got nLong = 1 after sendmessage if pItem.mask is not set to TVIF_TEXT.
The result I'm getting when assigning pItem.mask to TVIF_TEXT is GPF in COMCTL32.OCX.
Could you please advice.
Thanks and regards...
A few remarks to your code:

nChildHandle = GetWindow(hwnd, 5)
'This does not work when the TreeView-childwindow is not the first child. You should loop and check your windows with GetClassName. (in further evaluation I assume nChildHandle is correct)

nLong = SendMessage(nChildHandle, TVM_GETNEXTITEM, TVGN_ROOT, 0)
'Should return a valid handle to an item. Check the return value for zero.

pItem.hItem = nLong
pItem.mask = TVIF_TEXT
'Correct, but add the following two lines:

pItem.pszText = Space(65)
pItem.cchTextMax = 64
'These two lines are the key to your GPF in COMCTL32.OCX. The GPF means that some treeview function attempt to write to an undefined place in memory. this way you define that place and "allocate" it.

nLong = SendMessage(nChildHandle, TVM_GETITEM, 0, pItem)
'Correct when the above changes are made. Check return value for being zero (meaning a problem).


This should do the trick. If not, try to get some other masks (without TVIF_TEXT) and see if they (at least) work. Then we know where to work on.

Let me know if you have any new results.

Regards, Abel
BTW. the classname returned from GetClassName should be "SysTreeView32"
Dear abel,
   Thank you very very much for your help, I have successfully got the texts from a tree view object. May I ask for the messages to select a node, click and double click a node of a tree view object? Do I need to get these nodes' ID before sending these messages? If I do, would you mind telling me how?
   Thanks in advance and regards...
Oh boy, I really have to apologize for posting another question before the previous one was answered. It is not as easy as what I thought. I have got the text of the root node. I tried to get the children of that node and the next node at the same level, but I couldn't seem to get it work. Here's the tree structure:

Father
   - Son 1
   - Son 2
   - Son 3
Mother

I used tvm_getnextitem with tvgn_root and managed to get the text "father". Then I have this code
nLong = SendMessage(nChildHandle, TVM_GETNEXTITEM, TVGN_CHILD, nLong) 'I have got nLong from previous call
the text I have got this time is still "father". Then I tried
nLong = SendMessage(nChildHandle, TVM_GETNEXTITEM, TVGN_NEXT, nLong)
and this time I got blank.


I have updated pItem.hItem accordingly.

A million thanks to you, abel, and my regards...
Type TV_ITEM      'Maybe the Integers should also be Longs...

Exactly, the Type define is wrong, those Integers should be Longs.  Might just fixh your child issues.