Tooltip text formatting : *Making partly bold* - c#

Issue: I want to make Tooltip text Partly bold.
Example text that i want to show on tooltip:
label1: label1Value
label2: label2Value
Progress so far: I have made a custom tooptip class with my own implementation of Draw event. I have used:
DrawToopTipEventArgs newAgrs = new DrawToopTipEventArgs (
e.Graphics, e.AssociatedWindow, e.AssociatedControl,
e.Bounds, e.ToolTipText, this.BackColor, this.ForeColor,
new Font("Arial Unicode MS", 8.25F, FontStyle.Bold));
newAgrs.DrawText(TextFormatFlags.TextBoxControl);
Main Issue: This way am able to make complete tooltiptext bold, but still stuck how i can make only the value part bolds and keep rest of the labels as it is. (as shown above).

You'll have to measure your text and draw everything yourself.
private void ToolTip_Draw(object sender, DrawToolTipEventArgs e)
{
using (var boldFont = new Font(e.Font, FontStyle.Bold))
{
var headerText = "Header: ";
var valueText = "Value";
var headerTextSize = TextRenderer.MeasureText(headerText, e.Font);
TextRenderer.DrawText(e.Graphics, headerText, e.Font, e.Bounds.Location, Color.Black);
var valueTextPosition = new Point(e.Bounds.X + headerTextSize.Width, e.Bounds.Y);
TextRenderer.DrawText(e.Graphics, valueText, boldFont, valueTextPosition, Color.Black);
}
}
I hard-coded the header and value strings for simplicity. It should be trivial to extend this to work for multiple lines. The measured text size has a height, you can also get the height from the Font object itself.
The reason you're example is making everything bold is that you're just delegating all the drawing to a instance of DrawToolTipEventArgs with a new font and telling it to draw the tool tip text (all of it) with the new arguments. It happily took the new font and draw all the text using it.
One additional thing to keep in mind is that the Popup event should also be handled. That even is used to measure the size of the tooltip so you have enough room to draw your text. If you don't handle it, it may not be wide enough to handle the bold font. Specifically, you'll want to set the PopupEventArgs.ToolTipSize property.

Related

Resize a Label's font size to fit within a Panel without exceeding a maximum font size

I have created a boolean algebraic simplifier. For this, I take the expression at key stages during the simplification process, add it to a list and at the end use these expressions to show how the computer simplified the expression. E.g. For B•(A+~A) the contents of the label will be:
B•(A+~A) // Initial Expression
= B•(1) // Brackets simplified
= B•1 // Brackets removed
= B // Simplified expression.
I have created a standard Panel and I have dragged and dropped the Label within it, to dock the Label within the Panel.
I want to make it so that the font size of the text changes so that it fits the panel fully, because some complicated expressions may have lots of lines of working and may therefore otherwise not fit the screen.
However, if the user inputs a really simple expression e.g. A+1, the answer and the lines of working will be small. In this case I do not want the text to fill the panel as the font would be huge.
I am therefore trying to make it so that the Label's font size changes to make the expression fit within the Panel but limit the maximum font size so that a small amount of text does not use a massive font size.
Does anyone know how to do this?
I searched online and found the following code, however this does not fill the Panel:
WorkingOutLabel.Font = new Font(WorkingOutLabel.Font.FontFamily,
PanelHoldingWorkingLabel.Font.Height, FontStyle.Regular);
A Custom Control derived from Label that scales its Text size to fit the control's bounds.
A Graphics.ScaleTransform() transformation is applied when the calculated width of the Text is larger that the Control's ClientArea.
The Text is scaled when the controls is resized and/or when the Text changes.
Sample functionality:
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Text;
using System.Windows.Forms;
[DesignerCategory("Code")]
class AutoScaleLabel : Label
{
public AutoScaleLabel() => InitializeComponent();
private void InitializeComponent()
{
this.SetStyle(ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint |
ControlStyles.ResizeRedraw, true);
this.UpdateStyles();
}
protected override void OnLayout(LayoutEventArgs e)
{
base.OnLayout(e);
this.AutoSize = false;
}
protected override void OnPaint(PaintEventArgs e)
{
using (SolidBrush brush = new SolidBrush(this.ForeColor))
using (StringFormat format = new StringFormat(StringFormatFlags.NoClip |
StringFormatFlags.NoWrap | StringFormatFlags.FitBlackBox))
{
format.Trimming = StringTrimming.None;
SizeF textSize = e.Graphics.MeasureString(this.Text, this.Font, this.ClientSize, format);
if (textSize.Width > this.ClientSize.Width)
{
float scale = (float)this.ClientSize.Width / textSize.Width;
e.Graphics.ScaleTransform(scale, scale);
}
e.Graphics.Clear(this.BackColor);
e.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
e.Graphics.DrawString(this.Text, this.Font, brush, this.ClientRectangle, format);
}
}
}

Bold Font is Rendered Wrong

When I try to render a Chinese string like 试标记好不好 Graphics.DrawString draws it
even if I change the Font Linking to SimSun. On the other hand TextRenderer works but it fails to render readable strings when bold fonts are used. It seems there is no correct way to render bold strings.
The issue is described in greater detail here. Am I doing something wrong or does Windows not support professional looking localizable applications with some bold strings in the UI?
The code to repro the issue is for a Windows Forms application with two PictureBoxes:
const string combined = "测试标记好不好This is a aber long";
private void cFontSize_ValueChanged(object sender, EventArgs e)
{
Bitmap bmp = new Bitmap(750, 140);
Font f = new Font("Arial", (float)cFontSize.Value, IsBold ? FontStyle.Bold : FontStyle.Regular);
using (var g = Graphics.FromImage(bmp))
{
g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver;
// Rendering with a Background Color solves the issue but
// this would produce boxes of white or black color in the displayed image which looks even worse
TextRenderer.DrawText(g, combined, f, new Point(0, 0), FontColor);
}
cPictureBox.Image = bmp;
Bitmap bmp2 = new Bitmap(750, 140);
using (var g = Graphics.FromImage(bmp2))
{
g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver;
g.DrawString(combined, f, FontBrush, 0, 0);
}
cPicture2.Image = bmp2;
}
Update 1:
When I add as Font Link Setting to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontLink\SystemLink
Arial Bold
SIMSUNB.TTC,SimSun Bold
MSGOTHIC.TTC,MS UI Gothic
then Graphics.DrawString looks ok now althogh TextRender now gets problems. After restarting the application now both outputs look font wise ok although TextRenderer still has the problem that bold fonts become unreadable due to anti aliasing with black. I will restart the machine to check out any caching effects.

Fitting text into a listView

I want to create a listView that shows users nicknames for a chat program. For that I created a new class that inherits from listViewItem.
What i want to do is, depending on the length of the nickname scale my font size.
I have read lots of articles about scaling but ALL of them depend on a graphics object and i have no clue how i get one of those ??? i tried it with a label and there it would be from the paint event but listView doesnt have such an event? so how do i scale this font ?
Q:
How do I get the right fontsize that the Nickname will fit into a specified rectangle ?
EDIT: Forgot to say I'm completly new to anything with grafic stuff i only used the Designer and set some properties.
You should set OwnerDraw property of the ListView to true, add draw item event handler like this:
listView1.DrawItem += listView1_DrawItem;
And here is a simple implementation of what you want so you can play with and tune it up:
void listView1_DrawItem(object sender, DrawListViewItemEventArgs e)
{
float emSize = e.Item.Font.Size;
Font font = new Font(e.Item.Font.FontFamily, emSize);
while(e.Graphics.MeasureString(e.Item.Text, e.Item.Font).Width>e.Item.Bounds.Width)
{
emSize--;
font = new Font(e.Item.Font.FontFamily, emSize);
e.Item.Font = font;
}
e.DrawText();
}
You see that you need to change the font size and measure the string you want to display so it fits in the cell completely. Presuming that if your current font size doesn't fit, you want to make it smaller.
I marked #Nikola answer right because it explained a lot but in my case i needed something way simpler and thanks to #TaW i also got the problem with the Graphics solved here my code snippet
public static Font getNewFont(Font origFont, string text, float maxWidth, Graphics g)
{
float emSize = origFont.Size;
Font font = origFont;
while (g.MeasureString(text, font).Width > maxWidth)
{
emSize--;
font = new Font(origFont.FontFamily, emSize);
}
return font;
}

Changing Font Size for ListView Column in C#

I am creating a simple GUI, containing a listView which will be for use with a touch screen monitor. Therefore I require the text to be large, so it is easily readable and selectable. I can change the Font property of my listView to increase its size, although this also increases the column header font size in proportion (making the letters too big for the space).
Is there a method to change just the font size of the listView items and/or a means of changing the size of the text space of the column to cater for bigger letters?
I think I can use the ListBox.DrawColumnHeader event for this but I cannot figure out exactly how to piece it together!
Thanks in advance
This could help:
// Draws column headers.
private void listView1_DrawColumnHeader(object sender,
DrawListViewColumnHeaderEventArgs e)
{
using (StringFormat sf = new StringFormat())
{
// Store the column text alignment, letting it default
// to Left if it has not been set to Center or Right.
switch (e.Header.TextAlign)
{
case HorizontalAlignment.Center:
sf.Alignment = StringAlignment.Center;
break;
case HorizontalAlignment.Right:
sf.Alignment = StringAlignment.Far;
break;
}
// Draw the standard header background.
e.DrawBackground();
// Draw the header text.
using (Font headerFont =
new Font("Helvetica", 10, FontStyle.Bold)) //Font size!!!!
{
e.Graphics.DrawString(e.Header.Text, headerFont,
Brushes.Black, e.Bounds, sf);
}
}
return;
}
See msdn for more info.

Overriding DrawItem for ListBox - unselected items are not redrawn

This is a C# desktop application. The DrawStyle property of my ListBox is set to OwnerDrawFixed.
The problem: I override DrawItem to draw text in different fonts, and it works. But when I start resizing the form at the runtime, the selected item is drawn correctly, but the rest of them are not redrawn, causing text looking corrupt for unselected items.
Here's my code:
private void listDevices_DrawItem(object sender, DrawItemEventArgs e)
{
e.DrawBackground();
string textDevice = ((ListBox)sender).Items[e.Index].ToString();
e.Graphics.DrawString(textDevice,
new Font("Ariel", 15, FontStyle.Bold), new SolidBrush(Color.Black),
e.Bounds, StringFormat.GenericDefault);
// Figure out where to draw IP
StringFormat copy = new StringFormat(
StringFormatFlags.NoWrap |
StringFormatFlags.MeasureTrailingSpaces
);
copy.SetMeasurableCharacterRanges(new CharacterRange[] {new CharacterRange(0, textDevice.Length)});
Region[] regions = e.Graphics.MeasureCharacterRanges(
textDevice, new Font("Ariel", 15, FontStyle.Bold), e.Bounds, copy);
int width = (int)(regions[0].GetBounds(e.Graphics).Width);
Rectangle rect = e.Bounds;
rect.X += width;
rect.Width -= width;
// draw IP
e.Graphics.DrawString(" 255.255.255.255",
new Font("Courier New", 10), new SolidBrush(Color.DarkBlue),
rect, copy);
e.DrawFocusRectangle();
}
listDevices.Items.Add("Device001");
listDevices.Items.Add("Device002");
Also, the item that is drawn correctly (the selected one) is flickering on form resizing. No biggie, but if anyone know why.... tnx
Put the following code in the Resize event:
private void listDevices_Resize(object sender, EventArgs e) {
listDevices.Invalidate();
}
This should cause everything to be redrawn.
To stop the flickering, you need double buffering.
To do this, make a new class, derived from ListBox, and put the following in the constructor:
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
Or just paste this into a code file:
using System.Windows.Forms;
namespace Whatever {
public class DBListBox : ListBox {
public DBListBox(): base() {
this.DoubleBuffered = true;
// OR
// this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
}
}
}
Replace "Whatever" with the namespace your project uses, or make it something more useful. AFter compiling, you should be able to add a DBListBox in the form designer.
I repro the problem. There are several mistakes in the code, the font name is "Arial", you should not adjust rect.Width, you forget to call Dispose() on the fonts, brushes and regions. But they don't explain the behavior. There's something wrong with the clipping area that prevents the text from being properly updated. I don't see where that occurs, the Graphics object state is okay.
Graphics.DrawString() is a very troubled method, you should really avoid it. All Windows Forms controls, including ListBox, use TextRenderer.DrawText(). That solves the problem when I use it. I know measuring is more difficult, you could work around that by displaying the IP address at a fixed offset. Looks better too, they'll line up in a column that way.
It flickers because you use e.DrawBackground(). That erases the existing text, you draw the text right back on it. I don't think double-buffering is going to fix that, you'd have to draw the entire item so you don't have to draw the background. Tricky if you can't get the exact size of the text with the large font, a workaround is to draw into a bitmap first.

Categories