I'm attempting to write a custom button user control. I have run into a challenge when drawing the image.
Is there a simple way to draw the image accounting for the ImageAlign and TextImageRelation? (Kind of like StringFormat makes text aligning a breeze)
Or do I have to do all the aligning logic and stuff manually?
Thanks
What functionality are you trying to achieve? Perhaps it should instead inherit from the Button class (asssuming WinForms), and override appropiate methods. Depending on what you need to do, you will propably get much of the lower levels of functionality in the button for free, if you do this.
To get back to your question; No, if you need to draw stuff yourself, there is no magic easy way to determine where the individual pixels should go :-) One great helper in doing this, that you should be aware of, is the Graphics.DrawString method. It lets you measure the dimensions of a given text string when drawn on the control with the selected font and size.
I do not know of anything that does this stuff for you, but be aware of the ControlPaint class as that has a bunch of handy utility methods for painting controls.
Related
I am trying to make a UI prototype for a bus route design app. The intended behaviour is to let the user paint with a brush over the streets, but not over buildings. The idea is to get something like you see in the image below where the pink line represents the route that the user just painted.
I am currently using a basic InkCanvas and InkToolbar in order to do this.
My problem is that I have no idea on how to prevent users from painting over buildings. I tried to create several InkCanvas, each one of them representing a unique street, but that's a very clunky solution. Should I stick to this "solution" or is there any other thing that allows me to prevent the user from painting?
UWP-xaml InkCanvas: Is there a way to deny painting on specific zones?
Great question, for your requirement, the better way is that draw line in MapControl with MapPolyline.
If you want to draw the line with ink-canvas, You need to declare that the building is not available. and please check official code sample scenario 8. When the stroke
cross the circle, it will be removed.
I am doing some work for which I need to develop a control, it should be a simple graph that shows several points and two edges.
My problem is that I need to show up to 16k points, with an update rate of 30 Hz. Has anyone done something similar?, and has any advice?.
For example whether to inherit from FrameworkElement or Control (ItemsControl in this case). If the control inherits from FrameworkElememt it may have a better performance drawing the points in the OnRender method but I would miss the Templating feature that comes from inheriting from Control.
Or does there exist another control that can do this out there?
Thanks in advance for your time.
I ended up using InteropBitmap, it is the fatest bitmap rendering class from WPF.
It allows you to map the image that you want to paint (in memory) and then reder it as a Image. This was perfect as i needed to plot points on the screen.
I got great performance (almost 50Hz for 20k points), i also use PLINQ to update the points in memory.
check this article for more details...
Try and read about ZoomableCanvas. I believe it can solve your problem. You can render all the points as small rectangles/ellipses inside the ZoomableCanvas.
For example, let's say I want to create something complex. like a zoommable/pannable graph. like google maps, or a stock market graph or something.
XAML and that whole hierarchy doesn't really work. What I'm trying to do is kind of more like back in the day with GDI+/Winforms. Where I could override paint
i.e., "protected override void OnPaint(PaintEventArgs e)" and then I'd draw whatever the heck I wanted. Where I'd do double buffering. Like draw to a buffer and blip it to the screen.
But how do I go about this in WPF?
A fundamental difference between WPF and GDI/GDI+/WinForms is that WPF uses retained mode rendering (as opposed to the direct rendering of GDI). In a nutshell, this means that the system (actually, the hardware) is taking care of the double buffering for you. Instead of procedurally drawing to the screen / buffer, you rather declaratively provide a tree of vector objects and leave all the rendering to WPF.
The vector objects come in different levels of complexity / abstraction - the most low-level ones you might ever want to deal with are Visuals. The Shapes (Ellipse, Rectangle etc.) mentioned by David are already higher-level objects which can also handle user interaction like hit-testing etc.
You can use any of the WPF shapes, like Ellipse, Rectangle and then using the Canvas class you can move them:
var rect = new Rectangle();
//...set width, height...
Canvas.SetTop(rect, 10);
Canvas.SetLeft(rect, 15);
This should get you started. Keep in mind that zooming, stretching content, traslating and rotations can all be achieved using math functions, but don't panic! WPF's got some cut things about it too:
var rotateTransform1 = new RotateTransform(45);
rect.RenderTransform = rotateTransform1;
If you really, really want it, you can derive your control from UIElement or FrameworkElement and override OnRender where you will get a DrawingContext object which provides methods for drawing shapes, text, images.
But if you want to work in the WPF's philosophy and spirit, probably 99% of the times you don't need to override OnRender. WPF offers a lot (and I really mean A LOT) of ways to develop new controls by styling, templating and if these two don't do the job, then subclassing the appropriate control in the WPF's controls hierarchy.
As gstercken very good pointed before, WPF is not WinForms, you must think in WPF in order to do a good work.
I'm new to C# but not to OOP.
I'd like to make a "canvas" panel on which a user can draw shapes by mouseClick-ing but also delete them (nothing fancy, fixed sizes and whatnot, plain old pen objects). Like I said, I want the user to be able to delete whatever objects he alt-clicks on.
I'm not sure how exactly could I go about doing this. If I were using Flash, I'd probably do something like:
my_circle_object = new disc-or-whatever-etc;
canvas.addChild(my_circle_object);
my_circle_object.AddEventListener(MouseClickEvent, function_to_remove_child);
Now, since compiled languages are the devil when it comes to simple front-end UI related stuff, I'm sure It'll take 20 times more code to write this in C#. But, is there anything similar to my example?
I've spent all afternoon reading on things like GraphicsContainers, SmoothingPaint, Graphics Persistence using bitmaps etc. but I never found a simple add event method..
Thank you
The objects that you draw using the shape methods on a Graphics object (e.g. DrawLine, DrawEllipse, DrawRect, etc.) do not represent conceptual objects as far as the graphics API is concerned. Calling those functions simply draws the item to the graphics surface as a bitmap. Once that's done, there's nothing there to attach an event to.
You'll need to create your own shape types and have them draw themselves to the graphics object. You'll have to attach to the appropriate mouse events on whatever control you're using (I'm assuming a Panel) and do your own collision detection.
In normal C# it is easy to draw to a bitmap using the Grpahics.DrawString() method. Silverlight seems to have done away with Bitmap objects and Graphics is no longer available either. So...How am I meant to manipulate/create a bitmap when using Silverlight? If it helps, I am using Silverlight 3.
Let me tell you what I am doing. I am being given a template, basically a pre-rendered image. The user is then able to select from multiple images and enter the deisred text. I then render it to the image, adjusting size etc... within bounds and centering it in the pre-defined area of the image. If I can calculate the size (as in the MeasureString method) and then draw the string (as in the Graphics.DrawString method) that would be fine. The real question, no matter why I want to be able to do this, is can it be done?
The question is: why do you want to? Why not just use a TextBlock?
If you are trying to dynamically generate an image, use standard Silverlight/WPF controls (including TextBlock) and render them to a WritableBitmap.
Edit:
Ok, you've updated and expanded, which gives me more to go on. Unfortunately, you're not going to like the answer. First, keep in mind that Silverlight and WPF in general are vector based, and intended to be used as such. Although the Canvas allows you to do pseudo-pixel manipulations, you cannot be nearly as pixel-accurate as old-school GDI. This is a factor of your medium. If you absolutely have to measure things the way you want to measure them, I suggest you build your images on a remote server and transmit them to your Silverlight app.
You can calculate the size on-screen of the text rendered via a TextBlock using the ActualWidth and ActualHeight properties. But it only works on an already rendered control. Something like MeasureString is simply not available in Silverlight. Based on your description of your app, some user interaction could accomplish what you want. The user selects the image, enters the text, and is shown a preview. The user can then adjust the width and height of the various text areas until satisfied, at which point you can take a snapshot using the render method I liked to above.
The following may work, its a bit nebulous because I haven't tried yet myself.
The object you are looking for is the WritableBitmap.
You create a Visual tree, for example create your self a Grid or Canvas (you're not adding this to the UI). Add to it the selected image and a TextBlock positioned and sized as you prefer.
Create a new WritableBitmap either of a specific size or using the selected image to initialize it.
Use the WritableBitmap Render method passing the above root Grid or Canvas to it.
Now you have a bitmap which you should able to use to do whatever its you needed to do that required all this hoop jumping in the first place.