search
Twitter Rss Feeds
MicrosoftArticlesForumsGroups
C# .NET
VB.NET
Visual Studio .NET
ADO.NET
Xml/Xslt
VB 6.0
.NET CF
GDI+
LINQ
Deployment
Security
FoxPro
Silverlight / WPF
Entity Framework
RIA Services

Web ProgrammingArticlesForumsGroups
JavaScript
ASP
ASP.NET
Web Services

Non-MicrosoftArticlesForumsGroups
NHibernate
Perl
PHP
Ruby
Java
Linux / Unix
Apple
Open Source

DatabasesArticlesForumsGroups
SQL Server
Access
Oracle
MySQL
Other Databases

OfficeArticlesForumsGroups
Microsoft Excel
Microsoft Word
Microsoft Powerpoint
Publisher
Money

Operating SystemsArticlesForumsGroups
Windows 7
Windows Server
Windows Vista
Windows XP
Windows Update
MAC
Linux / UNIX

Server PlatformsArticlesForumsGroups
Share Point
BizTalk
Site Server
Exhange Server
IIS
Transaction Server

Graphic DesignArticlesForumsGroups
Macromedia Flash
Adobe PhotoShop
Microsoft Expression

OtherArticlesForumsGroups
Subversion / CVS
Ask Dr. Dotnetsky
Active Directory
Networking
Uninstall Virus
Job Openings
Reviews
Search Engines
Resumes

 
Realtime Stock Quote Tray Icon App
By Peter A. Bromberg, Ph.D.
Printer - Friendly Version
Peter Bromberg

Recently I noticed my buddy Robbe has one of these "streamer" apps running in a small web browser window on one of his machines so he can track his crummy stocks and how badly they are doing (hehe). I mentioned that I thought I could put together some sort of tray icon app that would be even better.

I didn't think it would be a lot of work because:

1) I already had done some screen-scraping code that did a pretty good job of getting realtime quotes from Yahoo finance.
2) I figured all I would need to do is drop a NotifyIcon control on a form and do it that way.

As luck would have it, I was only partly right. The NotifyIcon control in .Net is particularly limited. You can hook it up to a context menu, and you can set its Text property, and a few event handlers, and that's about it. Forget about displaying those neat Windows XP - style balloon tip thingies.

I searched the .NET and went through three different implementations of people's .NET balloon tip classes, and there was only one that did what I wanted - to close the balloon tip automatically on both Windows 2000 and Windows XP machines - after the specified timeout period.

The one I chose to use, a really first - class all - managed - code implementation, is this one:

http://www.codeproject.com/useritems/TaskbarNotifier.asp

I leave you with the link above if you want to explore further; all the necessary code to use same is in the downloadable solution below.

The only other thing left for me to do was to implement an elegant way to pop up a form the first time the app is run in order to allow the user to enter a list of their favorite stock symbols to check. While I was at it, I also added a small textbox where you can enter a number of minutes. By adding a timer control to the form, we can then show timed balloon tips every X minutes with the latest real - time quotes, courtesy of Yahoo. And, I put in a context menu item that takes you to the Yahoo Finance page of all your quotes from your list so that you can look at stock charts, get news, and financials. One caveat - it is illegal to redisplay Yahoo quotes on another site. In this case, where it is for personal use and you are going to frequently end up going to the Yahoo site via the context menu item and see all their ads and stuff anyway, I reasoned they probably won't get upset.

Once the first set of quotes has been retrieved, the Text property of the NotifyIcon is set with the results, so when you mouse over the icon, it will look like so:

And when the Balloon Tip comes up, it looks like this:

(Man, I didn't know Yahoo was up to $21! Last time I looked, it was like $9.... Damn!)

The key methods in the project are the GetTickers method, the WriteTickers method, and the GetQuotes method:

private string GetTickers()
{
string sTickers=String.Empty;
try
{
sTickers = Registry.LocalMachine.OpenSubKey("Software\\PAB\\QuoteMinder\\TickerList").GetValue("Symbols").ToString();

txtMin.Text= Registry.LocalMachine.OpenSubKey("Software\\PAB\\QuoteMinder\\AutoDisplay").GetValue("Min").ToString();

}
catch(Exception ex)

{

}
return sTickers;
}

private bool WriteTickers( string strTickers, string strMin)
{
try
{
Registry.LocalMachine.CreateSubKey("Software\\PAB\\QuoteMinder\\TickerList").SetValue("Symbols", strTickers);
stocks=strTickers;
Registry.LocalMachine.CreateSubKey("Software\\PAB\\QuoteMinder\\AutoDisplay").SetValue("Min", strMin);
int intrval=Convert.ToInt32(strMin);
if(intrval==0)
{
this.timer1.Enabled=false;
}
else
{
this.timer1.Interval =Convert.ToInt32(strMin)*1000*60;
this.timer1.Enabled=true;
this.timer1.Start();
}


}
catch(Exception ex)
{
return false;
}
return true;
}

public string GetQuotes(string QuoteList)
{
string serverURL= @"http://finance.yahoo.com/q?s=" + QuoteList+"&d=e";

//Create a HttpWebRequest object for the server search URL
HttpWebRequest webreq = (HttpWebRequest)WebRequest.Create(serverURL);
webreq.MaximumAutomaticRedirections =60;
webreq.UserAgent="Mozilla/4.0 (compatible; MSIE 6.0;Windows NT 5.0)";
//Retrieve HttpWebResponse object from the Search server URL
HttpWebResponse webresp = (HttpWebResponse)webreq.GetResponse();
//Create StreamReader object and pass the searchserver stream as parameter, with ASCII encoding
StreamReader strm = new StreamReader(webresp.GetResponseStream(), Encoding.ASCII);
//iterate through the stream, building return XML Document string
string res = strm.ReadToEnd();
strm.Close();
int startpos = res.IndexOf("Detailed");
string theQuotes="";
string tmpQuote="";
string[] arSymbols=QuoteList.Split(Convert.ToChar(" "));
for(int i = 0;i<arSymbols.Length;i++)
{
res=res.Substring(startpos);
startpos=res.IndexOf("<td nowrap align=left");
res=res.Substring(startpos);
startpos=res.IndexOf(">"+arSymbols[i].ToUpper()+"</a>");
res=res.Substring(startpos);
startpos = res.IndexOf("<b>" );
res=res.Substring(startpos);
int endpos = res.IndexOf("</b>");
tmpQuote=res.Substring(3,endpos-3);
theQuotes+= arSymbols[i] + " " +tmpQuote +" ";
startpos=endpos+3;
}
return theQuotes;
} // end GetQuotes

 

I also stuck in a P/Invoke call to do some toned beeps with a wav file when the thingy comes up, just to add a little "flair". You can download the whole solution and play with it to your heart's content below. Some interesting "TO-DO's" might include changing the way the WebRequest returns the stock results to perhaps a HashTable or an ArrayList of structs, or even a DataTable, and thereby make a provision in the Edit section to allow the user to add Limit Alerts that will fire if any of their stocks go above or below preset defined price limits (Oops! I got ambitious and already did it! - its all in the download below!).

Download the code that accompanies this article

 


Peter Bromberg is a C# MVP, MCP, and .NET consultant who has worked in the banking and financial industry for 20 years. He has architected and developed web - based corporate distributed application solutions since 1995, and focuses exclusively on the .NET Platform. Pete's samples at GotDotNet.com have been downloaded over 41,000 times. You can read Peter's UnBlog Here.  --><--NOTE: Post QUESTIONS on FORUMS!

Do you have a question or comment about this article? Have a programming problem you need to solve? Post it at eggheadcafe.com forums and receive immediate email notification of responses.



Pete's Blog   |    Pete's Resume   |    Robbe's Blog   |    Robbe's Resume   |    Archive #2   |    Archive #3   |    Dotnetslackers   |    XmlPitStop   |    Advertise   |   Contact Us   |   Privacy   |   Copyright (c) 2000 - 2009 eggheadcafe.com  All rights reserved.