线程安全窗口定位

时间:2019-01-28 08:32:13

标签: c# multithreading

我正在尝试找到一种方法来对表单进行线程安全操作。我创建了一个线程,以在显示表单时更改其位置,并在未显示表单时中止该线程。在我尝试更改位置之前,这一直有效。我尝试使用一种线程安全的方法来更改窗口的位置,但是找不到足够好的方法。

我检查了堆栈溢出情况,但是可能没有在搜索适当的线程。我也用同样的问题搜索过谷歌。

Form1 form;
IntPtr handle = FindWindow(null, WINDOW_NAME);
RECT rect;
Thread posThread;

public FormOverlay(Form1 _form) {
    InitializeComponent();

    form = _form;
    posThread = new Thread(move);
}

private void FormOverlay_Load(object sender, EventArgs e) {
    GetWindowRect(handle, out rect);

    this.Size = new Size(rect.right - rect.left, rect.bottom - rect.top);

    posThread.Start();
}

public struct RECT {
    public int left, top, right, bottom;
}

public void move() {
    while(form.isChecked()) { // Checkbox in another window
        this.Top = rect.top;
        this.Left = rect.left;

        Thread.Sleep(100);
    }
}

我知道

System.InvalidOperationException: 'Cross-thread operation not valid: Control 'FormOverlay' accessed from a thread other than the thread it was created on.

1 个答案:

答案 0 :(得分:0)

不要使用循环或线程来解决此问题,Winforms是基于事件的系统,因此请充分利用它。移动表单时将调用事件Move,您可以在其中放置代码。

您可能还希望订阅CheckedChanged,并在最初选中该框时也触发移动代码以更新窗口位置。

public FormOverlay(Form1 _form) {
    InitializeComponent();

    form = _form;
    form.SomeCheckbox.CheckedChanged += OnSomeCheckboxChanged
    this.Move += OnMove;
}

private void FormOverlay_Load(object sender, EventArgs e) {
    GetWindowRect(handle, out rect);

    this.Size = new Size(rect.right - rect.left, rect.bottom - rect.top);
}

public struct RECT {
    public int left, top, right, bottom;
}

private void OnSomeCheckboxChanged(object sender, System.EventArgs e) {
   DoMove();
}

private void OnMove(object sender, System.EventArgs e) {
   DoMove();
}

private void DoMove();
    if (form.isChecked()) { // Checkbox in another window
        this.Top = rect.top;
        this.Left = rect.left;
    }
}