跨历程设置父子窗口除了owner方案 C# 跨历程 设置窗口owner - 唐宋元明清2188 - 博客园,还有Win32-SetParent SetParent 函数 (winuser.h) - Win32 apps | Microsoft Learn
SetParent可以实现将子窗口嵌入另一个窗口中- 1 [DllImport("user32.dll", SetLastError = true)]
- 2 static extern int SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
复制代码 hWndChild是子窗口,hWndNewParent是新父窗口句柄,返回参数为子窗口的上一次父窗口句柄
我们建个demo试试,
可以使用syp++-查找窗口句柄。这里为了效率高,直接显示窗口句柄方便获取:- 1 CurrentHandleTextBox.Text = new WindowInteropHelper(this).Handle.ToString("X");
复制代码 根据其它窗口句柄和当前窗口句柄,设置SetParent- 1 private void AddChildWindow_OnClick(object sender, RoutedEventArgs e)
- 2 {
- 3 var inputInt32 = Convert.ToInt32(InputTextBox.Text, 16);
- 4 IntPtr inputPtr = (IntPtr)inputInt32;
- 5 var currentInPtr = new WindowInteropHelper(this).Handle;
- 6
- 7 var result = SetParent(inputPtr, currentInPtr);
- 8 MessageBox.Show($"SetParent Result:{result}");
- 9 }
复制代码 显示效果如下:
设置成功时,结果:
65552是上一个父窗口句柄,这是哪个窗口呢?
我们把65552换成16进制,通过syp++,能看到是这是桌面窗口
上面Demo详见 kybs00/SetParentDemo
SetParent函数非常强大,适合那些必要设置子窗口只在父窗口地区内显示,好比分屏软件,可以把父窗口完全当作一个显示器来使用。
根据小伙伴反馈,应用设置了uiAccess后,在此历程打开其它软件,其它软件内部调用SetParent实现相关功能时会失败。- 时间: 2025-01-08 18:03:44,034
- 线程ID: [1]
- 错误描述: 寄宿的 HWND 必须是指定父级的子窗口。
- 异常: System.InvalidOperationException: 寄宿的 HWND 必须是指定父级的子窗口。
- 在 System.Windows.Interop.HwndHost.BuildWindow(HandleRef hwndParent)
- 在 System.Windows.Interop.HwndHost.BuildOrReparentWindow()
- 在 System.Windows.Interop.HwndHost.OnSourceChanged(Object sender, SourceChangedEventArgs e)
- 在 System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
- 在 System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
- 在 System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
- 在 System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
- 在 System.Windows.PresentationSource.UpdateSourceOfElement(DependencyObject doTarget, DependencyObject doAncestor, DependencyObject doOldParent)
- 在 System.Windows.PresentationSource.OnVisualAncestorChanged(DependencyObject uie, AncestorChangedEventArgs e)
- 在 System.Windows.UIElement.OnVisualAncestorChanged(Object sender, AncestorChangedEventArgs e)
- 在 System.Windows.Media.Visual.ProcessAncestorChangedNotificationRecursive(DependencyObject e, AncestorChangedEventArgs args)
- 在 System.Windows.Media.Visual.ProcessAncestorChangedNotificationRecursive(DependencyObject e, AncestorChangedEventArgs args)
- 在 System.Windows.Media.Visual.ProcessAncestorChangedNotificationRecursive(DependencyObject e, AncestorChangedEventArgs args)
- 在 System.Windows.Media.Visual.AddVisualChild(Visual child)
- 在 System.Windows.FrameworkElement.set_TemplateChild(UIElement value)
- 在 System.Windows.Controls.ContentPresenter.UseContentTemplate.BuildVisualTree(FrameworkElement container)
- 在 System.Windows.StyleHelper.ApplyTemplateContent(UncommonField`1 dataField, DependencyObject container, FrameworkElementFactory templateRoot, Int32 lastChildIndex, HybridDictionary childIndexFromChildID, FrameworkTemplate frameworkTemplate)
- 在 System.Windows.FrameworkTemplate.ApplyTemplateContent(UncommonField`1 templateDataField, FrameworkElement container)
- 在 System.Windows.FrameworkElement.ApplyTemplate()
- 在 System.Windows.FrameworkElement.MeasureCore(Size availableSize)
- 在 System.Windows.UIElement.Measure(Size availableSize)
- 在 System.Windows.Controls.Border.MeasureOverride(Size constraint)
- 在 System.Windows.FrameworkElement.MeasureCore(Size availableSize)
- 在 System.Windows.UIElement.Measure(Size availableSize)
- 在 System.Windows.Controls.Control.MeasureOverride(Size constraint)
- 在 System.Windows.FrameworkElement.MeasureCore(Size availableSize)
- 在 System.Windows.UIElement.Measure(Size availableSize)
- 在 System.Windows.Controls.Grid.MeasureCell(Int32 cell, Boolean forceInfinityV)
- 在 System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV, Boolean& hasDesiredSizeUChanged)
- 在 System.Windows.Controls.Grid.MeasureOverride(Size constraint)
- 在 System.Windows.FrameworkElement.MeasureCore(Size availableSize)
- 在 System.Windows.UIElement.Measure(Size availableSize)
- 在 System.Windows.ContextLayoutManager.UpdateLayout()
- 在 MagicWindowSplit.SplitService.<SplitWindow>d__25.MoveNext()
- --- 引发异常的上一位置中堆栈跟踪的末尾 ---
- 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
- 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
- 在 MagicWindowSplit.SplitService.<SelectControlSplit>d__16.MoveNext()
- --- 引发异常的上一位置中堆栈跟踪的末尾 ---
- 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
- 在 System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
- 在 System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
复制代码 uiAccess历程启动软件,会默认添加管理员权限。为了简化后续形貌,我们称“uiAccess权限历程启动其它软件”,有uiAccess影响。
下面我们启动俩个雷同demo.exe,使用俩个不同历程的窗口,来验证SetParent情况
1.俩个均有uiAccess影响的窗口 - 正常
2.有uiAccess影响的窗口A、非uiAccess影响窗口B,在A内设置A为B的子窗口 - 正常
3.有uiAccess影响的窗口A、非uiAccess影响窗口B,在B内设置A为B的子窗口 - 错误,返回值0
原因是管理员权限题目,非管理员权限无法设置管理员权限窗口为其子窗口,仅用管理员权限验证也是一样的结果。
4. 有uiAccess影响的窗口A、非uiAccess影响窗口B,在A内设置B为A的子窗口 - 正常
5. 有uiAccess影响的窗口A、非uiAccess影响窗口B,在B内设置B为A的子窗口 - 错误
原因是管理员权限题目,非管理员权限无法设置管理员权限窗口为其父窗口,仅用管理员权限验证也是一样的结果。
所以设置SetParent失败与uiAccess影响无关,仅仅是管理员权限不敷。而上面小伙伴反馈的分屏软件调用SetParent非常是其它业务题目,毅仔有相关先容 System.InvalidOperationException:“寄宿的 HWND 必须是指定父级的子窗口。” - walterlv SetParent其它题目可以参考:SetParent 函数修改父窗口的误区-CSDN博客使用 SetParent 制作父子窗口的时候,如何设置子窗口的窗口样式以避免抢走父窗口的核心 - walterlv使用 SetParent 跨历程设置父子窗口时的一些题目(小心卡死) - walterlv出处:http://www.cnblogs.com/kybs0/让学习成为习惯,假设明天就有重大机遇等着你,你准备好了么本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文毗连,否则保留追究法律责任的权利。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |