1

C++ アプリでは、サード パーティのプロセスで実行されているウィンドウを指す hWnd があります。このウィンドウには、COM TreeView コントロールを拡張するコントロールが含まれています。このコントロールの CheckState を取得することに興味があります。
hWnd を使用して、commctrl.h から TreeView_GetRoot(hwnd) を使用して HTREEITEM を取得します。

hwnd はウィンドウを指し、hItem は TreeView_GetRoot(hwnd) からの戻り値です。それらは次のように使用されます。

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

このコードを、同じことを行う C# アプリに移植しようとしています (TreeView コントロールの CheckState をオフにします)。私は COM を使ったことがなく、まったくなじみがありません。

.NET mscomctl を使用してみましたが、TreeView_GetRoot または TreeView_GetCheckState に相当するメソッドが見つかりません。私は完全に立ち往生しており、C#でこのコードを再作成する方法がわかりません:(

提案?

4

2 に答える 2

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)

これを PInvoke を使用して C# に変換できます。まず、これらのマクロを関数として実装し、それらの関数を機能させるために必要なその他のサポートを追加します。これが私の最初のショットです。特に構造体のマーシャリングに関しては、私のコードを再確認する必要があります。さらに、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;
}
}
于 2008-09-17T03:52:08.223 に答える
1

Windows フォームの TreeView コントロールを使用しないのはなぜですか? このコントロールを使用している場合は、コントロールの CheckBoxes プロパティを true に設定してチェック ボックスを有効にし、チェックを表示するノードの Checked プロパティを設定します。

ルート ノードのコレクションを取得するには、TreeView の Nodes プロパティを使用します。これにより、アイテムのインデックス作成または追加が可能な TreeNodeCollection が返されます。

于 2008-09-16T23:10:22.660 に答える