تم تمييز عقدة TreeView حتى لم أقم بالنقر بزر الماوس الأيمن على العقدة

StackOverflow https://stackoverflow.com/questions/4333093

سؤال

أنا أعمل على winform وعلى واجهة المستخدم الخاصة بي ، هناك TreeView ، وجدت أنه سيتم تسليط الضوء على treeNode حتى أنني لم أقم بالنقر فوق العقدة بواسطة الماوس الأيمن (على سبيل المثال ، سيتم تسليط الضوء على Node1 عند النقر على الموضع التالي) لكنني حقًا لا أحب هذا السلوك لأنني أريد إظهار قائمة سياق مختلفة عندما لم أقم بالنقر فوق treenode

+rootnode

  |_ Node1                [ Right Click Here, Node1 will be highlighted]
  |
  |_ Node2                [ Right Click Here, Node2 will be highlighted]
هل كانت مفيدة؟

المحلول 3

لقد وجدت طريقة أخرى لمنع تمييز العقدة عندما لا ينقر المستخدم على العقدة ، ولم أقم فقط بتعيين الألوان الخلفية والتنبؤ لكل من العقدة عند إضافتها إلى الشجرة

newNode.BackColor = treeview1.BackColor;
newNode.ForeColor = treeview1.ForeColor;
treeview1.Nodes.Add(newNode);

ثم في حدث Mousedown ، قم بتعيين خاصية SelectionNode على النحو التالي

 private void treeView1_MouseDown(object sender, MouseEventArgs e)
 {
        TreeNode Node = treeView1.GetNodeAt(e.Location);
        if (Node != null && Node.Bounds.Contains(e.Location))
            treeView1.SelectedNode = Node;
        else
            treeView1.SelectedNode = null;
 } 

نصائح أخرى

بالانتقال من تعليقك إلى إجابة كيفن وينهولد ، فأنت تريد فقط السماح للمستخدم بالنقر في المساحة الفارغة لـ TreeView وإلغاء تحديد أي عقدة محددة.

يمكنك القيام بذلك عن طريق التعامل مع MouseDown حدث التابع TreeView السيطرة ، وتعيين SelectedNode منشأه إلى null إذا تم النقر فوق الماوس على موقع لا يحتوي على عقدة. على سبيل المثال ، يمكنك استخدام الكود التالي:

private void myTreeView_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
    if (myTreeView.HitTest(e.Location).Node == null)
    {
        myTreeView.SelectedNode = null;
    }
}

هذا يستفيد من HitTest طريقة لتحديد العقدة الموجودة في نقطة معينة ، تحديد موقع حدث الماوس كنقطة للاختبار. لا تحتاج إلى أي رمز آخر لتحديد العقد كالمعتاد عند المستخدم يفعل انقر عليها ؛ التي يتم التعامل معها تلقائيا من قبل TreeView.


تعديل: كما يشير تعليقي على السؤال ، ما زلت غير واضح بشكل استثنائي فيما يتعلق بما تحاول إنجازه هنا. إذا كنت مهتمًا فعليًا بمنع عقدة من التمييز مؤقتًا أثناء الضغط على زر الماوس الأيمن في المساحة الفارغة إلى جانب العقدة ، فإن الأمور تصبح أكثر تعقيدًا.

لقد بحثت في هذه المشكلة من قبل ، والجزء الصعبة هو أنه لم يتم استلام رسائل النوافذ أثناء إغلاق زر الماوس ، على الأقل ليس حتى يتم نقل الماوس (في هذه الحالة ، لم تعد العقدة محددة على أي حال) . يبدو أن هذا السلوك تمليه نظام التشغيل ولا يتغلب عليه بسهولة باستخدام الأحداث المعيارية. يمكنك محاولة إلغاء النقر على الزر الأيمن في MouseDown الحدث طوال اليوم ، ولكن يتم اختيار العقدة بواسطة Windows قبل أن يتم رفع هذا الحدث في سيطرتك (تذكر أن عناصر تحكم مقدمة من .NET مثل TreeView و ListView هي ببساطة مغلفة حول تلك الضوابط نفسها التي توفرها Windows API ، والتي تنفذ على ما يبدو السلوك "Select-Node-While-Right-Button-Down-Down" نفسه).

ماذا او ما يفعل العمل ، ومع ذلك ، هو تجاوز WndProc في مشتق TreeView السيطرة والتعامل مع WM_RBUTTONDOWN رسالة. لكن لاحظ أنه حتى ضبط SelectedNode خاصية ل null لا يعمل هنا ، لأنه لم تتم معالجته حتى بعد، بعدما يقوم Windows تلقائيًا بتحديد العقدة كاستجابة لزر الماوس الأيمن الذي يتم النقر عليه - لا يهم ما تفعله ، عليك منع القاعدة TreeView السيطرة من تلقي WM_RBUTTONDOWN رسالة. لذلك ، لديك بعض الخيارات في كيفية التعامل مع هذا:

  1. يمكنك ببساطة إلغاء رسالة النقر بزر الماوس الأيمن عن طريق الإنقاذ في وقت مبكر مع أ return بيان. بالطبع ، هذا يعني أنك لن تكون قادرًا على التعامل مع هذا الحدث في MouseDown معالج ، لأنه لم يمر في الواقع إلى السيطرة! لذلك إذا كنت ترغب في إظهار قائمة سياق منبثقة ، فربما لن يعمل هذا من أجلك.

    public class NewTreeView : System.Windows.Forms.TreeView
    {
        protected override void WndProc(ref System.Windows.Forms.Message m)
        {
            const int WM_RBUTTONDOWN = 0x204;
            if (m.Msg == WM_RBUTTONDOWN)
            {
                return;
            }
            base.WndProc(ref m);
        }   
    }
    
  2. يمكنك إظهار قائمة السياق الخاصة بك في Overridden WndProc الطريقة كاستجابة ل WM_RBUTTONDOWN الرسالة ، ثم return من الطريقة دون السماح للفئة الأساسية بالتعامل مع الرسالة. هذا يفعل نفس الشيء بالضبط مثل الحل الأول (يمنع الحدث النقر بزر الماوس الأيمن من التسبب في ظهور العقدة المحددة) ، ولكنه يسمح لك بإظهار قائمة سياق (أو القيام بأي شيء آخر تريده) كلما النقر بزر الماوس الأيمن يحدث. بالطبع ، هذا يعني أنه يجب احتواء جميع الكود ذي الصلة ضمن الفئة الفرعية الخاصة بك من TreeView التحكم ، الذي لا يتم التعامل معه في رمز واجهة المستخدم في النموذج الخاص بك ، والذي قد يكون أو لا يكون مناسبًا لك.

    public class NewTreeView : System.Windows.Forms.TreeView
    {
        protected override void WndProc(ref System.Windows.Forms.Message m)
        {
            const int WM_RBUTTONDOWN = 0x204;
            if (m.Msg == WM_RBUTTONDOWN)
            {
                //Create and show a context menu
                var myContextMenu = new ContextMenuStrip();
                myContextMenu.Items.Add("First Item");
                myContextMenu.Items.Add("Second Item");
                return;
            }
            base.WndProc(ref m);
        }   
    }
    
  3. يمكنك ارفع ملك RightMouseClick حدث من العرف الخاص بك TreeView الفصل كرد فعل على WM_RBUTTONDOWN الرسالة ، التي يمكنك التعامل معها بعد ذلك كما ترغب في رمز واجهة المستخدم في النموذج الخاص بك. بعدم تمرير WM_RBUTTONDOWN رسالة إلى القاعدة TreeView فئة التحكم ، وهذا يحقق نفس الهدف من الاقتراحين السابقين ، ولكنه يسمح لك بالتعامل مع حدث النقر على الزر الأيمن في رمز واجهة المستخدم الخاص بك بدلاً من الاضطرار إلى وضع كل منطقك في عنصر التحكم الفرعي. WndProc.

    public class NewTreeView : System.Windows.Forms.TreeView
    {
        protected override void WndProc(ref System.Windows.Forms.Message m)
        {
            const int WM_RBUTTONDOWN = 0x204;
            if (m.Msg == WM_RBUTTONDOWN)
            {
                //Raise your custom event
                OnRightMouseClick(new EventArgs());
                return;
            }
            base.WndProc(ref m);
        }   
    }
    

جرب هذا

  void treeView1_MouseDown(object sender, MouseEventArgs e)
    {


        TreeViewHitTestInfo h = treeView1.HitTest(e.Location);

        if (h.Location != TreeViewHitTestLocations.Label && h.Location!= TreeViewHitTestLocations.None )
        {
            treeView1.SelectedNode = null;
        }
    }

إذا فهمت أنك تريد تحديد أي عقدة بشكل صحيح إذا انقر المستخدم على مساحة فارغة داخل TreeView. يمكنك تحقيق ذلك من خلال التعامل مع حدث Mousedown-the Tree ووضع خاصية Tree's SelectionNode على TreeView.getNodeat (E.Location).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top