Unity3d user32.dll 拖动窗口并重新获得焦点

Posted

技术标签:

【中文标题】Unity3d user32.dll 拖动窗口并重新获得焦点【英文标题】:Unity3d user32.dll drag window and take focus back 【发布时间】:2017-09-27 11:26:46 【问题描述】:

我制作了一个无边框的窗口应用程序和一个“假”标题栏来拖动它。

我正在使用 user32.dll,

这个启动窗口拖动(由统一IBeginDragHandler触发):

public const int WM_NCLBUTTONDOWN = 0xA1;
public const int WM_NCLBUTTONUP = 0x00A2;
public const int WM_LBUTTONUP = 0x0202;

[DllImport("User32.dll")]
public static extern bool ReleaseCapture();

[DllImport("User32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);

IntPtr window = GetActiveWindow();
...
...
ReleaseCapture();
SendMessage(window, WM_NCLBUTTONDOWN, HTCAPTION, 0);

这个停止拖动(不确定这部分):

    ReleaseCapture();
    SendMessage(window, WM_NCLBUTTONUP, HTCAPTION, 0);
    SendMessage(window, WM_LBUTTONUP, HTCAPTION, 0);

它在编辑器和构建时运行良好,但在开发构建时产生错误:

出现异常情况:PlayerLoop内部函数 已被递归调用。请联系客户支持 示例项目,以便我们可以重现问题并进行故障排除 它。 LauncherWindow:SendMessage(IntPtr, Int32, Int32, Int32) LauncherWindow:StartWindowDrag()(位于 E:\Unity Projects\Crime Club Launcher\Assets\Scripts\Lib\LauncherWindow.cs:115) WindowDragZone:UnityEngine.EventSystems.IBeginDragHandler.OnBeginDrag(PointerEventData) (在 E:\Unity Projects\Crime Club Launcher\Assets\WindowDragZone.cs:9) UnityEngine.EventSystems.ExecuteEvents:执行(IBeginDragHandler, BaseEventData) (在 C:\buildslave\unity\build\Extensions\guisystem\UnityEngine.UI\EventSystem\ExecuteEvents.cs:64) UnityEngine.EventSystems.ExecuteEvents:执行(游戏对象, BaseEventData, EventFunction`1) (在 C:\buildslave\unity\build\Extensions\guisystem\UnityEngine.UI\EventSystem\ExecuteEvents.cs:261) UnityEngine.EventSystems.PointerInputModule:ProcessDrag(PointerEventData) (在 C:\buildslave\unity\build\Extensions\guisystem\UnityEngine.UI\EventSystem\InputModules\PointerInputModule.cs:261) UnityEngine.EventSystems.StandaloneInputModule:ProcessMouseEvent(Int32) (在 C:\buildslave\unity\build\Extensions\guisystem\UnityEngine.UI\EventSystem\InputModules\StandaloneInputModule.cs:434) UnityEngine.EventSystems.StandaloneInputModule:ProcessMouseEvent()(在 C:\buildslave\unity\build\Extensions\guisystem\UnityEngine.UI\EventSystem\InputModules\StandaloneInputModule.cs:412) UnityEngine.EventSystems.StandaloneInputModule:Process()(在 C:\buildslave\unity\build\Extensions\guisystem\UnityEngine.UI\EventSystem\InputModules\StandaloneInputModule.cs:186) UnityEngine.EventSystems.EventSystem:Update()(在 C:\buildslave\unity\build\Extensions\guisystem\UnityEngine.UI\EventSystem\EventSystem.cs:283)

您对此有何看法?

编辑: 好的,所以我终于通过替换摆脱了那个错误

SendMessage(window, WM_NCLBUTTONDOWN, HTCAPTION, 0);

作者:

private const int WM_SYSCOMMAND = 0x112;
private const int MOUSE_MOVE = 0xF012;
SendMessage(window, WM_SYSCOMMAND, MOUSE_MOVE, 0);

现在我有最后一个小问题: 窗口在鼠标释放时被拖放,但我看起来窗口正在失去对类似内容的关注: 第一次点击总是错过,我必须点击两次才能再次拖动或简单地与统一应用程序交互。

我在 OnEndDrag 中尝试了 User32 的函数: ShowWindow、SetActiveWindow、SetFocus 等... 我发现的所有内容都与该问题有关,但它们都没有明显的效果,我仍然必须单击两次。

【问题讨论】:

您能提供更多上下文吗?你想达到什么目的?你的部署目标是什么? 当然。我正在制作一个统一的游戏启动器,它将显示最新消息,必要时管理文件更新,并启动游戏。现在这个启动器只适用于我的游戏的 windows 版本。它将以固定分辨率以窗口模式(= 非全屏)运行。我想删除窗口标题栏(-popupwindow 参数)并使用我自己的按钮退出/最小化启动器并拖放它的窗口。通过一些搜索,我找到了 User32.dll 并且能够完全按照我的意愿进行操作,只是在删除结束时我仍然收到此错误。 和你的开始拖动代码? 窗口拖动正常,但是当我释放鼠标按钮时,我得到了那个错误,我必须在拖动区域上单击两次才能让它再次拖动。我不确定我是否以正确的方式使用 User32 @Smartis 好的,我终于明白了,你能看看我的编辑吗?如果您曾经使用过 user32.dll,我还有一个小问题 【参考方案1】:

终于摆脱了这个错误,将 SendMessage() 替换为:

SendMessageCallback(window, WM_SYSCOMMAND, MOUSE_MOVE, 0, WindowDropCallback, 0);

【讨论】:

以上是关于Unity3d user32.dll 拖动窗口并重新获得焦点的主要内容,如果未能解决你的问题,请参考以下文章

Unity3D 获取主窗口句柄

使用 user32.dll 获取特定窗口的句柄

尝试从 user32.dll 的 GetWindowText() 读取窗口时发生“System.ExecutionEngineException”类型的未处理异常

Unity3D GUI 拖动窗口

unity3d中拖动图片进去感觉被遮挡了

如何在 c# 中使用 user32.dll 从类“ThunderRT6ListBox”的窗口中检索值