我正在尝试阻止加载表单时出现闪烁。我正在通过新线程加载表单,然后调用回UI。但由于我在非UI线程上创建表单,因此覆盖(CreateParams)无法正常工作。当我在UI线程上创建它时,它可以完美地工作。如何在它回到UI线程时覆盖它?
// How the loading is done, from UI thread
Thread GetPage = new Thread(() => LoadPage<T>(panel));
public static void LoadPage<T>(Panel Panel)
{
Form form = Activator.CreateInstance(typeof(T)) as Form;
// Now invoke to UI
Panel.Invoke((MethodInvoker)delegate
{
form.TopLevel = false;
form.AutoScroll = true;
Panel.Controls.Add(form);
form.Show();
}
}
// Example of a form
public partial class Start : Form
{
protected override CreateParams CreateParams { get { CreateParams cp =
base.CreateParams; cp.ExStyle |= 0x02000000; return cp; } }
public Start()
{
}
}
答案 0 :(得分:5)
考虑到你正在调用UI线程,它与线程没有任何关系应该是显而易见的。事实上,只有在创建本机窗口时才会使用CreateParams返回的值。在Controls.Add()调用中会发生这种情况,该调用在UI线程上运行。代码的这个方面没有错。如果你试图设置在错误的线程上创建的窗口的父级,那么你需要崩溃程序。
真正的问题是您正在使用的WS_EX_COMPOSITED样式标志。只有顶级窗口才支持合成。 Winforms中的Form类。但是你通过将TopLevel属性设置为 false 来击败它。样式标志只是停止生效,对于客户端窗口没有其他选择。您需要将其移动到包含此子窗口的父窗体。
答案 1 :(得分:4)
不要这样做。必须在将要使用它们的线程上创建WinForms控件,并且必须在创建它们的线程中使用它们(唯一的例外是InvokeRequired
,Invoke
,{{1}和BeginInvoke
)。不遵守这些基本规则将导致失败。