Reputation: 49
I'm trying to programatically check a custom checkbox in a treeview. What I mean by custom, is that I call the below code to enable these checkboxes:
SetWindowLong(TreeView1.Handle, GWL_STYLE, GetWindowLong(TreeView1.Handle, GWL_STYLE) or TVS_CHECKBOXES)
I tried the below code to check it, but it did not work.
Node := TreeView1.Selected;
TVItem.mask := TVIF_STATE;
TVItem.hItem := Node.ItemId;
TreeView_GetItem(Node.TreeView.Handle, TVItem);
TVItem.stateMask := TVIS_CHECKED;
TVItem.mask := TVIS_CHECKED;
Thanks in advance
Upvotes: 1
Views: 1130
Reputation: 3602
What do you have TVIS_CHECKED defined as? It should be:
const
TVIS_CHECKED = $2000;
Then, assuming Value is a Boolean of whether or not the item is checked:
FillChar(TVItem, SizeOf(TVItem), 0);
TVItem.hItem := Node.ItemId;
TVItem.mask := TVIF_STATE;
TVItem.stateMask := TVIS_STATEIMAGEMASK;
if Value then
TVItem.state := TVIS_CHECKED
else
TVItem.state := TVIS_CHECKED shr 1;
TreeView_SetItem(Node.Handle, TVItem);
Upvotes: 1
Reputation: 54792
You have your state mask wrong, there's no TVIS_CHECKED
state mask (in fact there is no TVIS_CHECKED
, more on that later). Check boxes are managed through an image list, this is explained in the documentation.
Additionally, of course, you have to call TreeView_SetItem
:
const
TVIS_CHECKED = 2 shl 12;
var
Node: TTreeNode;
TVItem: TTVItem;
begin
Node := TreeView1.Selected;
if Assigned(Node) then begin
TVItem.mask := TVIF_STATE;
TVItem.hItem := Node.ItemId;
TreeView_GetItem(Node.TreeView.Handle, TVItem);
TVItem.stateMask := TVIS_STATEIMAGEMASK;
TVItem.state := TVIS_CHECKED;
TreeView_SetItem(Node.TreeView.Handle, TVItem);
end;
end;
TreeView_SetCheckState
but the VCL has got a weird error in the translation of the macro.
This is the macro in the header:
#define TreeView_SetCheckState(hwndTV, hti, fCheck) \
TreeView_SetItemState(hwndTV, hti, INDEXTOSTATEIMAGEMASK((fCheck)?2:1), TVIS_STATEIMAGEMASK)
where
#define INDEXTOSTATEIMAGEMASK(i) ((i) << 12)
This is why the made-up TVIS_CHECKED
is $2000, the define shifts 2 12 bits left when fCheck
is true (2 is the index of the checked image, 1 is unchecked).
This is VCL's translation:
function TreeView_SetCheckState(hwndTV: HWND; hti: HTreeItem; fCheck: BOOL): UINT;
var
LState: UINT;
begin
if IndexToStateImageMask(Integer(fCheck)) = 0 then
LState := 1
else
LState := 2;
Result := TreeView_SetItemState(hwndTV, hti, LState, TVIS_STATEIMAGEMASK);
where IndexToStateImageMask
is
Result := I shl 12;
Strangely, the VCL shifts fCheck
12 bits and then calls TreeView_SetItemState
with a state that makes no sense for a state image mask (TVIS_FOCUSED
(1), TVIS_SELECTED
(2)).
This is XE2, I suggest to test the macro first if you are working with a later version.
Upvotes: 4