this is my first ever question on this website but it has helped me a lot in the past.
i have a small (but annoying) problem with a project i am working on. i am using a picturebox control which loads a png file with transparent areas. the transparency part works perfectly fine, but i need the user to be able to drag this picturebox around with the mouse. the picturebox is contained within a panel with squares. the squares are drawn in an overridden OnPaint method of the panel.
the problem is that if i move the picturebox control, the area which is transparent does not draw the background fast enough and the squares are not drawn exactly where they should be. is there any way to get around this and make everything look nice and smooth?
i have attached a picture so that you can understand better what i am trying to say. for this example i am using just a line instead of the actual picture that i will be using so that everything is more obvious. notice the squares around the line, which are not in drawn properly.
http://s1084.photobucket.com/albums/j405/headbanging1638/?action=view¤t=problem.jpg
ps: i am using color.transparent for the backcolor of the picturebox
Maybe you could try to invalidate the layout on mousemove to force a faster rate of redraw?
I think pretty similar problem which I asked some time ago.
See my Question, and Answer which I accepted. I think it will help you.
Related
First let me say I love this site and often find the answers to my questions before I ever have to post. Now I have a question that I can't seem to find an answer to. Let me also mention that I'm somewhat new to programming and have only been doing it a few months.
With that out of the way here is whats going on.
I have a panel with a system.drawing graphics attached to it so I can render out pictures.
With these pictures that I render to the panel I want to be able to move them around, and then interact with them with and rotate them. Kinda like a jigsaw puzzle.
I can get the images to render, but need a way to tell if my mouse is over the picture that was last rendered in that location. Since an image might render overtop of another image I want to get the top/last rendered image.
Currently i have the images in a list that get rendered and I do have a couple of ideas of my own.
On a mouse click I scan all the image list last to first and find one that is currently being rendered in that spot and that would be my image.
Re render the screen last to first and as soon as a pixel changes where my mouse is that is my image.
Assign each pixel a image value and when rendering the image the pixels that are on it get assigned that image and the mouse can just pull that image.
Any help or feedback would be much appreciated.
Thank you.
The method you use will probably be largely dependent on your application. Without knowing much about what you're trying to do solution 3 seems the best.
With option 3 the majority of the work is being carried out as you add each image (i.e. assigning its value to the pixels it covers). The other options are are probably going to be less computationally expensive when you add the images but more expensive every mouse click. Assuming that this suits your application (which it most probably does if its similar to a jigsaw as you stated) I'd go with something like that.
It also assumes that your images are rectangular shapes where values can be added based on the corners rather than an arbitrary shape in which all points in the image must be manually calculated. With an arbitrary shape working out which method will be quicker will be more difficult to work out.
In summary, you'd be best to decide what operation will be carried out more often (adding images or mouse clicks) and carry out the work at the other one.
Either I'm not searching on quite the correct terms, or strangely no-one has asked about quite what I am looking for.
Put simply I'd like to have an image loaded into a user resizeable and moveable control (within the panel it belongs to). The image would need to have its opacity set. It should be resized via stretching if necessary no matter how the parent form or panel is resized. It should all be achievable fairly smoothly and on winforms.
I don't really want to re-invent the wheel here, and feel sure that something like this must have been done openly.
Strangely it seems difficult just to create a UserControl that's user resizeable and moveable at run time!?
I have a degree of understanding of drawing the image using ImageAttributes to reduce the opacity to the background, I am just wondering if there are useful resources for attempting the rest?
Thanks
I decided to take the plunge and make the effort to learn WPF. It was worth it, it makes all of this much easier to do when you get your head around it. It's so much more powerful, I think I'm converted.
I used this nice example too for how I can have resizeable and movable controls.
http://denismorozov.blogspot.co.uk/2008/01/how-to-resize-wpf-controls-at-runtime.html
I realise this isn't an answer quite for the original question on Winforms, but since no-one else was supporting and it seems Winforms is getting left behind, I thought I'd close the issue
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.
I am developing a tetris like game in winforms(C# and .netframework 2.0).
The winform has an background image and a picture-box which move down(new Location is assigned) at an interval of 500ms.
The problem is when picture-box moves down the background image of form flickers at the point where the picture-box was earlier located. If i don't use any background image, then there is no flickering.
Is there any graphics accelerator or any kind of solution using which the flickering problem can be solved.
The term used for this is Double Buffering. The idea is simple - start with 2 panes but only display one. Draw to a hidden pane, and quickly swap the hidden and visible panes. Rinse and repeat for every transition (animation).
Luckily, you dont have to deal with the nuts and bolts of this in .NET, controls do it for you. This SO question will help you: How to double buffer .NET controls on a form?
Set DoubleBuffered = true on your controls. This should help prevent flickering.
For documentation on the DoubleBuffered property, see here:
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.doublebuffered.aspx
If you are developing a game in Windows Forms you really ought to be overriding OnPaint and implementing painting of the sprites on every frame, as opposed to moving heavyweight PictureBox controls.
You will find you may get the flicker regardless of DoubleBuffer if you use the approach you mentioned. However, with all drawing done in OnPaint, then DoubleBuffer begins to work.
I did a quick search and found this interesting article on creating a game-loop in Windows Forms using OnPaint override. In particular take a look at GameStateDrawer which does the rendering directly to graphics context.
I have quite an uncommon question: Does anyone know whether it is possible to draw something on the backside of a WPF Window?
Normally people create Controls or draw images on the front side of a WPF Window. However, I would like to draw things on the backside. Here is an Image taken with the Snoop tool. Snoop has the functionality of viewing a WPF Application in 3D. Using the so-called Zoomer it is possible to look behind a window.
I would like to either draw an Image or put a Control so that you can see it with using the Zoomer functionality of snoop at the back of the application.
Has anyone got an idea of how this could be done?
Thanks,
Christian
There is no backside.
What most applications do is simply replace the control/window by another one as soon as it has rotated by 90 degrees.