Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unity3d user32.dll drag window and take focus back

Tags:

c#

unity3d

user32

I made a borderless windowed application and a "fake" title bar to drag it.

I'm using user32.dll,

This to start the window drag (triggered by unity 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);

And this to stop dragging (not sure about this part):

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

It works well on editor and on build, but an error spawn on developpement build :

An abnormal situation has occurred: the PlayerLoop internal function has been called recursively. Please contact Customer Support with a sample project so that we can reproduce the problem and troubleshoot it. LauncherWindow:SendMessage(IntPtr, Int32, Int32, Int32) LauncherWindow:StartWindowDrag() (at E:\Unity Projects\Crime Club Launcher\Assets\Scripts\Lib\LauncherWindow.cs:115) WindowDragZone:UnityEngine.EventSystems.IBeginDragHandler.OnBeginDrag(PointerEventData) (at E:\Unity Projects\Crime Club Launcher\Assets\WindowDragZone.cs:9) UnityEngine.EventSystems.ExecuteEvents:Execute(IBeginDragHandler, BaseEventData) (at C:\buildslave\unity\build\Extensions\guisystem\UnityEngine.UI\EventSystem\ExecuteEvents.cs:64) UnityEngine.EventSystems.ExecuteEvents:Execute(GameObject, BaseEventData, EventFunction`1) (at C:\buildslave\unity\build\Extensions\guisystem\UnityEngine.UI\EventSystem\ExecuteEvents.cs:261) UnityEngine.EventSystems.PointerInputModule:ProcessDrag(PointerEventData) (at C:\buildslave\unity\build\Extensions\guisystem\UnityEngine.UI\EventSystem\InputModules\PointerInputModule.cs:261) UnityEngine.EventSystems.StandaloneInputModule:ProcessMouseEvent(Int32) (at C:\buildslave\unity\build\Extensions\guisystem\UnityEngine.UI\EventSystem\InputModules\StandaloneInputModule.cs:434) UnityEngine.EventSystems.StandaloneInputModule:ProcessMouseEvent() (at C:\buildslave\unity\build\Extensions\guisystem\UnityEngine.UI\EventSystem\InputModules\StandaloneInputModule.cs:412) UnityEngine.EventSystems.StandaloneInputModule:Process() (at C:\buildslave\unity\build\Extensions\guisystem\UnityEngine.UI\EventSystem\InputModules\StandaloneInputModule.cs:186) UnityEngine.EventSystems.EventSystem:Update() (at C:\buildslave\unity\build\Extensions\guisystem\UnityEngine.UI\EventSystem\EventSystem.cs:283)

What do you think about this ?

EDIT : Okay so I finally got rid of that error by replacing

SendMessage(window, WM_NCLBUTTONDOWN, HTCAPTION, 0);

by :

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

Now I have a last little problem : The windows is dragged, dropped on mouse release, but I look like the window is loosing the focus on something like that : The first click always miss, I must click twice to be able to drag again or simply interact with the unity app.

I tried functions from User32 in OnEndDrag : ShowWindow, SetActiveWindow, SetFocus, etc... Everything I found related to that problem, but they all have no visible effect and I still must click twice.

like image 495
FLX Avatar asked Apr 29 '17 12:04

FLX


1 Answers

Finally got rid of this error by replacing SendMessage() by :

SendMessageCallback(window, WM_SYSCOMMAND, MOUSE_MOVE, 0, WindowDropCallback, 0);
like image 167
FLX Avatar answered Oct 22 '22 17:10

FLX