WPF Dynamic Cursor - c#

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.

Related

Setting a texture using a "tileset" to a WPF button

I'm trying to create a button using a tiled texture. Basically there are textures for the corners, borders and the center. These should be repeating, completing the button's texture completely, without having to create each texture for different button sizes. If possible, the texture should be made and applied at runtime (if possible, the textures should be combined into a single texture to keep performance higher when using large or many controls). The problem is that I don't know where to start with this. A simple reference to something that might solve this problem would be great.
If you don't understand what I mean, this may help. https://i.stack.imgur.com/t89dT.png
Note that the above images contains a simple texture with two borders and a solid fill, but if I would like to do something more complicated for e.g. the corners, this wouldn't be as easy to recreate with simple WPF button properties (I think).
Edit: I made a small gif animation hopefully explaining it a bit more: https://i.stack.imgur.com/fFhVY.gif
Regards, tizu

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.

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.

Rendering 2D primitives in scrollable view

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.

How do I draw a 3D border using visual styles?

I can draw a 3D border using ControlPaint.DrawBorder3D, but I get the 'Windows Classic' 3D border. I want to draw the current theme's 3D border - in the default XP theme, this is a 1px blue or gray border. How do I draw that, and how do I get its widths?
Sounds like you might need to look at System.Windows.Forms.VisualStyles.VisualStyleRenderer:
The System.Windows.Forms.VisualStyles
namespace exposes VisualStyleElement
objects that represent all of the
controls and user interface (UI)
elements that are supported by visual
styles. To draw or get information
about a particular element, you must
set a VisualStyleRenderer to the
element you are interested in.
To draw an element, use the
DrawBackground method. The
VisualStyleRenderer class also
includes methods, such as GetColor and
GetEnumValue, that provide information
about how an element is defined by the
current visual style.
There's a code sample on that page as well.
You will have to draw the border yourself, but you can get the color from VisualStyleElement.Window.Caption.Active and the size should be the size of the window frame (I believe), which is VisualStyleElement.Window.FrameBottom.Active. If you explore the VisualStyleElement.Window, you should be able to determine which window element has the information you need to draw your border.
Pre .NET Framework 2.0 Answer
I'm assuming that you are drawing your own, special control and you want to use elements of the currently active theme to draw it so it better fits with standard XP controls. You're NOT trying to, for example, enable theming on a standard Button control. Correct?
It's actually somewhat complicated. Your main focus should be UxTheme.dll. This houses everything you need for drawing themed controls. Here is a nice C# wrapper around this dll to make your life easier. There are others so if this isn't exactly what you wanted, I hope I've pointed you in the right direction.

Categories