Moving a picturebox with a timer - c#

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.

Related

C# redraw only foreground

I'm working on a college project (simulation) that needs to draw a lot of lines and objects to a custom UserControl. My current approach is just to redraw everything for every tick / update loop using Invalidate(). But it sure needs a lot of time to draw (which is resulting in very low FPS) especially when I need to draw thousands of lines and rectangles.
So how can I only re-draw a specific (group of) objects that move in every update loop and only re-draw the rest (the rarely updated objects) when needed? Or is there other way to optimize the way I draw in this problem?
My idea would be the following:
Draw your Control onto a Bitmap (or other image format) once, and save that Image. Then display that Bitmap on your Control. (Assuming you use a Control that can do that, i.e an ImageBox, not sure what would be best for that).
Whenever you update your graphic, keep track of what sections of your Control may be outdated, then redraw only these sections (drawing only the objects that touch that section), and copy the other sections from your saved image.
Display (and save) the new Image.

Make a PictureBox transparent and allow it to be moved

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

Animation Effects in WinForms/C#

I'm pasting an image from the game im building.
the matrix of empty cells you see are made of PictureBox[][].
I wan't whenever I drop a coin to one of the columns... I want it to go down but the purple stuff will hide the falling coin and the gray color you see wont hide it.
How do I make this effect?
please notice that in each PictureBox control I have set the BG Image as you can see
Don't do it like that.
Create custom control. In custom control, override Paint, and then draw COIN sprite first, then draw mask over it. Be sure that you use double-buffered painting here.
It will work like a charm, trust me!
And, since you are (I gueess) building 5-in-a-row game here, your custom control will be able to paint occupied slots as well.
By designing custom control, you'll be able to hide all the animation and graphics stuff away from your main form.
I don't think it is possible like that. Controls in WinForms cannot be transparent, that is the problem
I would think in three directions:
Forgetting about controls and
painting everything OnPaint event of
the form. It is not too complicated
(well it would be more complicated
to detect some mouse events like you
did now, as you wouldn't know which
graybox is hit, but rather just
mouse coordinates)
Experimenting with coin as a form
(forms can be transparent)
Possibly using WPF with same logic
you did, as controls can be
transparent there
Controls in Windows Forms can be transparent. You need to set the TransparencyKey of the Form to some color that you never plan on using (many people seem to love/hate Magenta for this), and then set the BackgroundColor of each PictureBox to the same color. The result should be a transparent PictureBox with its Image drawn over it. I'm pretty sure this won't work with the BackgroundImage property, mind you- just the Image property.
One potentially unwanted side effect of this method is that you'll be able to see whatever's behind your form (the desktop, other application windows, etc.) through the transparent places in the PictureBox.

How can I develop scale like measure it add on in Firefox

I want measuring tool in project that will be same as measure it in Firefox (add-on). How to do this?
To get such a think to work you'll need an application that runs as a tray icon or something like that. Then you open your application and tell him, that you'd like to measure.
Now, you'll go and put a transparent window onto the whole screen(s) and wait for a mouse move event. Within the mouse move event, you'll check the mouse button state. If it is going to be hit you know the starting position and you can draw some kind of user-control at this position and if the user releases the mouse button, you're going to stop the resizing of your user-control.
The user-control itself should be semi-transparent and checking for the resizing and/or paint events, to draw the ruler lines around the border.
Last but not least you can show some kind of tooltip or labelcontrol in relation to the position and size of your user-control and screen bounds to give some status informations.
To get a good starting point about how to get the transparent overlay part done, you can take a look into ObjectListView Overlay.
--EDIT--
One solution could be:
Create a separate transparent windows form
Upon certain key press, for instance Ctrl+Shift+R, show your app with lower transparency level; so that user can see the background.
Draw ruler upon form load
You may allow user to move the ruler window with mouse click.

Is it possible to trigger a "fake" scroll progmatically in WinForms?

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.

Categories