تم تمييز عقدة TreeView حتى لم أقم بالنقر بزر الماوس الأيمن على العقدة
سؤال
أنا أعمل على 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
رسالة. لذلك ، لديك بعض الخيارات في كيفية التعامل مع هذا:
يمكنك ببساطة إلغاء رسالة النقر بزر الماوس الأيمن عن طريق الإنقاذ في وقت مبكر مع أ
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); } }
يمكنك إظهار قائمة السياق الخاصة بك في 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); } }
يمكنك ارفع ملك
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).