I want to convert a xaml canvas to a png image using c#. I used RenderTargetBitmap as described in the second post here. It works quite well if the xaml that's meant to be converted is displayed in a window or a page and you can actually see it on screen. But if the window is closed or hidden or the canvas isn't a child of a window / page / frame, a blank image will be generated. Does anyone know why this happens or how to make it work?
I can't be sure but it may be that WPF is saving time by not rendering anything that isn't currently on screen, therefore when you grab the bitmap from the render target for that object, it hasn't been rendered and so it is blank.
I would suggest putting it on screen for the duration of your capture and then remove it. If the object is small it may even appear and disappear in no more than a flicker.
Related
I think I must be missing something obvious, but I'm unable to find this after several hours of searching. Is there no way to use a PictureBox or other control to contain an image with partial transparent/alpha-blended pixels, and place that over another image and have the blending be based on the image under it?
For example, this produces the results I want:
Place a panel on a form.
Add an OnPaint handler.
In the OnPaint handler draw 1 PNG, then draw another PNG over it, using Graphics.DrawImage for both.
This does not:
Place a PictureBox on a form and set it to a PNG.
Place another PictureBox on the form and set it to a PNG.
Place the 2nd picture box over the first.
...even if the 2nd picture box is just empty and has a background color of Transparent, it still covers the picture below it.
I've read this stems from all winform controls being windows, so by nature they aren't transparent.
...but even the 15 year old platform I'm migrating from, Borland's VCL, had several windowless controls, so it's hard to imaging winforms doesn't at least have some easy solution?
My first example above is one answer, true, but that adds a lot of work when you can only use one big panel and draw all of your "controls" inside of it. Much nicer if you can have separate controls with separate mouse events/etc. Even if not an image control, and a control I have to draw myself, that would be fine, as long as I can just put one image in each control. In VCL they called this a "paint box", just a rectangle area you could place on a form and draw whatever you want on it. Has it's own mouse events, Bounds, etc. If you don't draw anything in it, it is like it's not even there (100% transparent) other than the fact it still gets mouse events, so can be used as a "hot spot" or "target" as well.
The PictureBox control supports transparency well, just set its BackColor property to Transparent. Which will make the pixels of its Parent visible as the background.
The rub is that the designer won't let you make the 2nd picture box a child of the 1st one. All you need is a wee bit of code in the constructor to re-parent it. And give it a new Location since that is relative from the parent. Like this:
public Form1() {
InitializeComponent();
pictureBox1.Controls.Add(pictureBox2);
pictureBox2.Location = new Point(0, 0);
pictureBox2.BackColor = Color.Transparent;
}
Don't hesitate to use OnPaint() btw.
Sorry, I just found this... once I decided to Google for "winforms transparent panel" instead of the searches I was doing before, the TransPictureBox example show seems to do exactly what I need:
Transparency Problem by Overlapped PictureBox's at C#
Looks like there are 2 parts to it:
Set WS_EX_TRANSPARENT for the window style
Override the "draw background" method (or optionally could probably make the control style Opaque).
Say I have some grid that you need to scroll down to see all of its lines, and I'm interested in saving some lines that are not currently visible as a bitmap. Is it feasible, or do I have to actually scroll down, "take a snapshot", and then scroll up again?
This is a feasibility question, and thus I don't have code to share.
Yes. You can render any UIElement (and its children) to a writeable bitmap.
When you do that you also specify a transform. That means you can display any part of the UIElement (if you do not want it all).
Whether it is "visible" on screen is completely irrelevant to bitmap rendering. It does not work like a screen grab.
The output cropping is solely down to the size of the target bitmap and the render transform provided.
As an example Silverlight Rotate & Scale a bitmap image to fit within rectangle without cropping uses UIElements that are never part of the visual tree to create a bitmap that is then rendered.
I'm working on a module that displays DWG files in WPF. I've managed to use CadLib library but it's working very slowly and I want to make it faster. I found out that if I convert that DWG file to SVG format and then print it to my XPS printer and rename the file to ZIP, I can get .page file which is basically a XAML file that displays the original SVG object in XAML.
I want to display this XAML code on a custom control and be able to pan / zoom it around. I tried to place this XAML code in a Canvas and it did manage to show up there, but now I'm stuck trying to pan / zoom the shape that was drawn there. Also, the mouse events are fired only when you click the actual drawing itself, and not the Canvas, which will be hard for the user to click...
Any help would be highly appreciated :)
You could try creating nested Canvases : One that holds the vectors and is moved on demand, one that is fixed and serves as the viewport. Haven't tried that, but it should be feasible...
I need to get the actual height of the displayed content inside an opened pop up control:
Problem:
I want to show a lot of data in a grid inside a pop up. If this content became higher than the browser height, this content is cropped at the end of the window.
I there any way to get the height of this content (i know that pop up isn't in the visual tree)?
Try calling UpdateLayout() once all controls have been added to your popup.
You will then be able to get the ActualHeight of the popup.
This has a bit of a performance overhead so trying calling it as little as possible.
I currently have a Silverlight canvas that exceeds the viewable area of the screen (I'm letting the users drag the viewable areas around to navigate). I'm trying to display a modal popup that always shows up in the middle of the viewable area, and I can't seem to find any property that tells me what currently is on the screen. Basically if the user has panned down to the bottom and clicks something that causes a modal popup to appear it is stuck at the far top of the screen.
Any ideas anyone?
Thanks
~Steve
I don't think this is possible since the visibility isn't being surfaced. Perhaps with some fun JavaScript to figure out where the panning is?
Quite true. I wound up creating a holding canvas, making that full screen, and putting everything else as a child canvas within that. The modal popup now comes up in the holding canvas.
Gabriel GuimarĂ£es one works good.
App.Current.Host.Content.ActualHeight(and ActualWidth) does bring the browser size inside. Good for calculating position. And of course you can use LayoutUpdated on your main control to double check the sizes and resize stuff if need be.