How do you draw directly on an ActiveReports subreport? - c#

I want to create my own custom graphic based on some parameterized data and have it be generated in a subreport. I placed a ActiveReports.Picture element on the report. I then drew my image in memory using the System.Drawing.Graphics object and then set it to the Image property of the Picture control. This works OK, but the image on the generated PDF is blurry, even after setting the pdfExport1.ImageQuality to highest.
I think it would be better to draw directly on to the ActiveReports Document canvas, but I can't figure out how to make that work. All the examples out there point you to the same basic example:
http://www.datadynamics.com/Help/ActiveReports6/topic2107.html
The problem is that the example is out of context. I don't see where this code should run? Inside the sub-report? In the calling report? Outsize the report entirely? When I tried it in the report, the Pages property had no pages (got an index out of bounds error), so I may be doing it in the wrong event.
To be clear, this is not a data-driven report. I get all the data I need via parameters. No DB access is required.
Thanks.

In the examples in the documentation you referenced, the DrawLine is drawing on the parent document/report (not the subreport). You can however draw on a page as a section is processed. To do that, you put your rendering code inside of the processing events of the section such as BeforePrint event or AfterPrint event (I would avoid using the Format as there are many caveats when using Format).
To draw on the page from within a section's event, you can find the location of the section from the Section class' CurrentLocation property. For example, to draw a diagonal line across the entire section from the BeforePrint event you could use the following code:
public void Detail_BeforePrint(object sender, System.EventArgs eArgs)
{
this.CurrentPage.BackColor = System.Drawing.Color.Purple;
this.CurrentPage.ForeColor = System.Drawing.Color.YellowGreen;
this.CurrentPage.PenStyle = DataDynamics.ActiveReports.Document.PenStyles.Dot;
this.CurrentPage.PenWidth = 4;
this.CurrentPage.DrawLine(Detail.CurrentLocation.X, Detail.CurrentLocation.Y, this.PrintWidth, Detail.Height);
}
This code should work fine within a subreport or a parent report. Apparently you will need to change this.CurrentPage to ParentReport.CurrentPage if you want to draw on the page from within a subreport. If you want to draw relative to the page, you can use similar code but use the PageEnd event. There is a good example in the PageEnd Event's documentation. However, the PageEvents will only work for the parent report, it may be difficult to orient the drawing coordinates relative to a subreport's location.

It seems you have to draw on the main page, even from the subreport, which is why CurrentPage is null. So the following from the subreport works:
this.ParentReport.CurrentPage
http://www.datadynamics.com/forums/118838/ShowPost.aspx

Related

Get print page count without printing the document

This is somewhat similar to question about Is there a better way to get the page count from a PrintDocument than this?
But in my case I have a web-browser control with formatted html. At the moment I have option which calls ShowPrintPreviewDialog() so user can see how many pages going to be printed.
Is there anyway to get the no of pages which going to be printed, without launching the PrintPreview?
I am trying to create a method which will call OnTextChange and display print-page count automatically?
I have use PrintPage event
private void PrintDocumentOnPrintPage(object sender, PrintPageEventArgs e)
{
e.Graphics.DrawString(this.webBrowser1.DocumentText, this.webBrowser1.Font, Brushes.Black, 10, 25);
}
Bad news always travels slow at SO. You'll need to scratch the idea that this is practical.
Although unstated in the question, you should have already figured out by now that your PrintPage event handler doesn't work. It always produces a count of 1. That's because you never set the e.HasMorePages property to true, the property that causes more than one page to be generated.
To reliably set that property to true, you need to figure out exactly how the HTML gets rendered by the browser layout engine. And figure out exactly how to break it up into pages that don't cut, say, a line of text or an image in two. And figure out how to this is in the exact same way that the browser printing engine does this. A feat that's been attempted by many a programmer, accomplished by none. The browser's automation object model just doesn't have the needed api.
The only reasonable way is the one you already know. You have to call ShowPrintPreviewDialog(). Which readily displays the page count in the preview dialog, looks like this in IE11:
In case you'd consider snooping that number off the dialog: no, that cannot work either. The dialog doesn't use any controls, it is one monolithic window.

Image not loading correctly from BitmapImage in code behind

Okay, I'm attempting to load an image to an Image control on my page. Now as far as I know, I know how to do this (the method I'm using has worked before). But for some reason it's not working this time. The image is not being loaded.
Okay, let's start with the XAML. You can see it here.. Please note my excellent artistic skills. You can see that the top image is the left one on the screen and the bottom image is the right one. As you can also see, the image on the right is loaded in the XAML from a file in the Assets/Images folder. It should also be noted that we can take from this that the image loads okay - there aren't errors with the image. We can also see that the images are not blocked by anything (when the program runs, the right image shows just fine).
So the left image, 'image1' is the one that I'm loading from the code behind. Here is the code behind for that page. As you can see, there's not a lot. Yes I do use a view model, but it doesn't interface with the image at all (its only exposed properties are an Entity (for a selected item) and an ObservableCollection of entities (for the ItemsSource of a control)). As you can also see, I'm attempting to load the same image as is used for the static image (so I can say for sure that the image is okay for Silverlight).
If you're wondering about the BitmapCreateOptions line, that was something that someone suggested to me to add. I have tried removing it, but that doesn't seem to cause any difference.
The next question is - have I attempted to use the event handler for the failure? Yes I have. The error I get is 'AG_E_NETWORK_ERROR'.
I'm not sure what exactly this is about - I'm not loading from a network.
Can anyone offer assistance? Thanks.
I can't help but notice that in your XAML, you have a "../" at the start of the image path, but this is missing from the path you're using in code-behind. Could this be the problem?
Have You tried to call BeginInit and EndInit before and after setting the uri?
BitmapImage bmpImg = new BitmagImage();
bmpImg.BeginInit();
bmpImg.UriSource = new Uri(...);
bmpImg.EndInit();
Or use the constructor that takes an Uri. msdn

How do I assign an instance of the Image class to an Image control programatically?

Another noob question from me... Apologies!
My initial code would be as follows (this is simplified):
Image pic = new Image();
pic.ImageUrl = "~/Images/photo.jpg";
pic.BorderColor = "Black";
How can I assign the 'pic' Image object to an Image Control already on my ASP.NET page?
The following doesn't work but illustrates what I'm trying to do:
MyImageControl = pic;
I'm sure there must be an easier solution than:
MyImageControl.ImageUrl = pic.ImageUrl;
MyImageControl.BorderColor = pic.BorderColor;
If you want to dynamically put controls on the page you need to do just that. Have a container then add them to the container. If you have some sort of list or array that you are storing the controls in, you just need to iterate through the collection, setting any properties you need and call container.controls.add(control); You will have to do this every post-back as their state will not be kept.
Using an asp:Panel as your container where you want the controls to show up is the easiest way to style and position the controls.
SOLUTION (moved from original post) :
I have come up with something which works for me but would still be interested if there is a way to do what I've asked above - My solution is as follows.... Rather than having a blank Image Control in my .aspx page, I changed it for a PlaceHolder instead. Then, in the C# code, I can use the following to include my Image on the page:
MyPlaceHolder.Controls.Add(pic);

how to resize a picture programatically and add it to the web site

Hi there
I am working with visual web developer and would a) like to know how I could programatcally add a picture to the website, instead of going to Website and then add existing item. The idea I have is to upload the picture using the file upload control but then I want to have it added so that it can be accessed using a gridview.
b)I would also like to know how to size the picture using C# code obviously so that is displayed at the correct size.
best regards
arian
here is a full project with source code to manipulate images, including resize.
http://www.codeproject.com/KB/web-image/ASPImaging1.aspx
And a sample code only for resize
http://weblogs.asp.net/gunnarpeipman/archive/2009/04/02/resizing-images-without-loss-of-quality.aspx
You can use GetThumbnailImage to easily create a smaller verson of the uploaded image. The code looks something like (it's free typed without a compiler, so there may be some errors):
System.Drawing.Image pic = new System.Drawing.Bitmap(sourceFilename);
System.Drawing.Image thumb = pic.GetThumbnailImage(targetXSize,targetYSize,
new System.Drawing.Image.GetThumbnailImageAbort(this.GetThumbnailImageAbort),
IntPtr.Zero);
thumb.Save(thumbPathName);
I believe the Image implements IDisposable, so you need to remember to Dispose of them when you're done.
The abort parameter can be a function that simply does this (can't remember off the top of my head when it gets called):
bool GetThumbnailImageAbort() {
return false;
}

Render HTML as an Image

I'm generating a coupon based on dynamic input and a cropped image, and I'm displaying the coupon using ntml and css right now, the problem is, printing this has become an issue because of how backgrounds disappear when printing and other problems, so I think the best solution would be to be able to generate an image based on the html, or set up some kind of template that takes in strings and an image, and generates an image using the image fed in as a background and puts the coupon information on top.
Is there anything that does this already?
This is for an ASP.NET 3.5 C# website!
Thanks in advance.
edit: It'd be great if the output could be based on the HTML input, as the coupon is designed by manipulating the DOM using jQuery and dragging stuff around, it all works fine, it's just when it comes to the printing (to paper) it has z-indexing issues.
What you can do is create an aspx page that changes the response type to be in the format you want and then put the image into the stream. I created a barcode generator that does a similar thing. Excluding all the formalities of generating the image, you'll Page_Load will look something like this:
Bitmap FinalBitmap = new Bitmap();
MemoryStream msStream = new MemoryStream();
strInputParameter == Request.Params("MagicParm").ToString()
// Magic code goes here to generate your bitmap image.
FinalBitmap.Save(msStream, ImageFormat.Png);
Response.Clear();
Response.ContentType = "image/png";
msStream.WriteTo(Response.OutputStream);
if ((FinalBitmap != null)) FinalBitmap.Dispose();
and that's it! Then all you have to do in your image is set the URL to be something like RenderImage.aspx?MagicParm=WooHoo or whatever you need. That way you can have it render whatever you want to specify.
You can render html to a bitmap using the WebBrowser control in either a winforms or console application.
An example of this can be found here: http://www.wincustomize.com/articles.aspx?aid=136426&c=1
The above example can be modified to run in ASP.Net by creating a new STAThread and performing an Application.Run on it to start a new message loop.
PHP/Ruby Alternative
If you have accessed this question and are actually looking for soething that will work without Windows, you can try the KHTML library: http://wiki.goatpr0n.de/projects/khtmld
The website has a ridiculous name I admit, but I can assure you it is genuine. Other related pages are: the sourceforge page http://khtml2png.sourceforge.net/
Try PDFSharp...it's not exactly a "take this HTML and make a PDF" but with a small amout of fiddling you can easily make a PDF out of the info you are using to make the HTML.
MARKUP ONLY ALTERNATE SOLUTION
Use SVG and XSLT to transform the html data into an image that can be rendered/saved/etc.
I'll admit that at first it was tedious getting this to work because of all of the coordinates, but well worth the effort once it is running.
There is a very powerful image creation library called GD which I often use with PHP.
I am led to believe there is a wrapper for this library that ASP programmers can use. Try this
Unless the "other problems" are pretty severe, couldn't you just instruct your users to turn on Background Images when printing?
In any case, I'd default to serving a PDF rather than an image, doubly so since it is intended for print.
Just set up your css properly, so that you have a css file targeted at the print medium. It is pretty easy to guarantee that the coupon will always be legible, without worrying about whether they have bg images on or not. Needlesly moving to an image doesn't make any sense, unless there is some reason you don't want it to be machine readable.
I haven't tried to myself, but you should be able to render HTML into an image by using the WebBrowser control and the DrawToBitmap() method inherited from the base Control class.
UPDATE: I tried this myself and there are some caveats. The WebBrowser control doesn't seem to render the web page until the control is show, so the WebBrowser needs to be in a Form and the Form must be shown for the HTML to be rendered and the DocumentCompleted event to be raised.

Categories

Resources