TreeView com caixas de seleção e botões de opção

O componente TTreeView Delphi (localizado na guia da paleta de componentes "Win32") representa uma janela que exibe um lista hierárquica de itens, como os títulos em um documento, as entradas em um índice ou os arquivos e diretórios em um disco

Nó da árvore com caixa de seleção ou botão de opção?

O TTreeview do Delphi não suporta nativamente caixas de seleção, mas o controle WC_TREEVIEW subjacente. Você pode adicionar caixas de seleção ao vista da árvore substituindo o procedimento CreateParams do TTreeView, especificando o estilo TVS_CHECKBOXES para o controle. O resultado é que todos nós na árvore, haverá caixas de seleção anexadas a eles. Além disso, a propriedade StateImages não pode mais ser usada porque o WC_TREEVIEW usa essa lista de imagens internamente para implementar caixas de seleção. Se você deseja alternar as caixas de seleção, precisará fazer isso usando Enviar mensagem ou o Macros TreeView_SetItem / TreeView_GetItem a partir de CommCtrl.pas. O WC_TREEVIEW suporta apenas caixas de seleção, não botões de opção.

instagram viewer

A abordagem que você deve descobrir neste artigo é muito mais flexível: você pode ter caixas de seleção e botões de opção misturados com outros nós da maneira que desejar, sem alterar o TTreeview ou criar um novo classe para fazer isso funcionar. Além disso, você decide quais imagens usar para as caixas de seleção / botões de rádio simplesmente adicionando as imagens apropriadas à lista de imagens StateImages.

Adicionar uma caixa de seleção ou botão de opção

Ao contrário do que você possa acreditar, isso é bastante simples de realizar em Delphi. Aqui estão as etapas para fazê-lo funcionar:

  1. Configure uma lista de imagens (componente TImageList na guia da paleta de componentes "Win32") para o TTreeview. Propriedade StateImages que contém as imagens dos estados marcados e desmarcados para caixas de seleção e / ou botões de opção.
  2. Chame o procedimento ToggleTreeViewCheckBoxes (veja abaixo) nos eventos OnClick e OnKeyDown da exibição em árvore. O procedimento ToggleTreeViewCheckBoxes altera o StateIndex do nó selecionado para refletir o estado atual verificado / não verificado.

Para tornar sua visualização em árvore ainda mais profissional, verifique onde um nó é clicado antes de alternar as imagens de estado: alternando apenas o nó quando a imagem real é clicada, seus usuários ainda podem selecionar o nó sem alterar sua Estado.

Além disso, se você não quiser que seus usuários expandam / ocultem a visualização em árvore, chame o procedimento FullExpand no evento OnShow de formulários e defina AllowCollapse como false no evento OnCollapsing da visualização em árvore.

Aqui está a implementação do procedimento ToggleTreeViewCheckBoxes:

procedimento ToggleTreeViewCheckBoxes (
Nó: TTreeNode;
cUnChecked,
cVerificado,
cRadioUnchecked,
cRadioChecked: inteiro);
var
tmp: TTreeNode;
beginif Atribuído (Nó) thenbeginif Nó. StateIndex = cUnChecked então
Nó. StateIndex: = cChecked
outroE se Nó. StateIndex = cChecked então
Nó. StateIndex: = cUnChecked
senão se Nó. StateIndex = cRadioUnChecked então comece
tmp: = Nó. Pai;
se não Atribuído (tmp) então
tmp: = TTreeView (nó. TreeView) .Items.getFirstNode
outro
tmp: = tmp.getFirstChild;
enquanto Atribuído (tmp) dobeginif (tmp. StateIndex dentro
[cRadioUnChecked, cRadioChecked]) então
tmp. StateIndex: = cRadioUnChecked;
tmp: = tmp.getNextSibling;
fim;
Nó. StateIndex: = cRadioChecked;
fim; // se StateIndex = cRadioUnCheckedfim; // se atribuído (nó)
fim; (* ToggleTreeViewCheckBoxes *)

Como você pode ver no código acima, o procedimento inicia localizando todos os nós da caixa de seleção e ativando ou desativando-os. Em seguida, se o nó for um botão de opção desmarcado, o procedimento passará para o primeiro nó no nível atual, definirá todos os nós nesse nível para cRadioUnchecked (se forem nós cRadioUnChecked ou cRadioChecked) e, finalmente, alterna Node para cRadioChecked.

Observe como todos os botões de opção já verificados são ignorados. Obviamente, isso ocorre porque um botão de opção já marcado seria alternado para desmarcado, deixando os nós em um estado indefinido. Dificilmente o que você gostaria na maioria das vezes.

Veja como tornar o código ainda mais profissional: no evento OnClick da Treeview, escreva o código a seguir para alternar apenas o caixas de seleção se a imagem do estado foi clicada (as constantes cFlatUnCheck, cFlatChecked etc. são definidas em outros lugares como índices nas StateImages lista de imagens):

procedimento TForm1.TreeView1Click (Remetente: TObject);
var
P: TPoint;
início
GetCursorPos (P);
P: = TreeView1.ScreenToClient (P);
E se (htOnStateIcon dentro
TreeView1.GetHitTestInfoAt (P.X, P.Y)) então
ToggleTreeViewCheckBoxes (
TreeView1.Selected,
cFlatUnCheck,
cFlatChecked,
cFlatRadioUnCheck,
cFlatRadioChecked);
fim; (* TreeView1Click *)

O código obtém a posição atual do mouse, converte em coordenadas das árvores e verifica se o StateIcon foi clicado chamando a função GetHitTestInfoAt. Se fosse, o procedimento de alternância é chamado.

Principalmente, você esperaria que a barra de espaço alternasse caixas de seleção ou botões de opção, então veja como gravar o evento TreeView OnKeyDown usando esse padrão:

procedimento TForm1.TreeView1KeyDown (
Remetente: TObject;
var Chave: Word;
Shift: TShiftState);
beginif (Chave = VK_SPACE) e
Atribuído (TreeView1.Selected) então
ToggleTreeViewCheckBoxes (
TreeView1.Selected,
cFlatUnCheck,
cFlatChecked,
cFlatRadioUnCheck,
cFlatRadioChecked);
fim; (* TreeView1KeyDown *)

Por fim, veja como os eventos OnShow do formulário e OnChanging do Treeview podem parecer se você quiser impedir o colapso dos nós do treeview:

procedimento TForm1.FormCreate (Remetente: TObject);
início
TreeView1.FullExpand;
fim; (* FormCreate *)
procedimento TForm1.TreeView1Collapsing (
Remetente: TObject;
Nó: TTreeNode;
var AllowCollapse: Boolean);
início
AllowCollapse: = false;
fim; (* TreeView1Collapsing *)

Por fim, para verificar se um nó está marcado, basta fazer a seguinte comparação (no manipulador de eventos OnClick de um Button, por exemplo):

procedimento TForm1.Button1Click (Remetente: TObject);
var
BoolResult: booleano;
tn: TTreeNode;
beginif Atribuído (TreeView1.Selected) então comece
tn: = TreeView1.Selected;
BoolResult: = tn. StateIndex dentro
[cFlatChecked, cFlatRadioChecked];
Memo1.Text: = tn. Texto +
#13#10 +
'Selecionado:'
BoolToStr (BoolResult, True);
fim;
fim; (* Button1Click *)

Embora esse tipo de codificação não possa ser considerado de missão crítica, ele pode dar aos seus aplicativos uma aparência mais profissional e suave. Além disso, usando as caixas de seleção e os botões de opção criteriosamente, eles podem tornar seu aplicativo mais fácil de usar. Eles com certeza ficarão bem!

Esta imagem abaixo foi tirada de um aplicativo de teste usando o código descrito neste artigo. Como você pode ver, você pode misturar livremente nós com caixas de seleção ou botões de opção com aqueles que não possuem nenhum, embora não deva misturar nós "vazios" com "caixa de seleção"nós (dê uma olhada nos botões de opção na imagem), pois isso torna muito difícil ver quais nós estão relacionados.

instagram story viewer