如何在ListViewItem上移除选择边框

10
我正在使用SetWindowTheme和SendMessage使一个.NET ListView看起来像Windows Vista风格的ListView,但是该控件仍然在选定项周围显示虚线选择边框: listview 资源管理器中的选定项没有这种边框。我该如何删除它?
Windows资源管理器: windows explorer 编辑:解决方案:
public static int MAKELONG(int wLow, int wHigh)
{
    int low = (int)LOWORD(wLow);
    short high = LOWORD(wHigh);
    int product = 0x00010000 * (int)high;
    int makeLong = (int)(low | product);
    return makeLong;
}

SendMessage(olv.Handle, WM_CHANGEUISTATE, Program.MAKELONG(UIS_SET, UISF_HIDEFOCUS), 0);
7个回答

12

Telanor的解决方案对我起作用了。这是一个稍微更自包含的版本。

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

public class MyListView : ListView
{
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);

    private const int WM_CHANGEUISTATE = 0x127;
    private const int UIS_SET = 1;
    private const int UISF_HIDEFOCUS = 0x1;

    public MyListView()
    {
        this.View = View.Details;
        this.FullRowSelect = true;

        // removes the ugly dotted line around focused item
        SendMessage(this.Handle, WM_CHANGEUISTATE, MakeLong(UIS_SET, UISF_HIDEFOCUS), 0);
    }

    private int MakeLong(int wLow, int wHigh)
    {
        int low = (int)IntLoWord(wLow);
        short high = IntLoWord(wHigh);
        int product = 0x10000 * (int)high;
        int mkLong = (int)(low | product);
        return mkLong;
    }

    private short IntLoWord(int word)
    {
        return (short)(word & short.MaxValue);
    }
}

6
以非P/Invoke方式完成此操作...
覆盖您的ListView控件并添加以下内容:
protected override void OnSelectedIndexChanged(EventArgs e)
{
    base.OnSelectedIndexChanged(e);
    Message m = Message.Create(this.Handle, 0x127, new IntPtr(0x10001), new IntPtr(0));
    this.WndProc(ref m);
}

protected override void OnEnter(EventArgs e)
{
    base.OnEnter(e);
    Message m = Message.Create(this.Handle, 0x127, new IntPtr(0x10001), new IntPtr(0));
    this.WndProc(ref m);
}

3
将HotTracking属性设置为true会隐藏焦点矩形。这在我的Win7机器上重新制作了Explorer样式。
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;

class MyListView : ListView {
  public MyListView() {
    this.HotTracking = true;
  }
  protected override void OnHandleCreated(EventArgs e) {
    base.OnHandleCreated(e);
    SetWindowTheme(this.Handle, "explorer", null);
  }
  [DllImport("uxtheme.dll", CharSet = CharSet.Auto)]
  public extern static int SetWindowTheme(IntPtr hWnd, string appname, string subidlist);
}

请注意,获取下划线的项目是一个副作用。


2

我知道这可能有点过时了,Windows Forms现在已经过时了,但它仍在使用中,并且仍然存在问题。更糟糕的是,没有一个解决方案是优美的,有些甚至根本不起作用。

这里有一个非常简单的解决方案,当您创建自己的控件并继承ListView时,只需重写WndProc以永远不允许焦点。这将消除所有与焦点相关的虚线选择框、项目选择、子项目选择等。

using System.Windows.Forms;

public partial class NoSelectionListView : ListView
{
    public NoSelectionListView()
    {
        InitializeComponent();
    }

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == 0x0007) //WM_SETFOCUS
        {
            return;
        }
        base.WndProc(ref m);
    }
}

2

默认情况下,该属性似乎被设置为false。 - Ucodia
6
尽管 ShowFocusCues 本身没有起作用,但 MSDN 页面上列出的 WM_CHANGEUISTATE 帮助我得到了正确的答案。通过发送带有 UISF_HIDEFOCUS 的 WM_CHANGEUISTATE 消息,我成功地去除了焦点矩形。 - Telanor
@Telanor,请更新问题并附上您解决方案的代码片段。 - Joe

1

似乎没有特定的方法可以使用Windows Forms更改ListViewItem样式。

有时,使用托管代码无法更改某些Win32控件的行为。唯一的方法是进行一些P/Invoke以修改特定的行为。我发现这真的很棘手,但你别无选择。我经常在开发Windows Mobile UI(尤其是ListView)时遇到这种情况。

所以我对你的问题没有直接的答案,但我非常确定,如果使用Windows Forms不可能,你肯定可以使用P/Invoke。我能给你的唯一线索:


0
对我来说,直到控件显示出来,将焦点关闭才有效。
我是这样做的:
bool HideFocus { get; set; }

bool _hasEnter;

void OnEnter(object sender, EventArgs e)
{
    if (!_hasEnter)
    {
        _hasEnter = true;

        // Selection at startup wont change the actual focus 
        if (this.SelectedIndices.Count > 0)
            this.Items[this.SelectedIndices[0]].Focused = true;

        // Hide focus rectangle if requested 
        if (this.ShowFocusCues && this.HideFocus)
        {
            var lParam1 = MakeLong(UIS_SET, UISF_HIDEFOCUS);

            SendMessage(this.Handle, WM_CHANGEUISTATE, lParam1, 0);
        }
    }
}

请参见上面的https://dev59.com/43E85IYBdhLWcg3wnU0d#15768802,了解MakeLong调用。

此外,在控件显示之前选择的任何项目都不会设置选择焦点。

我基本上使用“设置焦点”事件来知道控件已显示并且实际上正在获得焦点,以进行更正。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接