|
|
I don't know what VisualStudio it came with but there is a VisualBasic PowerPack that added the basic graphics objects to the toolbox for C# WinForm usage.
There's also multiple articles about creating LED controls on this site. Search
If you want to do it yourself, then you need to start looking into UserControls, and basically you create a class inheriting from UserControl and then you override the OnPaint event.
This is the OnPaint I did, its not great but it looks like a little led (with fade from colour to colour) which is all I wanted.
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Pen borderPen = new Pen(Color.Black);
borderPen.Width = ClientSize.Width <= 16 ? 2 : 4;
if (this.IsError)
{
using (Graphics g = e.Graphics)
{
SolidBrush brushError = new SolidBrush(ColorError);
g.FillEllipse(brushError, 0, 0, ClientSize.Width, ClientSize.Height);
g.DrawEllipse(borderPen, 0, 0, ClientSize.Width, ClientSize.Height);
brushError.Dispose();
}
}
else
{
Pen pen = new Pen(PercentageColor);
SolidBrush brushInside = new SolidBrush(PercentageColor);
int colorStepGradient = 1;
byte colorGradient = 255 / 10;
using (Graphics g = e.Graphics)
{
g.SmoothingMode = SmoothingMode.AntiAlias;
int x = 0, y = 0;
Color origPenColor = pen.Color;
Color origBrushColor = brushInside.Color;
int width = ClientSize.Width, height = ClientSize.Height;
for (; x <= width && y <= height; x += colorStepGradient, y += colorStepGradient, width -= 2 * colorStepGradient, height -= 2 * colorStepGradient)
{
g.DrawEllipse(pen, x, y, width, height);
g.FillEllipse(brushInside, x, y, width, height);
byte newR = pen.Color.R;
byte newG = pen.Color.G;
byte newB = pen.Color.B;
if (pen.Color.R + colorGradient <= 255)
newR = (byte) (pen.Color.R + colorGradient);
if (pen.Color.G + colorGradient <= 255)
newG = (byte) (pen.Color.G + colorGradient);
if (pen.Color.B + colorGradient <= 255)
newB = (byte) (pen.Color.B + colorGradient);
Color newcolor = Color.FromArgb(newR, newG, newB);
pen.Color = newcolor;
brushInside.Color = newcolor;
}
pen.Color = origPenColor;
brushInside.Color = origBrushColor;
g.DrawEllipse(borderPen, 0, 0, ClientSize.Width, ClientSize.Height);
pen.Dispose();
brushInside.Dispose();
}
}
GraphicsPath path = new GraphicsPath();
path.AddEllipse(0, 0, ClientSize.Width, ClientSize.Height);
this.Region = new Region(path);
path.Dispose();
borderPen.Dispose();
}
|
|
|
|
|
I was just about to post that someone at work mentioned to me about the Visual Basic Power Pack. This is exactly what I was looking for.
Thanks so much for posting and walking a mile in my shoes.
I will look into the more specialized LED search you hyperlinked, but I suspect the Power Pack is all that I need.
I definitely want to avoid coding the "LEDs" by hand since I'm dealing with a lot of these things.
Thanks Again!!!
modified 25-Mar-13 16:33pm.
|
|
|
|
|
A custom user control seems a perfect solution then tbh.
You can go the route I took and do it all via code, or you could use the VB PowerPack to draw the circles on the empty canvas it gives you.
|
|
|
|
|
Fisrt let me say I dont have errors and all is working fine, I want to know the best way of doing this... I am consumming a web serving that return string xml...
<pre><api_result><data><credits>33</credits></data><call_result><result>True</result><error /></call_result></api_result>
I want the value "33", have the following and it works fine but wanted to know it's the right way to go...
string sReturnString = WebserviceName.ReturnMyValue(PassingSomeValues);
foreach (char cString in sReturnString.ToCharArray())
{
if (char.IsDigit(cString))
sCredits += cString.ToString();
}
return "Balance: sCredits";
I don't want to save it to a file, but just want to dislapy the value. Any recommnedations?
Thanking you in advance.
Addition: ..
Saving it to an xml file makes it easy to read the creadit element value <credits>33; but I dont want to create any files..
I remain joe!
modified 21-Mar-13 15:33pm.
|
|
|
|
|
- If you don't already have one, add a reference to
System.Xml.Linq ; - Add
using System.Linq; and using System.Xml.Linq; at the top of your code file; - Use:
XElement el = XElement.Parse(sReturnString);
string sCredits = (string)el.Elements("data").Elements("credits").FirstOrDefault();
return "Balance: " + sCredits;
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Thanks, appreciated!
I remain joe!
|
|
|
|
|
In my opinion this (or using XmlReader directly) is the way to go:
Consistency - the web service uses xml responses because it is a standard with some pros e.g. extensibility and formatting. By not parsing xml according to the standard, you don't get the benefits from the standard.
Performance - XmlElement.parse is built upon XmlReader which is a sequential reader. It is both faster and cheaper in memory than XmlDocument that builds a complete DOM in memory.
Kind Regards,
Keld Ølykke
|
|
|
|
|
@Keld, thanks for the info...
I remain joe!
|
|
|
|
|
I'd use an XmlDocument.
string s = "<api_result><data><credits>33</credits></data><call_result><result>True</result><error /></call_result></api_result>" ;
System.Xml.XmlDocument doc = new System.Xml.XmlDocument() ;
doc.LoadXml ( s ) ;
System.Xml.XmlNode nod = doc.DocumentElement.SelectSingleNode ( "data/credits" ) ;
string v = nod.InnerText ;
|
|
|
|
|
|
Boipelo wrote: I want to know the best way of doing this...
Depends on what "best" means.
But since you are doing nothing but a simple value lookup what you are doing is probably the most performant (although probably not in a significant way.)
There are upside/downsides to ignoring the XML itself. For example if they change element names on the message your code still works. But if they add another element first with a numeric value it doesn't.
Conversely using XML if they change names then the code would fail. But if they add another element it would still work.
|
|
|
|
|
I was also scared of "...if they add another element with a numeric value". I am not seeing them changing the "element name", that wont happen.
Thanks for the comment.
I remain joe!
|
|
|
|
|
Boipelo wrote: I was also scared of "...if they add another element with a numeric value"
but only if it is first.
You can do a indexOf for the element name and then start parsing the numeric.
|
|
|
|
|
I'm trying to add an event handler for form closing event. I'm not very good at doing event handlers. I looked at http://stackoverflow.com/questions/7076751/how-do-i-avoid-validating-cancel-causing-app-exit-to-hang[^], among other places on the internet, but the thread is not getting to my method. It wasn't building until I added the property for FormClosing at the top. Hopefully someone here has an idea why it's not working. Thanks!
public partial class GenericPC : UserControl
{
...
public FormClosingEventHandler Closing { get; set; }
public Control GetPC(<params>)
{
...
this.Closing += new System.Windows.Forms.FormClosingEventHandler(this.updateLogsOnClose);
...
}
private void updateLogsOnClose(object sender, System.ComponentModel.CancelEventArgs e)
{
logCountsToFile(logCountFile);
}
...
}
modified 21-Mar-13 11:28am.
|
|
|
|
|
The event name is Closing .
|
|
|
|
|
I changed it from FormClosing to Closing, as I changed in my code shown above, and it's still not going to my method when the form closes. Any ideas? It doesn't seem the like property for Closing gets called by anything. Do I need to set it somehow? Closing was causing a build error before I defined it. Maybe there's a system method I need to enable somewhere to get it defined by visual studio?
|
|
|
|
|
MichCl wrote: property for Closing
Get rid of that.
|
|
|
|
|
public Control GetPC(<params>)
{
...
this.Closing += new System.Windows.Forms.FormClosingEventHandler(this.updateLogsOnClose);
...
} That's not the form, and your usercontrol will not raise a FromClosingEvent; you'd need a reference to the form if you want to hook it's "Closing" handler (in the same way you need an instance when you use one of it's properties).
Alternatively, you could use the "Parent" property of your usercontrol to find the owning form.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
Thanks Eddy. I'm trying to figure out how to use theParent's Form to set me up with the Closing Handler. For some reason, the below code is not building. It says "System.Windows.Forms.FormClosingEventHandler is a type which is not valid in the given context". Any idea?
public partial class GenericPC : UserControl
{
...
public FormClosingEventHandler Closing { get; set; }
public Control GetPC(<params>, Form theParent)
{
...
theParent.Closing += new System.Windows.Forms.FormClosingEventHandler(this.updateLogsOnClose);
...
}
private void updateLogsOnClose(object sender, System.ComponentModel.CancelEventArgs e)
{
logCountsToFile(logCountFile);
}
...
}
|
|
|
|
|
Your modification is correct; but it looks like the eventhandler could use a different signature;
private void updateLogsOnClose(Object sender, FormClosingEventArgs e) As an alternative solution;
1 using System;
2 using System.Windows.Forms;
3 using System.Collections.Generic;
4
5 namespace test
6 {
7 class MyControl: UserControl
8 {
9 protected override void OnHandleCreated(EventArgs e)
10 {
11 base.OnHandleCreated(e);
12 FindForm().FormClosing += new FormClosingEventHandler(MyControl_FormClosing);
13 }
14 void MyControl_FormClosing(object sender, FormClosingEventArgs e)
15 {
16 System.Diagnostics.Debugger.Break();
17 }
18 }
19 class Program
20 {
21 public static void Main(string[] args)
22 {
23 using (var f = new Form())
24 {
25 MyControl uc = new MyControl() { Dock = DockStyle.Fill };
26 f.Controls.Add(uc);
27 f.ShowDialog();
28 }
29 }
30 }
31 }
The reason I'm not calling the FindForm method in the constructor of the UserControl is because it will not be assigned to a form at that point. (It's created on line 25, and added to the form on the next line)
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
If you definitely need access to the closing event from your control, you need to walk up the Parent hierarchy until you find the Form. It would look something like this:
private Form ParentForm(object item)
{
if (((Form)item).Parent is Form)
return ((Form)item).Parent;
return ParentForm(item);
} Then, it's a simple matter of hooking into the closing event handler.
I really wouldn't recommend doing it this way, but you could.
|
|
|
|
|
I got it working!! Thanks for your help!! It turns out I was missing "new":
theParent.FormClosing += new FormClosingEventHandler(this.updateLogsOnClose);
|
|
|
|
|
Hi,
I want to combine two drawings into one,and place in a line as show below
How to Upload pictures!!!
|
|
|
|
|
You need to provide a lot more detail about this problem: what sort of drawings, place on a line where ... ?
Use the best guess
|
|
|
|