winforms C# - Windows窗体:主线程和另一个线程中的Cursor.Current值不同

9rbhqvlz  于 2023-01-14  发布在  C#
关注(0)|答案(1)|浏览(174)

我试着在我的程序运行的不同时间检查游标的模式。我通过创建一个线程来实现这一点,当需要时,它会让我知道游标的当前状态。由于某种原因,我在主线程和新创建的线程上得到不同的输出。
我对Windows窗体应用程序中的Cursor类做了一个小实验。

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        this.Cursor = Cursors.AppStarting;
        new System.Threading.Thread(delegate()
        {
            while (true)
            {
                Console.WriteLine("--------------------------------");
                Console.WriteLine(Cursor.Current);
                Console.WriteLine("--------------------------------");
            }
        }).Start();
    }
}

基本上,当我的光标在AppStarting模式时,Cursor.Current应该等于Cursors.AppStarting,但由于某种原因,它打印的值是WaitCursor(这基本上意味着它等于Cursors.WaitCursor)。
有人知道为什么吗?
先谢谢你。
编辑:感谢所有评论和帮助我的人。

mkh04yzy

mkh04yzy1#

你的帖子陈述了一个不可靠的假设:
基本上,当我的光标处于AppStarting模式时,Cursor.Current应该等于Cursors.AppStarting...
然后在Form1中编写如下代码:

this.Cursor = Cursors.AppStarting;

问题是Cursor.Current的值不一定来自于this.Cursor。* 它来自于它所悬停的Control(对于NC和Client矩形是不同的)。
你可以通过移动光标来证明这一点,然后迭代控件树来比较Cursor.Current的静态值和控件本身的Cursor属性的值。当光标移动时,请特别注意前两行

private void displayCursors()
{
    richTextBoxCursors.Clear();
    richTextBoxCursors.SelectionColor = Color.Navy;
    richTextBoxCursors.AppendText($"Cursor : {Cursor.Current} {Environment.NewLine}");
    IterateControlTree(this, (control) => localAddEntry(control));

    void localAddEntry(Control control)
    {
        if (!(control is RichTextBox)) // Exempt the RichTextBox
        {
            var isDefault = control.Cursor.Equals(Cursors.Default);
            Color color = isDefault ? Color.Green : Color.Red;
            richTextBoxCursors.SelectionColor = color;
            richTextBoxCursors.AppendText($"{control.Name} : {control.Cursor} {Environment.NewLine}");
        }
    }
}

基本上,我读了Selvin出色的观察,并同意这“可能”是一个X-Y Problem。上面解释了**“主线程和另一个线程中Cursor.Current的值不同..."**只是它不是一个 * 线程 * 依赖性在这里占主导地位。
对于您现在编写的非UI线程,有什么替代方案?
在试图重现你的问题的过程中,我创建了一个full solution,它迭代控件树并为CursorChanged事件的每个控件附加一个处理程序,这“几乎”消除了连续轮询的需要,除了当光标由于UseWaitCursor属性而改变时,此事件不会触发。(~100 ms)在Cursor.Current的状态上也是如此。

其他观察结果(请参阅repo上的扩展自述文件)

  • 迭代窗体的控件树 *
internal void IterateControlTree(Control control, Action<Control> fx)
{
    fx(control);
    foreach (Control child in control.Controls)
    {
        IterateControlTree(child, fx);
    }
}

相关问题