Window Location Animation - wpf

I'm trying to animate my window's location.
SCENARIO:
I have a window, and when i click on my button, I want the window to move smoothly 100px from it's current location.
EXAMPLE:
Private Sub minimize_button_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles minimize_button.Click
Dim windowsize as integer = window1.top
windowsize = windowsize - 100
End Sub
But with XAML animation. I have no idea how to make this animation in this type of scenario.
Any answer is appreciated, Sincerely VenoMDee.

I don't believe you're going to be able to do this with a XAML animation, but you could still achieve this effect through either a DispatcherTimer or a Storyboard.
With every tick (time-based frame) you can reset the position of the window in code. Just fire the ticks of the timer to reproduce about 40 frames per second (every 150 milliseconds).
Hope that helps!

Here are a bit of a simpler solution:
if your trying to make you animation smooth, you need a Timer, but for every timer1.tick you need to decrease the interval unless it's > screen height. This will make it go faster the further it currently is. I've worked with this method before and the animation is really nice.
Timer1.Interval -= 1
Me.top = Me.Top * 1.05
If Me.Top > My.Computer.Screen.Bounds.Height Then
Timer1.Enabled = False
End If
Hope this helped!

Related

How to Set the Background of WPF Control and Ensure Rendering Immediately When Visible?

I have a WPF application that takes a screenshot of the contents of a WindowsFormsHost control and applies it to the background of a Grid control. The Grid acts as a transition screen from the WindowsFormsHost to other WPF controls. This is done to make a smooth transition effect and to avoid air space issues. I first capture the WinFormsHost control image as a bitmap and apply it to the Grid background. Then programmatically change the visibility of the transition Grid to visible. Then do an opacity animation to smoothly show another control. It works perfectly about 70 to 90 percent of the time depending on what computer I test the application on. The problem is that the transition Grid background is not being rendered fast enough or at the correct time. So that occasionally I am seeing a screenshot from a previous transition which does not match the current screen image at transition time.
If I could somehow ensure that the transition image was drawn before the Grid is made visible, it would work everytime. I just cannot see how to do this. The application seems to always wait until the last minute to do any rendering.
I have tried to force rendering with Dispatcher.Invoke() and Dispatcher.BeginInvoke() methods. I have also tried to delay the time when the Grid is made visible with a Dispatcher Timer, but no matter how much time there is between the call setting the background image and setting the visibility, the Grid does not always update. I have also tried things like InvalidateVisual() with no luck.
After looking at many examples into problems involving WPF's rending and UI threads, I made several attempts to correct the problem...
Attempt 1 - Works poorly, but attempt works better with a line of code that first sets background to nothing or black:
TransitionScreen.Visibility = Visibility.Visible
TransitionScreen.Background = Nothing
TransitionScreen.Background = New ImageBrush(BitmapToImageSource(GrabScreenshot(ScreenWidth, ScreenHeight)))
State = "WPFControlMode"
SwitchState()
Attempt 2 - Best results so far. Works fair to well depending on computer. Increasing the counter value does not improve results. The appearance of the TransitionScreen will be delayed with a larger counter value, but will have the same chance of showing a previous screenshot (about 1 in 5 times on my laptop):
Case "Transition"
'Grab Screen Shot and apply to transition screen...'
TransitionScreen.Visibility = Visibility.Visible
TransitionScreen.Background = Nothing
TransitionScreen.Background = New ImageBrush(BitmapToImageSource(GrabScreenshot(ScreenWidth, ScreenHeight)))
End Select
'The following code is inside a loop...'
If State = "Transition" Then
TransitionCounter += 1
If TransitionCounter = 25 Then
TransitionCounter = 0
TransitionScreen.Visibility = Visibility.Visible
TransitionScreen.Background = Nothing
TransitionScreen.Background = New ImageBrush(BitmapToImageSource(GrabScreenshot(ScreenWidth, ScreenHeight)))
State = "WPFControlMode"
SwitchState()
End If
End If
Attempt 3, 4, 5, ... - Attempts try to force rendering of control by working through Dispatcher. These attempts do not appear to help and often make the problem worse. They have been used in combination with both attempts 1 and 2.
Case "Transition"
'Grab Screen Shot and apply to transition screen...'
TransitionScreen.Visibility = Visibility.Visible
TransitionScreen.Background = Nothing
TransitionScreen.Background = New ImageBrush(BitmapToImageSource(GrabScreenshot(ScreenWidth, ScreenHeight)))
FlushWindowsMessageQueue()
End Select
'Tried many variations of the following procedure. Every dispatcher priority with both BeginInvoke and Invoke methods, as well as calling the methods through Application and TransitionScreen objects.'
Private Sub FlushWindowsMessageQueue()
Application.Current.Dispatcher.Invoke( _
New Action(AddressOf DummySub), _
DispatcherPriority.Background, _
New Object() {})
End Sub
Private Sub DummySub()
End Sub
There were more attempts also, but this should give you an idea of what I have tried. This is a real puzzle. This is the last major problem with a fairly involved project, and I am pretty much invested in the transition screen at this point. If you can think of anything, I will greatly appreciate it. Thanks.
I did come up with a work around for this problem. I do a transition animation before I take the screenshot. The transition animation results in a lower resolution image than the control would normally show. Then I take the screenshot of the lower resolution image which can be applied to the transition grid control, after it is made visible, fast enough that there is never a flicker. Then when I want to return to the WinFormsHost control, I run through this process in reverse. My application now works without flicker and run smoothly on most computers I have tried. On some computers with large monitors, there is sometimes a slight delay when rendering the transition screen, but still no flicker. The delay is about half a second, and I assume it has to do with the larger area that transition image must be rendered to.
Also, the above was done in combination with method/attempt #2. The flicker still occurs when in combination with attempt #1.

Get Mouse Position on Canvas (But NOT on window)?

I have a project in WPF 4 and vb.net 2010.
I have a canvas inside a window. The window is full screen, but the canvas is set to a solid 640x480 in the center of the window. I need to get the mouse position inside of the canvas, but NOT inside of the window. How do I do this?
Doesn't this work?
Point p = Mouse.GetPosition(canvas);
The position of the mouse pointer is
calculated relative to the specified
element with the upper-left corner of
element being the point of origin,
Hi the important thing is the
NOT on the Window
the canvas is part of the window as well.
one example:
the Window.AllowsTransparency state is on true
the Window.Background is #00000000 (completely transparent)
the Window.Style is None
the Window.State is Maximized and
there are NO controls or elements on the window!
...
so if you start the application you will see Nothing
now tell me how to get the mouseposition on the screen in pixel
!Warning!
if you juse Mouse.GetPosition(this); it will return x0 y0 every time
so I solved the Problem by using System.Windows.Forms.Control.MousePosition it's a bit a mix of wpf and Windows.Forms but I've given up xD.
Sorry for yelling :/
To make it easy for me I made a Extension:
<DebuggerHidden> _
<System.Runtime.CompilerServices.Extension> _
Public Function toWfpPoint(p As System.Drawing.Point) As Point
Return new Point(p.X, p.Y)
End Function
Now I just can juse it like this:
Dim MousPos As Point = System.Windows.Forms.Control.MousePosition.toWfpPoint

Can't consistently maximize WPF window

I have a minimized WPF window. I click the item in the taskbar to maximize. It makes a little audio ding, then I try again, and again. Usually about the third try it will maximize. What could cause it to refuse my initial maximize attempt?
One possibility is that you have some code that's changing the value of the ResizeMode property to NoResize.
See this page for more: http://msdn.microsoft.com/en-us/library/ms748948.aspx
Second, you might be overriding OnStateChanged and not calling base.OnStateChanged() consistently.
Third, you may have something hogging the UI's thread during your first attempts. Once that task--whatever it is--stops blocking then WPF can repaint the window in restored/maximized state.
I had a similar problem when trying to manually maximize a custom window.
The solution was to put the next code in my maximize button...
this.SizeToContent = System.Windows.SizeToContent.Manual;
this.MaxWidth = double.PositiveInfinity;
this.MaxHeight = double.PositiveInfinity;
this.Width = double.NaN;
this.Height = double.NaN;
this.WindowState = WindowState.Maximized;
Where 'this' referes to the Window.

Drag image within it's parent border?

I have created image viewer control, that provide zoom in/out the image, and when the image zoomed and be larger than it's viewer (you can't see all the image) I provided the ability to drag the image (like Windows Photo Viewer) using "TranslateTransform" but I wanna the image to stop dragging when it's border (left or right or left or down) is appeared, I have done some calculations of the width and height of the fourth sides and it's work fine but when you speedy drag the image it stop after it's border pass it's container border, and the distance increased by greater drag speed. For example: open an image in "Windows Photo Viewer" and zoomed it then drag it it's stop exactly when you reach it's border".
So I wanna the image to stop exactly when it's border appeared regardless of drag speed?
Appreciated your Helps,
Best Regards.
This looks like problem with your code. Can you just apply range check when you compute parameters for translate transform to avoid moving picture outside the region?
This is my code I have Image(name: imgView), insode grid(name: grdImage), I wanna the image(zoomed image) to move with mouse move in inside the Grid, and when it's borders reach the border of grid to stop, exactly like "Windows Photo Viewer". FYI: Im zoomed the image using the scaleTransform:
Private Sub imgView_MouseLeftButtonDown(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
_IsMouseCapture = True
imgView.CaptureMouse()
Dim tt = DirectCast(DirectCast(imgView.RenderTransform, TransformGroup).Children.First(Function(tr) TypeOf tr Is TranslateTransform), TranslateTransform)
start = e.GetPosition(grdImage)
origin = New Point(tt.X, tt.Y)
End Sub
Private Sub imgView_MouseLeftButtonUp(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
_IsMouseCapture = False
imgView.ReleaseMouseCapture()
End Sub
Private Sub imgView_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs)
If (Not _IsMouseCapture) Then
Return
End If
Dim tt = DirectCast(DirectCast(imgView.RenderTransform, TransformGroup).Children.First(Function(tr) TypeOf tr Is TranslateTransform), TranslateTransform)
Dim vx As Double = start.X - e.GetSafePosition(grdImage).X
Dim vy As Double = start.Y - e.GetSafePosition(grdImage).Y
tt.Y = origin.Y - vy
tt.X = origin.X - vx
End Sub`

In WPF, after DoubleAnimation UIElement property cannot be changed?

OK, I'm making a GUI for my MP3 player using WPF and I have a border that enlarges its width property for every second of the played track, thus making a "Progress Bar" for the currently played song. I named the border ProgressBarBorder. After the whole playlist is complete, I wanted to use a DoubleAnimation to fade out the border. Now, if I start the player again, the border reacts as it's supposed to (meaning the width starts from 0 and progresses to the end of the song), but the opacity property for some strange reason stays 0.0 (that is the value that DoubleAnimation sets). I have explicitly coded
ProgressBarBorder.Opacity = 1.0;
in the method that starts the playback. Nevertheless, it stays invisible. Now, if I don't use DoubleAnimation and just write
ProgressBarBorder.Opacity = 0.0;
when the playlist is complete, it does go back to 1.0 when I start the player again. This is the reason why I am positive that the animation is the one causing the problem. Also, isn't the property supposed to go back to it's original state after the animation is finished? If yes, my border should become visible automatically after the animation is complete.
Here's my partially pseudo-code:
if (TrackIsComplete)
{
DoubleAnimation Fading = new DoubleAnimation();
Fading.From = 1.0;
Fading.To = 0.0;
Fading.Duration = TimeSpan.FromSeconds(3);
ProgressBarBorder.BeginAnimation(Border.OpacityProperty, Fading);
}
and
private void PlayTrack()
{
ProgressBarBorder.Opacity = 1.0;
Play();
....
}
Could anyone help please? Thanks.
The animation is holding on to its target value. To free the dependency property of any animations, do a BeginAnimation with a null value:
private void PlayTrack()
{
ProgressBarBorder.BeginAnimation(Border.OpacityProperty, null);
ProgressBarBorder.Opacity = 1.0;
....
}
When an Animation ends, it continues holding the value. This is what is causing the behavior you noticed, where setting the property does not appear to update it. Here's some info on how to set a property after an animation has been applied to it.
Play around with the FillBevior of your animation timeline. This might help:
http://msdn.microsoft.com/en-us/library/system.windows.media.animation.fillbehavior.aspx

Resources