0

I am trying to find a way to do a thread-safe manipulation for positioning a form. I created a thread to change the position of a form when it is shown and to abort it when it is not shown. This works up until I try to change the position. I tried googling a thread-safe way to change the position of a window but couldn't find anything that worked well enough.

I checked around stack overflow but may not have been searching for the proper thread. I have also searched google with the same issue.

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);
    }
}

I get

System.InvalidOperationException: 'Cross-thread operation not valid: Control 'FormOverlay' accessed from a thread other than the thread it was created on.
Sanpas
  • 1,170
  • 10
  • 29
  • Possible duplicate of [Cross-thread operation not valid: Control accessed from a thread other than the thread it was created on](https://stackoverflow.com/questions/142003/cross-thread-operation-not-valid-control-accessed-from-a-thread-other-than-the) – ProgrammingLlama Jan 28 '19 at 08:32
  • 1
    `Thread Safe window positioning` there is none, you need to do all this stuff on the main ui thread, or marshal back to it – TheGeneral Jan 28 '19 at 08:33
  • Thank you @TheGeneral and John ! This solved my issue, the code ended up looking like this https://pastebin.com/BJk1xVPf – Admiral Jan 28 '19 at 08:46

1 Answers1

0

Don't use a loop or threads to solve this problem, Winforms is a Event based system so use it to your advantage. The event Move will be called when the form is moved and you can put your code in there.

You may want to also subscribe to CheckedChanged and have that fire the move code too to update the window position when the box is initially checked.

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;
    }
}
Scott Chamberlain
  • 124,994
  • 33
  • 282
  • 431