winforms 如何删除ListViewItem上的选择边框

myss37ts  于 2022-11-17  发布在  其他
关注(0)|答案(7)|浏览(240)

我正在使用SetWindowTheme和SendMessage使.net列表视图看起来像vista样式的列表视图,但是.net控件在选定项周围仍然有一个虚线选择边框:

资源管理器列表视图中的选定项目没有边框。如何删除边框?
Windows资源管理器:

编辑:解决方案:

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);
xmakbtuz

xmakbtuz1#

Telanors的解决方案对我很有效,这里有一个稍微独立的版本。

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);
    }
}
3xiyfsfu

3xiyfsfu2#

以NON 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);
}
iezvtpos

iezvtpos3#

将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);
}

请注意,给项目加下划线是一种副作用。

ds97pgxw

ds97pgxw4#

ListView.ShowFocusCues属性设置为false是否有帮助?

piok6c0g

piok6c0g5#

我知道这是相当古老的,Windows窗体现在已经过时了,但它仍然在使用,仍然是一个问题。更糟糕的是,这些解决方案都不优雅,有些甚至根本不工作。
这里有一个非常简单的解决方案,当你创建自己的控件继承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);
    }
}
5gfr0r5j

5gfr0r5j6#

似乎没有一种特定的方法可以使用Windows窗体更改ListViewItem样式。
有时候,使用托管代码无法更改某些Win32控件的行为。唯一的方法是执行一些P/Invoke来修改特定的行为。我发现这确实很棘手,但您没有其他选择。我在开发Windows移动的UI(使用ListView时就是如此)时经常遇到这种情况。
因此,我无法直接回答您的问题,但我非常肯定,如果使用Windows窗体不可能,您肯定可以使用P/Invoke。我能给予您的唯一线索是:

ttygqcqt

ttygqcqt7#

对我来说,关闭焦点直到控件显示出来才起作用。
我这样做了:

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);
        }
    }
}

有关MakeLong调用,请参见上面的https://stackoverflow.com/a/15768802/714557
此外,在显示控件之前的任何选定项都不会设置选择焦点。
我基本上使用“设置焦点”事件来了解控件是否已显示,以及它实际上是否正在获得焦点,以进行更正。

相关问题