label1 property join label2 property - c#

Can label1 text&property and label2 text&property become one and display it in label3 and added text = ? because what I am using now is using label1 and label2 putting side by side.
Tell me if there's another approach
Ps: I define the color in a database like red or blue.

Your can combine the text content like this:
label3.Text = label1.Text + " = " + label2.Text;
But you will loose the different colours. This is unfortunately not possible. For more details check this answer

Use string.format to combine the 2 labels texts together.
label3.Text = string.Format("{0}={1}", label1.Text, label2.Text);

you can write your own text image your label3. like here
and.
firstly set label3 AutoSize = false and set size .
// Add this lines to InitializeComponent() in yourform.Designer.cs
this.label1.TextChanged += new System.EventHandler(this.label_TextChanged);
this.label2.TextChanged += new System.EventHandler(this.label_TextChanged);
// this is label1 and label2 TextCahanged Event
private void label_TextChanged(object sender, EventArgs e)
{
SetMultiColorText(string.Format("{0} = {1}", label1.Text, label2.Text),label3);
}
// this method set multi color image text for label(paramter lb)
public void SetMultiColorText(string Text, Label lb)
{
lb.Text = "";
// PictureBox needs an image to draw on
lb.Image = new Bitmap(lb.Width, lb.Height);
using (Graphics g = Graphics.FromImage(lb.Image))
{
SolidBrush brush = new SolidBrush(Form.DefaultBackColor);
g.FillRectangle(brush, 0, 0,
lb.Image.Width, lb.Image.Height);
string[] chunks = Text.Split('=');
brush = new SolidBrush(Color.Black);
// you can get this colors from label1 and label2 colors... or from db.. or an other where you want
SolidBrush[] brushes = new SolidBrush[] {
new SolidBrush(Color.Black),
new SolidBrush(Color.Red) };
float x = 0;
for (int i = 0; i < chunks.Length; i++)
{
// draw text in whatever color
g.DrawString(chunks[i], lb.Font, brushes[i], x, 0);
// measure text and advance x
x += (g.MeasureString(chunks[i], lb.Font)).Width;
// draw the comma back in, in black
if (i < (chunks.Length - 1))
{
g.DrawString("=", lb.Font, brush, x, 0);
x += (g.MeasureString(",", lb.Font)).Width;
}
}
}
}

Related

Trying to read pixel color from PictureBox in C# WinForms

I am having an odd issue whereby when I then try to iterate over the pixels of the PictureBox or save the bmp it is just all black.
The intention of the tool is that you select a font, size, and style, and then it loops over the ASCII chars of that font and shows each character in the picture box, and converts the pixel data into a HEX array so I can use them on LCD displays.
The main part of the tool works whereby it is correctly looping through the ASCII chars and displaying them in the picture box but after each char is drawn to the picture box and I then try to iterate over the pixels of the PictureBox every pixel is returned as 0,0,0 RGB "black" and if I save the bmp which was drawn to the PictureBox that too is all black, but again I can see the bmp of that char correct drawn in the PictureBox yet the PictureBox data and bmp data does not match what I see in the PictureBox itself, I am truly lost as to why I am unable to correctly iterate or save the bmp or PictureBox.
I have tried not using async functions which is not ideal as I want the UI to be free, and I have tried various means to read the pixels and save the bmp but the result is the same. I hope to ask if anyone knows why I am getting this odd behavior and the solution to the issue.
Regards from Ed.
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace generateFonts
{
public partial class Form1 : Form
{
string font = "";
float fontSize = 0;
FontStyle fontStyle = FontStyle.Regular;
public Form1()
{
InitializeComponent();
comboBox1.SelectedIndex = 0;
comboBox2.SelectedIndex = 0;
comboBox3.SelectedIndex = 0;
font = comboBox1.SelectedItem.ToString();
fontSize = Convert.ToInt32(comboBox2.SelectedItem);
fontStyle = FontStyle.Regular;
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
font = comboBox1.SelectedItem.ToString();
}
private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
{
fontSize = Convert.ToInt32(comboBox2.SelectedItem);
}
private void comboBox3_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox3.SelectedIndex == 0)
fontStyle = FontStyle.Regular;
else if (comboBox3.SelectedIndex == 1)
fontStyle = FontStyle.Italic;
else if(comboBox3.SelectedIndex == 2)
fontStyle = FontStyle.Bold;
}
private async void button1_Click(object sender, EventArgs e)
{
await Task.Run(() => StartProcess(1));
}
private void StartProcess(int runs)
{
// Font
Font myFont = new Font(font, fontSize, fontStyle);
List<string> bytes = new List<string>();
string[] bits = { "0", "0", "0", "0", "0", "0", "0", "0" };
byte bitPos = 0;
for (byte i = 32; i < 126; i++)
{
//Create a Image-Object on which we can paint
Image bmp = new Bitmap(200, 200);
//Create the Graphics-Object to paint on the Bitmap
Graphics g = Graphics.FromImage(bmp);
string c = Convert.ToChar(i).ToString();
//Get the perfect Image-Size so that Image-Size = String-Size
SizeF size = g.MeasureString(c, myFont);
//Use this to become better Text-Quality on Bitmap.
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
//Here we draw the string on the Bitmap
g.DrawString(c, myFont, new SolidBrush(Color.Black), 0, 0);
if (!Directory.Exists("FontBmps"))
Directory.CreateDirectory("FontBmps");
this.Invoke((MethodInvoker)delegate ()
{
pictureBox2.Width = Convert.ToInt32(size.Width);
pictureBox2.Height = Convert.ToInt32(size.Height);
pictureBox2.Image = bmp; // <--- this is working and the picturebox shows the bmp correctly
bmp.Save("FontBmps/" + i + "_" + font + "_" + fontSize + "px_" + fontStyle + ".bmp", ImageFormat.Bmp); // <--- error here: this saves a black square instead of the bmp i see displayed in the picturebox GUI ??
// Even if i save the picturebox itself that too is just a black square instead of the correct image shown in the GUI ??
// now convert the bmp to a HEX array of pixels
for (int h = 0; h < pictureBox2.Height; h++)
{
for (int w = 0; w < pictureBox2.Width; w++)
{
Color colour = (pictureBox2.Image as Bitmap).GetPixel(w, h);
if (colour.R == 0 && colour.G == 0 && colour.B == 0)
{
bits[bitPos] = "1";
}
else
{
bits[bitPos] = "0"; // <-- never hits me, again for some reason the bmp or picturebox is all black pixels data but i see it correctly show in the picturebox GUI ??
}
if (bitPos < 7)
bitPos++;
else
{
//string bitStr = bits.ToString();
//string hex = Convert.ToByte(bitStr, 2).ToString("x2");
//bytes.Add(hex);
bitPos = 0;
for(byte n = 0; n < 8; n++)
{
bits[n] = "0";
}
}
}
}
if (bitPos != 0)
{
// TO DO...
}
});
Thread.Sleep(500); // <--- i have this just to see it displaying the chars but i have removed it with no effect to the issue
}
// now add List to a file in the correct format
foreach (string str in bytes)
{
Console.WriteLine(str);
// TO DO...
}
}
}
}
I believe the image is black, but some parts have transparency. That is, you would need to check Alpha (Color.A). What you see in the picture box, would be the background color of the picture box where it is transparent.
You won't see the transparency in the saved file, given that the ImageFormat.Bmp does not support transparency. Try Png instead, which supports transparency (and has lossless compression).
Alternatively, you can use Graphics.Clear to have the image be the color you want for background (white, I guess) before drawing to it.
Aside from that, I'll suggest to use bmp instead of (pictureBox2.Image as Bitmap), and use Bitmap.LockBits. That would improve performance.
This might be useful for reference: Converting a bitmap to monochrome. See also C# - Faster Alternatives to SetPixel and GetPixel for Bitmaps for Windows Forms App.

Can I change a size and style in a font viewer with Combobox? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
#Hello guys, I have this problem with Forms in C#, I want to make a font viewer, actually I want to
make two Combobox that make change the "graphics" and display the same name of the font in its style
and in a specific size of the second Combobox. The main problem is that the style and the size don't
change. Any error could be cool for me to be told :) Here is my code.#
namespace CodeImage35
{
class Visualizer : Form
{
Label choose;
PictureBox picbox; //this is for the text
Graphics textm; //the text in PictureBox
ComboBox fontsm; //font of the text
ComboBox size; //size of the font
String fonts; //I used this for get the fonts,maybe never is used
public Visualizer() //Here is the UI
{
this.Width = 600;
this.Height = 300;
this.Text = "Visualizer of fonts";
choose = new Label();
choose.Size = new Size(100, 20);
choose.Location = new Point(20, 20);
choose.Text = "Choose Font:";
picbox = new PictureBox();
picbox.Size = new Size(300, 200);
picbox.Location = new Point(100,150);
fontsm = new ComboBox();
fontsm.Location = new Point(110, 20);
fontsm.Size = new Size(350, 20);
size = new ComboBox();
size.Location = new Point(480, 20);
size.Size = new Size(100, 20);
System.Drawing.Text.InstalledFontCollection fonts = new InstalledFontCollection(); //this
//is for the fonts
foreach ( FontFamily style in fonts.Families )//I add them in the combobox here
{
fontsm.Items.Add(style.Name);
}
for( int s = 1; s <= 50; size++ )
{
size.Items.Add(s); //I add here the sizes from 1 to 50
}
picbox.Paint += new PaintEventHandler(write_in_PictureBox);
Controls.Add(fontsm);
Controls.Add(choose);
Controls.Add(size);
Controls.Add(picbox);
}
void write_in_PictureBox(object sender, PaintEventArgs e)
{
String text2 = fontsm.Text;
textm = e.Graphics;
int x = 0;
Int32.TryParse(size.Text, out x); //I tried with this function to make string to int for
//the parameter of "DrawString
textm.DrawString( text2 , new Font( text2, x ), Brushes.Black, new Point(10, 10) );
}
}
static class MainClass
{
static void Main()
{
Visualizer screen1 = new Visualizer();
Application.Run(screen1);
}
}
}
To begin fix this compiler error:
for( int s = 1; s <= 50; size++ )
{
size.Items.Add(s); //I add here the sizes from 1 to 50
}
the correct variable to increment is s . Also you cold avoid to start from 1, a value really too small to render a font and appreciate the result. Starting from 6 or 8 should be fine. Apart from that...
In order to draw a string, based on the input of the two combobox, you have to handle the SelectedValueChanged event (or SelectedIndexChanged). Those events happen when the user change (select) a value in the combobox.
Instead, the PaintEventHandler happens when a control is being painted. See Paint event.
Following your example you can attach the SelectedValueChanged event to a method that draws the string like you did in write_in_PictureBox method .
//put this at the end of the constructor method.
//The event will be triggered on both combobox, allowing the user to see the result of it's selection whatever combobox is edited
fontsm.SelectedValueChanged += (sender, args) => DrawFont();
size.SelectedValueChanged += (sender, args) => DrawFont();
//that's just a method to handle the event
private void DrawFont()
{
using (var g = picbox.CreateGraphics()) //remember to always dispose a disposable resource
{
//clear the area before draw the new string
g.Clear(DefaultBackColor);
if (!Int32.TryParse(size.Text, out int x)) x = 12; //if no value is selected for size combobox, use 12 as default
string text = fontsm.Text;
g.DrawString(text, new Font(text, x), Brushes.Black, new Point(10, 10));
}
}
By the way... if you just want to show a font preview... it would be much easier for you to just put a label and change it's text and font property :) .

Dynamic dialog boxes

I am working with Winforms and I have a question about making these more dynamic. For instance I can create a winform that has a group of text boxes that displays data however how would I make this dynamic? In terms of the number of text boxes the user can see depends on what data is found?
I know I can do something along the lines of the below:
TextBox tb = new TextBox();
In my scenario I have an application that reads through a bunch of documents and if a $ is found then a prompt appears asking the user to input a proper value, however, if the document has a lot of values that need updating then this is a lot of dialog boxes. So a good way to resolve this is to have the dialog box appear at the end (after the file has been read) with all the values that need updating and the user can update all these at once.
The problem that I see is that the number of values that need to be displayed can be anything from 1 on wards, which means the loop would need to account for this.
My current code is as below;
foreach (FileInfo fi in rgFiles)
{
current++;
fileProcessBar.Value = current / count * 60 + 40;
string[] alllines = File.ReadAllLines(fi.FullName);
for (int i = 0; i < alllines.Length; i++)
{
if (alllines[i].Contains("$"))
{
// prompt
int dollarIndex = alllines[i].IndexOf("--");
Regex regex = new Regex(#"(--.{1,100})");
var chars = regex.Match(alllines[i]).ToString();
string PromptText = chars.Replace("-", "");
string promptValue = CreateInput.ShowDialog(PromptText, fi.FullName);
if (promptValue.Equals(""))
{
}
else
{
alllines[i] = alllines[i].Replace("$", promptValue);
File.WriteAllLines(fi.FullName, alllines.ToArray());
}
}
}
prompt method:
public static string ShowDialog(string text, string caption)
{
Form prompt = new Form()
{
Width = 600,
Height = 150,
FormBorderStyle = FormBorderStyle.FixedDialog,
Text = caption,
StartPosition = FormStartPosition.CenterScreen
};
Label textLabel = new Label() { Left = 50, Top = 15, Width = 500, Text = text };
TextBox textBox = new TextBox() { Left = 50, Top = 52, Width = 500 };
Button confirmation = new Button() { Text = "Add", Left = 450, Width = 100, Top = 72, DialogResult = DialogResult.OK };
confirmation.Click += (sender, e) => { prompt.Close(); };
prompt.Controls.Add(textBox);
prompt.Controls.Add(confirmation);
prompt.Controls.Add(textLabel);
prompt.AcceptButton = confirmation;
prompt.MaximizeBox = false;
return prompt.ShowDialog() == DialogResult.OK ? textBox.Text : "";
}
My question is how can a winform be more dynamic as in terms of size and what is displayed? how can I create a new form without specifying size and position? but still not being a jumbled mess?
Make a new Form with a certain size. Then add a FlowLayoutPanel to the form which has almost the same width as the form and almost the same height. Leave enough space for the button that you need:
In the panel properties set the fields AutoSize to true and AutoSizeMode to GrowAndShrink:
Don't forget to specify the FlowDirection:
this.panel.FlowDirection = FlowDirection.TopDown;
Now you need just a method which adds your prompting controls to the controls of the FlowLayoutPanel (which will order them in an automatic fashion) :
public void AddToCanvas(string text)
{
this.flowLayoutPanel1.Controls.Add(new Label() {Text = text});
this.flowLayoutPanel1.Controls.Add(new TextBox());
Resize();
}
And a resize method to adjust the form to the amount of current controls inside it:
public void Resize()
{
Size s = new Size();
s.Height = this.flowLayoutPanel1.Height + this.button_Accept.Height +
(this.flowLayoutPanel1.Controls.Count * 10) + y_offset;
s.Width = this.flowLayoutPanel1.Width + 10;
this.MaximumSize = s;
this.Size = s;
}
With this input:
random text
$ Name
$ Address
random text
$ Age
random text
$ Planet
$ Continent
random text
$ StarSystem
I get the following Result:
EDIT:
Create a variable after you have read the contents of one file (before you loop through the lines):
DynamicPrompt dp = new DynamicPrompt("YourCaption");
for (int i = 0; i < alllines.Length; i++)
{
if (alllines[i].Contains("$"))
{
Start the loop and if you get to the important line call
dp.AddToCanvas(PromptText);

Dynamically added labels only show one

Ok so I decided to add controls to a panel on form_load based on labels in an array. Below is my code, but no matter how many files I upload through the button listener and reload this form, it only displays one label and nothing more. Why is it only displaying one? I have added a breakpoint and verified that the count does go up to 2, 3, etc.
Code:
public partial class Attachments : Form
{
ArrayList attachmentFiles;
ArrayList attachmentNames;
public Attachments(ArrayList attachments, ArrayList attachmentFileNames)
{
InitializeComponent();
attachmentFiles = attachments;
attachmentNames = attachmentFileNames;
}
private void Attachments_Load(object sender, EventArgs e)
{
ScrollBar vScrollBar1 = new VScrollBar();
vScrollBar1.Dock = DockStyle.Right;
vScrollBar1.Scroll += (sender2, e2) => { pnl_Attachments.VerticalScroll.Value = vScrollBar1.Value; };
pnl_Attachments.Controls.Add(vScrollBar1);
Label fileName;
for (int i = 0; i < attachmentNames.Count; i++)
{
fileName = new Label();
fileName.Text = attachmentNames[i].ToString();
pnl_Attachments.Controls.Add(fileName);
}
}
private void btn_AddAttachment_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
string fileName = openFileDialog1.FileName;
attachmentFiles.Add(fileName);
attachmentNames.Add(Path.GetFileName(fileName));
this.Close();
}
}
}
This is because the labels are all stacking on top of each other. You will need to specify a top for each one or use an auto-flow panel.
Adding the following line after creating the new label will ensure all labels are visible (you may have to adjust the multiplier depending on your font):
fileName.Top = (i + 1) * 22;
As competent_tech stated the labels are stacking on top of each other, but another approach is to modify the location value of the label.The benefit to this is you can control the absolute location of the label.
fileName.Location = new Point(x, y);
y += marginAmount;
x is the vertical position on the form and y is the horizontal location on the form. Then all that has to be modified is the amount of space you want in between each label in the marginAmount variable.
So in this for loop
for (int i = 0; i < attachmentNames.Count; i++)
{
fileName = new Label();
fileName.Text = attachmentNames[i].ToString();
pnl_Attachments.Controls.Add(fileName);
}
You could modify it to this:
for (int i = 0; i < attachmentNames.Count; i++)
{
fileName = new Label();
fileName.Text = attachmentNames[i].ToString();
fileName.Location = new Point(x, y);
y += marginAmount;
pnl_Attachments.Controls.Add(fileName);
}
Then all you have to do is define x, y, and the marginAmount.

color tree node with 2 colors but not through the user

I want to color on part of tree node but not through the user (without using "selected node")
so DrawMode is not helping me.
I am using c#
For example I want that all tree nodes with space on the text will color in one side at green and the other side to red.
Thanks!!
DrawMode is the way to go. You have to set it to OwnerDrawText, and subscribe to the DrawNode event. I.e.:
this.treeView1.DrawMode = System.Windows.Forms.TreeViewDrawMode.OwnerDrawText;
this.treeView1.DrawNode += new System.Windows.Forms.DrawTreeNodeEventHandler(this.treeView1_DrawNode);
This is just a sample of how the drawing method could look like. It's up to you to modify it in order to have a good graphical result, but it can give you an idea of the way to go.
private void treeView1_DrawNode(object sender, DrawTreeNodeEventArgs e)
{
Font nodeFont = e.Node.NodeFont;
if (nodeFont == null) nodeFont = ((TreeView)sender).Font;
string txt = e.Node.Text;
int idx = txt.IndexOf(' ');
string greenTxt;
string redTxt;
if (idx >= 0)
{
greenTxt = txt.Substring(0, idx);
redTxt = txt.Substring(idx);
}
else
{
greenTxt = txt;
redTxt = string.Empty;
}
Rectangle greenRect = new Rectangle(e.Bounds.Location, new Size((int)Math.Ceiling(e.Graphics.MeasureString(greenTxt, nodeFont).Width), e.Bounds.Height));
Rectangle redRect = new Rectangle(e.Bounds.Location + new Size(greenRect.Width, 0), new Size((int)Math.Ceiling(e.Graphics.MeasureString(redTxt, nodeFont).Width), e.Bounds.Height));
e.Graphics.DrawString(greenTxt, nodeFont, Brushes.Green, greenRect);
if (!string.IsNullOrEmpty(redTxt))
e.Graphics.DrawString(redTxt, nodeFont,
Brushes.Red, redRect);
}
You can find a more complex example here.

Categories