单击父级为面板的另一个应用程序的窗口时如何将表单移动到前台

2023-12-05

我使用下面的代码来启动应用程序并将其移动到我的表单上的面板中。在这个例子中我使用记事本,仅作为示例。稍后我将使用不同的应用程序。

当另一个应用程序移动到我的表单前面时,我只能通过单击标题栏将我的表单移动到前台。如果我单击 MDI 子区域(记事本移入的面板),则不会发生任何情况。
有办法实现吗?

Imports System.Runtime.InteropServices
Public Class Form1
    Declare Auto Function SetParent Lib "user32.dll" (ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As Integer
    Declare Auto Function SendMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim proc As Process
        proc = Process.Start("notepad.exe")
        proc.WaitForInputIdle()
        SetParent(proc.MainWindowHandle, Me.Panel1.Handle)
        SendMessage(proc.MainWindowHandle, 274, 61488, 0)
    End Sub
End Class

问题在于,托管(重新设置父级)窗口在激活时不会导致托管窗体也激活,因此它会被带到前台。
托管窗口并不完全是子窗口,托管窗体不会从它接收任何消息。

将承载窗体的窗体带到前台的可能方法foreign窗口,当此窗口接收焦点时(您单击或以其他方式激活它)
它用设置WinEventHook安装一个 Hook 来监视窗口放置状态的变化(EVENT_SYSTEM_FOREGROUND).
您指定感兴趣的窗口的句柄,(您的proc.MainWindowHandle在这里),加上它的ProcessId and ThreadId。请注意,这些与您的应用程序的调用不同获取窗口线程进程ID()需要获取此信息。

当您激活foreign窗口中,Hook 调用指定的回调委托(这里,ForegroundChangedEventDelegate),依次执行它指向的方法(ForegroundStateChangedCallback)
当调用此方法时,它会检查引起通知的对象是否是OBJID_WINDOW该事件实际上是EVENT_SYSTEM_FOREGROUND。如果是这种情况,它会调用设置窗口位置将托管窗体带到前台,但不激活它,因此托管窗口不会失去焦点

Notes:

  • The SetWinEventHook委托是在构造函数中创建的(Sub New()) 的父 Form,以及用于防止委托在错误的时间被垃圾收集的 GC SafeHandle。
    它发布于OnHandleDestroyed()override,其中钩子过程也被取消钩子

  • 请参阅表格中的进口声明:

      Imports [Your App Namespace].NativeMethods  
    

这意味着您必须指定应用程序的命名空间才能使导入按预期工作。在 VB.NET 中,通常是应用程序的名称及其主目录Namespace匹配;如果您的应用程序被命名,WinFormsApp1,那么就是Imports WinFormsApp1.NativeMethods

  • 要激活 Hook,一旦更改了该窗口的父级,就可以使用其句柄来调用SetForegroundStateChangedHook()方法。就这样。
    当窗体关闭时,钩子被释放

我建议使用中的代码将窗口脱钩至其原始状态设置父级(并且可能在关闭托管表单之前将其设置回原始值)。你可以发送WM_CLOSE如果需要的话到窗口。


Imports [Your App Namespace].NativeMethods

Public Class SomeForm

    Private hForegrundChangedEventHook As IntPtr
    Private ReadOnly ForegrundChangedEventDelegate As WinEventDelegate
    Private Shared GCForegroundStateSafetyHandle As GCHandle

    Public Sub New()
        InitializeComponent()
        ForegrundChangedEventDelegate = New WinEventDelegate(AddressOf ForegroundStateChangedCallback)
        GCForegroundStateSafetyHandle = GCHandle.Alloc(ForegrundChangedEventDelegate)
    End Sub

    Protected Overrides Sub OnHandleDestroyed(e As EventArgs)
        GCForegroundStateSafetyHandle.Free()
        UnhookWinEvent(hForegrundChangedEventHook)
        MyBase.OnHandleDestroyed(e)
    End Sub

    Private Sub SetForegroundStateChangedHook(hWnd As IntPtr)
        Dim processId As UInteger
        Dim targetThreadId = GetWindowThread(hWnd, processId)
        hForegrundChangedEventHook = WinEventHookOne(SWEH_Events.EVENT_SYSTEM_FOREGROUND, ForegrundChangedEventDelegate, processId, targetThreadId)
    End Sub

    Friend Sub ForegroundStateChangedCallback(hWinEventHook As IntPtr, eventType As SWEH_Events, hWnd As IntPtr, idObject As SWEH_ObjectId, idChild As Long, dwEventThread As UInteger, dwmsEventTime As UInteger)
        If idObject = SWEH_ObjectId.OBJID_WINDOW AndAlso eventType = SWEH_Events.EVENT_SYSTEM_FOREGROUND Then
            Dim flags = SWP_Flags.SWP_ASYNCWINDOWPOS Or SWP_Flags.SWP_NOACTIVATE Or SWP_Flags.SWP_NOSIZE Or SWP_Flags.SWP_NOMOVE
            SetWindowPos(Handle, IntPtr.Zero, 0, 0, 0, 0, flags)
        End If
    End Sub
End Class

NativeMethods类

将此类添加到项目中并按照所述导入到您的表单中

Imports System.Runtime.InteropServices

Public Class NativeMethods

    <DllImport("user32.dll", SetLastError:=True)>
    Friend Shared Function GetWindowThreadProcessId(hWnd As IntPtr, ByRef lpdwProcessId As UInteger) As UInteger
    End Function

    <DllImport("user32.dll", SetLastError:=True)>
    Friend Shared Function SetWindowPos(hWnd As IntPtr, hWndInsertAfter As IntPtr, x As Integer, y As Integer, cx As Integer, cy As Integer, uFlags As SWP_Flags) As Boolean
    End Function

    Friend Delegate Sub WinEventDelegate(
        hWinEventHook As IntPtr,
        eventType As SWEH_Events,
        hwnd As IntPtr, idObject As SWEH_ObjectId,
        idChild As Long,
        dwEventThread As UInteger,
        dwmsEventTime As UInteger)

    <DllImport("user32.dll", SetLastError:=False)>
    Friend Shared Function SetWinEventHook(
        eventMin As SWEH_Events,
        eventMax As SWEH_Events,
        hmodWinEventProc As IntPtr,
        lpfnWinEventProc As WinEventDelegate,
        idProcess As UInteger,
        idThread As UInteger,
        dwFlags As SWEH_dwFlags) As IntPtr
    End Function

    <DllImport("user32.dll", SetLastError:=False)>
    Friend Shared Function UnhookWinEvent(hWinEventHook As IntPtr) As Boolean
    End Function

    Friend Shared WinEventHookInternalFlags As SWEH_dwFlags =
        SWEH_dwFlags.WINEVENT_OUTOFCONTEXT Or SWEH_dwFlags.WINEVENT_SKIPOWNPROCESS


    Friend Shared Function WinEventHookOne(evt As SWEH_Events, weDelegate As WinEventDelegate, idProcess As UInteger, idThread As UInteger) As IntPtr
        Return SetWinEventHook(evt, evt, IntPtr.Zero, weDelegate, idProcess, idThread, WinEventHookInternalFlags)
    End Function


    Friend Shared Function GetWindowThread(hWnd As IntPtr, ByRef processID As UInteger) As UInteger
        processID = 0
        Return GetWindowThreadProcessId(hWnd, processID)
    End Function


    ' SetWinEventHook Events
    Friend Enum SWEH_Events As UInteger
        EVENT_MIN = &H1
        EVENT_MAX = &H7FFFFFFF
        EVENT_SYSTEM_SOUND = &H1
        EVENT_SYSTEM_ALERT = &H2
        EVENT_SYSTEM_FOREGROUND = &H3
        EVENT_SYSTEM_MENUSTART = &H4
        EVENT_SYSTEM_MENUEND = &H5
        EVENT_SYSTEM_MENUPOPUPSTART = &H6
        EVENT_SYSTEM_MENUPOPUPEND = &H7
        EVENT_SYSTEM_CAPTURESTART = &H8
        EVENT_SYSTEM_CAPTUREEND = &H9
        EVENT_SYSTEM_MOVESIZESTART = &HA
        EVENT_SYSTEM_MOVESIZEEND = &HB
        EVENT_SYSTEM_CONTEXTHELPSTART = &HC
        EVENT_SYSTEM_CONTEXTHELPEND = &HD
        EVENT_SYSTEM_DRAGDROPSTART = &HE
        EVENT_SYSTEM_DRAGDROPEND = &HF
        EVENT_SYSTEM_DIALOGSTART = &H10
        EVENT_SYSTEM_DIALOGEND = &H11
        EVENT_SYSTEM_SCROLLINGSTART = &H12
        EVENT_SYSTEM_SCROLLINGEND = &H13
        EVENT_SYSTEM_SWITCHSTART = &H14
        EVENT_SYSTEM_SWITCHEND = &H15
        EVENT_SYSTEM_MINIMIZESTART = &H16
        EVENT_SYSTEM_MINIMIZEEND = &H17
        EVENT_SYSTEM_DESKTOPSWITCH = &H20
        EVENT_SYSTEM_END = &HFF
        EVENT_OEM_DEFINED_START = &H101
        EVENT_OEM_DEFINED_END = &H1FF
        EVENT_UIA_EVENTID_START = &H4E00
        EVENT_UIA_EVENTID_END = &H4EFF
        EVENT_UIA_PROPID_START = &H7500
        EVENT_UIA_PROPID_END = &H75FF
        EVENT_CONSOLE_CARET = &H4001
        EVENT_CONSOLE_UPDATE_REGION = &H4002
        EVENT_CONSOLE_UPDATE_SIMPLE = &H4003
        EVENT_CONSOLE_UPDATE_SCROLL = &H4004
        EVENT_CONSOLE_LAYOUT = &H4005
        EVENT_CONSOLE_START_APPLICATION = &H4006
        EVENT_CONSOLE_END_APPLICATION = &H4007
        EVENT_CONSOLE_END = &H40FF
        EVENT_OBJECT_CREATE = &H8000
        EVENT_OBJECT_DESTROY = &H8001
        EVENT_OBJECT_SHOW = &H8002
        EVENT_OBJECT_HIDE = &H8003
        EVENT_OBJECT_REORDER = &H8004
        EVENT_OBJECT_FOCUS = &H8005
        EVENT_OBJECT_SELECTION = &H8006
        EVENT_OBJECT_SELECTIONADD = &H8007
        EVENT_OBJECT_SELECTIONREMOVE = &H8008
        EVENT_OBJECT_SELECTIONWITHIN = &H8009
        EVENT_OBJECT_STATECHANGE = &H800A
        EVENT_OBJECT_LOCATIONCHANGE = &H800B
        EVENT_OBJECT_NAMECHANGE = &H800C
        EVENT_OBJECT_DESCRIPTIONCHANGE = &H800D
        EVENT_OBJECT_VALUECHANGE = &H800E
        EVENT_OBJECT_PARENTCHANGE = &H800F
        EVENT_OBJECT_HELPCHANGE = &H8010
        EVENT_OBJECT_DEFACTIONCHANGE = &H8011
        EVENT_OBJECT_ACCELERATORCHANGE = &H8012
        EVENT_OBJECT_INVOKED = &H8013
        EVENT_OBJECT_TEXTSELECTIONCHANGED = &H8014
        EVENT_OBJECT_CONTENTSCROLLED = &H8015
        EVENT_SYSTEM_ARRANGMENTPREVIEW = &H8016
        EVENT_OBJECT_END = &H80FF
        EVENT_AIA_START = &HA000
        EVENT_AIA_END = &HAFFF
    End Enum

    ' SetWinEventHook Window Objects
    Friend Enum SWEH_ObjectId As Long
        OBJID_WINDOW = &H0
        OBJID_SYSMENU = &HFFFFFFFFUI
        OBJID_TITLEBAR = &HFFFFFFFEUI
        OBJID_MENU = &HFFFFFFFDUI
        OBJID_CLIENT = &HFFFFFFFCUI
        OBJID_VSCROLL = &HFFFFFFFBUI
        OBJID_HSCROLL = &HFFFFFFFAUI
        OBJID_SIZEGRIP = &HFFFFFFF9UI
        OBJID_CARET = &HFFFFFFF8UI
        OBJID_CURSOR = &HFFFFFFF7UI
        OBJID_ALERT = &HFFFFFFF6UI
        OBJID_SOUND = &HFFFFFFF5UI
        OBJID_QUERYCLASSNAMEIDX = &HFFFFFFF4UI
        OBJID_NATIVEOM = &HFFFFFFF0UI
    End Enum

    ' WinEventDelegate flags
    Friend Enum SWEH_dwFlags As UInteger
        WINEVENT_OUTOFCONTEXT = &H0     ' Events are ASYNC - No dll needed
        WINEVENT_SKIPOWNTHREAD = &H1    ' Don't call back for events on installer's thread
        WINEVENT_SKIPOWNPROCESS = &H2   ' Don't call back for events on installer's process
        WINEVENT_INCONTEXT = &H4        ' Events are SYNC, this causes your dll to be injected into every process
    End Enum

    ' SetWindowPos flags
    <Flags>
    Public Enum SWP_Flags As UInteger
        SWP_NOSIZE = &H1
        SWP_NOMOVE = &H2
        SWP_NOZORDER = &H4
        SWP_NOREDRAW = &H8
        SWP_NOACTIVATE = &H10
        SWP_DRAWFRAME = &H20
        SWP_FRAMECHANGED = &H20
        SWP_SHOWWINDOW = &H40
        SWP_HIDEWINDOW = &H80
        SWP_NOCOPYBITS = &H100
        SWP_NOOWNERZORDER = &H200
        SWP_NOREPOSITION = &H200
        SWP_NOSENDCHANGING = &H400
        SWP_NOCLIENTSIZE = &H800
        SWP_NOCLIENTMOVE = &H1000
        SWP_DEFERERASE = &H2000
        SWP_ASYNCWINDOWPOS = &H4000
    End Enum
End Class
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

单击父级为面板的另一个应用程序的窗口时如何将表单移动到前台 的相关文章

  • 如何正确使用Dispatcher.BeginInvoke?

    我几乎在互联网上到处搜索 我用谷歌搜索了很多次并找到了很多结果 但我仍然找不到解决我的问题的方法 我正忙着改造旧的WinForms应用程序到新的 WPF 应用程序 但我在使用某些命令时遇到问题 在他们使用的 Winforms 应用程序中Co
  • 基本 WinForm KeyDown 事件处理

    我正在使用 WinForms 我已经为KeyDown主窗体的事件 从而调用按钮的Click事件处理程序 The Click调用的事件处理程序取决于按下的特定键 如果用户单击该按钮而不是使用该键 然后随后尝试使用该键 则该键 例如向下箭头 将
  • 不建议在 VB.Net 中使用 Mid()、Instr()、LBound()、UBound() 等吗?

    我有 C 背景 但现在主要使用 VB Net 在我看来 上述函数 以及其他函数 例如 UCase LCase 等是 VB6 及之前版本的遗留物 在 VB Net 中使用这些函数是不受欢迎的 还是纯粹取决于个人喜好 我个人的偏好是远离它们 但
  • 如何使树视图不可折叠?

    使用WinForms中的TreeView控件 是否有一个属性可以设置为隐藏每个节点的折叠节点图标 另外 如何永久展开 TreeView 中的所有节点 你需要处理OnBeforeExpand事件和设置Cancel to true privat
  • Vb.net 捕获 Ctrl+C

    I want to capture when someone uses CtrlC even when off focus im using Visual Basic 2010 好的 我为您提供了一个经过验证有效的解决方案 不过 您将需要一
  • WinForms 应用程序设计 - 将文档从 SQL Server 移动到文件存储

    我有一个连接到 SQL Server 的标准 WinForms 应用程序 该应用程序允许用户上传当前存储在数据库中的文档 在使用图像列的表中 我需要更改这种方法 以便将文档存储为文件 并将文件的链接存储在数据库表中 使用当前的方法 当用户上
  • VB.NET 中的“阴影”与“覆盖”

    这两个关键词有什么意义Shadows http msdn microsoft com en us library 1h3wytf6 aspx and 覆盖 http msdn microsoft com en us library k777
  • 如何在 vb.net 中使用 Stacktrace 返回错误行号

    我正在尝试创建某种错误捕获方法来返回错误行号 当进程中止时 我们会发送一封中止电子邮件 该电子邮件为我们提供了错误号 and 错误描述但我想知道实际上哪里出了错误 我知道你可以执行以下操作 1 code here 2 code here 3
  • 如何判断一个类是否被某个特定属性修饰

    我试图确定接口是否用特定属性装饰 例如我有以下界面
  • 动态版本控制

    我有一种情况 我希望版本控制在构建时是动态的 版本图案
  • WinApi:获取 COM 表单的控件名称

    我想用 Net 框架替换我当前的 UI 自动化工具 QTP 我需要测试 VB6 COM 应用程序 框架的基础之一是使用表单名称 到目前为止 我未能找到使用 Win API 获取这些数据的方法 该解决方案只有一个约束 即该解决方案必须依赖 N
  • Visual Studio 2022 - 编译旧应用程序时出错

    我们正在尝试在 Visual Studio 2022 中使用 VB6 32 位应用程序 编译 2002 年以来非常旧的应用程序 我们需要调试此应用程序并能够在 Windows 10 计算机上运行此应用程序 编译时 我们发现以下错误 这似乎是
  • 按比例调整图片框的大小以调整表单大小

    我希望每次 用户调整表单的大小 图片框中的图像也使用相同的值 按比例 调整大小 我在互联网上搜索了一些代码并在中找到了这个答案堆栈溢出 https stackoverflow com a 6501997 3264464 https stac
  • 删除DataGridView(表)中的多行

    我有一个数据表 myTable 它与 DataGridView dgv 绑定 DataGridView dgv 有一个复选框列 我的目标是删除在按钮事件中选中的行 数据表当然会更新 现在我的代码仅适用于删除一行 不适用于多行 感谢帮助 pr
  • 将 PDF 嵌入到 WPF 应用程序中

    我正在尝试在 WPF 应用程序中嵌入 显示 PDF 到目前为止 我已经尝试过这些解决方案 但没有成功 在 a 中显示 PDFWindowsFormsHost主持一个AxAcroPdf控制 类似于显示的内容here http hugeonio
  • 如何以编程方式对 WebBrowser 控件安全警报回答“是”

    我正在使用 WebBrowser 控件以编程方式访问单个网站 但每当我登录时 我都会收到此证书安全警报 由于我信任该网站 并且我还需要以编程方式自动登录 因此此对话框会妨碍我 我搜索了解决方案并发现一个和我类似的问题 https stack
  • SetCurrentDirectoryW 中的错误 206

    在我之后之前不清楚的问题 https stackoverflow com questions 44389617 long path name in setcurrentdirectoryw 我以某种方式能够创建一个具有长路径名的目录 但是
  • C#中如何移动PictureBox?

    我已经使用此代码来移动图片框pictureBox MouseMove event pictureBox Location new System Drawing Point e Location 但是当我尝试执行时 图片框闪烁并且无法识别确切
  • VB.NET 中的模块变量何时实例化?

    我想知道在程序的生命周期中 模块中的变量将被初始化 如下例所示 Module Helper Friend m Settings As New UserSettings Sub Foo End Sub Sub Bar End Sub End
  • 如何防止用户控件表单在 C# 中处理键盘输入(箭头键)

    我的用户控件包含其他可以选择的控件 我想实现使用箭头键导航子控件的方法 问题是家长控制拦截箭头键并使用它来滚动其视图什么是我想避免的事情 我想自己解决控制内容的导航问题 我如何控制由箭头键引起的标准行为 提前致谢 MTH 这通常是通过重写

随机推荐