使用WinAPI设置ListViewItem的Checked状态

时间:2016-05-10 18:39:35

标签: c# listview winapi

我有以下代码,我试图用来检查和取消选中列表视图中的项目。在所有内容下,检查功能似乎正常。问题是取消选中功能不起作用,并且检查已检查的项目只会使复选框可见而不触发已检查的事件或取消选中该框。我发现的一切都告诉我这应该有效,但我无法在这里提出一个有效的解决方案。任何人都可以解释为什么0x1000没有取消选中这些项目以及为什么复选框对我不可见?

谢谢

  public class NativeMethods
  {
    private const int LVM_FIRST = 0x1000;
    private const int LVM_SETITEMSTATE = LVM_FIRST + 43;

    private const int LVIF_STATE = 0x8;

    private const int LVIS_UNCHECKED = 0x1000;
    private const int LVIS_CHECKED = 0x2000;
    private const int LVIS_CHECKEDMASK = 0x3000;

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public struct LVITEM
    {
      public int mask;
      public int iItem;
      public int iSubItem;
      public int state;
      public int stateMask;
      [MarshalAs(UnmanagedType.LPTStr)]
      public string pszText;
      public int cchTextMax;
      public int iImage;
      public IntPtr lParam;
      public int iIndent;
      public int iGroupId;
      public int cColumns;
      public IntPtr puColumns;
    };

    [DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]
    public static extern IntPtr SendMessageLVItem(IntPtr hWnd, int msg, int wParam, ref LVITEM lvi);

    /// <summary>
    /// Check all rows on the given listview
    /// </summary>
    /// <param name="list">The listview whose items are to be checked</param>
    public static void CheckAllItems(ListView list)
    { // -1 index means all items in the list
      SetItemState(list, -1, LVIS_CHECKED, LVIS_CHECKEDMASK);
    }

    /// <summary>
    /// Uncheck all rows on the given listview
    /// </summary>
    /// <param name="list">The listview whose items are to be unchecked</param>
    public static void UncheckAllItems(ListView list)
    { // -1 index means all items in the list
      SetItemState(list, -1, LVIS_UNCHECKED, LVIS_CHECKEDMASK);
    }

    /// <summary>
    /// Set the item state on the given item
    /// </summary>
    /// <param name="list">The listview whose item's state is to be changed</param>
    /// <param name="itemIndex">The index of the item to be changed</param>
    /// <param name="mask">Which bits of the value are to be set?</param>
    /// <param name="value">The value to be set</param>
    public static void SetItemState(ListView list, int itemIndex, int mask, int value)
    {
      LVITEM lvItem = new LVITEM();
      lvItem.mask = LVIF_STATE;
      lvItem.stateMask = mask;
      lvItem.state = value;
      SendMessageLVItem(list.Handle, LVM_SETITEMSTATE, itemIndex, ref lvItem);
    }
  }

修改

我在这里仔细检查了行为,当我选择&#34;全部检查&#34;对于未选中的项目和&#34;取消选中全部&#34;对于已检查的项目。它们变得无形。 &#34;取消选中所有&#34;不会将项目从选中更改为未选中,但显然是正确的状态,因为选择&#34;取消全选&#34;没有检查项目结果根本没有变化。对于&#34;全选&#34;同样如此。当所有项目都已被检查时。

1 个答案:

答案 0 :(得分:0)

我在这里为我的错误道歉。我切换了掩码和值,所以这是正确的解决方案:

public class NativeMethods
{
  private const int LVM_FIRST = 0x1000;
  private const int LVM_SETITEMSTATE = LVM_FIRST + 43;

  private const int LVIS_UNCHECKED = 0x1000;
  private const int LVIS_CHECKED = 0x2000;
  private const int LVIS_STATEIMAGEMASK = 0x3000;

  [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
  public struct LVITEM
  {
    public int mask;
    public int iItem;
    public int iSubItem;
    public int state;
    public int stateMask;
    [MarshalAs(UnmanagedType.LPTStr)]
    public string pszText;
    public int cchTextMax;
    public int iImage;
    public IntPtr lParam;
    public int iIndent;
    public int iGroupId;
    public int cColumns;
    public IntPtr puColumns;
  };

  [DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]
  public static extern IntPtr SendMessageLVItem(IntPtr hWnd, int msg, int wParam, ref LVITEM lvi);

  /// <summary>
  /// Select all rows on the given listview
  /// </summary>
  /// <param name="list">The listview whose items are to be selected</param>
  public static void CheckAllItems(ListView list)
  {
    SetItemState(list, -1, LVIS_STATEIMAGEMASK, LVIS_CHECKED);
  }

  /// <summary>
  /// Deselect all rows on the given listview
  /// </summary>
  /// <param name="list">The listview whose items are to be deselected</param>
  public static void UncheckAllItems(ListView list)
  {
    SetItemState(list, -1, LVIS_STATEIMAGEMASK, LVIS_UNCHECKED);
  }

  /// <summary>
  /// Set the item state on the given item
  /// </summary>
  /// <param name="list">The listview whose item's state is to be changed</param>
  /// <param name="itemIndex">The index of the item to be changed</param>
  /// <param name="mask">Which bits of the value are to be set?</param>
  /// <param name="value">The value to be set</param>
  public static void SetItemState(ListView list, int itemIndex, int mask, int value)
  {
    LVITEM lvItem = new LVITEM();
    lvItem.stateMask = mask;
    lvItem.state = value;
    SendMessageLVItem(list.Handle, LVM_SETITEMSTATE, itemIndex, ref lvItem);
  }
}