Click here to Skip to main content
15,906,816 members
Please Sign up or sign in to vote.
3.00/5 (2 votes)
See more:
Hey guys,
I've been searching google for days after an effect that will spin a window in wpf on the Window.Loaded event.
When i'm saying spining, its meaning that i want the window to show as it spin on its Y axis with a specific speed.
any advice? thank a head!

What I have tried:

.....................................................................
Posted
Updated 29-Feb-16 6:13am
Comments
Sergey Alexandrovich Kryukov 1-Mar-16 20:19pm    
Now please see my article I just wrote: How to Rotate a WPF Window?
And thank you for this pretty interesting question, up-voted...
—SA

1 solution

There is no such thing as spinning a window, but you can relatively easily spin some content. And if this content mimics the appearance of a standard window, you can create an impression of a spinning window.

That was the idea, but how to achieve that?

The problem consists of at least two parts, how to show your pseudo-window at an angle, and how animate this view by changing this angle with time. You can use two approaches, 2D and 3D. With 3D, you can use WPF 3D model shaped as a rectangular parallelepiped with a window on one side. (Please see 3-D Graphics Overview[^].) It will be not to hard to show it on a background of a window, but showing it "in the air" would be much harder. I would try to just use a transparent background.

But with 2D approach, you can pretty easily achieve a non-rectangular shape of a background window perfectly matching your current pseudo-window object. You can allow transparency and make this window's Background transparent.

Of course, first you would need to get rid of all the non-client areas of your "real" background window, which is achieved by using the special window style, None:
Window.WindowStyle Property (System.Windows)[^],
https://msdn.microsoft.com/en-us/library/system.windows.windowstyle%28v=vs.110%29.aspx[^].
Also, remove the window's borders (border style).

To show the rectangular UI element at an angle, let me assume that you don't want to show it in space perspective. Oddly enough, this is not a transform supported by standard WPF transforms (and not by System.Drawing transforms). Such transform is not affine (which also sounds a bit surprising) and cannot be created, but it's tricky enough; you would have to do all yourself, up to the pixel level with all the interpolation problems. But if you agree to limit the view with a simple parallel projection, which can also create fair rotation impression, you can use the transform.

To transform your image, you can use
Transform Class (System.Windows.Media)[^],
Transforms Overview[^].

The transform you need to show rotation is scale transform in X direction (if you "rotate" around the vertical axes): ScaleTransform Class (System.Windows.Media)[^].

Now, animation. First of all, forget "Window.Loaded event" and never remember it. I don't even want to discuss it now. You just have to keep the view animated all the time, or during some predefined period of time. Now, due to two factors, you cannot use standard WPF animation. These factors are: you really want to show uniform rotation speed, your transform factor should be a sinusoidal function of time, because the change of angle is a linear function; the second factor is: you have to recalculate and adjust the region as you rotate.

So, you have to animate the rotation from scratch. This is how: create a separate thread and calculate all the geometry for every phase of rotation. Then, in a pretty short cycle, you have to calculate the real time in the moment (use System.Diagnostics.Stopwatch, Stopwatch Class (System.Diagnostics)[^]). On each phase, you have to notify the rendering subsystem to re-render your window. You cannot call anything related to UI from non-UI thread. Instead, you need to use the method Invoke or BeginInvoke of System.Windows.Threading.Dispatcher (for both Forms or WPF) or System.Windows.Forms.Control (Forms only).

[EDIT #1]

You should not assign different value of ScaleTransform to UIElement.RenderTransform in a loop; this is impossible. Instead, do it only once (one normal place for it, as well as for creation of a thread, in overridden OnContentRendered), and then, in the thread loop, change the scale factor Transform.ScaleX.

You need to pass an instance of Dispatcher and ScaleTransform to a thread. I explained a good way to do it based on the ThreadWrapper I proposed here: How to pass ref parameter to the thread[^].

[END EDIT #1]

You will find detailed explanation of how it works and code samples in my past answers:
Control.Invoke() vs. Control.BeginInvoke(),
Problem with Treeview Scanner And MD5.

See also more references on threading:
.NET event on main thread,
How to get a keydown event to operate on a different thread in vb.net,
Control events not firing after enable disable + multithreading.

If you do all that properly, your show may really impress people.

It's possible that someone could give you other solutions or give more detail on, say, 3D model approach…

[EDIT #2]

Answered in detail in my new short (Tips & Tricks) article How to "Rotate" a WPF Window?

This article covers only more interesting "2D" approach with "pseudo-rotation" of a "pseudo-window" which produced a spinning impression, which I think is pleasing enough. The WPF 3D API approach will take a lot more effort and would be more trivial at the same time…

[END EDIT #2]

—SA
 
Share this answer
 
v7
Comments
oronsultan 1-Mar-16 10:19am    
Listen Sergey, i know you from earlier discussions but this time you even outdid yourself, i think...
your answer can't be more detailed. to be honest, i don't know if i have enough code experience to achieve all you wrote but i will definitely give it a try. I will keep you posted, thanks a lot for dedicating the time to answer me :-)
Sergey Alexandrovich Kryukov 1-Mar-16 10:44am    
You are very welcome.

One more idea: at first moment after having all your "normal" window rendered, you can make a screenshot of a part of the screen occupied by this real window and remember it. (You will find more than enough questions and answers on taking screenshots with WPF.) Then you hide your "normal" window or change it to the None-style one and use obtained image to mimic rotating pseudo-window, which would be really just a captured image going through required transform (or, in 3D model approach, used as a "pattern" covering a big side of a rotating parallelepiped). And, with scale transform, don't forget that the transform factor (as well as the actual current width of the Clip geometry) should be a sinusoidal function of time.

—SA
oronsultan 1-Mar-16 10:55am    
...
oronsultan 1-Mar-16 10:56am    
...
Sergey Alexandrovich Kryukov 1-Mar-16 11:05am    
I did not say "rectangle", not in the sense of Rectangle WPF class. Look at Common Transformation Properties. In particular, it can be any UI element's UIElement.RenderTransform; and you can also use Geometry.Transform, because it will help you to obtain matching clip for the window with rotating UI element. It means, any UI element.
—SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900