Large string in label causing application to hang (C# Windows) - c#

I am having an windows application where I am fetching data from db and binding that to a label. I am using timer and scrolling the label, this works fine when the string is around 150 characters but when I have string of around 30000 characters it just hangs out the application.
lblMsg1.AutoEllipsis = true;
private void timer1_Tick(object sender, EventArgs e)
{
try
{
if (lblMsg1.Right <= 0)
{
lblMsg1.Left = this.Width;
}
else
lblMsg1.Left = lblMsg1.Left - 5;
this.Refresh();
}
catch (Exception ex)
{
}
}
public void bindData()
{
lblMsg.Text = "Some Large text";
}
public void Start()
{
try
{
timer1.Interval = 150;
timer1.Start();
}
catch (Exception ex)
{
Log.WriteException(ex);
}
}
Why is this related to string length and causing application to hang? Thanks in advance.

I guess you are trying to create a news ticker?
I am not sure that labels are designed to hold such big strings.
Use a picturebox instead and update your code.
Define two variables in your form class. One to hold text offset and the other to hold the graphics object for the picture box. Like this:
private float textoffset = 0;
System.Drawing.Graphics graphics = null;
In the form onload do this:
private void Form1_Load(object sender, EventArgs e)
{
textoffset = (float)pictureBox1.Width; // Text starts off the right edge of the window
pictureBox1.Image = new Bitmap(pictureBox1.Width, pictureBox1.Height);
graphics = Graphics.FromImage(pictureBox1.Image);
}
Your timer should then look like this:
private void timer1_Tick(object sender, EventArgs e)
{
graphics.Clear(BackColor);
graphics.DrawString(newstickertext, new Font(FontFamily.GenericMonospace, 10, FontStyle.Regular), new SolidBrush(Color.Black), new PointF(textoffset, 0));
pictureBox1.Refresh();
textoffset = textoffset-5;
}

Instead of a Label, use a TextBox and set the ScrollBars, MultiLine and WordWrap properties according to your needs. To disable editing of the TextBox (and, thus, make it behave similar to a label), use the ReadOnly property.

Related

Make picture box move across screen during runtime

I am using Windows Forms (.NET Framework) and am trying to make a picture box move a cross a screen.
I have tried using timers and this while loop but the image (it's supposed to be a plane) does not appear in the case of the while loop and the use of timers makes it difficult to remove past picture Boxes so they appear to generate a sequence of planes. How can I accomplish this?Does it have something to do with Sleep()?
private void Button1_Click(object sender, EventArgs e)
{
//airplane land
//drawPlane(ref locx, ref locy);
//timer1.Enabled = true;
while (locx > 300)
{
var picture = new PictureBox
{
Name = "pictureBox",
Size = new Size(30, 30),
Location = new System.Drawing.Point(locx, locy),
Image = Properties.Resources.plane2, //does not appear for some reason
};
this.Controls.Add(picture);
Thread.Sleep(500);
this.Controls.Remove(picture);
picture.Dispose();
locx = locx - 50;
}
You can use a "Timer" to change the position of the PictureBox regularly.
Here is a simple demo that using Timer Class you can refer to.
public partial class Form1 : Form
{
private System.Timers.Timer myTimer;
public Form1()
{
InitializeComponent();
myTimer = new System.Timers.Timer(100);
myTimer.Elapsed += new System.Timers.ElapsedEventHandler(myTimer_Elapsed);
myTimer.AutoReset = true;
myTimer.SynchronizingObject = this;
}
private void myTimer_Elapsed(object sender, ElapsedEventArgs e)
{
pictureBox1.Location = new Point(pictureBox1.Location.X + 1, pictureBox1.Location.Y);
}
private void btStart_Click(object sender, EventArgs e)
{
myTimer.Enabled = true;
}
}
The result,

how to change the drawstring position when the user changes the coordinates values

i am planning to write something on a picture box.in the page load event i am able to do that.
Graphics g = Graphics.FromImage(pictureBox1.Image);
Font font = new Font("Courier New", 6);
payagainst = "PARADISE TRADING, CONT & REAL ESTATE";
g.DrawString(payagainst, font, new SolidBrush(Color.Black), pagainstX, pagainstY);
My requirement is there is two textbox in the form ie to mention the the X and Y coordinates of the newly drawn label. If the user changes the values in the textbox position of the label has to be changed according to the values given in the text box. in the text box leave event i have written the code as follows. but its not working. whats the correct method to achieve this.
private void txtpaX_Leave(object sender, EventArgs e)
{
if (flag != 0)
{
Graphics gs = Graphics.FromImage(pictureBox1.Image);
Font font = new Font("Courier New", 6);
payagainst = "PARADISE TRADING, CONT & REAL ESTATE";
amount = 3300;
gs.DrawString(payagainst, font, new SolidBrush(Color.Black), float.Parse(txtpaX.Text), float.Parse(txtpaY.Text));
flag = 1;
}
}
any help will be appreciated
What is supposed to happen after the string is printed over the image?
Do you need to save the image or pass it on or is the display in the PictureBox the only aim?
For the latter case this is the way to do it:
You place the drawing code only in the Paint event and call it, by invalidating the PictureBox, either whenever the TextBoxes have a change or when you leave them..:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawString(yourText, yourFont, yourBrush,
float.Parse(textBox1.Text), float.Parse(textBox2.Text));
}
// this will show up only after leaving the textbox:
private void textBox_Leave(object sender, EventArgs e)
{
pictureBox1.Invalidate();
}
// this will provide a live change:
private void textBox_TextChanged(object sender, EventArgs e)
{
pictureBox1.Invalidate();
}
Note that you should hook this code to both TextBoxes!
This code will persist the drawing but it will not change the actual Bitmap. Which I guess wouldn't make sense until you know exactly where the text should go..
If you want to change the actual Image you can do it like this:
private void stampButton_Click(object sender, EventArgs e)
{
using (Graphics G = Graphics.FromImage(pictureBox1.Image))
G.DrawString(yourText, yourFont, yourBrush,
float.Parse(textBox1.Text), float.Parse(textBox2.Text));
}
..and then maybe save it like this:
private void saveButton_Click(object sender, EventArgs e)
{
pictureBox1.Image.Save("yourfilename", System.Drawing.Imaging.ImageFormat.yourfileformat);
}

Update multiple pictureboxes at the same time

I have four PictureBoxes (each PictureBox represents one dice) and a Timer that changes every 100ms source pictures (loaded in memory as List<Bitmap> imagesLoadedFromIncludedResources).
Code:
private List<PictureBox> dices = new List<PictureBox>();
private void timer_diceImageChanger_Tick(object sender, EventArgs e)
{
foreach (PictureBox onePictureBox in dices)
{
oneDice.WaitOnLoad = false;
onePictureBox.Image = //... ;
oneDice.Refresh();
}
}
I need to change all the images at once - at this moment, you can see that the images are changing from left to right with a small delay.
I tried variant with one Thread for each PictureBox (using Control.Invoke method from this answer) - it is visually little better but not perfect.
You can try to suspend form's layout logic:
SuspendLayout();
// set images to pictureboxes
ResumeLayout(false);
Parallel.ForEach
(
dices,
new ParallelOptions { MaxDegreeOfParallelism = 4 },
(dice) =>
{
dice.Image = ...;
dice.WaitOnLoad = false;
dice.Refresh();
}
);
The problem is that UI controls can only be accessed from the UI thread. If you want to use this approach, you must create a copy of your PictureBoxes and then replace the UI ones once the operation is done.
Another approach would be creating two PictureBoxes, with the first one just on the top of the other one (hiding the latter)... you change all the images and then, once the processing is complete, you iterate all the ones in the back putting them on the top which would result in a lesser delay.
I'd approach this differently - it's been a while since I've played with WinForms stuff, but I'd probably take more control over the rendering of the images.
In this example I've got the images all in one source bitmap stacked vertically, stored as a resource in assembly:
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private Timer timer;
private Bitmap dice;
private int[] currentValues = new int[6];
private Random random = new Random();
public Form1()
{
InitializeComponent();
this.timer = new Timer();
this.timer.Interval = 500;
this.timer.Tick += TimerOnTick;
this.dice = Properties.Resources.Dice;
}
private void TimerOnTick(object sender, EventArgs eventArgs)
{
for (var i = 0; i < currentValues.Length; i++)
{
this.currentValues[i] = this.random.Next(1, 7);
}
this.panel1.Invalidate();
}
private void button1_Click(object sender, EventArgs e)
{
if (this.timer.Enabled)
{
this.timer.Stop();
}
else
{
this.timer.Start();
}
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.Clear(Color.White);
if (this.timer.Enabled)
{
for (var i = 0; i < currentValues.Length; i++)
{
e.Graphics.DrawImage(this.dice, new Rectangle(i * 70, 0, 60, 60), 0, (currentValues[i] - 1) * 60, 60, 60, GraphicsUnit.Pixel);
}
}
}
}
}
The source is here if it helps: http://sdrv.ms/Wx2Ets

Text animation in Windows Forms

I was wondering if there was a way of adding a sort of animation to text displayed on a form.
What I had in mind when I thought of this was kind of similar to what you can do with text in PowerPoint (i.e. a typewriter-like animation where the text is typed one at a time, have the whole textbox appear with a certain effect etc), I'm just looking to find out what you can do using Windows Forms.
Currently I'm using a textbox to display information on my form application, though in hindsight I realise labels would have worked just as well.
EDIT: Turns out I was using labels after all, I just gave it a name with 'textbox' inside for lack of a better description.
public partial class Form1 : Form
{
int _charIndex = 0;
string _text = "Hello World!!";
public Form1()
{
InitializeComponent();
}
private void button_TypewriteText_Click(object sender, EventArgs e)
{
_charIndex = 0;
label1.Text = string.Empty;
Thread t = new Thread(new ThreadStart(this.TypewriteText));
t.Start();
}
private void TypewriteText()
{
while (_charIndex < _text.Length)
{
Thread.Sleep(500);
label1.Invoke(new Action(() =>
{
label1.Text += _text[_charIndex];
}));
_charIndex++;
}
}
}
Now, I personally wouldn't do this because gratuitous animations tend to annoy users. I'd only use animation sparingly - when it really makes sense.
That said, you can certainly do something like:
string stuff = "This is some text that looks like it is being typed.";
int pos = 0;
Timer t;
public Form1()
{
InitializeComponent();
t = new Timer();
t.Interval = 500;
t.Tick += new EventHandler(t_Tick);
}
void t_Tick(object sender, EventArgs e)
{
if (pos < stuff.Length)
{
textBox1.AppendText(stuff.Substring(pos, 1));
++pos;
}
else
{
t.Stop();
}
}
private void button1_Click(object sender, EventArgs e)
{
pos = 0;
textBox1.Clear();
t.Start();
}
or something like that. It'll tick off ever half second and add another character to the multi-line text box. Just an example of what someone could do.

How to customize Button Control like this one?

I want to make a custom button control (image button is ok) like this one.
I'm a new user, so I can't post image here. So I uploaded the picture here
I'm kind of desperate right now after trying some tutorials
Any suggestion is highly appreciated.
Thanks
Updated 08/10/2019: I asked this question so many years ago, and at that time I didn't have the permission to upload image, so the image I uploaded to the third party site is long gone now. I got many requests about re-uploading the image, so here is what I remember from that project I did eight years ago, I just find some random images about window form that match my memory
This is when the button is in normal state
This is when the button is hovered or clicked, with the rounded border
You could create a class that inherits from Button to keep all your styling in one place. To do the hover and pressed states you can override the mouse enter / leave events of the button and change style.
Here is an example from one of our projects (I changed the colours but your get the idea). Where we change some colours you could switch the images.
public class MossieButton : Button
{
private static Font _normalFont = new Font("Arial", 10F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
private static Color _back = System.Drawing.Color.Grey;
private static Color _border = System.Drawing.Color.Black;
private static Color _activeBorder = System.Drawing.Color.Red;
private static Color _fore = System.Drawing.Color.White;
private static Padding _margin = new System.Windows.Forms.Padding(5, 0, 5, 0);
private static Padding _padding = new System.Windows.Forms.Padding(3, 3, 3, 3);
private static Size _minSize = new System.Drawing.Size(100, 30);
private bool _active;
public MossieButton()
: base()
{
base.Font = _normalFont;
base.BackColor = _border;
base.ForeColor = _fore;
base.FlatAppearance.BorderColor = _back;
base.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
base.Margin = _margin;
base.Padding = _padding;
base.MinimumSize = _minSize;
}
protected override void OnControlAdded(ControlEventArgs e)
{
base.OnControlAdded(e);
UseVisualStyleBackColor = false;
}
protected override void OnMouseEnter(System.EventArgs e)
{
base.OnMouseEnter(e);
if (!_active)
base.FlatAppearance.BorderColor = _activeBorder;
}
protected override void OnMouseLeave(System.EventArgs e)
{
base.OnMouseLeave(e);
if (!_active)
base.FlatAppearance.BorderColor = _border;
}
public void SetStateActive()
{
_active = true;
base.FlatAppearance.BorderColor = _activeBorder;
}
public void SetStateNormal()
{
_active = false;
base.FlatAppearance.BorderColor = _border;
}
}
Can't see the picture but I guess you can change the border of the button and set a background image.
button1.FlatStyle = FlatStyle.Flat;
button1.BackgroundImage = Bitmap.FromFile("image.jpg");
I think the simplest way is set some properties of the button like below and
this.button1.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.button1.Image = "Any Image"
this.button1.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
this.button1.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
then write the code for
private void button1_Click(object sender, EventArgs e)
{
//Code for Image Appearance.
button1.Text = "OnClick";
}
private void button1_MouseEnter(object sender, EventArgs e)
{
//Code for Image Appearance.
button1.Text = "Enter";
}
private void button1_MouseLeave(object sender, EventArgs e)
{
//Code for Image Appearance.
button1.Text = "Normal";
}
Update:
I don't know whether I am going correct or not but I think You can also achive your goal by putting a Button and a label inside a panel and arrange them according to your choice. Make the button1.FlatStyle = System.Windows.Forms.FlatStyle.Flat at initial with Label.Text="Normal". Then on Mouse enter to the Panel draw a rectangle with a border around the button and change the text of the label to "Hover". Like that Clicking on the Panel also you change the rectangle border according to you and make the label.Text="OnClick".

Categories

Resources