Animate a e.Graphics.DrawLine with arrowhead - c#

I need to "animate" an arrow. It can go in any direction (up, down, left, right and diagonals) and the arrowhead will be at the end. It needs to appear as if it is growing from orgin to the end.
To make matters more complicated it has to be in a user control so it is possible to add to the controls collection in the forms and remove it to delete it from the screen, and its background is really transparent (no color.transparent) so i can't paint the background to "clear" the previous line.
I have it static already (drawn from origin to end) but i can't animate it. I tried to add a timer in the user control but I fail to get a correct algorithm to calculate the intermediate ends of the line while it is growing.
Any help would be appreciated.
Thanks

When using animation on a Windows form you have to use another thread. Look into using a background worker: http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

You don't need another thread - I have succesfully implemented Windows Forms animation.
My design:
Use a Windows.System.Forms.Timer object to call a callback function 'Animate()' at regular intervals
the Animate() function updates a property of your arrow, and then calls Invalidate() on the windows control
this all happens in the same UI thread, so yuo will not get any flicker effects (as long as your control has double duffering switched on).

Related

Animated Busy Indicator in Compact Framework 2.0

So I'm pulling some stuff from a database via a different thread, and want the form to remain usable while doing so, and also want to show the user a progress indicator until the DB code finishes.
In 'normal' winforms I'd use a ProgressBar with the ProgressBarStyle set to Continuous, but CF doesn't have that. Neither does it seem to support animated GIFs in a PictureBox (which would have been an easy way).
So what are my options for doing something like this?
EDIT: Don't want to use an hourglass mouse cursor because that implies to the user that the UI is busy (it's not).
Thanks
You could look for a 3rd party progress bar control that supports the Continuous progress bar style, or a control that supports animated gifs - you're not the first running into this limitation, but I'm not sure if there are any good ones out there.
Rolling your own "continuous" progress bar UserControl shouldn't be very hard, you get a decent result with just a timer to call Invalidate, and using Graphics.FillRectangle in the Paint event.
An alternative to an animated gif control could be to create a "film strip" UserControl, where you provide an image (non-gif) that contains all "frames" of the gif layed out horizontally or vertically. Again you'd need a timer to call Invalidate and increase the frame number, and Graphics.DrawImage has an overload to specify which portion of the film strip image is drawn.
Instead of the timer you could use #josef's comment to increment the "current frame" whenever the worker thread has finished a portion of the work. The animated gif's "movement" would then actually show the user that work is being done.

Simple multi-threading issue

I have a class called Movement which moves a picture box (guy on the left) on my form to a random position when it's Lead method gets executed. I also have a method which moves another picture box (dark guy on the right) called SetMrShadowToMove. These two picture boxes are suppose to move at the same time and arrive at the random point (one point for both picture boxes) at the same time.
For now, these methods use a timer to move the picture boxes, but my main intention was to have a loop which runs until the picture box's coordinates meet the random point picked while using Thread.Sleep to delay the process and make an animation of it.
To do that, I need to run both methods on different threads, so my UI thread doesn't get frozen and these methods would run at the same time.
My problem is that I don't know how to run these methods on different threads, and also don't know how to access the picture boxes on the other threads (it seems that this has something to do with invoking and stuff!).
What is the best way to solve this problem?
The best way (in my opinion) is by using a background worker.
those things can do there calculations in the background. If you you want to update the interface after that you can use there report progress event to invoke your main (interface) thread and redraw the screen. You can also the work complete even if you want to have a event of the background worker as a final even (for example if mister shadow is 'destroyed' or something).
I don't know your code of mister shadow so I don't have any direct example code for you. But a full example about how to use a background worker can be found on msdn here. I hope this will help you.

SurfaceListBox not responding to touch gestures for several seconds

I have a WPF-program that has a grid with two columns. First one has buttons and second one has WindowsFormsHost-element that embeds an ActiveX component. One button hides the WindowsFormsHost-element and shows a SurfaceListBox on the same location on screen in the second column. If I have touched the WindowsFormsHost element just before pressing this button, it takes approximately 8 seconds from the last touch until the SurfaceListBox becomes responsible for touch gestures.
The thread is probably not blocked, because I can use the buttons in another column, and use use the ListBox with mouse.
The ListBox remains unresponsive for touch events forever, if I touch it within the 8 second waiting time. So it seems that somehow the ListBox does not get the touch events.
If I programmatically create another ListBox, it does not work either, for 8 seconds, if it is placed in same are on screen than the WindowsFormsHost was.
I noticed there is a method CaptureTouch() for UIElement, but I cannot get hold of to the TouchDevice that I could pass it as parameter. I have set ManipulationEnabled="true" for every UIElement and no TouchEvent will be fired.
I have also desperately used UpdateLayout() etc with no luck.
So I think the touch gestures are somehow routed wrong and after the waiting time it implicitly fixes the routing, but is there a way I could make the touch gestures work in the ListBox immediately?
The problem disappeared when I removed "focus tracking for launching on-screen keyboard" from my program.
So in case of somebody else struggles with the same problem,
http://www.infragistics.com/community/blogs/blagunas/archive/2013/12/17/showing-the-windows-8-touch-keyboard-in-wpf.aspx and SurfaceListBoxes aren't meant for each other.

Scroll to a position in Scrollviewer with normal scrollanimation

I have a metro styled app with a scrollviewer. Now I would like to scroll to a position when the user clicks a button. I tried:
MainScrollViewer.ScrollToHorizontalOffset(x);
But then its "jumping" there quickly. I want to have a smooth animation up to x.
There is no API out of the box that would allow you to do that.
There is also no property that you could target with an animation.
You would need to either use frame-based animation (basically figure out where you are in the timeline and on each CompositionTarget.Rendering event - update the offset) or create an attached dependency property that calls ScrollToHorizontalOffset when its value changes and target that property with an animation.
You could create a method that runs async and has a timer which increments the ScrollToHorizontalOffset(int x).
Say every 500ms it adds 10px.

c# Winforms: Refreshing a portion of a GUI (containing 1 or more controls)

I have a Control that can overlay multiple C# user controls in my GUI. This control has a semi-transparent background in order to 'grey-out' portions of the GUI and the class looks somethink like this:
public greyOutControl: UserControl
{
// Usual stuff here
protected overide OnPaint()
{
paintBackround();
base.OnPaint();
}
}
Currently the control sometimes gets caught in a loop and constantly re-draws the background, making the semi-transparent color appear less and less transparent.
My idea to combat this is the following (in broad terms):
1) Determine what controls the greyOutControl is on top of
2) call Refresh() on those controls to update the display
3) continue drawing the greyOutControl.
My question is: How can I determine which controls the greyOutControl overlaps?, or is there a way that I can refresh only the part of the GUI that greyOutControl covers?
Why don't you keep track of your transparent controls and paint them after all the other controls are drawn?. Painting anything at the top of the Z-order shouldn't cause the other controls to be repainted.
I don't see a direct way of finding the overlapping controls. I think you might need to check the whole control tree to find out that. About refreshing, you can use Control.Invalidate(Rectangle) method to specify which part to refresh.
The solution to this problem I found was to programmatically take a screen shot of the area being overlayed and then use that image as the background for the control being overlayed. This then allows you to put the alpha overlay into the image within the OnPaint() method and the control to draw itself correctly.
This does have the disadvantage that the background isn't updated in the overlapping control, but unless there was a number of event handlers watching if something changes and then update the overlayed control I cant see any way around the issue. Sometimes I regret not trying to use WPF!

Categories

Resources