diff --git a/docs/Changelog.md b/docs/Changelog.md index b2f9177..1e58347 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -4,11 +4,14 @@ - There is an issue with the `window-scale` mpv property, it does not work correctly in mpv either, so I've removed support for it and - added an own implementation `script-message mpv.net window-scale`. + added my own implementation `script-message mpv.net window-scale`. - The previous Beta replaced the CS-Script library with my own C# scripting implementation. - If a player window border is near to a screen border and the window size changes, the player windows sticks to that near screen border location. + Furthermore the `remember-position` option remembers a near screen border + position instead of remembering the window center position. +- High DPI multi monitor fix. - `start-size` option has new options, see in config editor and manual. diff --git a/src/App.config b/src/App.config index 6eb6c18..ccc7a5d 100644 --- a/src/App.config +++ b/src/App.config @@ -5,4 +5,4 @@ - + \ No newline at end of file diff --git a/src/Misc/Help.cs b/src/Misc/Help.cs index f604c4f..c6200bd 100644 --- a/src/Misc/Help.cs +++ b/src/Misc/Help.cs @@ -167,6 +167,11 @@ namespace mpvnet { public static string ApplicationKey { get; } = @"HKCU\Software\" + Application.ProductName; + public static void SetInt(string name, object value) + { + SetValue(ApplicationKey, name, value); + } + public static void SetValue(string path, string name, object value) { using (RegistryKey regKey = GetRootKey(path).CreateSubKey(path.Substring(5), RegistryKeyPermissionCheck.ReadWriteSubTree)) diff --git a/src/Misc/Program.cs b/src/Misc/Program.cs index eb706ac..89892ea 100644 --- a/src/Misc/Program.cs +++ b/src/Misc/Program.cs @@ -21,7 +21,7 @@ namespace mpvnet Application.SetCompatibleTextRenderingDefault(false); if (App.IsStartedFromTerminal) - WinAPI.AttachConsole(-1 /*ATTACH_PARENT_PROCESS*/); + Native.AttachConsole(-1 /*ATTACH_PARENT_PROCESS*/); if (core.ConfigFolder == "") return; @@ -73,15 +73,15 @@ namespace mpvnet { if (proc.MainWindowHandle != IntPtr.Zero) { - WinAPI.AllowSetForegroundWindow(proc.Id); - var data = new WinAPI.COPYDATASTRUCT(); + Native.AllowSetForegroundWindow(proc.Id); + var data = new Native.COPYDATASTRUCT(); data.lpData = string.Join("\n", args2.ToArray()); data.cbData = data.lpData.Length * 2 + 1; - WinAPI.SendMessage(proc.MainWindowHandle, 0x004A /*WM_COPYDATA*/, IntPtr.Zero, ref data); + Native.SendMessage(proc.MainWindowHandle, 0x004A /*WM_COPYDATA*/, IntPtr.Zero, ref data); mutex.Dispose(); if (App.IsStartedFromTerminal) - WinAPI.FreeConsole(); + Native.FreeConsole(); return; } @@ -97,7 +97,7 @@ namespace mpvnet Application.Run(new MainForm()); if (App.IsStartedFromTerminal) - WinAPI.FreeConsole(); + Native.FreeConsole(); mutex.Dispose(); } diff --git a/src/Native/Native.cs b/src/Native/Native.cs index 25a1e27..7e838b3 100644 --- a/src/Native/Native.cs +++ b/src/Native/Native.cs @@ -3,8 +3,10 @@ using System; using System.Drawing; using System.Runtime.InteropServices; -public class WinAPI +public class Native { + static Version Windows_10_1607 = new Version(10, 0, 14393); // Windows 10 1607 + [DllImport("kernel32.dll")] public static extern bool AttachConsole(int dwProcessId); @@ -36,9 +38,16 @@ public class WinAPI [DllImport("user32.dll")] public static extern void ReleaseCapture(); + [DllImport("user32.dll")] + public static extern int GetDpiForWindow(IntPtr hwnd); + [DllImport("user32.dll")] public static extern bool AdjustWindowRect(ref RECT lpRect, uint dwStyle, bool bMenu); + [DllImport("user32.dll")] + public static extern bool AdjustWindowRectExForDpi( + ref RECT lpRect, uint dwStyle, bool bMenu, uint dwExStyle, uint dpi); + [DllImport("user32.dll")] public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags); @@ -97,4 +106,50 @@ public class WinAPI [MarshalAs(UnmanagedType.LPTStr)] public string lpData; } + + public static int GetResizeBorder(int v) + { + switch (v) + { + case 1 /* WMSZ_LEFT */ : return 3; + case 3 /* WMSZ_TOP */ : return 2; + case 2 /* WMSZ_RIGHT */ : return 3; + case 6 /* WMSZ_BOTTOM */ : return 2; + case 4 /* WMSZ_TOPLEFT */ : return 1; + case 5 /* WMSZ_TOPRIGHT */ : return 1; + case 7 /* WMSZ_BOTTOMLEFT */ : return 3; + case 8 /* WMSZ_BOTTOMRIGHT */ : return 3; + default: return -1; + } + } + + public static void SubtractWindowBorders(IntPtr hwnd, ref RECT rc, int dpi) + { + RECT r = new RECT(0, 0, 0, 0); + AddWindowBorders(hwnd, ref r, dpi); + rc.Left -= r.Left; + rc.Top -= r.Top; + rc.Right -= r.Right; + rc.Bottom -= r.Bottom; + } + + public static void AddWindowBorders(IntPtr hwnd, ref RECT rc, int dpi) + { + uint windowStyle = (uint)GetWindowLong(hwnd, -16); // GWL_STYLE + uint windowStyleEx = (uint)GetWindowLong(hwnd, -20); // GWL_EXSTYLE + + if (Environment.OSVersion.Version >= Windows_10_1607) + AdjustWindowRectExForDpi(ref rc, windowStyle, false, windowStyleEx, (uint)dpi); + else + AdjustWindowRect(ref rc, windowStyle, false); + } + + public static int GetDPI(IntPtr hwnd) + { + if (Environment.OSVersion.Version >= Windows_10_1607) + return GetDpiForWindow(hwnd); + else + using (Graphics gx = Graphics.FromHwnd(hwnd)) + return GetDeviceCaps(gx.GetHdc(), 88 /*LOGPIXELSX*/); + } } diff --git a/src/Native/NativeHelp.cs b/src/Native/NativeHelp.cs deleted file mode 100644 index 4522676..0000000 --- a/src/Native/NativeHelp.cs +++ /dev/null @@ -1,41 +0,0 @@ - -using System; - -using static WinAPI; - -namespace mpvnet -{ - public static class NativeHelp - { - public static int GetResizeBorder(int v) - { - switch (v) - { - case 1 /* WMSZ_LEFT */ : return 3; - case 3 /* WMSZ_TOP */ : return 2; - case 2 /* WMSZ_RIGHT */ : return 3; - case 6 /* WMSZ_BOTTOM */ : return 2; - case 4 /* WMSZ_TOPLEFT */ : return 1; - case 5 /* WMSZ_TOPRIGHT */ : return 1; - case 7 /* WMSZ_BOTTOMLEFT */ : return 3; - case 8 /* WMSZ_BOTTOMRIGHT */ : return 3; - default: return -1; - } - } - - public static void SubtractWindowBorders(IntPtr hwnd, ref RECT rc) - { - RECT r = new RECT(0, 0, 0, 0); - AddWindowBorders(hwnd, ref r); - rc.Left -= r.Left; - rc.Top -= r.Top; - rc.Right -= r.Right; - rc.Bottom -= r.Bottom; - } - - public static void AddWindowBorders(IntPtr hwnd, ref RECT rc) - { - AdjustWindowRect(ref rc, (uint)GetWindowLong(hwnd, -16 /* GWL_STYLE */), false); - } - } -} diff --git a/src/WinForms/MainForm.cs b/src/WinForms/MainForm.cs index f1a7ece..e9da7eb 100644 --- a/src/WinForms/MainForm.cs +++ b/src/WinForms/MainForm.cs @@ -10,7 +10,7 @@ using System.ComponentModel; using System.Globalization; using static mpvnet.Core; -using static WinAPI; +using static Native; namespace mpvnet { @@ -19,12 +19,13 @@ namespace mpvnet public static MainForm Instance { get; set; } public static IntPtr Hwnd { get; set; } public new ContextMenuStripEx ContextMenu { get; set; } - Point LastCursorPosition; - int LastCursorChanged; - int LastCycleFullscreen; - int LastAppCommand; - int TaskbarButtonCreatedMessage; - int ShownTickCount; + Point LastCursorPosition; + + int LastCursorChanged; + int LastCycleFullscreen; + int LastAppCommand; + int TaskbarButtonCreatedMessage; + int ShownTickCount; Taskbar Taskbar; List RecentFiles; @@ -107,11 +108,19 @@ namespace mpvnet int posX = RegistryHelp.GetInt("PosX"); int posY = RegistryHelp.GetInt("PosY"); - - if (posX != 0 && posY != 0 && App.RememberPosition) + + if ((posX != 0 || posY != 0) && App.RememberPosition) { Left = posX - Width / 2; Top = posY - Height / 2; + + int horizontal = RegistryHelp.GetInt("HorizontalLocation"); + int vertical = RegistryHelp.GetInt("VerticalLocation"); + + if (horizontal == -1) Left = posX; + if (horizontal == 1) Left = posX - Width; + if (vertical == -1) Top = posY; + if (vertical == 1) Top = posY - Height; } if (core.WindowMaximized) @@ -452,17 +461,18 @@ namespace mpvnet Point middlePos = new Point(Left + Width / 2, Top + Height / 2); var rect = new RECT(new Rectangle(screen.Bounds.X, screen.Bounds.Y, width, height)); - NativeHelp.AddWindowBorders(Handle, ref rect); + AddWindowBorders(Handle, ref rect, GetDPI(Handle)); + int left = middlePos.X - rect.Width / 2; int top = middlePos.Y - rect.Height / 2; Rectangle workingArea = screen.WorkingArea; Rectangle currentRect = new Rectangle(Left, Top, Width, Height); - if (HorizontalLocation(screen) == -1) left = Left; - if (HorizontalLocation(screen) == 1) left = currentRect.Right - rect.Width; + if (GetHorizontalLocation(screen) == -1) left = Left; + if (GetHorizontalLocation(screen) == 1) left = currentRect.Right - rect.Width; - if (VerticalLocation(screen) == -1) top = Top; - if (VerticalLocation(screen) == 1) top = currentRect.Bottom - rect.Height; + if (GetVerticalLocation(screen) == -1) top = Top; + if (GetVerticalLocation(screen) == 1) top = currentRect.Bottom - rect.Height; Screen[] screens = Screen.AllScreens; int minLeft = screens.Select(val => val.WorkingArea.X).Min(); @@ -485,11 +495,14 @@ namespace mpvnet SetWindowPos(Handle, IntPtr.Zero, left, top, rect.Width, rect.Height, 4); } - public int HorizontalLocation(Screen screen) + public int GetHorizontalLocation(Screen screen) { Rectangle workingArea = screen.WorkingArea; Rectangle rect = new Rectangle(Left - workingArea.X, Top - workingArea.Y, Width, Height); + if (workingArea.Width / (float)Width < 1.2) + return 0; + if (rect.X * 3 < workingArea.Width - rect.Right) return -1; @@ -499,11 +512,14 @@ namespace mpvnet return 0; } - public int VerticalLocation(Screen screen) + public int GetVerticalLocation(Screen screen) { Rectangle workingArea = screen.WorkingArea; Rectangle rect = new Rectangle(Left - workingArea.X, Top - workingArea.Y, Width, Height); + if (workingArea.Height / (float)Height < 1.2) + return 0; + if (rect.Y * 3 < workingArea.Height - rect.Bottom) return -1; @@ -623,13 +639,35 @@ namespace mpvnet { if (WindowState == FormWindowState.Normal) { - RegistryHelp.SetValue(App.RegPath, "PosX", Left + Width / 2); - RegistryHelp.SetValue(App.RegPath, "PosY", Top + Height / 2); + SavePosition(); + RegistryHelp.SetValue(App.RegPath, "Width", ClientSize.Width); RegistryHelp.SetValue(App.RegPath, "Height", ClientSize.Height); } } + void SavePosition() + { + int posX = Left + Width / 2; + int posY = Top + Height / 2; + + Screen screen = Screen.FromControl(this); + + int x = GetHorizontalLocation(screen); + int y = GetVerticalLocation(screen); + + if (x == -1) posX = Left; + if (x == 1) posX = Left + Width; + if (y == -1) posY = Top; + if (y == 1) posY = Top + Height; + + RegistryHelp.SetInt("PosX", posX); + RegistryHelp.SetInt("PosY", posY); + + RegistryHelp.SetInt("HorizontalLocation", x); + RegistryHelp.SetInt("VerticalLocation", y); + } + protected override CreateParams CreateParams { get { CreateParams cp = base.CreateParams; @@ -726,27 +764,28 @@ namespace mpvnet break; case 0x0214: // WM_SIZING { - var rc = Marshal.PtrToStructure(m.LParam); - var r = rc; - NativeHelp.SubtractWindowBorders(Handle, ref r); + RECT rc = Marshal.PtrToStructure(m.LParam); + RECT r = rc; + SubtractWindowBorders(Handle, ref r, GetDPI(Handle)); + int c_w = r.Right - r.Left, c_h = r.Bottom - r.Top; - Size s = core.VideoSize; + Size videoSize = core.VideoSize; - if (s == Size.Empty) - s = new Size(16, 9); + if (videoSize == Size.Empty) + videoSize = new Size(16, 9); - float aspect = s.Width / (float)s.Height; + float aspect = videoSize.Width / (float)videoSize.Height; int d_w = (int)(c_h * aspect - c_w); int d_h = (int)(c_w / aspect - c_h); int[] d_corners = { d_w, d_h, -d_w, -d_h }; int[] corners = { rc.Left, rc.Top, rc.Right, rc.Bottom }; - int corner = NativeHelp.GetResizeBorder(m.WParam.ToInt32()); + int corner = GetResizeBorder(m.WParam.ToInt32()); if (corner >= 0) corners[corner] -= d_corners[corner]; - Marshal.StructureToPtr(new RECT(corners[0], corners[1], corners[2], corners[3]), m.LParam, false); + Marshal.StructureToPtr(new RECT(corners[0], corners[1], corners[2], corners[3]), m.LParam, false); m.Result = new IntPtr(1); } return; diff --git a/src/mpv.net.csproj b/src/mpv.net.csproj index 924465d..0dba253 100644 --- a/src/mpv.net.csproj +++ b/src/mpv.net.csproj @@ -149,7 +149,6 @@ - diff --git a/src/mpv/Core.cs b/src/mpv/Core.cs index 3b25732..6cc582b 100644 --- a/src/mpv/Core.cs +++ b/src/mpv/Core.cs @@ -248,13 +248,11 @@ namespace mpvnet if (!File.Exists(_ConfigFolder + "mpv.conf")) { string conf = Properties.Resources.mpv_conf; - Graphics gx = Graphics.FromHwnd(IntPtr.Zero); - float scale = WinAPI.GetDeviceCaps(gx.GetHdc(), 88 /*LOGPIXELSX*/) / 96.0f; + float scale = Native.GetDPI(IntPtr.Zero) / 96.0f; if (scale != 1) conf = conf.Replace("console-scale=1", "console-scale=" + scale); - gx.Dispose(); File.WriteAllText(_ConfigFolder + "mpv.conf", conf); } } @@ -356,7 +354,7 @@ namespace mpvnet mpv_event evt = (mpv_event)Marshal.PtrToStructure(ptr, typeof(mpv_event)); if (WindowHandle == IntPtr.Zero) - WindowHandle = WinAPI.FindWindowEx(MainForm.Hwnd, IntPtr.Zero, "mpv", null); + WindowHandle = Native.FindWindowEx(MainForm.Hwnd, IntPtr.Zero, "mpv", null); //Debug.WriteLine(evt.event_id.ToString()); @@ -1210,9 +1208,9 @@ namespace mpvnet string dll = Environment.GetEnvironmentVariable("AviSynthDLL"); if (File.Exists(dll)) - WinAPI.LoadLibrary(dll); + Native.LoadLibrary(dll); else - WinAPI.LoadLibrary("AviSynth.dll"); + Native.LoadLibrary("AviSynth.dll"); WasAviSynthLoaded = true; }