i try to print out the content of my editor:
PrintDialog pd = new PrintDialog();
pd.PageRangeSelection = PageRangeSelection.AllPages;
pd.UserPageRangeEnabled = true;
FlowDocument fd = DocumentPrinter.CreateFlowDocumentForEditor(CurrentDocument.Editor);
DocumentPaginator dp = ((IDocumentPaginatorSource)fd).DocumentPaginator;
bool? res = pd.ShowDialog();
if (res.HasValue && res.Value)
{
fd.PageHeight = pd.PrintableAreaHeight;
fd.PageWidth = pd.PrintableAreaWidth;
fd.PagePadding = new Thickness(50);
fd.ColumnGap = 0;
fd.ColumnWidth = pd.PrintableAreaWidth;
pd.PrintDocument(dp, CurrentDocument.Editor.FileName);
}
The test-document i used has about 14 pages (with this pagesize-settings).
i tested it: the printdialog appears and I´ve chosen a pagerange (i typed "1-3" into the textbox) and clicked print. above the printdocument() I set a breakpoint and looked into the printdialog-object. it says pd.PageRangeSelection = PageRangeSelection.UserPage and pd.PageRange = {1-3}. I guess this is right, because I wanted to print out only page 1-3. then the printdocument() executed and in the output-pdf (for testing I use a pdf-printer) has 14 pages (the whole document was printed).
where is my mistake? why does the pagerange-setting not work?
thanks for your help
In your code you manually set:
pd.PageRangeSelection = PageRangeSelection.AllPages;
This is why your code prints all the pages.
The reason for this is because FlowDocument's DocumentPaginator does not handle UserPageRanges. You can see that FlowDocument implementation creates a FlowDocumentPaginator, and it doesn't take into account ranges.
If it did handle it, in FlowDocumentPaginator.(Async)GetPage you would see, code checking to see if the page requested to be printed is in an index of available pages; or maybe if a key exists in a Dictionary whose value is the DocumentPage to print.
In other words, and the reason the PrintDialog default has UserPageRangeEnabled set to false, is because in order to use that feature, you'll usually have to write your own DocumentPaginator or you have to add some logic to compile a new temporary document to hold only the pages you want to print.
Feel free to ask any questions.
Related
I'm trying to generate a PDF report using SelectPDF. The report is multi-page long, and as such I need pagebreaks. Whenever these pagebreaks show up, I need top and bottom margins so the report won't look ugly, but I can only find the option to add margins for every page or no pages, but not "every page except the first one".
The source of the report is HTML/CSS that I have set up. The contents are dynamic, so I cannot manually control the text... The greatest granularity I have is controlling the CSS.
HtmlToPdf converter = new HtmlToPdf();
converter.Options.PdfPageSize = PdfPageSize.A4;
converter.Options.PageBreaksEnhancedAlgorithm = true;
converter.Options.MarginTop = 20;
converter.Options.MarginBottom = 20;
The "MarginTop" option adds the top margin to every single page. It works excellently for every page except for the first one, where I need it to be 0, but I can't find any options to do that. Does it exist?
It's not possible to do that using margins. You can however workaround this using headers/footers:
HtmlToPdf converter = new HtmlToPdf();
converter.Options.PdfPageSize = PdfPageSize.A4;
converter.Options.PageBreaksEnhancedAlgorithm = true;
converter.Options.DisplayHeader = true;
converter.Header.Height = 20;
converter.Header.DisplayOnFirstPage = false;
converter.Options.DisplayFooter = true;
converter.Footer.Height = 20;
I'm pulling the content from a text file into a RichTextBox. I've got the RichTextBox set up to where it only shows 6 lines at a time. I've got a search method that finds the text I need within the RichTextBox, but what I am needing it to do is display 6 specific lines. Each "item" in my text file consists of 6 lines. No matter which of the six lines the search method finds the text on, I need the RichTextBox to only display the 6 lines of each "item" with the currently selected "found" text remaining highlighted.
I've gotten it working reasonably well thanks to a few code examples I've pull from this site. But every now and then, it doesn't work entirely well, and am looking for some advice from a fresh set of eyes looking at my code and perhaps even be told an easier/more efficient way to go about it. But here is my code so far. Thanks in advance!
try
{
string s = txtFindPlaylistEntry.Text;
rtxEditPlaylistEntry.Focus();
findPosEntry = rtxEditPlaylistEntry.Find(s, findPosEntry, RichTextBoxFinds.None);
// Jump to the line we need.
int count = rtxEditPlaylistEntry.GetLineFromCharIndex(findPosEntry);
count = (count - (count % 6)) + 1; // Must be divisible by 6 then plus 1
rtxEditPlaylistEntry.SelectionStart = rtxEditPlaylistEntry.Find(rtxEditPlaylistEntry.Lines[count]);
rtxEditPlaylistEntry.ScrollToCaret();
rtxEditPlaylistEntry.Select(findPosEntry, s.Length);
findPosEntry += txtFindPlaylistEntry.Text.Length;
}
catch
{
MessageBox.Show("No occurences found");
findPosEntry = 0;
}
As of right now, I'm attempting to use a line count with modulus plus 1 to get the line I need. Like I said, it works, just not 100% of the time and I can't figure out why.
EDIT to try to accommodate Minimal, Complete, Verifiable.
I've already posted my "find" function. Here is other related code that might be useful. First, here is my code for creating the various controls I am using.
rtxEditPlaylistEntry = new RichTextBox();
rtxEditPlaylistEntry.Location = new System.Drawing.Point(15, 90);
rtxEditPlaylistEntry.Size = new System.Drawing.Size(375, 85);
rtxEditPlaylistEntry.Multiline = true;
rtxEditPlaylistEntry.ScrollBars = RichTextBoxScrollBars.None;
Here is my button function to pull text from a file and place it into the RichTextBox.
private void btnBrowseForPlaylistToEditEntry_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "LPL Files|*.lpl";
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
savedFileNameEntry = openFileDialog.SafeFileName;
txtPathToPlaylistToEditEntry.Text = openFileDialog.FileName;
}
// After finding the file, load it into the richtextbox control
using (StreamReader sr = File.OpenText(openFileDialog.FileName))
{
// Initially show the first 6 lines (IE first entry). This should be accomplished by
// the richtextbox control settings
rtxEditPlaylistEntry.Text = sr.ReadToEnd();
}
previousNextCount = 0;
}
I hope this is sufficient. If not please let me know!
Im trying to translate this VBA code from an Outlook AddIn to C#
Private Sub objInspector_Activate() Handles objInspector.Activate
Dim wdDoc As Microsoft.Office.Interop.Word.Document = objInspector.WordEditor
wdDoc.Windows(1).Panes(1).View.Zoom.Percentage = lngZoom
End Sub
But I can't get access to the Panes.View.Zoom.Percentage property
The main idea is that when the user opens an email, he will get a custom zoom level.
What I got at the moment is:
void Inspector_Activate()
{
// this bool is true
// bool iswordMail = objInspector.IsWordMail();
//I get the word document
Document word = objInspector.WordEditor as Microsoft.Office.Interop.Word.Document;
word.Application.ActiveDocument.ActiveWindow.View.Zoom.Percentage = 150;
// at this point i'm getting an exception
// I've also tried with
// word.ActiveWindow.ActivePane.View.Zoom.Percentage = 150; getting the same exception
}
The exception is :
An exception of type 'System.Runtime.InteropServices.COMException'
occurred in OutlookAddInTest.dll but was not handled in user code
Additional information: This object model command is not available in
e-mail.
I'm quite new in C# and Office addins, any advise?
Use word.Windows.Item(1).View.Zoom.Percentage = 150 (where word comes from Inspector.WordEditor)
word.Application.ActiveDocument.ActiveWindow.View.Zoom.Percentage = 150;
What property exactly fires the exception?
Anyway, there is no need to call the Application and ActiveDocument properties in the code. The WordEditor property of the Inspector class returns an instance of the Document class (not Word Application instance).
Thanks to Eugene Astafiev for his help.
The square brackets did the trick
VBA
Private Sub objInspector_Activate() Handles objInspector.Activate
Dim wdDoc As Microsoft.Office.Interop.Word.Document = objInspector.WordEditor
wdDoc.Windows(1).Panes(1).View.Zoom.Percentage = 150
End Sub
C#
private void Inspector_Activate()
{
Document wdDoc = objInspector.WordEditor;
wdDoc.Windows[1].Panes[1].View.Zoom.Percentage = 150;
}
I've been wanting this forever, and then I stumbled on a nice project in the MSDN Gallery Outlook 2010: Developing an Inspector Wrapper. It has a set of wrappers for all the Outlook objects, so you get a true event for every item of interest. Not sure if it's the most efficient thing ever, but it seems to work.
I have trouble with my eyesight so want black everything, and zoom everything. I seem to be able to do that by overriding the Activate() method. It's all pretty new so we'll see if it survives long term.
protected virtual void Activate() {
var activeDocument = Inspector.WordEditor as Document;
if (activeDocument == null)
return;
var mailZoom = GetSetting("MailZoom", 125);
if (mailZoom != 0)
activeDocument.Windows[1].View.Zoom.Percentage = mailZoom;
if (GetSetting("MailBlack", true)) {
activeDocument.Background.Fill.ForeColor.RGB = 0;
activeDocument.Background.Fill.Visible = msoTrue;
activeDocument.Saved = true;
}
}
In this example, GetSetting is just a function that returns a setting from an INI file. you can use constants or some other storage method.
There might be a better way to get the white on black text, but this seems pretty good.
There might be a better way to get the result I'm looking for. Basically I have a page that dynamically loads content into a div using jquery.load().
So far it works great for static content, but now I have a repeater that I want to be able to include in this content. So I wanted to use a generic handler (maybe a webservice) to dynamically generate the rendered html of the user control and insert (or append, or load) it into the div.
So far I've had no luck.
Initially I tried this method
UCPeople ucPeople = new UCPeople { RoleType = (roleType.ToLower() == "board" ? RoleTypes.Board : RoleTypes.Executive) };
TextWriter myTextWriter = new StringWriter();
HtmlTextWriter myWriter = new HtmlTextWriter(myTextWriter);
ucPeople.RenderControl(myWriter);
return myTextWriter.ToString();
Which just returns an empty string.
So then I tried adding the control to a page instance, and it still came out blank.
Then I tried to load the userconrol into the new page instance with this.
var page = new Page(){ViewStateMode = ViewStateMode.Disabled };
UCPeople ucPeople = (UCPeople)page.LoadControl("~/our-company/people/UCPeople.ascx");
That seemed to get further, but the usercontrol throw an error because it's not in a form.
When I checked the form was null for that page. So I figured I needed to create an instance of the page, and I tried it two different ways.
var p2 = (Page)PageParser.GetCompiledPageInstance("~/our-company/people/peopleTest.aspx",
"~/our-company/people/peopleTest.aspx", context);
var p = (Page)System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath("~/our-company/people/peopleTest.aspx", typeof(Page));
Both still yielded a null form.
I'm out of ideas. Any suggestions?
Thanks.
I just want to know how I can print a flow document without showing Print Dialog in WPF.
Thanks for help…
You can use the PrintDialog class without showing the dialog (without calling ShowModal)
This is one of the ways you can change default printer or change other settings:
using System.Printing; //add reference to System.Printing Assembly
//if you want to modify PrintTicket, also add
//reference to ReachFramework.dll (part of .net install)
...
var dlg = new PrintDialog();
dlg.PrintQueue = printer; // this will be your printer. any of these: new PrintServer().GetPrintQueues()
dlg.PrintTicket.CopyCount = 3; // number of copies
dlg.PrintTicket.PageOrientation = PageOrientation.Landscape;
dlg.PrintVisual(canvas);
Try
PrintDialog dialog = new PrintDialog();
dialog.PrintVisual(_PrintCanvas, "My Canvas");