Rendering 2D primitives in scrollable view - 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.

Related

WPF Dynamic Cursor

I am creating a vector graphic editor in WPF. I am rendering the artwork using a D3DImage that has been customised using SharpDX so that I use it with Direct2D. When an item is selected, resize handles appear around the selected item. I want the cursor to change when the user hovers over these resize handles, but they are rendered in Direct2D and are not WPF elements. How do I accomplish this?
Well, if you’re doing your own rendering to D3DImage, you gotta do your own hit testing.
If your geometry’s relatively simple (boxes, circles, polylines, not too many of them), you can hit test these handles shapes in mouse move event handler. Either manually, or by using e.g. FillContainsPoint D2D APIs.
Or, if you aren’t doing something very color-sensitive like a desktop publishing, you can encode resize handles in the color of your shapes. Use a couple of least significant bits of the blue channel (human eyes are least sensitive to blue), read the color under the mouse, change cursor accordingly to the blue color value.
Or, you can switch to DXGI_FORMAT_R16G16B16A16_UNORM for your render target (looks like D2D supports that format), this way you can add much more per-pixel data to your image without any visible artifacts (use lower bytes of each of the 3 color channels). This however complicates rendering, you’ll need to do one more pass to convert the texture into A8R8G8B8 for the WPF.
P.S. I wonder why don’t you use WPF elements instead? 2D vector graphics there is rather advanced. You can easily create/manipulate/fill/outline these shapes programmatically (just place then on a canvas), this way WPF will handle all these hit tests, and rendering, and more.

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.

Keep form and controls proportion deployng a c# application for any screen size

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# :)

How to display images on top of each other using C# (Forms or WPF)?

I need to display images on top of each other. This can either be a composite\layered image or separate images. This will typically be a larger image with smaller images on top. With the composite\layered approach the smaller images would each need to be a separate (and accessible) layer. With the separate images approach the smaller images are on top with a transparent background. With either approach the smaller images must be accessible i.e. can be moved (dragged) or deleted. The app needs to display these images together (as if it was one image) and keep track of the coordinates (position) of the smaller images.
The current (proof-of-concept) solution has a PictureBox control that displays the large image and a treeview. Nodes are dragged from the treeview to the picture box and rendered using the graphics DrawString or DrawImage methods – these draw the smaller images. The problem is that once the smaller image is drawn I cannot get back to it as a separate graphics object. The picture box “sees” it as part of the current image.
I need to do this in C# (WinForms or WPF). And the image type must be a common and open format i.e. not proprietary. Preferably no 3rd party controls.
Any suggestions\guidance?
WPF would be the technology of my choice for this project.
Drag & Drop way nicer, without flickering, better concept
Rendering directly on HW, way smoother for image manipulation
General idea of the implementation:
MVVM pattern
ViewModel holding your layer information
ItemsControl bound to the collection of Small overlay Images holding a DataTemplate which visualizes the images thour custom UserControl based on a Thumb (for drag & drop functionality) displayes the small images on top.
Easy to add functionality to drag, edit, hide each small image seperately.
The problem is that once the smaller image is drawn I cannot get back
to it as a separate graphics object. The picture box “sees” it as part
of the current image.
That behaviour is perfectly normal. GDI drawing does not work with objects. To do what you are asking, you need to track any event that can cause a change in the final image and when such an event occur, you need to draw the whole image from the begining, including the first image (assigning the background image, I guess).
May be create picture box per image. The transparent background will give the effect of single image.

c# Winforms Controls rendering the components they are positioned over to a bmp (intelligent screenshot?)

The problem:
I have a UserControl (LightBox) which overlays a number of other controls to allow the user to see the controls it is positioned over, but not allow the users to interact with the controls under the Lightbox. Winforms is (almost notoriously as I'm finding out) bad at handling alpha-blending.
Question:
How can I get the Lighbox control to render a bmp (snapshot) of whatever it is positioned over when it is created?
Explanation:
The reason I am looking to do this is to allow the Lightbox to draw its own background from this rendered snapshot. This would (hopefully) stop the issues that I am experiencing with large quantities of flicker and undesirable rendering affects.
Is this even possible?!
Thanks for your help.
EDIT 1:
This question seems to expain some of the issues that I am facing and at least describes what I am attempting to do i.e. create a buffer of the background image. However, there are no links explaining how this might ab achieved
You can use the Control.DrawToBitmap function to draw the control to a Bitmap:

Categories