.NET C# drawing slowly - c#

I have a problem drawing something quickly in .NET. I don't think that any thing in particular should take much time, but on every machine I've tried it on, I get serious issues. This is implemented in vs2008 .NET, using C# (with some stuff in C++, but nothing relevant to the drawing).
I have three screens, and the user should be able to toggle between them with no lag. On the first screen, there are four buttons, eight user controls consisting of two buttons and 6 labels each, a text field, and a dropdown box. I don't think of it as being that much.
On the second screen, I have four labels, six buttons, and two controls that have six buttons, one opengl drawing context, and about ten labels each.
On the third screen, I have one opengl context and 10 buttons.
Flipping from any screen to any screen takes literally about a second. For instance, if I flip from the second screen to the first, the entire application blanks out, showing the background screen, and then the first screen is drawn. Many times, a screen is drawn piecemeal, as if the machine were deliberately handcrafting delicate and delicious letters in a factory in Sweden and then shipping each one individually to my screen. I exaggerate, and I want to make that clear, because I don't think Swedes are as slow as this redraw.
The first and second screen are drawn in memory, and stored there, with just a '.Hide()' and '.Show()' to make them appear and disappear. Double buffering doesn't seem to matter. The third screen is drawn anew each time, and appears to take the same amount of time to draw as the first and second.
Any thoughts? What could be going on? How can I track it down?
Thanks!
Edit: I should add that any C++ processing and the like happens in its own thread. There is the occasional MethodInvoke to draw the results of the operation to the screen, but this problem happens without calling any functions, just by pressing buttons to go from one screen to the next.

In addition to the profiler that was mentioned, you might also turn off your OpenGL contexts. If you notice a speed-up, then you'll know it's your graphics stuff, and you can focus your optimisations accordingly.
Points awarded for Swedish humour.

How can I track it down?
dotTrace - http://www.jetbrains.com/profiler/

Are you doing any other processing during the "screen flip" event? other than just letting the form be redrawn? If you are processing something between flips (maybe your c++ addition?), and you are not multi-threading, you get that white out effect. The form is probably waiting for CPU time to redraw itself.

I have never used OpenGL in such a way myself, but you might want to look at the way in that the OpenGL contexts are flipped. When switching from one page to another you might be getting a device reset (in DirectX terms), which could be causing the delay.
If at all possible have a device draw to a back System.Drawing.Bitmap, and use that bitmap on the screens. Make your OpenGL code aware of the current page the user is on, and you might get the speed up you seek.
To test this before making huge changes, try removing the OpenGL displays on your form.
This is all a whim.

Related

Post-processing screen image before rendering it on display

I'm working on a tinny software (C# and WPF) that does some filtering to the screen output. Examples on the filtering I'm talking about:
Customizable blue light filtering.
Increase/Decrease screen brightness (via changing the colors, not actual brightness)
Inverting screen colors.
And some more, but the simple idea is to tweak the pixel values of the screen after everything else is done rendering, but before showing the result.
Q1: How can I actually access (and then edit) the screen image/frame?
I've heard of getting and editing the screen DC directly (Win32) but I don't know if it's a good way, nor how to do it exactly.
Q2: what is the best way of applying these filters?
I think that tweaking every single pixel individually is a really bad way of doing it. (My code runs on the CPU and this process needs to be done every frame!)
Q3: Is there an event or hook for when windows is refreshing/updating the screen?
If yes, how can I register this process to it?
Note: I want a really performant way so that I don't lose any frame rate if possible.
Note: My preferred language for this is C#, C++ is ok.
Thanks a ton.

Slow drawing when using many controls in C#

I've been trying to create a roll-playing game for a little over a year now, and I thought a good way to test it and flesh it out a bit would be to turn it into a Dungeons and Dragons variant. However, the inherent problem with using a DnD setup is that there's a lot to keep track of, to the point where it becomes impossible for a single person to do by themselves. As such, I thought of writing a C# program to help.
I ran into this problem when I tried using a series of PictureBox objects to represent the spaces on the map where characters can move. I wanted to use PictureBoxes because that would allow me to use images to represent terrain and characters occupying the given space. However, the map I am using is roughly 46 x 75 1-inch squares, totaling 3450 PictureBoxes. This, understandably, slows the application down so much that it actually freezes for minutes at a time while it redraws the map every so often.
I tried two solutions. First, I tried using a Panel object for its free scrolling capabilities in the hopes that the application wouldn't have to redraw the whole map, but rather only the subset of PictureBoxes visible at that time. This helped only a little, and not enough to make the application usable. Second, I looked online, including this forum, and found people having similar problems. However, the problems they were having were entirely unrelated to mine (aside from the whole slow redraw thing) and thus the solutions didn't really apply to me. I did see a few recurring lines that I tried:
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
I'm not really sure what they do, but they did help a bit. I am still seeing way too much lag, though.
I'm out of ideas at the moment. Is there a better control I could use or a different way of drawing? Thanks in advance for your help!
I would try to develop a solution that only renders the images that are visible on the screen at any given time. Images should only be rendered when you scroll them into focus.
This is a common technique since rendering UI is usually the slowest operation by far. I would bind a view model object to the visible objects, which means you only have to render a subset of the images instead of the entire screen.
Grids with endless scroll sometimes use this approach.

How to draw animations on top of winforms controls?

I'd like to create some animations to make my (old) winforms app look a little nicer. The basic premise would be something like this:
I have a button I can press, and when I do, a random letter appears on top of the button and "flies" over to a textbox. Once the letter arrives at its destination, the letter vanishes and is appended to the text in the textbox.
This should be async, meaning there can be multiple letters on the way at the same time.
My problem is that I do not really know how to accomplish this. I know I can draw things on top of my controls by creating a graphics -object and drawing with it, but unless I force a redraw (Invalidate, or something else), the previous drawing is not cleared. However, if I do force the redraw, things tend to go all flickery (with or without DoubleBuffered set to true).
So I'm a bit at a loss in here, and despite my best efforts at googling, I wasn't able to find a suitable solution. Probably because drawing animations on winforms isn't all that popular (wpf would probably suit this ten times better), but I'd still like to at least learn if it is possible to accomplish.
What if you first draw it on a bitmap, then bitblt it to the screen/form. Look at the accepted answer in: Simple Game in C# with only native libraries

C# PictureBox control flickering / performance issues

I am currently working in Windows Form Apps and am making what will essentially be a map editor for a game. The way i have gone about this is by having a central TabControl where each TabPage contains a custom PictureBox control and all the other UI controls are around this central TabControl. The PictureBox uses its Paint event to draw everything that is placed on the map, and therefore draws multiple images of many sizes, rotations and scales etc to the single PictureBox. This has all gone well so far. The TabPage is essentially used as a view window for the PictureBox and is of size (1280x720).
The problem is with the scale to which the maps are being produced. The avg (and also maximum) map size on screen is around 19200x10800px and can be made up of hundreds of items at any one point. When drawing just a backdrop image of size 19200x10800px the PictureBox starts to flicker when it redraws and makes the program unusable. As the map is so big you are able to pan around them and this is where the flickering really shows. Also i do not want to use a 19200x10800px image source if possible for the sake of file sizes and the scaled image quality isn't an issue at all.
I have done heaps of reading on why this might be and feel like I have tried everything up until this point. So far ive tried:
Having the background image only 1920x1080 and scaling it up by 10x
Starting with a 1920x1080 image, programatically resizing it and drawing this image
Slicing the background into multiple segments (i tried many different amounts) and drawing only the ones that the view window can see (tried this for both a small(1080p) and large(10800p) images)
Using graphics clipping so that only the things on screen would be drawn
Used Double Buffering on both the picturebox and the form that the picturebox is on
Converting the image at initialisation to an "optimised bitmap" with faster formatting and then drawing the bitmap
I've probably tried a couple other things along with minor optimisations but its taken me so long ive forgotten the rest. From what i've read its most likely something to do with the control redrawing too slowly for some sort of performance reason or a limitation with picturebox's, however exactly what is going on i cannot tell due to lack of experience with form apps controls.
Currently to draw the background in the Paint event i have either:
g.DrawImage(image, new Rectangle(0, 0, (int)(image.Size.Width * levelScale), (int)(image.Size.Height * levelScale)));
or
g.ScaleTransform(levelScale, levelScale);
g.DrawImage(image, new Rectangle(0, 0, (int)(image.Size.Width), (int)(image.Size.Height)));
Where g is the Graphics object.
Have I hit the limit of Win form apps capabilities or is there something i may be missing?
Any and all help appreciated,
Thanks in advance.
Just for formality I though id answer my own question just in case anyone else would like to know the outcome.
Based off the overwhelming consensus that winforms was just not made to do the things I was trying to do with it I decided I had to move to some other platform. Suggested to me was WPF, DirectX and OpenGL but after some extensive searching around I found what I think is the optimal solution.
In order to utilise the power of DirectX hardware acceleration MS has made it so that you can embed XNA graphics devices into a winforms application. Essentially you can create custom controls that run in the normal winform style that have access to a much higher caliber of graphics control. In this manner (with a bit of extra work) I have replaced the picturebox I was using with a custom graphics control which handles all of the drawing. This has worked very well, and on the up side i havent had to take too much of a hit to my development time.
For those looking for more info refer to this question which has further links that should help. Once again thanks to all those who gave their advice!
This is a quoted answer from the URL at the bottom. There are code examples at the link at the bottom. Hope this is helpful; not sure if you tried this yet and maybe it'll help you get a little more juice out of the existing picturebox control. As explain in the other answers, it sounds like you will be forced to a more powerful solution in the near future regardless (DirectX/OpenGL or WPF)
** Partial quote from http://social.msdn.microsoft.com/Forums/en-US/68ecd1f6-2eeb-45ce-a881-24c62145ab0e/c-picturebox-problems
"I'd guess the real problem is that it takes too long to redraw the images. GDI+ is pretty slow, it doesn't use any video hardware acceleration. To speed it up, be sure to avoid rescaling the drawing and to use the Format32PArgb format. It is about 10 times faster than any other format. Load the images into a Bitmap with the right format first."
If you have a LOT of items (Maybe realized as controls), forget about the standard event mechanism of Windows Forms. Some time ago, i've written a logic gate editor/simulator which supported lots of thousands of gates in the editor and was really fast. There, I've used the canvas and draw the gates as custom "images" instead of putting them as controls. You'll have to write a custom GetUnderlyingGate function which resolves the current gate / tile (Is your editor a tilemap editor?) from a coordinate array. Also, there were some visible area optimizations.
Maybe, when i'm back home, I'll upload some sourcecode and notify you.

Rotate Windows form upside down

I have a C# application that has an existing WinForm that I now need to display upside down.
The application will be displayed on a touchscreen Windows 7 device. If two people are using the device, one person is viewing it right-side-up while another user will be simultaneously viewing it upside-down. I will need to have one control displayed right-side-up while another control is displayed upside-down, each duplicate forms. Both need to be functional. It is not necessary for the title bar and Windows close, maximize, and minimize to be rotated.
Is there a way to easily rotate this Form and all of its contents without having to rewrite it from scratch?
Unfortunately, rotating controls is not directly possible in WinForms.
At least, not if you want them to retain their functionality. It would be relatively simple to draw the control into a bitmap, rotate the bitmap, and then draw that back to the desired location on the form. But you would obviously lose the ability to interact with the controls. They would just be static representatives of their original selves.
But making functional upside-down controls just isn't going to happen. I mean, you could try to write a bunch of custom drawing code for owner-drawn controls, but you'll still run into a bunch of bugs, corner cases, and compatibility problems. The Win32 controls that WinForms is based on just don't support this. No big surprise, really, considering they were invented some 20–25 years before anyone thought of computer screens that you could carry around in your pocket and rotate in any direction. There is a good reason that UI technologies like WPF came out around the time that touch screens and tablets did.
There are some possibilities that can be explored when it comes to flipping the entire screen, but that's not going to help when you want different controls going different directions. (And I guess it betrays my vantage point as a desktop app guy when I say this, but that just sounds like an incredibly confusing UI.)
If you absolutely have to have this, someone else is going to have to give you another route to hack it, perhaps along the lines of Dhawalk's comment: hosting the WinForms control inside of a WPF app that does provide built-in support for rotated controls. I don't know enough about this to make any concrete suggestions down that path. From a few minutes of searching, it appears that WindowsFormsHost does not actually support rotation transforms, so this may be a non-starter anyway.

Categories

Resources