Winforms: creating a dynamic timeline control - c#

I need to create a winforms control what looks something like this:
Currently i'm considering taking a picturebox/panel and overriding onpaint event and drawing all the stuff myself. But somehow this approach doesn't seem right.
I was wondering maybe there's an easier way out or perhaps a better solution?
How would you make a control like this?

No, that is the right way to do it. Trying to use something like a TableLayoutPanel is not only excruciatingly painful, it also sucks serious mud taking a second or more to paint itself. It will take a bunch of code, but it isn't hard code. Plenty of for loop opportunities as well.
Get the scrolling view with panel's AutoScrollMinSize. Use Graphics.TranslateTransform() passing AutoScrollPosition in the Paint event or OnPaint override. The latter is recommended, derive your own control from Panel to keep the code separate. You have lots of flexibility here to customize the appearance, have fun.

The last time I did something like this I did the grid as a bitmap, loaded the image into a picture box, and drew directly on the image. The problem with using the paint event it's not persistent with minimizing etc unless you keep redrawing it.

It would probably be easier to override a literal control or inherit from the CompositeControl class and then render it with HTML (tables) and Javascript as opposed to drawing it.

Related

Remove left and right side borders

I want my TextBox to look like this
How can I remove the left and right sides of my TextBox control?
Normally, you'd have to override the OnPaint event to do this, for a Textbox however, this will not work because OnPaint wont get called.
An approach would be to subclass TextBox as described here
However I wouldnt suggest you to do this at all, it sounds like a daunting task to me (never did this myself), espacially when you are new to programming.
Maybe it would suffice to just draw a line above or beneath the TextBox?
-edit-
Maybe this will explain it better:
The TextBox is special in that you can't custom paint it.
If you just want a custom border, you can create a new UserControl and add a TextBox with border style set to None. Make sure you leave enough room around the outside of the TextBox for a border. Then paint the border on the UserControl surface.
An alternative method would be to handle the WM_NCPAINT message of the TextBox and paint the border then, but that is significantly more complicated.
Source: shawn.ohern in msdn forums: here
(Sorry I didnt know how to link to his post directly)
-edit2-
This link shows a way to create your own TextBox, which, again, I would not recommend to someone who is new to c# and programming ;)
Windows Forms is based on Win32 API which, unlike WPF which uses declarative language for describing UI, gives you full control of painting your own control.
Take a look here: Custom Control Painting and Rendering.

Notification from parent to child that the position was changed

I have a custom control that needs to be informed of layout changes from the parent. So if the parent relayouts the child, i want to calculate the new visual position. Unfortunately ArrangeOverride on the child won't get called, which makes sense, because the position doesn't really change inside the child control. Now in the layout pass, my custom control gets properly positioned but the ArrangeOverride is not called.
To give you a clearer picture of what i'm trying to achieve: I have a control, that blurs the background giving an aero glass like effect. To achieve that, my control renders a background control into a visual brush and calculates the viewbox for that brush to make the background shine through, which then is blurred via a blur effect. Its working perfectly fine, as long as the layout doesn't change. If it does, i need to update the brush. And i did this inside the ArrangeOverride method.
So i tried to use ArrangeOverride, MeasureOverride, various combinations of Invalidating or Parent invalidating. At first i inherited from ContentControl but changed that to Decorator, thinking that the Decorator might have some special behavior to no use. I want to avoid LayoutChanged as much as possible because its a very very evil event. I would give you some code, but there is nothing special about it and i think its a rather fundamental problem not really bound to my code. The layouter by the way can be anything(not only canvas).
So what event, methods or ways do i have to get informed of the parent telling my control "I know you didn't changed anything, but i did repositioned you".
So i fixed it in a way i'm not very happy about, but it resolved alot of other unecessary stuff just to make it work, like when the blur control itself is animated. So this solution works now with whatever happens. While i avoided the LayoutUpdated event, i used a similar "evil" event. CompositionTarget.Rendering so in the Loaded event, i register to the rendering event, in the Unloaded i unregister from the rendering event. That way it doesn't matter how often Loaded or Unloaded gets called. In the rendering event itself i just trigger my VisualBrush.Viewbox invalidation code. This works perfectly fine, even if though the event is fired alot. I don't use the blur that much so it doesn't impact the performance so much ... for now.

Drawing Custom Control above all other controls (previously added)

I have a UserControl that adds other UserControls, but I want the "latest" control added to be topmost so it's above the others. Because the controls should be overlapping eachother. Like a card game. So I add 5 controls, the first one should have the least priority the latest the most priority - most visible.
Any ideas?
Or do I have to override the Paint method for the "container" control? And Control.CreateGraphics() and draw it?
Consider BringToFront and SendToBack methods of the Control class.
Check out answers to these questions too
How to set Z-order of a Control using WinForms
Bring Winforms control to front
Just use userControl1.BringToFront() when you add the new control.
Note however, that won't prevent the user from "tabbing" into the controls that are underneath it. For that, you need to disable or make invisible the other controls.
In Windows Forms, the order in which controls are added to their parents' Controls collection determines the order of their rendering.
This means that either you handle the addition of child controls in code and use the appropriate insert positions, or you move the controls around in the designer (which, unfortunately, often means dangerous hand edits to the *.Designer.cs file).
I recommend that you go for the first approach, which is the only feasible method for larger WinForms projects anyway, and make the control insertion logic explicit in your code. The good news, by the way, is that there is no need to tinker with paint handlers, so your worry about hacks like using CreateGraphics() is unjustified and dispelled :)

Owner-Drawn ToolStripDropDownButton

I'm writing some custom behavior for a ToolStripDropDown control. I'd also like to modify the ToolStripDropDownButton itself to display a colored shape.
I see that I can handle the Paint event and draw whatever I like. However, is there any way to have the button paint the default background before I paint the shape? It would be hard to get the background exactly right, especially with future versions of .NET and Windows.
In plain ol' Windows, I could invoke the default proc handler before or after my paint code. I'm not seeing any way to accomplish that in .NET. Or perhaps there's a way to tell the button to paint only the background?
When you handle the Paint event (as opposed to overriding the OnPaint method in a derived class) the base class (default proc handler) is already getting called. Everything gets drawn as normal, and then you're essentially drawing on top of that in the Paint event. You can see that clearly here:
The trick is making sure that you leave enough of the control's clipping rectangle exposed to show the part you want. The e.ClipRectangle property retrieves the entire button's client area, so if you just
fill that with a color swatch, you're going to cover up the drop-down arrow and default background, too. The above demonstration was created using the following ugly sample code:
private void ToolStripDropDownButton1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.FillRectangle(Brushes.Chartreuse,
e.ClipRectangle.X + 3, e.ClipRectangle.Y + 3,
e.ClipRectangle.Width - 12,
e.ClipRectangle.Height - 12);
}
Other than that, I don't think there's a way to customize what exactly gets drawn by the base class. Owner-drawing (at least in WinForms) tends to be an all-or-nothing affair. You get complete control,
but it comes at the price of having to implement everything yourself.
Of course, in case you haven't already noticed, the ToolStrip control already doesn't look like a native Windows control. And even worse, it is always going to look exactly the same as it does now,
even in future versions of Windows that completely overhaul the UI. (The MenuStrip is plagued by
this same phenomenon, and the difference is very visible in Windows Vista/7 where the standard API menus have changed dramatically). The reason is that both controls are drawn entirely in C# code written in their WinForms implementations. Personally, I think it looks ridiculously cheesy, and wouldn't use it in one of my applications on a bet.
You can assign a custom renderer that uses the UxTheme API to draw the buttons, which will get much closer to approximating the look of the native menus and toolbars. A pretty thorough sample is available here. I've written something very similar for the WinForms development that I've done requiring the additional features of the ToolStrip class (such as embedding combo boxes) not offered by the
old-school MainMenu and ToolBar controls that simply wrap their Windows API equivalents. By choosing to do things this way, you do have more control over exactly what parts of the base class renderer you wish to call, as you've written the code explicitly yourself. Highly recommended if you're
the type that cares at all about UI, native feel, or user experience.

What is the best way to do a flicker-free animated C# custom control?

I am currently creating a custom control that needs to handle animation in a C# project. It is basically a listbox that contains a fixed number of elements that are subject to move. An element (another user control with a background image and a couple of generated labels) can move upwards, downwards or be taken out of the list.
I would like to create animated movement as the elements get moved around within the container custom control but it seems to me that moving controls around using lines such as
myCustomControl.left -= m_iSpeed;
triggered within a timer event is flickery and has a terrible rendering, even with double buffering turned on.
So here's the question : What is the best way to achieve a flicker-free animated C# control? Should I just not create custom controls and handle all of the drawing within a panel's background image that I generate? Is there a super animation method that I have not discovered? :)
Thanks!
your best bet for flicker-free animation is to do the painting yourself (use the Graphics object in the Paint event handler) and use double-buffering. In your custom control you will need code like this in the constructor:
this.SetStyle(ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer |
ControlStyles.AllPaintingInWmPaint | ControlStyles.SupportsTransparentBackColor,
true);
A similar discussion took place this morning on this question. visual c# form update results in flickering. so I will be lazy and give the same answer I gave there:
You could try to call this.SuspendLayout(); before you start your move and this.ResumeLayout(false); when you have finished moving all of the controls. In this way all controls should draw at once and you should have less of a flicker.
On a side note I have tried to reproduce this here at work, but seem to be failing. Can you give some more sample code that I can fix maybe?
See How to double buffer .NET controls on a form.
The normal way to get flicker-free animation is to implement double-buffering. Take a look at this Code Project article
http://www.codeproject.com/KB/GDI-plus/flickerFreeDrawing.aspx
Minimizing calls to paint until you are ready is also a good idea.

Categories