|
Why is that "the best option"? I see no reason why it is better than say WPF. Or flipping picture images as the OP is thinking of.
|
|
|
|
|
Gerry Schmitz wrote: why it is better than say WPF. In the original question the OP states: "I'm a total noob at C# 2005", which suggests that WPF would be an even bigger mountain to climb.
Use the best guess
|
|
|
|
|
You assume too much. If the OP was prepared to use WPF, I would have posted a solution that any "noob" would have understood.
Any solution (in this case) that is at least object-oriented is superior to one that simply "draws".
The OP is creating a UI (not some scribbles); and creating "leds" implies managing "state" (i.e. on/off); image controls (the OP's thinking), "shapes", etc. are a lot more useful in this case than simply "drawing" (as you are suggesting).
|
|
|
|
|
Gerry Schmitz wrote: You assume too much Not at all; if someone states that they are completely new to C# then it's a fair bet that they would not find WPF easy.
Gerry Schmitz wrote: Any solution (in this case) that is at least object-oriented is superior to one that simply "draws". I never claimed that it wasn't.
Gerry Schmitz wrote: more useful in this case than simply "drawing" (as you are suggesting). I made no such suggestion; I merely pointed the OP at the .NET Graphics Class[^] which can be used to draw circles. I left the actual implementation to him/her to figure out.
Use the best guess
|
|
|
|
|
|
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[^]
|
|
|
|