Помощь при переносе команд commctrl на C # - PullRequest
1 голос
/ 17 сентября 2008

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

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 ]

2 голосов
/ 17 сентября 2008

У нас есть следующие определения из 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;
}
}
1 голос
/ 17 сентября 2008

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...