Pergunta

Em um aplicativo C++, tenho um hWnd apontando para uma janela em execução em um processo de terceiros.Esta janela contém controles que estendem o controle COM TreeView.Estou interessado em obter o CheckState deste controle.
Eu uso o hWnd para obter um HTREEITEM usando TreeView_GetRoot(hwnd) de commctrl.h

hwnd aponta para a janela e hItem é o valor de retorno de TreeView_GetRoot (hwnd).Eles são usados ​​da seguinte forma:

int iCheckState = TreeView_GetCheckState(hwnd,  hItem);
switch (iCheckState)
{
   case 0:
      // (unchecked)
   case 1:
      // checked
   ...
}

Estou tentando portar esse código para um aplicativo C# que faz a mesma coisa (desativa o CheckState do controle TreeView).Nunca usei COM e não estou familiarizado.

Tentei usar o .NET mscomctl, mas não consigo encontrar métodos equivalentes a TreeView_GetRoot ou TreeView_GetCheckState.Estou totalmente preso e não sei como recriar esse código em C# :(

Sugestões?

Foi útil?

Solução

Temos estas definições de CommCtrl.h:

#define TreeView_SetItemState(hwndTV, hti, data, _mask) \
{ TVITEM _ms_TVi;\
  _ms_TVi.mask = TVIF_STATE; \
  _ms_TVi.hItem = (hti); \
  _ms_TVi.stateMask = (_mask);\
  _ms_TVi.state = (data);\
  SNDMSG((hwndTV), TVM_SETITEM, 0, (LPARAM)(TV_ITEM *)&_ms_TVi);\
}

#define TreeView_SetCheckState(hwndTV, hti, fCheck) \
  TreeView_SetItemState(hwndTV, hti, INDEXTOSTATEIMAGEMASK((fCheck)?2:1), TVIS_STATEIMAGEMASK)

Podemos traduzir isso para C# usando PInvoke.Primeiro, implementamos essas macros como funções e, em seguida, adicionamos qualquer outro suporte necessário para fazer com que essas funções funcionem.Aqui está minha primeira chance.Você deve verificar meu código, especialmente quando se trata do marechaling da estrutura.Além disso, você pode postar a mensagem cruzada em vez de chamar o SendMessage.

Por fim, não tenho certeza se isso funcionará, pois acredito que os controles comuns usam mensagens wm_user+.Quando essas mensagens são enviadas em processo cruzado, os endereços do parâmetro de dados não são modificados e o processo resultante pode causar uma violação de acesso.Isso seria um problema em qualquer idioma que você use (C ++ ou C#), então talvez eu esteja errado aqui (você diz que tem um programa C ++ em funcionamento).

static class Interop {

public static IntPtr TreeView_SetCheckState(HandleRef hwndTV, IntPtr hti, bool fCheck) {
    return TreeView_SetItemState(hwndTV, hti, INDEXTOSTATEIMAGEMASK((fCheck) ? 2 : 1), (uint)TVIS.TVIS_STATEIMAGEMASK);
}

public static IntPtr TreeView_SetItemState(HandleRef hwndTV, IntPtr hti, uint data, uint _mask) {
    TVITEM _ms_TVi = new TVITEM();
    _ms_TVi.mask = (uint)TVIF.TVIF_STATE;
    _ms_TVi.hItem = (hti);
    _ms_TVi.stateMask = (_mask);
    _ms_TVi.state = (data);
    IntPtr p = Marshal.AllocCoTaskMem(Marshal.SizeOf(_ms_TVi));
    Marshal.StructureToPtr(_ms_TVi, p, false);
    IntPtr r = SendMessage(hwndTV, (int)TVM.TVM_SETITEMW, IntPtr.Zero, p);
    Marshal.FreeCoTaskMem(p);
    return r;
}

private static uint INDEXTOSTATEIMAGEMASK(int i) { return ((uint)(i) << 12); }

[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(HandleRef hWnd, int msg, IntPtr wParam, IntPtr lParam);

private enum TVIF : uint {
    TVIF_STATE = 0x0008
}

private enum TVIS : uint {
    TVIS_STATEIMAGEMASK = 0xF000
}

private enum TVM : int {
    TV_FIRST = 0x1100,
    TVM_SETITEMA = (TV_FIRST + 13),
    TVM_SETITEMW = (TV_FIRST + 63)
}

private struct TVITEM {
    public uint mask;
    public IntPtr hItem;
    public uint state;
    public uint stateMask;
    public IntPtr pszText;
    public int cchTextMax;
    public int iImage;
    public int iSelectedImage;
    public int cChildren;
    public IntPtr lParam;
}
}

Outras dicas

Por que você não está usando um controle TreeView do Windows Forms?Se você estiver usando esse controle, defina a propriedade CheckBoxes do controle como true para habilitar as caixas de seleção e defina a propriedade Checked nos nós que deseja exibir marcados.

Para obter a coleção de nós raiz, use a propriedade Nodes do TreeView.Isso retorna um TreeNodeCollection ao qual você pode indexar ou adicionar itens.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top