我有两个项目作为单独的进程运行,但属于同一个应用程序:
TMasterMainForm
和TMasterModalForm
)TSlaveForm
)使用此应用程序的典型方法如下:
TMasterMainForm
。TMasterMainForm
中的按钮来运行从属设备。TSlaveForm
。TForm.Handle
TMasterMainForm
发送给Slave。 (通过IPC = WM_COPYDATA)完成步骤5,以便当Slave关闭时,它可以将前景窗口设置回TMasterMainForm
。这样做是为了改善用户体验。
在我们介绍TMasterModalForm
之前,这很好。
TMasterModalForm
可以使用TMasterMainForm
中的其他按钮启动。它是一个单独的窗口,但是以模态显示,并且TMasterMainForm
作为其显式弹出父级。
现在当TSlaveForm
关闭时,Slave应用程序会在SetForegroundWindow
的句柄上调用TMasterMainForm
,但这不再正确,因为有一个模态形式({{1} })在它之上。
所以问题是:
如何管理在这种非常重要的情况下设置前景窗口?
PS:这是一个简化的描述,真正的应用程序也在做这个前台窗口的东西。答案 0 :(得分:5)
您无法将前景窗口设置为主主窗体,因为它已被禁用。它被禁用,因为您正在显示一个模式表单,其所有者是主表单。
显而易见的解决方案是将前景窗口设置为模态窗体而不是主窗体。由于您的奴隶应用程序可能无法轻易知道哪个窗口处于活动状态,因此您应该重新设置IPC以允许从属应用程序向主应用程序询问哪个窗口处于活动状态,然后将其设置为前景窗口。
更优雅的解决方案是让主应用程序调用{{1}}。事实上,从主进程调用SetForegroundWindow
可能更简单。当然,从属进程仍然需要向主服务器发送消息以便调用它。拼图中的最后一部分是处理焦点窃取限制,但你可以使用AllowSetForegroundWindow
来做到这一点。您需要从属进程调用此方法来传递主进程的ID。
答案 1 :(得分:3)
要解决您的问题,我不会从slave应用程序调用SetForegroundWindow,而是将自定义激活消息发送到主应用程序。在此消息中,您可以在WParam或LParam中传递所需的句柄。主应用程序本身可以确定它是否可以激活该句柄,或者需要激活模式窗体。您将激活正确窗口的责任放在应用程序本身中。
PS:您不需要WM_COPYDATA来发送句柄。你可以直接传入你组成的任何消息的WParam或LParam。这就像我上面解释的那样发送回句柄,但也适用于首先发送给从站的句柄。