|
You could write your own label class that simply overrides the base paint method.
"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997 ----- "...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001
|
|
|
|
|
You can't get rid of it.
If this is a problem, why even use a Label? Why not just render the text yourself with DrawString? You'd probably end up doing the same thing if you made your own Label control and supplied your own drawing code anyway.
|
|
|
|
|
I can't use DrawString because I need to know the exact length of the text: that's why the autosize property is so convenient. I just set the texts of the labels and add the width properties to know the final length of all the labels.
If I'm using DrawString or something that overrides the WM_PAINT of the label, how do I know the length in pixels of the text?
|
|
|
|
|
Tony_P wrote: I can't use DrawString because I need to know the exact length of the text
That's what MeasureString is for.
|
|
|
|
|
Alright I've just found this in the meantime. Thank you for your time!
|
|
|
|
|
this is what I came up with:
public class EnhancedLabel : Label
{
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
Brush fore = new SolidBrush(this.ForeColor);
Brush back = new SolidBrush(this.BackColor);
SizeF s = g.MeasureString(this.Text, this.Font);
this.Width = (int)s.Width;
this.Height = (int)s.Height;
g.FillRectangle(back, this.Left, this.Top, this.Width, this.Height);
g.DrawString(this.Text, this.Font, fore, this.Location);
}
}
|
|
|
|
|
And a version 2.0, much better ;o
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
Brush fore = new SolidBrush(this.ForeColor);
Brush back = new SolidBrush(this.BackColor);
g.FillRectangle(back, this.Location.X, this.Location.Y, this.Width, this.Height);
g.DrawString(this.Text, this.Font, fore, Point.Empty);
}
protected override void OnTextChanged(EventArgs e)
{
Graphics g = System.Drawing.Graphics.FromHwnd(this.Handle);
SizeF s = g.MeasureString(this.Text, this.Font);
this.Width = (int)s.Width;
this.Height = (int)s.Height;
base.OnTextChanged(e);
}
|
|
|
|
|
Just a couple of points - You should dispose of your brushes, or better still put them in using blocks.
using (Brush back = new SolidBrush(ForeColor))
{
e.Graphics.FillRectangle(back, Location.X, Location.Y, Width, Height);
}
using (Brush fore = new SolidBrush(BackColor))
{
e.Graphics.DrawString(Text, Font, fore, Point.Empty);
}
You can use the Size struct's static Round method to convert the SizeF
Size = Size.Round(s);
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
Right, thank you for the tips. I used the brushes without even checking if it was a disposable object. Shame on me.
|
|
|
|
|
Hi,
the most expensive one, the one you really should dispose of, is the result of Graphics.FromHwnd()
for the brushes, you might consider keeping them in a class member, rather than creating and disposing them all the time.
creating a Graphics, as you do, is something I avoid even at modest cost; so I am not in favor of
your 2.0 solution; instead I would do everything in OnPaint, possibly do MeasureString inside
a test on text changed.
|
|
|
|
|
Well the problem is that I need the width/height of the label without painting it, so I can't do everything in the paint event.
The best way is probably to store the brushes, for sure.
Can I store the Graphics.FromHwnd() the same way or can the value of Graphics.FromHwnd() change?
|
|
|
|
|
Tony_P wrote: I need the width/height of the label without painting it
Huh? if you need it inside OnPaint only, then do the MeasureString in OnPaint just before you
use DrawString. if you need its result outside OnPaint, I would try and execute OnPaint once
before you need the sizes.
Keeping a Graphics does not feel right; for one it is an expensive object, and it contains many things that may be different each time you get a graphics; e.g. every time you move ab object over a Form, the Form may get Paint events with varying clip regions in the Graphics object. Also the user might change the resolution of the screen, and whatever more.
|
|
|
|
|
Why don't you just write a function that does something like this:
class BlahBlah
{
SizeF m_textSize;
public SizeF MeasureText(string text)
{
(using Graphics graphics = Graphics.FromHwnd(this))
{
m_textSize = graphics.MeasureString(text, someFont);
}
return m_textSize;
}
}
"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997 ----- "...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001
|
|
|
|
|
I will do such things only if I see no reasonable alternative; I try and avoid creating a new Graphics as much as I can. In OnPaint the Graphics is for free, so why not take advantage of that one?
In the few 100K lines of C# code I have at hand, I found only two instances of Graphics.FromHwnd;
I do use Graphics.FromImage of course when drawing onto a Bitmap, there simply is no alternative there.
|
|
|
|
|
i can't access my MSN application ID in my project.I created APPID and added the web refernce.When i run and click on submit it's going in catch and refershing the page.
|
|
|
|
|
I don't think anyone here knows what you're talking about. MSN AppID?? What AppID?? What web reference to what service?? Submit?? Submit what to where??
Also, you may want to re-ask this question in the ASP.NET Forum.
|
|
|
|
|
I have a status strip which displays a progress bar during initialization and execution phases of my application.
In the designer I set Max=100 Min=0 Step=10
The bar progresses as expected, but when I reach completion I set the bar value to 100, put out my complete message, and sleep the thread for 1 second. The Progress bar is always showing only about 80% of the progress bar painted.
I've experimented by taking the value to 101 (for example) and it doesn't like that. I've also paused the code and validated that the value is indeed set to 100.
Has anyone experienced this or (better yet) figured out how to fix this?
Thanks in advance.
|
|
|
|
|
LongRange.Shooter wrote: and sleep the thread for 1 second.
Then what? What code executes after the sleep? You are sleeping the main or UI thread so no updating to the screen will occur.
led mike
|
|
|
|
|
If you call Thread.Sleep after setting the Value of ProgressBar, the bar will not get painted, so you'll see this result. Putting the UI thread to sleep or tying it up doings other things prevents any painting of the form or its controls.
|
|
|
|
|
Okay...cut short my entire process. Here it is:
private void SetProgress( int progressValue, string message )
{
this.loadProgress.Step = progressValue;
this.loadProgress.PerformStep( );
this.loadStatus.Text = message;
this.Refresh( );
Application.DoEvents( );
Thread.Sleep( 1000 );
}
|
|
|
|
|
The Thread.Sleep is not required and is actually hindering the process by not allowing any code to execute on the thread you called Sleep on. DoEvents will yield the thread to processing the message loop (including painting) but you have to be VERY careful in using it. Since button presses and other UI controls will still work, you could end up with a user clicking twice on the same button because DoEvents allows both clicks to be processed.
|
|
|
|
|
Hi,
Controls are not updated at the instant that the new value is set and may never get updated if the UI thread is busy. To see if this is the problem you could insert a call to Application.DoEvents() immediately after setting the progress bar value to 100.
Longer term you may need to separate your application processing into a separate thread so that the UI is free to update when you want it to.
Alan.
[EDIT: and like the others said, don't go to sleep!]
|
|
|
|
|
As people have already pointed out, if you sleep the thread your UI will never have the change to get updated.
Try to do this.Invalidate() before sleeping your thread.
Application.DoEvents() is another workaround for this.
|
|
|
|
|
Assumptions:
1) Local Intranet - non-public traffic
2) A single 'server' application will accept ISerializable objects from up to 25 different clients.
3) Objects are not sent at predetermined times (IE not on a timer) but by user interaction
I'm trying to figure out the best way to send objects over TCP. Lets say these objects range from 355 bytes all the way up to 69500 bytes.
Because we're dealing with 25 different clients I'd like this all done asyncronously.
Now, there's 2 ways I can think to do this.
1)
Asyncronously accept a Header class with an (int)size and a System.Type variables using Socket.BeginReceive(). In testing, this header class is about 300-400 bytes. On receipt of this object, create a byte array of the size indicated in the Header object. Then do a blocking .Receive() for the actual object.
On the clients, I'd first send this Header object over, followed immediatly by the actual object.
2)
Ignore the header class, just send over the entire object. On the server, use a buffer to concat say 1024 bytes at a time until the object does not fail a try/catch DeSerialize method.
I've got both ways working, #2 seems messy, because I'm relying on try/catch clauses. However, I've tried neither on a larger roll out. Is there perhaps a better way of doing this?
|
|
|
|
|
menzelAtPCA wrote: I'm trying to figure out the best way to send objects over TCP
No longer requires you writing socket code. There are other mechanisms like Web Service or Remoting.
menzelAtPCA wrote: A single 'server' application
The other mechanisms also afford using an application server rather than developing your own server application.
I have no idea if any of that interests you but there was no indication that you are aware of any of it.
led mike
|
|
|
|