Comments (16)
@MajorXAML good callout on the caption height and WindowChrome however I think this is a bit more complicated. The style comment indicates the caption height being set to 1 is a workaround to some theming issues, (I think) related to using SingleBorderWindow
WindowStyle:
wpfui/WPFUI/Styles/Controls/Window.xaml
Line 35 in 2ff8a5c
Additionally, we have to contend with the TitleBar
control handling the WindowChrome functionality (instead of the Window). It looks like this was already identified awhile ago from the comments in TitleBar.RootGrid_MouseDown
. I tried enabling the implementation there, and it does work but has a funky side-effect that the window position is offset based on the Window.RestoreBounds value (e.g. when the drag starts, the window is restored to its original position on the screen and offset from the mouse, not under the mouse). It also has the downside of restoring the ParentWindow
when the TitleBar
is simply clicked, which isn't expected behavior.
Since RestoreBounds
can't directly be set, a quick and dirty fix might be simply setting the ParentWindow.Left
and .Top
values after restoring the window on the drag event. In practice though that would likely cause some jumpy window behavior, so definitely not a great solution either.
Edit: fixed some line links
from wpfui.
@Aelarion, I think this is due to the rather non-standard size and asymmetrical arrangement, DPI can also be a problem because it was already troublesome with SnapLayout
from wpfui.
Hey @Aelarion, the DPI tweaks you added greatly improve the window drag behavior. In any case, double-click still randomly does not work.
I don't always get the error, but if I have one Demo app open in the debugger and open a second instance of the application outside of Visual Studio, the second instance easily generates this bug.
I think the app sometimes catches (click + drag + click) instead of (click + click), thus triggering the swipe and ignoring the double-click maximization. Or (click + click (hold) + drag), as a result, it maximizes and restores immediately.
Probably would have to check in MouseMove event whether DoubleClick was there a moment ago
from wpfui.
@pomianowski glad to hear it! On the double click issue that would definitely make sense (click + drag).
I don't want to overstep my bounds but I think maybe we should open a separate issue for the double click / drag clash, seems like maybe we have an opportunity to clean up some logic in the event handlers.
from wpfui.
@Aelarion sure, please send your DPI correction in new PR and I will make a new issue related to double click.
from wpfui.
WindowChrome has all the functionality of a standard window, except for snap layouts. Dragging does not work because of this https://github.com/lepoco/wpfui/blob/main/WPFUI/Styles/Controls/Window.xaml#L50
Increase it to 40-50 and it will work, but the Titlebar buttons will become inactive. To fix that, you need to add this for each button WindowChrome.IsHitTestVisibleInChrome="True"
Btw, snap layout, I do not know how it is implemented, but I think it is buggy.
from wpfui.
Sorry for the comment spam but just wanted to add while fresh in my mind --
There may be some hacky Win32 voodoo we could try strictly when the mouse drags on the TitleBar
control while it is maximized. I remember having to do some SendMessage
/ WM_NCHITTEST
black magic back in my WinForms days ...eyes glaze over thinking about dragging and resizing a WinForm with no title bar...
from wpfui.
I've already tried a bit of Win32 parkour with SnapLayout, and I don't really like these sloppy workarounds.
I think it's best to dig in here and try to get something out
https://github.com/dotnet/wpf/tree/main/src/Microsoft.DotNet.Wpf/src
from wpfui.
After doing a bit more digging it seems like we can set the ParentWindow.Left
and ParentWindow.Top
values prior to changing the WindowState
to prevent that jumpy behavior. From what I can find this is actually the recommended way to do it (see https://stackoverflow.com/questions/11703833/dragmove-and-maximize)
Not sure if it makes more sense to subscribe to this.MouseMove
or the RootGrid
one, but just was playing around and came up with this:
private void RootGrid_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton != MouseButtonState.Pressed || ParentWindow == null) return;
if (IsMaximized)
{
// calculate a point that makes sense to drag from
var point = PointToScreen(e.MouseDevice.GetPosition(this));
ParentWindow.Left = point.X - (ParentWindow.RestoreBounds.Width * 0.5);
ParentWindow.Top = point.Y; // needs some tuning, window is placed a little low on the cursor
// style has to be quickly swapped to None to avoid restore animation delay
var style = ParentWindow.WindowStyle;
ParentWindow.WindowStyle = WindowStyle.None;
ParentWindow.WindowState = WindowState.Normal;
ParentWindow.WindowStyle = style;
ParentWindow.DragMove();
}
}
In this case, I was specifically avoiding calling MaximizeWindow()
to restore, since I'm not sure we want to respect the MaximizeActionOverride
for WindowChrome behavior.
This actually works pretty good for the maximize-->drag functionality. As you can see in the implementation, we have to change the WindowStyle to None
for a brief moment -- without doing this, you end up with a delay for the restore animation to play which is really annoying (and actually ends up messing with the drag location under the mouse).
The only snag I have with this is seeing like a frame or two of jank -- I can't quite put my finger on what's causing it, but it seems it's either the rendering while the WindowStyle is set to None
or something with resizing (or both). All in all though, it's pretty tolerable.
Edit: adding gif to show working POC, unfortunately this doesn't capture the frame of jank
And here's a quick screen cap of the resize jank frame:
from wpfui.
@Aelarion When dragged from the edge in the multi-monitor setup it throws the application to the side.
from wpfui.
Also, double-click stopped working sometimes
from wpfui.
@pomianowski hmm, I tried this across 2 side by side monitors, I'm not able to reproduce the issue. I also am not sure how double clicking would be effected, I can't reproduce that issue either. Unless there's somewhere that the MouseMove event is stepping on the MouseDown event
I think definitely an issue to address though is this line:
wpfui/WPFUI/Controls/TitleBar.cs
Line 484 in a0795c3
I didn't consider this before but in a multi-monitor setup, where the "top" screen coordinates might be negative, this would cause monitor jumping. Definitely can fix setting to ParentWindow.Top = screenPoint.Y
instead of hardcoded 0
.
Can you just try that workaround to see if it helps with the window jumping? It's the only thing I can think of, other than maybe the Left
calculation getting screwed up by DPI scaling or something funky:
wpfui/WPFUI/Controls/TitleBar.cs
Line 483 in a0795c3
from wpfui.
Just tried scaling my monitor DPI way up to 150%, yup that was the problem. That's my own fault for not RTFM'ing on PointToScreen
and DPI-aware funkiness with the application.
I will work on a fix for this -- essentially would just need to account for the scaling and multiple the final Left
and Top
values by appropriate X and Y DPI scaling factors and should be good to go.
from wpfui.
Just troubleshooting with DPI scaling, I can get this working, the only issue I see is in .NET Framework 4.6 VisualTreeHelper.GetDpi
is not available (starts at 4.6.2). As a workaround, we can grab DPI values from Reflection, but that has its own trade-offs.
Can you see if this works for you? The asymmetrical window arrangement will have to be a separate issue I tackle -- just want to get the basic math stuff right first.
private void RootGrid_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton != MouseButtonState.Pressed || ParentWindow == null) return;
if (IsMaximized)
{
var dpiXProperty = typeof(SystemParameters).GetProperty("DpiX", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
var dpiYProperty = typeof(SystemParameters).GetProperty("Dpi", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
var dpiX = (int)dpiXProperty.GetValue(null, null);
var dpiY = (int)dpiYProperty.GetValue(null, null);
//var dpi = VisualTreeHelper.GetDpi(ParentWindow); --> not available in .NET 4.6
var screenPoint = PointToScreen(e.MouseDevice.GetPosition(this));
screenPoint.X *= (96.0 / dpiX);
screenPoint.Y *= (96.0 / dpiY);
// TODO: refine the Left value to be more accurate
// - This calculation is good enough using the center
// of the titlebar, however this isn't quite accurate for
// how the OS operates.
// - It should be set as a % (e.g. screen X / maximized width),
// then offset from the left to line up more naturally.
//ParentWindow.Left = dpi.DpiScaleX * (screenPoint.X - (ParentWindow.RestoreBounds.Width * 0.5));
//ParentWindow.Top = dpi.DpiScaleY * screenPoint.Y;
ParentWindow.Left = screenPoint.X - (ParentWindow.RestoreBounds.Width * 0.5);
ParentWindow.Top = screenPoint.Y;
// style has to be quickly swapped to avoid restore animation delay
var style = ParentWindow.WindowStyle;
ParentWindow.WindowStyle = WindowStyle.None;
ParentWindow.WindowState = WindowState.Normal;
ParentWindow.WindowStyle = style;
ParentWindow.DragMove();
}
}
EDIT: fixed typo for DPI Y property ("Dpi" not "DpiY")
from wpfui.
It begins to seem to me that this class has too much responsibility, can you set up a separate class to manage DPI and screen stuff?
from wpfui.
@pomianowski agreed, will do when I get some more time tonight. Can you just confirm when you have time to test that the above code works for the window jumping issue you were seeing?
from wpfui.
Related Issues (20)
- Display icons for BreadcrumbBar from NavigationViewItem
- nuget.org naming HOT 2
- Target runtime win-x64 publish failed HOT 1
- ResizeMode="CanMinimize" is not working
- Timepicker does not work
- WebView & WebView2 Do Not Properly Respond to Arrow Key Inputs HOT 2
- Why does NavigationView not support menu groups without head page HOT 1
- I would like to see support not only for Mica but also for acrylic.
- Navigation issue with dynamically added NavigationViewItem HOT 1
- WPF UI Gallery Problem
- Option to disable the Application.Current
- Icon is not working HOT 3
- DataGrid selection and right click Event
- Snackbar no longer appears when setting Opacity via App.xaml style
- Blank project is garbage that doesn't work due to an error.
- TitleBarButton not found in xaml (Binding Error)
- How to pass parameters in navigation HOT 2
- Tutorial link in README.md broken
- Questdb.Net
- A minimal guide to a minimal, themed, single-window project. HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from wpfui.