使用 SetParent 冻结父窗口

Posted

技术标签:

【中文标题】使用 SetParent 冻结父窗口【英文标题】:Using SetParent freeze the parent window 【发布时间】:2013-02-20 09:18:35 【问题描述】:

我有一个 C# 应用程序,它创建一个表单并将其堆叠在另一个应用程序的窗口前面。 我通过使用SetParent 来做到这一点。但是,(新)父窗口会冻结。

我该如何解决?这是线程的问题吗?

这是有效的:

private void Test(object sender, EventArgs e)
        
            FormCover cov = new FormCover();
            IntPtr hwnd = Win32Utils.FindWindowByCaptionStart(IntPtr.Zero, TrackerName, null);

            Win32Utils.SetParent(cov.Handle, hwnd);
            cov.SetDesktopLocation(0, 0);

            cov.Show();
        

但这(带有计时器已过事件)不是

public partial class Form1 : Form
    

FormCover cover;

void tmrCheck_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        
            ShowCover();
        

private void ShowCover()
        
            cover = new FormCover();
            IntPtr hwnd = Win32Utils.FindWindowByCaptionStart(IntPtr.Zero, TrackerName, null);

            cover.CoverInitialize(hwnd);
            cover.Activate();
        

//------

public partial class FormCover : Form
    
        public delegate void IntPtrDlg(IntPtr param);

        public FormCover()
        
            InitializeComponent();
        

        internal void CoverInitialize(IntPtr hwdnParent)
        
            if (this.InvokeRequired)
            
                this.Invoke(new IntPtrDlg(CoverInitialize), new object[]  hwdnParent );
            
            else
            
                Win32Utils.SetParent(this.Handle, hwdnParent);
                this.SetDesktopLocation(0, 0);
            
        

        internal void CoverActivate(IntPtr handleFormulario)
        
            if (!Visible)
                this.Show();
        

        internal void CoverFinalize()
        
            Hide();
            Win32ParentUtils.SetParent(Handle, new IntPtr());
        
    

这两个样本有什么区别?第一个工作正常,第二个正在冻结aprent窗口。

【问题讨论】:

我猜你不能像这样简单地创建一个窗口......一个窗口需要一个消息泵,当它不是模态窗口时。 尝试在 GUI 线程上运行整个 ShowCover 方法(通过使用 (Begin)Invoke 方法),就像在 CoverInitialize 中所做的那样 【参考方案1】:

正如我刚才所说,您需要为您的表单创建一个消息泵。 试试

Thread thread = new Thread( () =>

     var formCover = new FormCover();
     Application.Run(formCover);
);
thread.ApartmentState = ApartmentState.STA;
thread.Start();

那么您应该能够设置表单的父级。

请参阅here 以获取更多参考。

【讨论】:

这非常有效。但是,当我调整父窗口的大小时,子窗口会消失。当我移动父窗口或聚焦它的任何子控件时,它不会发生。仅在调整窗口大小时才向下发送 z-index。我想我应该打电话给BringToFront,但它从来没有被调用过。我想我应该开始另一个问题。 第二个问题贴在这里:***.com/questions/14979341/…

以上是关于使用 SetParent 冻结父窗口的主要内容,如果未能解决你的问题,请参考以下文章

关于WinForm 中 调用SetParent这个API的问题

关于Qt中QWidget的setParent的使用方法

WPF 使用SetParent嵌套窗口

WPF 使用SetParent嵌套窗口

如何修复运行时崩溃 - QObject::setParent: 无法设置父级,新父级在不同的线程中?

SetParent 的文档中的“同步 UIState”是啥意思?