I'm using a FlowDocumentScrollViewer to print out log outputs to my application window, and am getting some rather weird spacing issues. Most of the spaces are correctly sized, but I'll consistently get way too large of spaces in some areas. Here's an example:
Correctly spaced: "d Copying E:\Projects"
What is displayed: "d Copying E:\Projects"
I had to use multiple spaces to reflect the spacing issue above, but I guarantee that it is indeed just displaying one space, incorrectly sized. This is easily verifiable by copying the text from my FlowDocumentScrollViewer into a text editor like notepad++. Here's the printing code for my simplest FlowDocumentScrollViewer:
LogBox.Document = new FlowDocument();
LogBox.Document.Background = LogBox.Background;
LogBox.Document.Foreground = LogBox.Foreground;
LogBox.Document.Blocks.Add(logParagraph = new Paragraph());
logParagraph.Margin = new Thickness(0); //Tested making Margin 0, didn't help
logParagraph.FontFamily = font;
logParagraph.FontSize = defaultFontSize;
...
public void PrintLog(String s)
{
logParagraph.Inlines.Add(s);
}
I've never seen anything like this, and searching for it on google is very difficult since everyone that uses "spacing" as a keyword really means line height... any help is appreciated.
Have you tried...
LogBox.TextAlignment = TextAlignment.Left;
and / or
logParagraph.TextAlignment = TextAlignment.Left;
owo? Because as I can see, in some cases the Block is getting an auto alignments to justify / stretch the text in the line~ Don't know why but seems to happen ;o
You could try adding a Run object in the PrintLog method, and modifying its properties like CharacterSpacing, and maybe try other ones as well. Sorry I don't have access to Visual Studio at the moment so I can't actually try it.
public void PrintLog(String s)
{
var run = new Run();
// modify run properties here
logParagraph.Inlines.Add(run);
}
You can view the MS documentation here: Run Class
Related
I read on MSDN that .NET 4.6.1 supports auto correct now.
The files in %appdata%/Microsoft/Spelling// were created automatically and I added the following line to the default.acl (file is still UTF-16 with BOM):
tramampoline|trampoline
I have set the project to target 4.6.1 and enabled SpellCheck on a RichTextBox:
<RichTextBox SpellCheck.IsEnabled="True" Language="de-DE"/>
While it highlights the word when typed wrong in the usual manner, there is no autocorrection happening.
What am I missing here?
I don't quite understand the note:
Note: These new file-formats are not directly supported by the WPF spell checking API’s, and the custom dictionaries supplied to WPF in applications should continue to use .lex files.
I know this is old, but as far as I know you need to handle AutoCorrect on your own (if I'm wrong please correct me with an example). You can do this as follows:
var caretPosition = richTextBox.CaretPosition;
// Make sure you're passing a textpointer at the end of the word you want to correct, i.e. not like this ;)
errorPosition = richTextBox.GetNextSpellingErrorPosition(caretPosition, LogicalDirection.Backward);
if(errorPosition == null)
{
return;
}
var errors = richTextBox.GetSpellingError(errorPosition);
// Default would be to only replace the text if there is one available replacement
// but you can also measure which one is most likely with a simple string comparison
// algorithm, e.g. Levenshtein distance
if (errors.Suggestions.Count() == 1)
{
var incorrectTextRange = richTextBox.GetSpellingErrorRange(errorPosition);
var correctText = error.Suggestions.First();
var incorrectText = incorrectTextRange.Text;
// Correct the text with the chosen word...
errors.Correct(correctText);
}
// Set caret position...
An important note would be not to use the RTB's CaretPosition, but rather to use a textpointer at the end of the word you wish to correct. If your textpointer/caret is in a weird spot (e.g. the end of 20 whitespaces), the GetNextSpellingErrorPosition method may take up to 60 seconds before it returns (depending on the hardware/number of words in your RTB).
I have a MS Word add-in that needs to extract text from a range of text based solely on its formatting: in my case in particular, if the text is underlined or struck through, the range of characters/words that are underlined or struck through need to be found so that I can keep track of them.
My first idea was to use Range.Find, as is outlined here, but that won't work when I have no idea what the string is that I'm looking for:
var rng = doc.Range(someStartRange, someEndRange);
rng.Find.Forward = true;
rng.Find.Format = true;
// I removed this line in favor of putting it inside Execute()
//rng.Find.Text = "";
rng.Find.Font.Underline = WdUnderline.wdUnderlineSingle;
// this works
rng.Find.Execute("");
int foundNumber = 0;
while (rng.Find.Found)
{
foundNumber++;
// this needed to be added as well, as per the link above
rng.Find.Execute("");
}
MessageBox.Show("Underlined strings found: " + foundNumber.ToString());
I would happily parse the text myself, but am not sure how to do this while still knowing the formatting. Thanks in advance for any ideas.
EDIT:
I changed my code to fix the find underline issue, and with that change the while loop never terminates. More specifically, rng.Find.Found finds the underlined text, but it finds the same text over and over, and never terminates.
EDIT 2:
Once I added the additional Execute() call inside the while loop, the find functioned as needed.
You need
rng.Find.Font.Underline = wdUnderline.wdUnderlineSingle;
(At the moment you are setting the formatting for the specified rng, rather than the formatting for the Find)
I've already tried asking the question on their forums but as yet to have received a response, hope someone can help me on here.
I have setup a custom report screen in asp.net where people can drag labels and fields and Migradoc produces this accordingly by using textframes and top/left/width/height properties to lay them out in the same place they were dragged/resized to. This all works great however one issue I have is if the text is longer than the textframe it runs off the page and I need the page to move on accordingly whilst retaining the other objects in place.
I can use the below code to measure a string:
Style style = document.Styles["Normal"];
TextMeasurement tm = new TextMeasurement(style.Font.Clone());
float fh = tm.MeasureString(value, UnitType.Millimeter).Height;
float fw = tm.MeasureString(value, UnitType.Millimeter).Width;
But it's only useful for comparing the width against the frame and not the height because it could be different once put into a smaller area. Does anyone know how I can measure this string based on bound width/height values i.e. within a text frame.
Look at the CreateBlocks() method in the XTextFormatter class and how it calls MeasureString in a loop to break the text to multiple lines.
I'm afraid you have to implement such a loop yourself.
Or maybe use the PrepareDocument() method of the DocumentRenderer class to let MigraDoc do the work and just query the dimensions when it's done.
BTW: a similar question had been asked at the forum before:
http://forum.pdfsharp.net/viewtopic.php?p=3590#p3590
Answer includes some source code.
An easy way to do this (using I-liked-the-old-stack-overflow's link) is to add the PdfWordWrapper class to your project and then calculate the dimensions of your text as follows:
var wrapper = new PdfWordWrapper(g, contentWidth); //g is your XGraphics object
wrapper.Add("My text here", someFont, XBrushes.Black);
wrapper.Process();
var dimensions = wrapper.Size; //you can access .Height or .Width
//If you want to reuse the wrapper just call .Clear() and then .Add() again with some new text
I'm using NPOI to output excel from Asp.Net MVC app and works very well with plain text but have now been requested to add formatting and am having problems where I need to have a single cell with bold text followed by non-bold text. e.g.
This text bold - this text normal
I know I can give a cell a single style but this won't help and I cannot see anyway to give a cell some pre-formatted rich text.
The only possible solution that I can think of is creating two cells separately and the merge them together but will that then mean the formatting will be lost?
Is there a way to do this that I have missed in NPOI?
You may try this:
var font = reportWorkbook.CreateFont();
font.FontHeightInPoints = 11;
font.FontName = "Calibri";
font.Boldweight = (short)NPOI.SS.UserModel.FontBoldWeight.BOLD;
var cell = headerRow.CreateCell(0);
cell.SetCellValue("Test Bold");
cell.CellStyle = reportWorkbook.CreateCellStyle();
cell.CellStyle.SetFont(font);
Fortunately, you able to do that... Look at this code:
Font f1=wb.CreateFont();
f1.Color=HSSFColor.RED.index;
ws.GetRow(1).GetCell(0).RichStringCellValue.ApplyFont(1, 5, f1);
Seems that the Ernie Banzon answer no longer works exactly as described, possibly due to a namespace change (or in fact that I'm using the HSSF namespace?)
// usings
using NPOI.HSSF.UserModel;
// IWorkbook doc
IFont font = doc.CreateFont();
font.FontHeightInPoints = 11;
font.FontName = "Arial";
font.Boldweight = (short)FontBoldWeight.BOLD;
Use this option
font.Boldweight = (short)700;//FontBoldWeight.Bold;
Actual syntax should be like below. But both of these syntax doesn't works sometime
font.Boldweight = FontBoldWeight.Bold ;
Or
font.Boldweight = (short)FontBoldWeight.Bold;
FontBoldWeight is type enum, which after type casting may not work sometime. As a workaround if you type caste or use actual short value of enum directly, it works. Below is the declaration of FontBoldWeight. it will make things clear.
**public enum FontBoldWeight
{
None = 0,
Normal = 400,
Bold = 700,
}**
After a fair amount of investigation it seems that you are not able to do this inside of NPOI as it doesn't provide the necessary functionality to allow you to set formatting on specific text within a cell like I was attempting to do.
I'm rendering text using FormattedText, but there does appear to be any way to perform per-char hit testing on the rendered output. It's read-only, so I basically only need selection, no editing.
I'd use RichTextBox or similar, but I need to output text based on control codes embed in the text itself, so they don't always nest, which makes building the right Inline elements very complex. I'm also a bit worried about performance with that solution; I have a large number of lines, and new lines are appended often.
I've looked at GlyphRun, it appears I could get hit-testing from it or a related class, but I'd be reimplementing a lot of functionality, and it seems like there should be a simpler way...
Does anyone know of a good way to implement this?
You can get the geometry of each character from a FormattedText object and use the bounds of each character to do your hit testing.
var geometry = (GeometryGroup)((GeometryGroup)text.BuildGeometry(new Point(0, 0))).Children[0];
foreach (var c in geometry.Children)
{
if (c.Bounds.Contains(point))
return index;
index++;
}
In OnRender you can render these geometry objects instead of the formatted text.
The best way is to design a good data structure for storing your text and which also considers hit-testing. One example could be to split the text into blocks (words, lines or paragraphs depending on what you need). Then each such block should have a bounding-box which should be recomputed in any formatting operations. Also consider caret positions in your design.
Once you have such facility it becomes very easy to do hit-testing, just use the bounding boxes. It will also help in subsequent operations like highlighting a particular portion of text.
Completely agree with Sesh - the easiest way you're going to get away with not re-implementing a whole load of FormattedText functionality is going to be by splitting up the individual items you want to hit-test into their own controls/inlines.
Consider using a TextBlock and adding each word as it's own Inline ( or ), then either bind to the inline's IsMouseDirectlyOver property, our add delegates to the MouseEnter & MouseLeave events.
If you want to do pixel-level hit testing of the actual glyphs (i.e. is the mouse exactly in the dot of this 'i'), then you'll need to use GlyphRuns and do manual hit testing on the glyphs (read: hard work).
I'm very late to the party--if the party is not over, and you don't need the actual character geometry, I found something like this useful:
for (int i = 0; i < FormattedText.Text.Length; i++)
{
characterHighlightGeometry = FormattedText.BuildHighlightGeometry(new Point(), i, 1);
CharacterHighlightGeometries.Children.Add(characterHighlightGeometry);
}
BuildGeometry() only includes the actual path geometry of a character. BuildHighlightGeometry() generates the outer bounds of all characters--including
spaces, so an index to a space can be located by:
foreach (var c in CharacterHighlightGeometries.Children)
{
if (c.Bounds.Contains(centerpoint))
{
q = c;
cpos = index;
break;
}
index++;
}
Hope this helps.