web-dev-qa-db-ja.com

ツリービューにフォーカスがない場合、C#WinFormsはツリーノードを強調表示します

あいさつ。

ゲームのシナリオを編集するためのインターフェイスを作成しています。基本的には、ネストされた条件とアクションを持つイベントで構成されます。したがって、2つのツリービューを使用することを計画しました。1つはイベントを選択するためのもので、もう1つはイベント内の条件/アクションを選択して編集するためのものです。

これで、イベント(左のツリービューで)を選択してから、右のツリービューで何かを選択しようとすると、左のツリービューで青い選択長方形が表示されなくなります。ユーザーがどのイベントを編集しているかわからなくなったため、これは明らかに悪いことです。

現在の選択内容に関する何らかの情報を保持していることがわかった唯一の方法は、SelectedImageIndexを使用することですが、これは異なる1つの小さな画像のみです。

ツリービューにフォーカスがないときにツリーノードを強調表示する他の方法はありますか? Graphics.DrawRectangleか何かでもできることはわかっていますが、描画はPaintイベントで行う必要があり、treeviewにはPaintイベントがないということを聞いたので、フォーカスを失ったイベントで描画してから、フォームをドラッグすると思います画面か何かから、それは「消去」されますか?

とにかく、アイデアがあったら教えてください(選択されたツリーノードと選択されていないツリーノードに別のアイコンを使用する以外)

ありがとう!

29
Istrebitel

探しているのは、HideSelectionTreeViewプロパティです。

MSDNから:

ツリービューがフォーカスを失っても、選択されたツリーノードが強調表示されたままかどうかを示す値を取得または設定します。

リンク: http://msdn.Microsoft.com/en-us/library/system.windows.forms.treeview.hideselection.aspx

コード:

TreeView.HideSelection = false;
58
aKzenT

それはまだ表示されますが、画面と現在の設定によっては明るい灰色でのみ表示されます!

OnDrawNodeイベントをオーバーライドします。そのため、Microsoftから継承した新しいクラス(「SpecialTreeView」と呼びます)を作成しますTreeViewのようなclass SpecialTreeView : TreeView。次に、次のイベントオーバーライドを追加します。

protected override void OnDrawNode(DrawTreeNodeEventArgs e)
{
    TreeNodeStates treeState = e.State;
    Font treeFont = e.Node.NodeFont ?? e.Node.TreeView.Font;

    // Colors.
    Color foreColor = e.Node.ForeColor;
    string strDeselectedColor = @"#6B6E77", strSelectedColor = @"#94C7FC";
    Color selectedColor = System.Drawing.ColorTranslator.FromHtml(strSelectedColor);
    Color deselectedColor = System.Drawing.ColorTranslator.FromHtml(strDeselectedColor);

    // New brush.
    SolidBrush selectedTreeBrush = new SolidBrush(selectedColor);
    SolidBrush deselectedTreeBrush = new SolidBrush(deselectedColor);

    // Set default font color.
    if (foreColor == Color.Empty)
        foreColor = e.Node.TreeView.ForeColor;

    // Draw bounding box and fill.
    if (e.Node == e.Node.TreeView.SelectedNode)
    {
        // Use appropriate brush depending on if the tree has focus.
        if (this.Focused)
        {
            foreColor = SystemColors.HighlightText;
            e.Graphics.FillRectangle(selectedTreeBrush, e.Bounds);
            ControlPaint.DrawFocusRectangle(e.Graphics, e.Bounds, foreColor, SystemColors.Highlight);
            TextRenderer.DrawText(e.Graphics, e.Node.Text, treeFont, e.Bounds,
                                         foreColor, TextFormatFlags.GlyphOverhangPadding);
        }
        else
        {
            foreColor = SystemColors.HighlightText;
            e.Graphics.FillRectangle(deselectedTreeBrush, e.Bounds);
            ControlPaint.DrawFocusRectangle(e.Graphics, e.Bounds, foreColor, SystemColors.Highlight);
            TextRenderer.DrawText(e.Graphics, e.Node.Text, treeFont, e.Bounds,
                                         foreColor, TextFormatFlags.GlyphOverhangPadding);
        }
    }
    else
    {
        if ((e.State & TreeNodeStates.Hot) == TreeNodeStates.Hot)
        {
            e.Graphics.FillRectangle(SystemBrushes.Window, e.Bounds);
            TextRenderer.DrawText(e.Graphics, e.Node.Text, hotFont, e.Bounds,
                                         System.Drawing.Color.Black, TextFormatFlags.GlyphOverhangPadding);
        }
        else
        {
            e.Graphics.FillRectangle(SystemBrushes.Window, e.Bounds);
            TextRenderer.DrawText(e.Graphics, e.Node.Text, treeFont, e.Bounds,
                                         foreColor, TextFormatFlags.GlyphOverhangPadding);
        }
    }
}

コードをコンパイルすると、デザイナーのツールボックスに「SpecialTreeView」が表示されます。 TreeViewを、同じ名前を使用するこの新しいものに置き換えます。異なるのは、選択の色だけです。選択するとselectedColorになり、選択しないとdeselectedColorになります。

これがお役に立てば幸いです。

16
MoonKnight

高速解:

プロパティを設定します。

  • HideSelection = false;
  • DrawMode = TreeViewDrawMode.OwnerDrawText;

次に、DrawNodeイベントハンドラーで次の操作を行います。

private void treeView1_DrawNode(object sender, DrawTreeNodeEventArgs e) {
  e.DrawDefault = true;
}

Windwos 7では、これにより、選択範囲の周りの破線のボックスを含む古いレンダリングが復元されます(実際には少し古くなっています)。テキストはフォーカスがあると白になり、フォーカスがないと黒になります。背景は青色で表示されたままです。

この回答は新しいものではなく、他の回答にもこれらの手順が含まれていますが、これは最低限必要な手順です(少なくともWindows 7では、他のOSをテストしていませんでした)。

9
Louis Somers

完全に完璧な解決策ではありませんが、かなり近いです:

treeView.HideSelection = false;
treeView.DrawMode = TreeViewDrawMode.OwnerDrawText;
treeView.DrawNode += (o, e) =>
{
    if (!e.Node.TreeView.Focused && e.Node == e.Node.TreeView.SelectedNode)
    {
        Font treeFont = e.Node.NodeFont ?? e.Node.TreeView.Font;
        e.Graphics.FillRectangle(Brushes.Gray, e.Bounds);
        ControlPaint.DrawFocusRectangle(e.Graphics, e.Bounds, SystemColors.HighlightText, SystemColors.Highlight);
        TextRenderer.DrawText(e.Graphics, e.Node.Text, treeFont, e.Bounds, SystemColors.HighlightText, TextFormatFlags.GlyphOverhangPadding);
    }
    else
        e.DrawDefault = true;
};
treeView.MouseDown += (o, e) =>
{
    TreeNode node = treeView.GetNodeAt(e.X, e.Y);
    if (node != null && node.Bounds.Contains(e.X, e.Y))
        treeView.SelectedNode = node;
};
8
Bachor

前のものと似ていますが、外観はWin10標準に似ています。

treeView.HideSelection = false;
treeView.DrawMode = TreeViewDrawMode.OwnerDrawText;

treeView.DrawNode += (o, e) =>
{
    if (e.Node == e.Node.TreeView.SelectedNode)
    {
        Font font = e.Node.NodeFont ?? e.Node.TreeView.Font;
        Rectangle r = e.Bounds;
        r.Offset(0, 1);
        Brush brush = e.Node.TreeView.Focused ? SystemBrushes.Highlight : Brushes.Gray;
        e.Graphics.FillRectangle(brush, e.Bounds);
        TextRenderer.DrawText(e.Graphics, e.Node.Text, font, r, SystemColors.HighlightText, TextFormatFlags.GlyphOverhangPadding);
    }
    else
        e.DrawDefault = true;
};

treeView.MouseDown += (o, e) =>
{
    TreeNode node = treeView.GetNodeAt(e.Location);
    if (node != null && node.Bounds.Contains(e.Location)) treeView.SelectedNode = node;
};
1
Ivan

より簡単な方法を見つけました:

  1. TreeView.HideSelection = Trueに設定します
  2. 以下をTreeView.AfterSelect-Callbackに追加します:
    private void treeViewBenutzerverwaltung_AfterSelect(object sender, TreeViewEventArgs e)
    {
        // Select new node
        e.Node.BackColor = SystemColors.Highlight;
        e.Node.ForeColor = SystemColors.HighlightText;
        if (_lastSelectedNode != null)
        {
            // Deselect old node
            _lastSelectedNode.BackColor = SystemColors.Window;
            _lastSelectedNode.ForeColor = SystemColors.WindowText;
        }
        lastSelectedNode = e.Node;
    }
    
0
Sam