qidao123.com技术社区-IT企服评测·应用市场
标题:
.NET 跨历程设置父子窗口SetParent
[打印本页]
作者:
自由的羽毛
时间:
2025-1-10 19:52
标题:
.NET 跨历程设置父子窗口SetParent
跨历程设置父子窗口除了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企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 qidao123.com技术社区-IT企服评测·应用市场 (https://dis.qidao123.com/)
Powered by Discuz! X3.4