Pregunta

En una aplicación C++, tengo un hWnd que apunta a una ventana que se ejecuta en un proceso de terceros.Esta ventana contiene controles que amplían el control COM TreeView.Estoy interesado en obtener el CheckState de este control.
Utilizo hWnd para obtener un HTREEITEM usando TreeView_GetRoot(hwnd) de commctrl.h

hwnd apunta a la ventana y hItem es el valor de retorno de TreeView_GetRoot(hwnd).Se utilizan de la siguiente manera:

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

Estoy buscando trasladar este código a una aplicación C# que hace lo mismo (desactiva CheckState del control TreeView).Nunca he usado COM y no estoy muy familiarizado.

Intenté usar .NET mscomctl pero no puedo encontrar métodos equivalentes a TreeView_GetRoot o TreeView_GetCheckState.Estoy totalmente atascado y no sé cómo recrear este código en C# :(

¿Sugerencias?

¿Fue útil?

Solución

Tenemos estas definiciones 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 traducir esto a C# usando PInvoke.Primero, implementamos estas macros como funciones, y luego agregamos cualquier otro soporte necesario para que esas funciones funcionen.Aquí está mi primera oportunidad.Debe verificar mi código, especialmente cuando se trata del ensayador de la estructura.Además, es posible que desee publicar el mensaje cruzado en lugar de llamar a SendMessage.

Por último, no estoy seguro de si esto funcionará, ya que creo que los controles comunes usan mensajes WM_USER+.Cuando estos mensajes se envían de proceso transversal, las direcciones del parámetro de datos no están modificadas y el proceso resultante puede causar una violación de acceso.Esto sería un problema en cualquier idioma que use (C ++ o C#), así que tal vez me equivoque aquí (usted dice que tiene un programa de C ++ que funciona).

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;
}
}

Otros consejos

¿Por qué no utiliza un control TreeView de Windows Forms?Si está utilizando este control, establezca la propiedad CheckBoxes del control en verdadero para habilitar las casillas de verificación y establezca la propiedad Checked en los nodos que desea mostrar marcados.

Para obtener la colección de nodos raíz, utilice la propiedad Nodos de TreeView.Esto devuelve una TreeNodeCollection a la que luego puede indexar o agregar elementos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top