Question

Dans une application C ++, un hWnd pointant vers une fenêtre s'exécutant dans un processus tiers. Cette fenêtre contient des contrôles qui étendent le contrôle COM TreeView. Je suis intéressé par l'obtention de l'état de contrôle de ce contrôle.
J'utilise hWnd pour obtenir un HTREEITEM à l'aide de TreeView_GetRoot (hwnd) à partir de commctrl.h

hwnd pointe vers la fenêtre et hItem est une valeur renvoyée par TreeView_GetRoot (hwnd). Ils sont utilisés comme suit:

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

Je souhaite transférer ce code dans une application C # qui fait la même chose (désactive le CheckState du contrôle TreeView). Je n'ai jamais utilisé COM et je ne suis pas très familier.

J'ai essayé d'utiliser le .NET mscomctl, mais je ne trouve pas de méthodes équivalentes à TreeView_GetRoot ou TreeView_GetCheckState. Je suis totalement coincé et je ne sais pas comment recréer ce code en C #: (

Des suggestions?

Était-ce utile?

La solution

Nous avons ces définitions 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)

Nous pouvons traduire cela en C # en utilisant PInvoke. Tout d'abord, nous implémentons ces macros en tant que fonctions, puis ajoutons ce que un autre support est nécessaire pour que ces fonctions fonctionnent. Voici mon premier coup. Vous devriez vérifier ma code surtout quand il s’agit du marshalling de la structure. De plus, vous voudrez peut-être publier le message en cross-thread au lieu d'appeler SendMessage.

Enfin, je ne sais pas si cela fonctionnera du tout, car j'estime que le commun les contrôles utilisent les messages WM_USER +. Lorsque ces messages sont envoyés inter-processus, les adresses du paramètre de données ne sont pas modifiés et le processus résultant peut provoquer une violation d'accès. Ce serait un problème dans tout le langage que vous utilisez (C ++ ou C #), alors je me trompe peut-être (vous dites que votre programme fonctionne C ++).

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

Autres conseils

Pourquoi n'utilisez-vous pas un contrôle Windows Forms TreeView? Si vous utilisez ce contrôle, définissez la propriété CheckBoxes du contrôle sur true pour activer les cases à cocher, puis définissez la propriété Checked sur les nœuds que vous souhaitez afficher cochés.

Pour obtenir la collection de nœuds racine, utilisez la propriété Nodes de TreeView. Cela renvoie une TreeNodeCollection sur laquelle vous pouvez ensuite indexer ou ajouter des éléments.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top