I am using tchart with graphics 3d for real time chart plotting. whenever I try to call print preview for the chart, the preview page is just a blank page and the actual chart background becomes black. I tried different tricks and i found this printpreview works in normal canvas. but as soon as i write the line
Chart1.Graphics3D = new Graphics3DDirect2D(Chart1.Chart);
print preview does not work .
If I call export function, e.g. export to pdf functionality then the pdf file has exported chart in it and alternate route can be I can print the pdf.
But I want to use print preview and give user a functionality to change margins and other things as per their need.
Link for the demo project is http://www.filedropper.com/sampleprojecttchartprint
Link for the Video describing issue is http://tinypic.com/r/2ufg7f5/5
What am I doing wrong here?
There is a limitation with the wrapper TeeChart uses, a limitation documented here:
http://bugs.teechart.net/show_bug.cgi?id=356
As suggested, the workaround is to use the GDI+ canvas for image exportation, e.g.
private void InitializeChart()
{
tChart1.Graphics3D = new Graphics3DDirect2D(tChart1.Chart);
tChart1.Aspect.View3D = false;
FastLine series = new FastLine(tChart1.Chart);
series.FillSampleValues(1000);
}
TChart tChart2;
private void button1_Click(object sender, EventArgs e)
{
if(tChart2 == null) tChart2 = new TChart();
MemoryStream ms = new MemoryStream();
tChart1.Export.Template.Save(ms);
ms.Position = 0;
tChart2.Import.Template.Load(ms);
tChart2.Export.Image.PNG.Width = tChart1.Width;
tChart2.Export.Image.PNG.Height = tChart1.Height;
tChart2.Export.Image.PNG.Save(#"C:\tmp\direct2d.png");
}
Related
I'm trying to create a program which scrolls through files located on my computer and displays the files. This is working for me so far but I'm getting content in actual size so the webbrowser adds a scrollbar(obviously). I want the content to scale automatically so it fits in the webbrowser without having to scroll.
Code:
WebBrowser web = new WebBrowser();
System.Drawing.Rectangle workingRectangle = Screen.PrimaryScreen.WorkingArea;
int heightWebcontrol = workingRectangle.Height / 100 * 85;
int widthwebControl = workingRectangle.Width / 100 * 75;
web.Size = new Size(widthwebControl, heightWebcontrol);
web.Location = new Point(0, 0);
web.Navigate(fileName);
this.Controls.Add(web);
Large image in webbrowser, this is just 1/5th of the image:
So basicly, this large image, needs automatically to be scales so it fits the browser exactly.
Thanks guys.
As an option, you can handle DocumentCompleted event of the WebBrowser control and set the style of image based on the size.
For example:
1) Create a Windows Forms Project
2) Open Form1 in desgn mode and drop a WebBrowser control on it.
3) Double click on title-bar of form to handle Load event of the form and use following code:
private void Form1_Load(object sender, EventArgs e)
{
this.webBrowser1.Navigate("https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png");
}
4) Double click on WebBrowser control to handle its DocumentCompleed event and use following code:
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
webBrowser1.Document.Body.SetAttribute("scroll", "no");
var img = webBrowser1.Document.GetElementsByTagName("img")
.Cast<HtmlElement>().FirstOrDefault();
var w = img.ClientRectangle.Width;
var h = img.ClientRectangle.Height;
img.Style = string.Format("{0}: 100%", w > h ? "Width" : "Height");
}
You will see following result, while the original image size is 544x184:
Note 1
This is just an example of what you can do. You can make the decision more intelligent, for example check if the image size is less than the browser size, then you don't need to apply any scaling.
Note 2 - (This is my choice)
If you setup WebBrowser control to support showing modern content the better style for the image will be:
img.Style = "max-width:100%;max-height:100%";
This way, the image will be fit in the browser when it's larger than browser. Also it will not resize when the browser is large enough.
I have this idea of this world map image and when I click a country on it, it shows information of that country in a MessageBox for example does anyone have an idea how to do that?
I have a rectangle and a button and when i click the button it shows the image in the rectangle but i thought if i use polygons to shape the country's but I'm a little stuck.
I would like to have every country apart and maybe that the borders light up when clicked
You can do this pretty easily using WPF:
Find a nice World Map in SVG format. I used this one from Wikipedia:
Download and install Inkscape then open the SVG you've just downloaded. Inkscape has a nice feature that makes it possible to save an SVG as a XAML.
Import the ViewBox from the XAML file into your WPF window/etc:
For each Path in the XAML you can add a MouseEnter/MouseLeave event handler or you can use the same one for all the Paths
Sample code:
private void CountryMouseEnter(object sender, MouseEventArgs e)
{
var path = sender as Path;
if (path != null)
{
path.Fill = new SolidColorBrush(Colors.Aqua);
}
}
private void Country_MouseLeave(object sender, MouseEventArgs e)
{
var path = sender as Path;
if (path != null)
{
path.Fill = new SolidColorBrush(Colors.Black);
}
}
Now it's just a matter of changing colors/showing MessageBoxes etc.
GitHub
My first thought: You could bind a command to the view that will be triggered by a click on a position. If you're using WPF you can bind command parameters to the command to get the x and y of your click...
After that you have to handle the content of your messagebox and the highlighting of the borders depending on the position xy.
have fun :D
Option 1
There is a project on Code Project that someone created that defines hotspots that are clickable with events. You could use that to overlay your map and define the hotspots where you need them.
C# Windows Forms ImageMap Control
Option 2
You could bind to the MouseUp Event on the Image and use the following to see if it is in a Rectangle
private void mapMouseUp(object sender, MouseEventArgs e) {
Rectangle rect1 = new Rectangle(0, 0, 100, 100);
Rectangle rect2 = new Rectangle(0, 100, 100, 100);
if (rect1.Contains(e.Location)) {
// Do your stuff
} else if (rect2.Contains(e.Location)) {
// Do your stuff
}
}
Below is the process I worked in Windows forms for printing.
I used PrintDocument class. It contains PrintPage event and I used that to draw the graphics of what I need to print and obtained the result successfully as I expected.
Below is the code:
public PrintDocument Printing
{
m_printDocument = new PrintDocument();
m_printDocument.PrintPage += new PrintPageEventHandler(OnPrintPage);
}
The code for OnPrintPage as follows:
protected virtual void OnPrintPage(object sender, PrintPageEventArgs e)
{
//Image img = I have the things to be printing in the form of image.
e.Graphics.DrawImage(img, new Point(0,0));
}
In WPF:
I am working with Fixed document and by using the below code I can print
PrintDialog print = new PrintDialog();
print.PrintDocument(FixedDocument.DocumentPaginator, "Print") //Where Fixed document contains the data to be printed.
This results is insufficient memory to continue the execution of the program.
But I got Fixed document without any problem.
Any solutions ...?
I hope the similar thing as like Windows form would be there in WPF too...
I used to get this when my pages contained lots of visual elements (drawings/images/ complex diagrams). Instead of printing the complete document at once (which can lead to out of memory)
print.PrintDocument(FixedDocument.DocumentPaginator, "Print")
I printed one of its page.
PrintQueue selectedPrntQueue = printDialog.PrintQueue;
XpsDocumentWriter writer = PrintQueue.CreateXpsDocumentWriter(selectedPrntQueue);
SerializerWriterCollator collator = writer.CreateVisualsCollator();
collator.BeginBatchWrite();
var paginator = FixedDocument.DocumentPaginator;
FixedPage fixedPage = paginator.GetFixedPage(printedPageCount)
ContainerVisual newPage = new ContainerVisual();
Size sz = new Size(pageSize.Height.Value, pageSize.Width.Value);
fixedPage.Measure(sz);
fixedPage.Arrange(new Rect(new Point(), sz));
fixedPage.UpdateLayout();
newPage.Children.Add(fixedPage);
collator.Write(newPage);
I had to do GC after printing few pages (my magic number was 10).
You may need to tweak the this up to your requirement.
We've got a large stock of paper forms that we need to fill out. It's very tedious to do this by hand, so we're building an application. It should provide a form to fill in data, be able to show print preview, print the data on the paper form, and keep the history.
Currently, we have a FixedPage which we print like this:
var dlg = new PrintDialog();
if (dlg.ShowDialog() == true)
{
var doc = new FixedDocument();
doc.DocumentPaginator.PageSize = new Size(11.69 * 96, 8.27 * 96); // A4 Landscape
var fp = Application.LoadComponent(new Uri("/FixedPage.xaml", UriKind.Relative)) as FixedPage;
fp.DataContext = this;
fp.UpdateLayout();
var pc = new PageContent();
((IAddChild)pc).AddChild(fp);
doc.Pages.Add(pc);
dlg.PrintTicket.PageOrientation = System.Printing.PageOrientation.Landscape;
dlg.PrintDocument(doc.DocumentPaginator, string.Format("Form #{0}", FormNumber));
}
For the print preview we have a custom UserControl with scanned image of the paper form on background and the data on foreground. Basically, it's repeating the FixedPage layout, and all this makes us think there's a flaw in our design.
Is there a better way to do what we want?
I was tasked with the same problem and wanted to avoid writing my own templating system to save time, unit testing, and my sanity.
I ended up writing a hybrid to did some cool things. First, I wrote my templates using HTML and CSS. It was very easy to do and allowed for great flexibility when making minor adjustments from our Marketing department.
I filled the template with my own tags (e.g [code_type/], [day_list]...[/day_list]) and string replaced the text with a dictionary of tags that could be a single or multivalued.
After generating the html, I would use an html to pdf library I found that uses the open-source webkit engine to render and create the generated pdf. It turned out very stable and took around 2 weeks to write the initial program. Everyone was very pleased and testing was a breeze.
If you want more details, send me a message or reply to this.
We have managed to find a solution, which allows us to throw away a bunch of renundant code. It is still ugly:
public class CustomDocumentViewer : DocumentViewer
{
public static readonly DependencyProperty BackgroundImageProperty =
DependencyProperty.Register("BackgroundImage", typeof(Image), typeof(CustomDocumentViewer), new UIPropertyMetadata(null));
public Image BackgroundImage
{
get { return GetValue(BackgroundImageProperty) as Image; }
set { SetValue(BackgroundImageProperty, value); }
}
protected override void OnDocumentChanged()
{
(Document as FixedDocument).Pages[0].Child.Children.Insert(0, BackgroundImage);
base.OnDocumentChanged();
}
protected override void OnPrintCommand()
{
var printDialog = new PrintDialog();
if (printDialog.ShowDialog() == true)
{
(Document as FixedDocument).Pages[0].Child.Children.RemoveAt(0);
printDialog.PrintDocument(Document.DocumentPaginator, "Test page");
(Document as FixedDocument).Pages[0].Child.Children.Insert(0, BackgroundImage);
}
}
}
...
<local:CustomDocumentViewer x:Name="viewer" BackgroundImage="{StaticResource PaperFormImage}"/>
...
InitializeComponent();
viewer.Document = Application.LoadComponent(new Uri("/PaperFormDocument.xaml", UriKind.Relative)) as IDocumentPaginatorSource;
The reason why we're using Application.LoadComponent instead of binding is a five years old bug: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=293646
I am trying to print the content of RichTextBox including the Adorner Layers inside.
I am using this code to print
double w = Editor.ExtentWidth; // Editor is the RichTextBox
double h = Editor.ExtentHeight;
LocalPrintServer ps = new LocalPrintServer();
PrintQueue pq = ps.DefaultPrintQueue;
XpsDocumentWriter xpsdw = PrintQueue.CreateXpsDocumentWriter(pq);
PrintTicket pt = pq.UserPrintTicket;
if (xpsdw != null)
{
pt.PageOrientation = PageOrientation.Portrait;
PageMediaSize pageMediaSize = new PageMediaSize(w, h);
pt.PageMediaSize = pageMediaSize;
xpsdw.Write(Editor);
}
The problem I'm facing is that this code only prints the content that is visible on the screen, not the whole content of the Editor.
EDIT
The pictures are adorner layers, If I print using the method above, it only prints the visible part on the screen not the whole document.
Edit
I'm trying to print each page separately but I cant force Editor.InvalidateVisual(); after doing a Editor.PageDown(); Is there a way I can do that in my method ?
When controls draw on the adorner layer, they search up the tree until they find an adorner layer. Often times this is a the window level. In some cases, you'll want an adorner layer closer to the control, or directly around the control. In this case, wrap the control with an <AdornerDecorator><RichTextBox /></AdornerDecorator>
In your case, you'd probably want to pass a parent element of adorner decorator, or the decorator itself to the print logic. This way the print logic would include the adorner layer as part of the visual. Maybe something like this:
<Grid Name="EditorWrapper">
<AdornerDecorator>
<RichTextBox />
</AdornerDecorator>
</Grid>
Then, pass "EditorWrapper" to the print logic.
EDIT
If you just want to print the contents of the RichTextBox, then you might be best to use the built-in pagination capabilities of the FlowDocument. FlowDocument implements IDocumentPaginatorSource, which will return a paginator that can print the document. Pass that paginator to the XpsDocumentWriter and it should dump the content properly.
var doc = Editor.Document;
var src = doc as IDocumentPaginatorSource;
var pag = src.DocumentPaginator;
xpsdw.Write(pag);
I found this code here:
// Serialize RichTextBox content into a stream in Xaml or XamlPackage format. (Note: XamlPackage format isn't supported in partial trust.)
TextRange sourceDocument = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd);
MemoryStream stream = new MemoryStream();
sourceDocument.Save(stream, DataFormats.Xaml);
// Clone the source document's content into a new FlowDocument.
FlowDocument flowDocumentCopy = new FlowDocument();
TextRange copyDocumentRange = new TextRange(flowDocumentCopy.ContentStart, flowDocumentCopy.ContentEnd);
copyDocumentRange.Load(stream, DataFormats.Xaml);
// Create a XpsDocumentWriter object, open a Windows common print dialog.
// This methods returns a ref parameter that represents information about the dimensions of the printer media.
PrintDocumentImageableArea ia = null;
XpsDocumentWriter docWriter = PrintQueue.CreateXpsDocumentWriter(ref ia);
if (docWriter != null && ia != null)
{
DocumentPaginator paginator = ((IDocumentPaginatorSource)flowDocumentCopy).DocumentPaginator;
// Change the PageSize and PagePadding for the document to match the CanvasSize for the printer device.
paginator.PageSize = new Size(ia.MediaSizeWidth, ia.MediaSizeHeight);
Thickness pagePadding = flowDocumentCopy.PagePadding;
flowDocumentCopy.PagePadding = new Thickness(
Math.Max(ia.OriginWidth, pagePadding.Left),
Math.Max(ia.OriginHeight, pagePadding.Top),
Math.Max(ia.MediaSizeWidth - (ia.OriginWidth + ia.ExtentWidth), pagePadding.Right),
Math.Max(ia.MediaSizeHeight - (ia.OriginHeight + ia.ExtentHeight), pagePadding.Bottom));
flowDocumentCopy.ColumnWidth = double.PositiveInfinity;
// Send DocumentPaginator to the printer.
docWriter.Write(paginator);
}
Adorner layers are are drawing oriented. So one option left is to convert the entire RichTextBox into a drawing and print that as an Image in XPS.
Although this poses multiple issues...
It will print the external and internal contents that occupy or occupied by the richtextbox i.e. editor toolbar (if it is part of the control template of the rich text box), internal scroll bars etc.
If there are scrollbars then the content out of the scrollbars are not going to be printed as the image will be the exact "snapshot" of the textbox (with remaining text clipped by srollbars).
Will you be happy with that?
I didn't find any way that works 100% for this problem, so I'm trying to transform all my adorner layers to actual images. I'll update the question once I get a 100% working solution.