2008-09-16 16 views
1

Dans une application C++, j'ai un hWnd pointant vers une fenêtre exécutée dans un processus tiers. Cette fenêtre contient des contrôles qui étendent le contrôle COM TreeView. Je suis intéressé à obtenir le CheckState de ce contrôle.
J'utilise le hWnd pour obtenir une HTREEITEM en utilisant TreeView_GetRoot (HWND) de Commctrl.hAssistance portage des commandes commctrl en C#

points de HWND à la fenêtre et hItem est la valeur de retour TreeView_GetRoot (hwnd). Ils sont utilisés comme suit:

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

Je cherche au port 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 familier.

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

Suggestions?

Répondre

2

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 ceci en C# en utilisant PInvoke. Tout d'abord, nous implémentons ces macros en tant que fonctions, puis nous ajoutons autre support nécessaire pour que ces fonctions fonctionnent. Voici ma première photo. Vous devriez vérifier mon code en particulier quand il s'agit de la formation de la structure. En outre, vous pouvez afficher le message cross-thread au lieu d'appeler SendMessage.

Enfin, je ne sais pas si cela fonctionnera du tout puisque je crois que les contrôles communs utilisent WM_USER + messages. Lorsque ces messages sont envoyés entre processus, les adresses du paramètre de données ne sont pas modifiées et le processus résultant peut provoquer une violation d'accès. Ce serait un problème quel que soit le langage utilisé (C++ ou C#), donc peut-être que je me trompe ici (vous dites que vous avez un programme C++ fonctionnel).

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

Oui, cela a fonctionné. – Kenn

1

Pourquoi vous n'utilisez pas un contrôle Windows Forms TreeView? Si vous utilisez ce contrôle, réglez de la commande Vérifiez la propriété CheckBoxes à true pour activer les cases à cocher et définissez la propriété Checked sur les nœuds que vous souhaitez afficher

Pour obtenir la collection de nœuds racine, utilisez la propriété Nœuds de TreeView.Cela retourne une TreeNodeCollection que vous pouvez ensuite indexer ou ajouter des éléments à

+0

La fenêtre est détenue par un tiers. Je n'ai aucun contrôle sur cela. Le fabricant de cette application a choisi d'implémenter le contrôle en utilisant une extension de l'objet COM. – Kenn