I'm busy implementing some image resizing operations. The gist of it is for every 1 pixel the form resizes, the image will resize by 1 pixel. For now, I have only implemented width reduction. I have an overridden Panel that I use to paint my image in OnPaint method.
I am listening to the From.Resize and I'm doing the width reduction in there. When that is done, I call Invalidate on my custom Panel which redraws the image. This all works.
As you can imagine the form resizes quicker than what my image reduction code runs and that is fine. If I take my time and resize slowly, then the Form size and image size stay in sync but if I do a "hard" resize, the Form quickly becomes smaller than the image. It seems resizing does not block UI thread.
Is there some way I can "block" or slow down the resizing so the two can stay in sync width wise?
Related
I would need a picturebox that contains a graphic for an actor. The actor is placed on PictureBoxes that contain a tileset graphic. The actor should be able to move freely which i already did, but the transparent .PNG Actor-Image has a control-colored background when I load it into the form.
Question:
How could I make the background of this Image transparent AND allow to be moved?
The problem with windowsforms is that its control does not have true transparency
The transparency of a control is based on the BackgroundColor or BackgroundImage of its parent and that is why your PictureBox is Control-Colored
Now if you want to make it true transparency you have some options
Draw everything yourself
You can use the power of gdi+ or Graphics to draw everything, but only the needed ones
Handle the draw of the control
This could be a tricky one, you can override the method OnPaint and OnPaintBackground of the picture box so it do not redraw its background (Control-Colored), the bad side of this is that it will have a lot of flickering and buggy background on movement
Use another techology
I'm not sure but if I'm not mistaken you could use wpf for this, altough it could change your entire project
I know this is an "already heard" problem: I have searched a lot but I did not find anything that cleared my mind.
I am developing a c# application with a GUI containing some controls like buttons (made with images) and text.
I developed it setting the main form size to 800x600 but now I need the application to work also on a 1920x1080 screen.
Two problems:
If I position a button near the top-right corner of the main form and set AnchorStyles to Top-Right, when I switch to the big screen, the button is (in proportion) much more close to top-left corner than in the little screen (because the anchor keeps the distance from the border). Is there a way to set a proportional distance from the border?
How can I scale the dimensions of the controls proportionally to the screen size? Shall I use AutoScaleMode like suggested here?
There is a way to add a capability to a form at design time - the ToolTip control does it, that makes properties available to every control on a form. These are called "Extender Providers"
http://msdn.microsoft.com/en-us/library/ms171836
You would want to look at the controls, and cache their sizes and fonts at design time, and the size of the form.
The provider would hang off the form.SizeChanged event at run time. When the size changes, you use the new and original (design time) sizes of the form to calculate and X and Y ratio. You then go through each control and use it's design time size and the ratios to determine its new size and font size. This can get flaky if you allow the user to select sizes that are not the same aspect ratio as your original.
Anyway, that is how it was done in Delphi, and everyone knows if you can do it in Delphi, you can do it in C# :)
What is the best approach to render a large number of 2D graphical elements (lines, text, shapes, etc.) in a scrollable view on windows using C#?
You could put a PictureBox (of whatever overall size required) onto a Panel with AutoScroll set to True, and then draw everything you need at once onto the PictureBox using a Graphics object.
However, if the overall size of the drawing surface is extremely large, this approach would not be practical (since it would mean having a huge PictureBox and a correspondingly huge Bitmap, which could consume a large amount of memory). If this were the case, you'd be better off creating your own scrollable user control (horizontal and vertical) and rendering only the visible portion of the overall surface in the control's Paint event.
The first approach would be easier and faster to write, but might consume too much memory. The second approach would require more work on your part, but would minimize memory consumption.
There is a scrollviewcontainer control but not on the toolbox by default. I would do the above approach to a picture box and embed it inside this control. Also, you can use SetStyle to enable double buffering to prevent flicker. Another option is to build a class to handle double buffering (draw to a bitmap object and push out the results using CreateGraphics). There are some good examples out there.
Is it possible to trigger a "fake" scroll progmatically in WinForms?
The scenario:
A form with various drawings on it done with System.Drawing (and no scrollbars).
What I would like:
Progmatically tell the Form the user has scrolled by 10 pixels to the left.
The Form moves the existing drawing 10 pixels to the left.
The Form generates a paint event with a ClipRectangle containing just the right-hand 10 pixels that are now empty.
Is this possible or do I need to handle this myself?
You can add a panel to the form that is larger then the form. Keep the scroll bar turned off and manually scroll the panel by setting the value properties of the VerticalScroll and HorizontalScroll properties of the Panel.
Then add your drawing to the panel instead of the form.
this.panel1.VerticalScroll.Value = 50;
this.panel1.HorizontalScroll.Value = 100;
I honestly have no idea whether that would work, but my guess is that if a scrollbar isn't present on the form it wouldn't.
However, I would expect that if you have a PictureBox control that was sized larger than the client area of the form, and you moved it, it would be updated with only the specific clip region.
You could try putting the drawing whatever it is in a separate container then just moving the location of the container to a location off the main form. .location = -10,0 for example. This will create the illusion that it moved a certain number of pixels off the screen. You can also always fire your own repaint event if the location change does not successfully do this. Other than that you can always owner draw everything.
Since you're using System.Drawing you'll need to tell the drawing methods (OnPaint() or where ever you're drawing) to start drawing at an x offset of -10 pixels. Everything you draw would then be offset by that amount.
Shifting the whole drawing left 10 pixels would be cause to invalidate the whole screen region, not just the 10 pixels on the right of the screen. There are a couple of ways you could do this:
1) Set your offset to -= 10 pixels. Invalidate the whole screen by calling Invalidate(). This would force a redraw of the entire screen and, as long as you have coded your offsets correctly, will redraw everything 10 pixels over.
2) Take an in-memory dump of what's on the screen and make an Image out of it. Then redraw that image 10 pixels to the left off the screen. After that, simply Invalidate the right-most 10 pixels.
Method #2 is, in fact, a lot slower than method #1. Redrawing the screen is quite fast if you don't have millions of things you need to draw.
I'm trying to move a picturebox in a containing control by changing its Top and Left properties every 20ms. On a black background it's a bit smoother but when assigning a BackgroundImage to the control, the picturebox leaves a trail behind it until the control is redrawn a few seconds later, slows down abruptly then launches forward, or moves in a jagged trajectory.
I think when the PictureBox control is redrawn, the thread that changes its left and top properties is halted until redrawn is complete and that causes it to queue up any iterations of the timer loop that were held up, when the redraw is complete.
Is there anyway to smoothen up the picturebox's movement?
Thanks
F
I'd suggest drawing an image in one control as opposed to moving around controls.
Create a custom control, override OnPaint and draw your "picture box" inside there. If you do this you can also back buffer. Do this by calling Graphics.FromImage() to create a graphics object from an image. Paint onto that and finally call g.DrawImage on the REAL graphics object (in the eventArgs) once you're done drawing.
I don't know exactly how to resolve the problem (other than switching to WPF) but I can say the lag you're getting is coming from the invalidation of the areas that are being updated as you move the PictureBox. What you want to do is somehow back-buffer the new position and switch to the buffer, rather than relying on GDI to do the redraw in realtime. HTH.