2008-09-16 2 views
1

В приложении C++ у меня есть hWnd, указывающий на окно, выполняющееся в стороннем процессе. Это окно содержит элементы управления, которые расширяют элемент управления TreeView. Я заинтересован в получении CheckState этого элемента управления.
Я использую HWND, чтобы получить HTREEITEM используя TreeView_GetRoot (HWND) от commctrl.hПомощь портирование команд commctrl на C#

HWND пунктов к окну и hItem является возвращаемым значением из TreeView_GetRoot (HWND). Они используются следующим образом:

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

Я ищу порт этот код в приложение C#, который делает то же самое (выключает CheckState контроля TreeView). Я никогда не пользовался COM, и я совершенно незнакомый.

Я попытался использовать .NET mscomctl, но не могу найти эквивалентные методы для TreeView_GetRoot или TreeView_GetCheckState. Я полностью застрял и не знаю, как воссоздать этот код в C# :(

Предложение?

ответ

2

У нас есть эти определения из 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) 

Мы можем перевести это на C# с помощью PInvoke. Во-первых, мы реализуем эти макросы в качестве функций, а затем добавляем все, что необходимо для поддержки этих функций: . Вот мой первый снимок. Вы должны проверить мой код , особенно когда речь идет о сортировке структуры. Кроме того, вы можете отправить сообщение поперечной нитью вместо вызова SendMessage.

Наконец, я не уверен, что это будет работать вообще, поскольку я считаю, что общие элементы управления используют сообщения WM_USER +. Когда эти сообщения отправляются кросс-процессом, адреса данных данных не изменяются, и в результате процесс может вызвать нарушение доступа. Это было бы проблемой на любом используемом вами языке (C++ или C#), поэтому, возможно, я здесь не прав (вы говорите, что у вас есть работающая программа на 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; 
} 
} 
+0

Да, это сработало. – Kenn 2008-09-26 21:17:29

1

Почему вы не используете управление Windows Forms TreeView? Если вы используете этот контроль, установите Контрольный CheckBoxes, установите флажок «Истина для включения» и установите свойство Проверено на узлах, которые вы хотите отобразить.

Чтобы получить коллекцию корневых узлов, используйте свойство Nodes TreeView. Это возвращает TreeNodeCollection, который затем можно индексировать или добавить элементы.

+0

Окна принадлежат третьему лицу. Я не контролирую это. Создатель этого приложения решил реализовать элемент управления, используя расширение COM-объекта. – Kenn 2008-09-16 23:18:19

Смежные вопросы