Wenn man ein GUI designed mit einer ListBox oder einer ListView unter Windows.Forms, gibt es immer eine Kleinigkeit, die mir unangenehm ins Auge sticht. Und zwar der gepunktete Rahmen um die aktuell ausgewählte Zeile. Eigentlich eine Kleinigkeit, könnte man meinen, aber ich finde, dass das immer irgendie störend aussieht. Daher hab ich mich vor einiger Zeit mal auf die Suche gegeben, wie man diesen “FocusRectangle” mit einfachen Mitteln los wird und hab auch eine Lösung gefunden.

Wieder einmal muss man dazu ein bisschen auf die WinAPI zugreifen, weil .NET von sich aus keine einfache Lösung dafür bereitstellt außer, man tut sich die Mühe an und überschreibt DrawItem und zeichnet die ganze Liste selbst (in meinen Augen keine Lösung).

Als Ergebnis hab ich eine kleine Extensionmethode zusammen gestellt, die man lediglich nach dem Initialisieren der Form aufrufen muss.


public static class Extensions
{
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    private 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;

    private static 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 static short IntLoWord(int word)
    {
        return (short)(word & short.MaxValue);
    }

    public static void RemoveFocusRectangle(this Control control)
    {
        SendMessage(control.Handle, WM_CHANGEUISTATE, MakeLong(UIS_SET, UISF_HIDEFOCUS), 0);
    }
}

So… Was passiert hier? Also auf SendMessage gehe ich jetzt nicht näher ein, da es dazu auch gar nicht soviel zu sagen gibt außer, dass es die wohl wichtigste und am häufigsten verwendete Methode unter Windows ist. Wir verwenden SendMessage, um die Nachricht WM_CHANGEUISTATE an das jeweilige Control zu senden. Diese Nachricht sagt lediglich aus, dass der Status des Controls verändert werden soll. Interessanter ist dann eher der Inhalt von WParam. Hier gibt man nämlich an, was passieren soll: UIS_SET bedeutet, dass etwas gesetzt werden soll. Und gesetzt werden soll das Flag UISF_HIDEFOCUS. Die genauen Details zu WM_CHANGEUISTATE können aus der MSDN übernommen werden: https://msdn.microsoft.com/de-de/library/windows/desktop/ms646342.aspx

Wenn man das Ganze dann zum Beispiel im Shown-Event ausführt, sieht man für das jeweilige Control keinen störenden Focus-Rahmen mehr


private void Form1_Shown(object sender, EventArgs e)
{
    WindowShown?.Invoke();
    listView1.RemoveFocusRectangle();
}