8

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.

FLX
  • 2,626
  • 4
  • 26
  • 57
  • Could you provide more context? What are you trying to achieve? Whats your deploy target? – Smartis has left SO again May 03 '17 at 08:33
  • Sure. I'm making a game launcher with unity, that will show latest news, manage files updates if necessary, and launch the game. For now this launcher is just for the windows version of my game. It will be runned in windowed mode (= not fullscreen), at a fixed resolution. I want to remove the windows title bar (-popupwindow argument) and use my own buttons to exit/minimize the launcher and drag&drop it's window. With some search I found User32.dll and was able to do exactly what I wanted, except that I still got this error at the end of the drop. – FLX May 03 '17 at 12:05
  • and your code for start dragging? – Smartis has left SO again May 03 '17 at 12:08
  • The window is dragging fine, but when I release the mouse button I got that error and I must click twice on the drag zone to make it drag again. I'm not really sure that i'm using User32 the right way – FLX May 03 '17 at 12:09
  • The code to start dragging is the last two lines in the first code block of my post, this is placed is the OnDrag function of IBeginDragHandler : "ReleaseCapture(); SendMessage(window, WM_NCLBUTTONDOWN, HTCAPTION, 0);" – FLX May 03 '17 at 12:11
  • 1
    @Smartis Ok I finally got it, can you have a look at my edit ? I have a last little question if you ever worked with user32.dll – FLX May 04 '17 at 06:17
  • Did you try to activate the window's focus? http://stackoverflow.com/a/3787106/856152 – Smartis has left SO again May 04 '17 at 12:56
  • Well, I tried functions like SetActiveWindow, ShowWindow... I don't remember using SetForegroundWindow so i will try that tonight. In your link, TheCodeKing is importing this function as SetForegroundWindowNative, and is wrapping it into his own SetForegroundWindow function. Can you tell me more about the purpose of this ? Is it necessary and/or a pattern that I should know ? Thanks a lot – FLX May 04 '17 at 13:13
  • I tried SetForeground but got no result. I then understood that OnEndDrag was never called because of the focus loss. I replaced SendMessage with SendMessageCallback and the callback works. However, I tried every functions I found but i'm still not able to get the focus back in unity... – FLX May 05 '17 at 08:32
  • Encountering this 4 years later... did you ever figure out how to get back the unity window focus? – rygo6 Feb 11 '21 at 04:38
  • @rygo6 : In the WindowDropCallback, execute the SetFocus method (you have to import it from user32.dll) – FLX Mar 07 '21 at 10:42
  • did you by chance ever get window resizing to work as well? – rygo6 Mar 08 '21 at 06:17
  • No, I only needed a small window. – FLX Mar 19 '21 at 12:51

1 Answers1

3

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

SendMessageCallback(window, WM_SYSCOMMAND, MOUSE_MOVE, 0, WindowDropCallback, 0);
FLX
  • 2,626
  • 4
  • 26
  • 57