<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>Ryan O'Neill's www.rhinomobile.net</title><link>http://www.rhinomobile.net/</link><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/Rhinomobile" /><description>Some musings on mobile and embedded technology, programming and products.</description><language>en</language><managingEditor>noreply@blogger.com (Ryan O'Neill)</managingEditor><lastBuildDate>Thu, 07 Jul 2011 14:57:10 PDT</lastBuildDate><generator>Blogger</generator><atom:id xmlns:atom="http://www.w3.org/2005/Atom">tag:blogger.com,1999:blog-37149201</atom:id><openSearch:totalResults xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/">24</openSearch:totalResults><openSearch:startIndex xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/">1</openSearch:startIndex><openSearch:itemsPerPage xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/">25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/Rhinomobile" /><feedburner:info uri="rhinomobile" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item><title>Professional Development Plan 2010</title><link>http://feedproxy.google.com/~r/Rhinomobile/~3/qJIboF93UDo/professional-development-plan-2010.html</link><author>noreply@blogger.com (Ryan O'Neill)</author><pubDate>Wed, 10 Mar 2010 21:16:00 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-37149201.post-4506399461913859681</guid><description>Being someone who constantly reads has been great for my career in developing new skills and learning new technologies. I believe that "&lt;a href="http://www.industriallogic.com/xp/ContinuousLearning.pdf"&gt;Continuous Learning&lt;/a&gt;" is very important for any software developer especially considering the rapid change in the advances of technology as well as the maturation and evolution of the software development profession.&lt;br /&gt;&lt;br /&gt;In January, I read James Marcus Bach's &lt;a href="http://www.amazon.com/gp/product/1439109087?ie=UTF8&amp;amp;tag=rhinomobile-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=1439109087"&gt;Secrets of a Buccaneer Scholar&lt;/a&gt;, and really identified with it. Bach is someone who is a huge proponent of self-study. I consider myself largely self-taught, yet someone who has learned at the feet of the most respected men in the software development profession by reading their works.&lt;br /&gt;&lt;br /&gt;The two books which really had a dramatic and immediate impact on how I not only developed software but thought about developing software were Martin Fowler's &lt;a href="http://www.amazon.com/gp/product/0201485672?ie=UTF8&amp;amp;tag=rhinomobile-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0201485672"&gt;Refactoring: Improving the Design of Existing Code&lt;/a&gt; and Steve McConnell's &lt;a href="http://www.amazon.com/gp/product/0735619670?ie=UTF8&amp;amp;tag=rhinomobile-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0735619670"&gt;Code Complete: A Practical Handbook of Software Construction&lt;/a&gt; (the first version). These books opened doors for me and my voraciousness for reading technical books spiraled out of control from there. How I have chosen which books to read in the past could be described as random at best.&lt;br /&gt;&lt;br /&gt;In Bach's book, he had mapped out areas of study which he focuses on. As I thought more about that, I realized that there are a few areas of study that I want to focus on and further develop my own skills in this year. So I decided to pick 6 areas to focus on:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Planning and Estimation&lt;/li&gt;&lt;li&gt;Analysis and Design&lt;/li&gt;&lt;li&gt;Testing&lt;/li&gt;&lt;li&gt;Leadership Strategy&lt;/li&gt;&lt;li&gt;Presentation&lt;/li&gt;&lt;li&gt;Business&lt;/li&gt;&lt;/ul&gt;Within each of these 6 areas, I decided to pick two books which I would like to read. Some of these books I have owned for years but not read, some I had bought recently but not read, and some are available on O'Reilly's Safari Books Online, to which I have a full subscription. I then set a goal for myself to read all twelve books by the end of this year. Some of them I have not started, some of them I am partially through, and some of them I have completed:&lt;br /&gt;&lt;br /&gt;Planning and Estimation&lt;br /&gt;&lt;a href="http://www.amazon.com/gp/product/0131479415?ie=UTF8&amp;amp;tag=rhinomobile-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0131479415"&gt;Agile Estimating and Planning&lt;/a&gt; by Mike Cohn (2005) (0% Completed)&lt;br /&gt;&lt;a href="http://www.amazon.com/gp/product/0735605351?ie=UTF8&amp;amp;tag=rhinomobile-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0735605351"&gt;Software Estimation: Demystifying the Black Art&lt;/a&gt; by Steve McConnell (2006) (24% Completed)&lt;br /&gt;&lt;br /&gt;Analysis and Design&lt;br /&gt;&lt;a href="http://www.amazon.com/gp/product/0321509366?ie=UTF8&amp;amp;tag=rhinomobile-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0321509366"&gt;Emergent Design: The Evolutionary Nature of Professional Software Development&lt;/a&gt; by Scott Bain (2008) (32% Completed)&lt;br /&gt;&lt;a href="%3Ca%20href=%22http://www.amazon.com/gp/product/0201895420?ie=UTF8&amp;amp;tag=rhinomobile-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0201895420"&gt;Analysis Patterns: Reusable Object Models&lt;/a&gt; by Martin Fowler (1996) (6% Completed)&lt;br /&gt;&lt;br /&gt;Testing&lt;br /&gt;&lt;a href="http://www.amazon.com/gp/product/0471358460?ie=UTF8&amp;amp;tag=rhinomobile-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0471358460"&gt;Testing Computer Software&lt;/a&gt;, 2nd Edition by Cem Kaner et. al. (1999) (6% Completed)&lt;br /&gt;&lt;a href="http://www.amazon.com/gp/product/0321534468?ie=UTF8&amp;amp;tag=rhinomobile-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0321534468"&gt;Agile Testing: A Practical Guide for Testers and Agile Teams&lt;/a&gt; by Lisa Crispin et. al. (2009) (0% Completed)&lt;br /&gt;&lt;br /&gt;Leadership Strategy&lt;br /&gt;&lt;a href="http://www.amazon.com/gp/product/0321620704?ie=UTF8&amp;amp;tag=rhinomobile-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0321620704"&gt;Leading Lean Software Development: Results are not the Point&lt;/a&gt; by Mary Poppendieck et. al. (2009) (0% Completed)&lt;br /&gt;&lt;a href="http://www.amazon.com/gp/product/0470560452?ie=UTF8&amp;amp;tag=rhinomobile-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0470560452"&gt;One Strategy: Organizing, Planning, and Decision Making&lt;/a&gt; by Steven Sinofsky et. al. (2009) (60% Completed)&lt;br /&gt;&lt;br /&gt;Presentation&lt;br /&gt;&lt;a href="http://www.amazon.com/gp/product/0596801998?ie=UTF8&amp;amp;tag=rhinomobile-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0596801998"&gt;Confessions of a Public Speaker&lt;/a&gt; by Scott Berkun (2009) (100% Completed)&lt;br /&gt;&lt;a href="http://www.amazon.com/gp/product/0814401570?ie=UTF8&amp;amp;tag=rhinomobile-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0814401570"&gt;Speak to Win: How to Present with Power in Any Situation&lt;/a&gt; by Brian Tracy (2008) (18% Completed)&lt;br /&gt;&lt;br /&gt;Business&lt;br /&gt;&lt;a href="http://www.amazon.com/gp/product/0060833459?ie=UTF8&amp;amp;tag=rhinomobile-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0060833459"&gt;The Effective Executive: The Definitive Guide to Getting the Right Things Done&lt;/a&gt; by Peter Drucker (1967) (100% Completed)&lt;br /&gt;&lt;a href="http://www.amazon.com/gp/product/0060799072?ie=UTF8&amp;amp;tag=rhinomobile-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0060799072"&gt;The Ten-Day MBA 3rd Ed.: A Step-By-Step Guide To Mastering The Skills Taught In America's Top Business Schools&lt;/a&gt; by Steven Silbiger (2005)  (17% Completed)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37149201-4506399461913859681?l=www.rhinomobile.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rhinomobile/~4/qJIboF93UDo" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2010-03-11T01:36:20.589-05:00</atom:updated><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.rhinomobile.net/2010/03/professional-development-plan-2010.html</feedburner:origLink></item><item><title>Quick Hitter: The King of Kong: A Fistful of Quarters</title><link>http://feedproxy.google.com/~r/Rhinomobile/~3/4rBa1lWeT-M/quick-hitter-king-of-kong-fistful-of.html</link><category>Zilog Z80</category><category>Quick Hitter</category><author>noreply@blogger.com (Ryan O'Neill)</author><pubDate>Sun, 19 Aug 2007 21:06:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-37149201.post-1462886034977507004</guid><description>Champion versus challenger. The perennial winner versus the lovable loser. The guy people love to hate versus the guy people love to cheer. The same qualities that make a heated sports rivalry so spectacular are in full effect in Seth Gordon's amazing documentary &lt;a href="http://www.billyvssteve.com/"&gt;The King of Kong: A Fistful of Quarters&lt;/a&gt;. Gordon's story details the battle between challenger Steve Wiebe and champion Billy Mitchell as they vie for the Donkey Kong world record. Wiebe, with a wife, two kids, no job, and a penchant for crying, fights for integrity and respectability. Mitchell, the 1980's arcade master with the 1970's haircut, fights for video game supremacy. Colorful characters are plentiful throughout which only adds to the narrative. A highly gripping and entertaining picture.&lt;br /&gt;&lt;br /&gt;What is a movie review doing on a blog about mobile and embedded technology?&lt;br /&gt;&lt;br /&gt;Well, the main CPU for the Donkey Kong arcade game machine was a Zilog Z80.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37149201-1462886034977507004?l=www.rhinomobile.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rhinomobile/~4/4rBa1lWeT-M" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2007-08-20T00:36:32.947-04:00</atom:updated><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.rhinomobile.net/2007/08/quick-hitter-king-of-kong-fistful-of.html</feedburner:origLink></item><item><title>Quick Hitter: Installing Windows Embedded CE 6</title><link>http://feedproxy.google.com/~r/Rhinomobile/~3/oUQQXNXCuz0/quick-hitter-installing-windows.html</link><category>Windows Embedded CE</category><category>Quick Hitter</category><author>noreply@blogger.com (Ryan O'Neill)</author><pubDate>Thu, 16 Aug 2007 21:16:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-37149201.post-1943105478266055788</guid><description>&lt;p&gt;During the installation of Windows Embedded CE 6, sometimes the installer displays a dialog box stating that it "Could not access network location [url]." An example of this is displayed in Image 1. Hitting the Retry button on the dialog may not have any effect at first. What appears to work when this occurs is to open Internet Explorer, type the url in the location bar and hit Enter. Hit the Cancel button on the File Download dialog. Then, go back to the installer dialog and hit the Retry button again. This time it should work fine.&lt;/p&gt;&lt;p&gt;&lt;u&gt;Image 1&lt;/u&gt; - Error Dialog&lt;/p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_GhRaWNC6A8Q/RsMn1Emr4VI/AAAAAAAAAG0/HvNMr49Ja5M/s1600-h/quickhitter01.jpg"&gt;&lt;img style="cursor: pointer;" src="http://1.bp.blogspot.com/_GhRaWNC6A8Q/RsMn1Emr4VI/AAAAAAAAAG0/HvNMr49Ja5M/s320/quickhitter01.jpg" alt="" id="BLOGGER_PHOTO_ID_5098962995836084562" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37149201-1943105478266055788?l=www.rhinomobile.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rhinomobile/~4/oUQQXNXCuz0" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2008-12-10T05:46:55.145-05:00</atom:updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_GhRaWNC6A8Q/RsMn1Emr4VI/AAAAAAAAAG0/HvNMr49Ja5M/s72-c/quickhitter01.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.rhinomobile.net/2007/08/quick-hitter-installing-windows.html</feedburner:origLink></item><item><title>Webcast Review: Testing the Most Critical Part of Your Application</title><link>http://feedproxy.google.com/~r/Rhinomobile/~3/K5rtY_ItHhc/webcast-review-testing-most-critical.html</link><category>MSDN Webcast</category><category>Windows Mobile</category><author>noreply@blogger.com (Ryan O'Neill)</author><pubDate>Wed, 15 Aug 2007 21:00:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-37149201.post-6191451983206893117</guid><description>&lt;p&gt;In &lt;a href="http://msevents.microsoft.com/cui/WebCastEventDetails.aspx?culture=en-US&amp;EventID=1032340727&amp;CountryCode=US"&gt;this webcast&lt;/a&gt;, Microsoft MVP and frequent MSDN Webcast presenter &lt;a href="http://www.pluralsight.com/blogs/jimw/"&gt;Jim Wilson&lt;/a&gt; provides an overview and a demonstration of the Local Server Framework. The Local Server Framework, also known as FakeServer, is a new tool included with the Windows Mobile 6 SDK. The Local Server Framework provides both a native dll and a managed wrapper for setting up a testing server which runs directly on a Windows Mobile device.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Running a test server on a Windows Mobile device provides greater control over an application's test environment by removing network setup and maintenance from the equation. When building mobile applications, often times the server component is being developed in parallel with the client. Using the Local Server Framework for testing, therefore, is a great way to cut down on the impact of client and server modifications. Jim mentions how blame for miscommunication when versions are out of sync is usually placed on the client because it is the application that exposes the error. For this and other reasons, he believes that a mobile client should not trust server data unconditionally and that the application should validate transmitted data just like user-entered data. By using the Local Server Framework, developers can modify the FakeServer to see how their mobile applications respond to these and other spurious inputs. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;From an information perspective, this is a great resource on the Local Server Framework, a tool which has not seen nearly any publicity since the release of Windows Mobile 6. This webcast shares the necessary information needed to get started  using the Local Server Framework making it very effective.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37149201-6191451983206893117?l=www.rhinomobile.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rhinomobile/~4/K5rtY_ItHhc" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2007-08-19T23:58:47.974-04:00</atom:updated><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.rhinomobile.net/2007/08/webcast-review-testing-most-critical.html</feedburner:origLink></item><item><title>Windows Mobile Native Unit Testing</title><link>http://feedproxy.google.com/~r/Rhinomobile/~3/EGp4gGUasuo/windows-mobile-native-unit-testing.html</link><category>Unit Testing</category><category>C++</category><category>Windows Mobile</category><author>noreply@blogger.com (Ryan O'Neill)</author><pubDate>Tue, 14 Aug 2007 21:40:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-37149201.post-2587504817867214697</guid><description>&lt;p&gt;When applied with discipline and care, unit testing can be a powerful weapon in a software developer's arsenal. It allows a developer to garner feedback on functional correctness as well as refactor an existing codebase with security and confidence. Additional benefits of unit testing can be greater modularity, looser coupling, and an easier ability to measure whether software is meeting functional requirements.&lt;/p&gt;&lt;p&gt;There is a wealth of information on the Internet regarding unit testing and unit testing frameworks, but very few items are Windows Mobile specific. With the .NET Compact Framework, unit testing can currently be done with the &lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=f9176708-9f57-4c0f-97fb-f9c65a9bbf22&amp;amp;displaylang=en"&gt;Mobile Client Software Factory&lt;/a&gt;, released in mid-2006. And with the upcoming release of Visual Studio 2008 and the .NET Compact Framework version 3.5, unit tests are integrated into Visual Studio for managed mobile development.&lt;/p&gt;&lt;p&gt;The managed side is covered pretty well at this point (or will be when Visual Studio 2008 comes out), but what about the native side? What is available for C++ developers on Windows Mobile to use? One answer is CppUnitLite.&lt;/p&gt;&lt;p&gt;CppUnitLite was written by Michael C. Feathers, author of &lt;a href="http://www.amazon.com/gp/product/0131177052?ie=UTF8&amp;amp;tag=rhinomobile-20&amp;amp;linkCode=as2&amp;amp;amp;amp;amp;amp;amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0131177052"&gt;Working Effectively with Legacy Code&lt;/a&gt;. Feathers was also the original author of CppUnit and developed CppUnitLite when he realized that CppUnit could have been "smaller, easier to use, and far more portable if it used some C idioms and only a bare subset of the C++ language." [Feathers p48] &lt;/p&gt;&lt;p&gt;Here are steps to setup CppUnitLite for use with Windows Mobile. &lt;/p&gt;&lt;p&gt;1. &lt;a href="http://www.objectmentor.com/resources/bin/CppUnitLite.zip"&gt;Download CppUnitLite&lt;/a&gt; from the &lt;a href="http://www.objectmentor.com/index.html"&gt;Object Mentor&lt;/a&gt; website.&lt;/p&gt;&lt;p&gt;2. Extract the following files from the om/CppUnitLite section of the zip file:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Failure.h&lt;/li&gt;&lt;li&gt;SimpleString.h&lt;/li&gt;&lt;li&gt;Test.h&lt;/li&gt;&lt;li&gt;TestHarness.h&lt;/li&gt;&lt;li&gt;TestRegistry.h&lt;/li&gt;&lt;li&gt;TestResult.h&lt;/li&gt;&lt;li&gt;Failure.cpp&lt;/li&gt;&lt;li&gt;SimpleString.cpp&lt;/li&gt;&lt;li&gt;Test.cpp&lt;/li&gt;&lt;li&gt;TestRegistry.cpp&lt;/li&gt;&lt;li&gt;TestResult.cpp&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;(In this demo, these&amp;nbsp;files have been extracted to C:\CppUnitLite)&lt;/p&gt;&lt;p&gt;3. Open the Solution which requires unit tests.(In this demo, the solution is named StackExample. This solution contains one project, Stack, which contains two files, Stack.h and Stack.cpp. Image 1 contains a screenshot of the solution loaded in the Solution Explorer. Stack.h is displayed in Code Listing 1. Stack.cpp is displayed in Code Listing 2.)&lt;/p&gt;&lt;p&gt;&lt;u&gt;Image 1&lt;/u&gt; - StackExample solution in Solution Explorer&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_GhRaWNC6A8Q/RsEiDEmr4MI/AAAAAAAAAFs/0pC8fadx6aI/s1600-h/CppUnitLite01.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5098393689331065026" style="cursor: pointer" alt="" src="http://3.bp.blogspot.com/_GhRaWNC6A8Q/RsEiDEmr4MI/AAAAAAAAAFs/0pC8fadx6aI/s320/CppUnitLite01.jpg" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a class="cul1" href="javascript:togglecomments('cul1')"&gt;&lt;u&gt;Code Listing 1&lt;/u&gt; - Stack.h&lt;/a&gt;&lt;/p&gt;&lt;div class="commenthidden" id="cul1"&gt;&lt;pre&gt;#ifndef Stack_h&lt;br /&gt;#define Stack_h&lt;br /&gt;&lt;br /&gt;#if (_MSC_VER &amp;gt; 1000)&lt;br /&gt;#pragma once&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;/*!&lt;br /&gt; * \brief&lt;br /&gt; * This class is a stack which holds integer&lt;br /&gt; * values.&lt;br /&gt; *&lt;br /&gt; * The size of the stack is determined at time&lt;br /&gt; * of construction. A stack uses the last-in&lt;br /&gt; * first-out approach.&lt;br /&gt; */&lt;br /&gt;class Stack&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    Stack(int maxSize);&lt;br /&gt;    virtual ~Stack();&lt;br /&gt;&lt;br /&gt;    bool IsEmpty() const;&lt;br /&gt;    void Push(int item);&lt;br /&gt;    int Pop();&lt;br /&gt;private:&lt;br /&gt;    int* m_items;&lt;br /&gt;    int  m_currentSize;&lt;br /&gt;    int  m_maxSize;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;#endif&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;a class="cul2" href="javascript:togglecomments('cul2')"&gt;&lt;u&gt;Code Listing 2&lt;/u&gt; - Stack.cpp&lt;/a&gt;&lt;/p&gt;&lt;div class="commenthidden" id="cul2"&gt;&lt;pre&gt;#include "Stack.h"&lt;br /&gt;#include &amp;lt;stdexcept&amp;gt;&lt;br /&gt;&lt;br /&gt;using namespace std;&lt;br /&gt;&lt;br /&gt;/*!&lt;br /&gt; * \brief&lt;br /&gt; * This method is the constructor for the Stack class.&lt;br /&gt; *&lt;br /&gt; * \param maxSize&lt;br /&gt; * This parameter is the maximum number of integers&lt;br /&gt; * the stack can hold.&lt;br /&gt; */&lt;br /&gt;Stack::Stack(int maxSize)&lt;br /&gt;{&lt;br /&gt;    m_maxSize = maxSize;&lt;br /&gt;    m_items = new int[maxSize];&lt;br /&gt;    m_currentSize = 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/*!&lt;br /&gt; * \brief&lt;br /&gt; * This method is the destructor for the Stack class.&lt;br /&gt; */&lt;br /&gt;Stack::~Stack()&lt;br /&gt;{&lt;br /&gt;    delete[] m_items;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/*!&lt;br /&gt; * \brief&lt;br /&gt; * This function calculates whether or not the&lt;br /&gt; * stack is currently empty.&lt;br /&gt; *&lt;br /&gt; * \returns&lt;br /&gt; * This function returns true if the stack is&lt;br /&gt; * empty, or false otherwise.&lt;br /&gt; */&lt;br /&gt;bool Stack::IsEmpty() const&lt;br /&gt;{&lt;br /&gt;    return (m_currentSize == 0);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/*!&lt;br /&gt; * \brief&lt;br /&gt; * This function adds an integer value to the stack.&lt;br /&gt; *&lt;br /&gt; * \param item&lt;br /&gt; * This parameter is the integer value to add to the stack.&lt;br /&gt; *&lt;br /&gt; * \throws exception&lt;br /&gt; * This function throws an exception if a value is pushed&lt;br /&gt; * when the stack is already full.&lt;br /&gt; */&lt;br /&gt;void Stack::Push(int item)&lt;br /&gt;{&lt;br /&gt;    if (m_currentSize &amp;gt;= m_maxSize)&lt;br /&gt;    {&lt;br /&gt;        throw exception("Stack is full.");&lt;br /&gt;    }&lt;br /&gt;    else&lt;br /&gt;    {&lt;br /&gt;        m_items[m_currentSize++] = item;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/*!&lt;br /&gt; * \brief&lt;br /&gt; * This function removes an integer value from the stack.&lt;br /&gt; *&lt;br /&gt; * \returns&lt;br /&gt; * This function returns the last integer value added to&lt;br /&gt; * the stack and removes it.&lt;br /&gt; *&lt;br /&gt; * \throws exception&lt;br /&gt; * This function throws an exception if this function is&lt;br /&gt; * called when the stack is empty.&lt;br /&gt; */&lt;br /&gt;int Stack::Pop()&lt;br /&gt;{&lt;br /&gt;    if (IsEmpty())&lt;br /&gt;    {&lt;br /&gt;        throw exception("Stack is empty.");&lt;br /&gt;    }&lt;br /&gt;    else&lt;br /&gt;    {&lt;br /&gt;        return m_items[--m_currentSize];&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;4. Add a new Win32 Smart Device Project to the solution named CppUnitLite and place it in the directory where the CppUnitLite source code was extracted in Step 2.&lt;/p&gt;&lt;p&gt;&lt;u&gt;Image 2&lt;/u&gt; - Add New Project Wizard &lt;/p&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_GhRaWNC6A8Q/RsEngkmr4NI/AAAAAAAAAF0/nACUSaQwyUM/s1600-h/CppUnitLite02.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5098399693695344850" style="cursor: pointer" alt="" src="http://1.bp.blogspot.com/_GhRaWNC6A8Q/RsEngkmr4NI/AAAAAAAAAF0/nACUSaQwyUM/s320/CppUnitLite02.jpg" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;5. Add all Windows Mobile platform SDKs to the new project. &lt;p&gt;&lt;u&gt;Image 3&lt;/u&gt; - Win32 Smart Device Project Wizard (Platform)&lt;/p&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_GhRaWNC6A8Q/RsEp_0mr4OI/AAAAAAAAAF8/tNAes6tXoYI/s1600-h/CppUnitLite03.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5098402429589512418" style="cursor: hand" alt="" src="http://2.bp.blogspot.com/_GhRaWNC6A8Q/RsEp_0mr4OI/AAAAAAAAAF8/tNAes6tXoYI/s320/CppUnitLite03.jpg" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;6. Set the Application type to Static Library and turn off Precompiled header in the Additional options section.&lt;/p&gt;&lt;p&gt;&lt;u&gt;Image 4&lt;/u&gt; - Win32 Smart Device Project Wizard (Application Settings)&lt;/p&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_GhRaWNC6A8Q/RsEr70mr4PI/AAAAAAAAAGE/hVnjfhHsehk/s1600-h/CppUnitLite04.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5098404559893291250" style="cursor: hand" alt="" src="http://2.bp.blogspot.com/_GhRaWNC6A8Q/RsEr70mr4PI/AAAAAAAAAGE/hVnjfhHsehk/s320/CppUnitLite04.jpg" border="0"&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;7.&amp;nbsp;Move the project file and the readme.txt file into the main directory where the CppUnitLite files are stored. The project needs to be removed and readded to the solution within Visual Studio.&lt;/p&gt;&lt;p&gt;&lt;u&gt;Image 5&lt;/u&gt; - Directory listing of CppUnitLite files.&lt;/p&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_GhRaWNC6A8Q/RsEvukmr4QI/AAAAAAAAAGM/f0j7rBtj6lw/s1600-h/CppUnitLite05.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5098408730306535682" style="cursor: hand" alt="" src="http://1.bp.blogspot.com/_GhRaWNC6A8Q/RsEvukmr4QI/AAAAAAAAAGM/f0j7rBtj6lw/s320/CppUnitLite05.jpg" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;8. Using the Add-&amp;gt;Existing Item... mechanism, add the header files (*.h)&amp;nbsp;to the Header files section and add the source files (*.cpp) to the Source files section.&lt;/p&gt;&lt;p&gt;&lt;u&gt;Image 6&lt;/u&gt; - CppUnitLite project with all header and source files added&lt;/p&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_GhRaWNC6A8Q/RsExIkmr4RI/AAAAAAAAAGU/712jhGxczLA/s1600-h/CppUnitLite06.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5098410276494762258" style="cursor: hand" alt="" src="http://1.bp.blogspot.com/_GhRaWNC6A8Q/RsExIkmr4RI/AAAAAAAAAGU/712jhGxczLA/s320/CppUnitLite06.jpg" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;This walkthrough assumes that the code to be tested is in a static library (*.lib). In the example, Stack.h and Stack.cpp are in a static library project named Stack. &lt;/p&gt;&lt;p&gt;9. Add a new project to the solution and name it &lt;em&gt;LibraryName&lt;/em&gt;.Tests. In the example, the project is named Stack.Tests. &lt;/p&gt;&lt;p&gt;10. Right-click on the project and choose properties. In the Common Properties-&amp;gt;References section add the other two projects as references by using the Add New Reference button.&lt;/p&gt;&lt;p&gt;&lt;u&gt;Image 7&lt;/u&gt; - References added to the project properties.&lt;/p&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_GhRaWNC6A8Q/RsJ7c0mr4SI/AAAAAAAAAGc/Nm7V6MjryO0/s1600-h/CppUnitLite07.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5098773463224279330" style="cursor: hand" alt="" src="http://3.bp.blogspot.com/_GhRaWNC6A8Q/RsJ7c0mr4SI/AAAAAAAAAGc/Nm7V6MjryO0/s320/CppUnitLite07.jpg" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;11. In the Configuration Properties-&amp;gt;C/C++-&amp;gt;General section is an option named Additional Include Directories.&amp;nbsp;Add the directories which contain the header files of the classes to be tested as well as the directory which contains the CppUnitLite header files. In the example, these two directories are ..\Stack and C:\CppUnitLite.&lt;/p&gt;&lt;p&gt;&lt;u&gt;Image 8&lt;/u&gt; - Additional Include Directories added to the project properties.&lt;/p&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_GhRaWNC6A8Q/RsJ8u0mr4TI/AAAAAAAAAGk/EH4ZVaweBJ4/s1600-h/CppUnitLite08.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5098774871973552434" style="cursor: hand" alt="" src="http://3.bp.blogspot.com/_GhRaWNC6A8Q/RsJ8u0mr4TI/AAAAAAAAAGk/EH4ZVaweBJ4/s320/CppUnitLite08.jpg" border="0"&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;12. Add a .cpp file with a command line main method for Windows Mobile in it. This file should include TestHarness.h from CppUnitLite. In the main method, create a TestResult variable and pass it into TestRegistry::runAllTests as done in the StackMain.cpp example in Code Listing 3.&lt;/p&gt;&lt;p&gt;&lt;a class="cul3" href="javascript:togglecomments('cul3')"&gt;&lt;u&gt;Code Listing 3&lt;/u&gt; - StackMain.cpp&lt;/a&gt; &lt;/p&gt;&lt;div class="commenthidden" id="cul3"&gt;&lt;pre&gt;#include "TestHarness.h"&lt;br /&gt;#include &amp;lt;windows.h&amp;gt;&lt;br /&gt;&lt;br /&gt;int _tmain(int argc, _TCHAR* argv[])&lt;br /&gt;{&lt;br /&gt;    TestResult tr;&lt;br /&gt;    TestRegistry::runAllTests(tr);&lt;br /&gt;&lt;br /&gt;    return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;13. Add a file named corresponding to the class to be tested. In the example, the Stack class is being tested, so the file is named StackTest.cpp. The code for this file is listed in Code Listing 4.&lt;/p&gt;&lt;p&gt;&lt;a class="cul4" href="javascript:togglecomments('cul4')"&gt;&lt;u&gt;Code Listing 4&lt;/u&gt; - StackTest.cpp&lt;/a&gt; &lt;/p&gt;&lt;div class="commenthidden" id="cul4"&gt;&lt;pre&gt;#include "TestHarness.h"&lt;br /&gt;#include "Stack.h"&lt;br /&gt;#include &amp;lt;string&amp;gt;&lt;br /&gt;&lt;br /&gt;TEST( MultiPushPop, Stack )&lt;br /&gt;{&lt;br /&gt;    Stack s(10);&lt;br /&gt;    s.Push(14); &lt;br /&gt;    LONGS_EQUAL(14, s.Pop());&lt;br /&gt;    s.Push(12);&lt;br /&gt;    s.Push(18);&lt;br /&gt;    s.Push(27); &lt;br /&gt;    LONGS_EQUAL(27, s.Pop());&lt;br /&gt;    s.Push(38);&lt;br /&gt;    s.Push(2);&lt;br /&gt;    s.Push(12);&lt;br /&gt;    LONGS_EQUAL(12, s.Pop());&lt;br /&gt;    LONGS_EQUAL( 2, s.Pop());&lt;br /&gt;    LONGS_EQUAL(38, s.Pop());&lt;br /&gt;    LONGS_EQUAL(18, s.Pop());&lt;br /&gt;    LONGS_EQUAL(12, s.Pop());&lt;br /&gt;    CHECK(s.IsEmpty());&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;TEST( PushExceedsMax, Stack )&lt;br /&gt;{&lt;br /&gt;    Stack s(5);&lt;br /&gt;    s.Push(1);&lt;br /&gt;    s.Push(2);&lt;br /&gt;    s.Push(3);&lt;br /&gt;    s.Push(4);&lt;br /&gt;    s.Push(5);&lt;br /&gt;    try&lt;br /&gt;    {&lt;br /&gt;        s.Push(6);&lt;br /&gt;        FAIL("Push should have exceeded max stack size");&lt;br /&gt;    }&lt;br /&gt;    catch (std::exception ex)&lt;br /&gt;    {&lt;br /&gt;        // Expected behavior&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;TEST( PushPop, Stack )&lt;br /&gt;{&lt;br /&gt;    Stack s(10);&lt;br /&gt;    s.Push(27000);&lt;br /&gt;    CHECK(!s.IsEmpty());&lt;br /&gt;    int value = s.Pop();&lt;br /&gt;    LONGS_EQUAL(27000, value);&lt;br /&gt;    CHECK(s.IsEmpty());&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;TEST( PopEmpty, Stack )&lt;br /&gt;{&lt;br /&gt;    Stack s(10);&lt;br /&gt;    try&lt;br /&gt;    {&lt;br /&gt;        // This test should throw an exception&lt;br /&gt;        int value = s.Pop();&lt;br /&gt;        FAIL("Popping an empty stack should throw an exception");&lt;br /&gt;    }&lt;br /&gt;    catch (std::exception ex)&lt;br /&gt;    {&lt;br /&gt;        // Expected behavior&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;TEST( IsEmpty, Stack )&lt;br /&gt;{&lt;br /&gt;    Stack s(10);&lt;br /&gt;    CHECK(s.IsEmpty());&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;TEST( Creation, Stack )&lt;br /&gt;{&lt;br /&gt;    Stack s(10);&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;13. Set the .Tests project (Stack.Tests) as the startup project by right-clicking on the project and choosing Set as Startup Project.&lt;/p&gt;&lt;p&gt;14. Build all the projects.&lt;/p&gt;&lt;p&gt;15. Make sure to choose the same emulator or device for all three projects otherwise multiple emulator windows may pop up.&lt;/p&gt;&lt;p&gt;16. Run the project. Hopefully, a message stating "There were no test failures" is then displayed in the Output window as shown in Image 9.&lt;/p&gt;&lt;p&gt;&lt;u&gt;Image 9&lt;/u&gt; - Successful Test Run&lt;/p&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_GhRaWNC6A8Q/RsKBE0mr4UI/AAAAAAAAAGs/3PvyKRPi71g/s1600-h/CppUnitLite09.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5098779647977185602" style="cursor: hand" alt="" src="http://3.bp.blogspot.com/_GhRaWNC6A8Q/RsKBE0mr4UI/AAAAAAAAAGs/3PvyKRPi71g/s320/CppUnitLite09.jpg" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Aside from the examples that come with CppUnitLite, there are additional examples within &lt;a href="http://www.amazon.com/gp/product/0131177052?ie=UTF8&amp;amp;tag=rhinomobile-20&amp;amp;linkCode=as2&amp;amp;amp;amp;amp;amp;amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0131177052"&gt;Working Effectively with Legacy Code&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37149201-2587504817867214697?l=www.rhinomobile.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rhinomobile/~4/EGp4gGUasuo" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2008-12-10T05:46:56.555-05:00</atom:updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_GhRaWNC6A8Q/RsEiDEmr4MI/AAAAAAAAAFs/0pC8fadx6aI/s72-c/CppUnitLite01.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">7</thr:total><feedburner:origLink>http://www.rhinomobile.net/2007/08/windows-mobile-native-unit-testing.html</feedburner:origLink></item><item><title>Webcast Review: Building High-Performance Applications Using the .NET Compact Framework</title><link>http://feedproxy.google.com/~r/Rhinomobile/~3/-fja5uNSE3o/webcast-review-building-high.html</link><category>MSDN Webcast</category><category>.NET Compact Framework</category><author>noreply@blogger.com (Ryan O'Neill)</author><pubDate>Thu, 09 Aug 2007 20:07:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-37149201.post-9177140742607229299</guid><description>On August 8th, 2007, the Microsoft .NET Compact Framework team's lead software developer, Steven Pratschner, conducted an extremely informative MSDN webcast entitled &lt;a href="http://msevents.microsoft.com/cui/WebCastEventDetails.aspx?culture=en-US&amp;EventID=1032345908&amp;amp;CountryCode=US"&gt;"Building High-Performance Applications Using the .NET Compact Framework"&lt;/a&gt;. For people unfamiliar with &lt;a href="http://blogs.msdn.com/stevenpr/"&gt;Steven's blog&lt;/a&gt;, performance is a topic which he has covered quite extensively there. This webcast included discussion of a wide array of topics ranging from performance comparisons with native code to the implementation of the .NET CF garbage collector.&lt;br /&gt;There are many notable highlights in this 71 minute webcast including the following subjects:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A comparison of method calls on performance:&lt;br /&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Managed Method calls are 2.3x the cost of a native call&lt;/li&gt;&lt;li&gt;Virtual Method calls are 1.5x the cost of a method instance call&lt;/li&gt;&lt;li&gt;P/Invoke Method calls are 5x the cost of a managed instance call&lt;/li&gt;&lt;li&gt;(Unfortunately though it did not discuss the performance of static methods versus instance methods nor the use of interfaces)&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;The effect of boxing on performance demonstrated through the use of a simple demo game containing a grid of blocks being rotated.&lt;/li&gt;&lt;li&gt;How to use the .NET CF Remote Performance Monitor to look at metrics including the total number of garbage collections, memory usage, and objects allocated.&lt;/li&gt;&lt;li&gt;How to use the new CLR Profiler, which will be included in version 3.5 of the .NET Compact Framework. This provided detailed information to the level of showing which methods within the demo application were causing a high percentage of object allocations.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Why it is better to use an indexer or custom iterator over a foreach statement&lt;/li&gt;&lt;/ul&gt;Early in the session, Steven mentions how code is just-in-time compiled or jitted, on a per method basis. How code is jitted is important when testing the performance of methods. Steven reveals an extremely useful approach. He says to run the method once so that it gets jitted. Then, call the method again this time measuring for performance. Following these steps gives the true runtime of the method as opposed to the jit time and runtime combined.&lt;br /&gt;&lt;br /&gt;Other fascinating topics are discussed including collections, reducing application startup times and reflection. This is definitely a webcast that developers working on enterprise level line of business applications using the .NET CF should watch.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37149201-9177140742607229299?l=www.rhinomobile.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rhinomobile/~4/-fja5uNSE3o" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2007-08-19T23:58:08.410-04:00</atom:updated><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.rhinomobile.net/2007/08/webcast-review-building-high.html</feedburner:origLink></item><item><title>iPhone Business Usage</title><link>http://feedproxy.google.com/~r/Rhinomobile/~3/kg2-2QIJZBk/iphone-business-usage.html</link><category>iPhone</category><author>noreply@blogger.com (Ryan O'Neill)</author><pubDate>Wed, 25 Jul 2007 07:00:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-37149201.post-8188062704756906566</guid><description>&lt;a href="http://www.crn.com/"&gt;CRN&lt;/a&gt; (Channel Reseller News) and &lt;a href="http://www.crn.com/crntech/"&gt;CRN Tech&lt;/a&gt; have recently had two commentaries regarding the business practicality of Apple's iPhone. First was Frank J. Ohlhorst's &lt;a href="http://www.crn.com/hardware/201200135"&gt;The iPhone Has No Business In Business&lt;/a&gt; where Ohlhorst compares the Apple iPhone hype to that of Windows 95 and deems the iPhone as inferior to BlackBerry, Treo, Windows Mobile and Symbian devices for business use. Ed Moltzen then posted a follow up blog entry entitled &lt;a href="http://www.crn.com/networking/201200472?cid=CRNFeed"&gt;A Pro-Business Argument For The iPhone&lt;/a&gt; where he says the following:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;The iPhone has pretty darn good push email functionality (if you can sync your Yahoo, AOL, Gmail, or .Mac email to the device.) You can also set up POP mail or Exchange (if IMAP support is set up on the Exchange Server.) For those who can access Lotus Notes via webmail, you can do that on the iPhone's Safari browser although sending email or performing other Notes functions can be mind-bendingly difficult. (But if you can auto-forward Notes email to another account, like Yahoo, that works fine.) The bottom line for email on the iPhone: for most people it will work well.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Two things are bothersome with the above statements. &lt;br /&gt;&lt;br /&gt;One, saying that the iPhone works with Exchange and then throwing in a caveat in parentheses is misleading. Unfortunately, respected technology journalist Walt Mossberg falls into the same trap in his &lt;a href="http://solution.allthingsd.com/20070626/the-iphone-is-breakthrough-handheld-computer/"&gt;iPhone review&lt;/a&gt;, "It can also handle corporate email using Microsoft’s Exchange system, if your IT department cooperates by enabling a setting on the server." Saying the iPhone works with Exchange as long as a system administrator flips a setting is like saying that John is a millionaire (as long as he buys the winning lottery ticket). Unless someone with a 'C' as the first letter in her title (CEO, CFO, CIO, CTO) is carrying the iPhone, don't expect that setting to get flipped. Additionally, the Microsoft Exchange Team has posted their own &lt;a href="http://msexchangeteam.com/archive/2007/07/10/446015.aspx"&gt;rebuttal&lt;/a&gt; to Walt Mossberg's statement.&lt;br /&gt;&lt;br /&gt;Two, even suggesting that iPhone users auto-forward their email to another service is absolutely ludicrous. Not only does it go against almost all business security policies, but in some cases forwarding email in that manner can open a company up to liability as well. Also, how would clients react to finding out that their email sent to john.smith@xyzcompany.com is passing through (or residing on) Yahoo's, Google's, or AOL's email servers? Definitely not positively. Of course it still happens where people do this, but to suggest it as standard operating procedure is irresponsible. &lt;br /&gt;&lt;br /&gt;Regardless of whether the iPhone becomes a staple of business use or not, the attention that this topic receives is good for the industry as a whole. As Ohlhorst points out, "[b]ut the hype does have benefits for the channel—namely, the resurgence of interest in mobile applications and business communications devices." Reminds one of the old saying -- "There is no such thing as bad publicity".&lt;br /&gt;&lt;br /&gt;(Special thanks to &lt;a href="http://nino.net/blogs/"&gt;Nino Benvenuti&lt;/a&gt; for editing this entry.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37149201-8188062704756906566?l=www.rhinomobile.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rhinomobile/~4/kg2-2QIJZBk" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2007-08-19T23:57:29.126-04:00</atom:updated><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.rhinomobile.net/2007/07/iphone-business-usage.html</feedburner:origLink></item><item><title>AUTDv1 Text Messaging Impact</title><link>http://feedproxy.google.com/~r/Rhinomobile/~3/tp53h6g7w14/autdv1-text-messaging-impact.html</link><category>Sprint</category><category>Windows Mobile</category><author>noreply@blogger.com (Ryan O'Neill)</author><pubDate>Tue, 24 Jul 2007 06:30:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-37149201.post-5745432030265193528</guid><description>With Exchange 2003 and Windows Mobile 2003, Microsoft attempted to mitigate the wide-spread usage of RIM BlackBerry's push email service with a technology named Always Up-To-Date, or AUTD. This first version of AUTD worked by sending an SMS control message to the Windows Mobile 2003 phone whenever an event occurred within Exchange which modified a folder marked for synchronization. The Windows Mobile 2003 phone would then download the updates from Exchange.&lt;br /&gt;&lt;br /&gt;For more background information, see &lt;a href="http://www.microsoft.com/technet/prodtechnol/exchange/2003/autd.mspx#EIC"&gt;Microsoft Technet: How to Configure Always Up-To-Date Notifications&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Image1 shows a chart detailing my text message usage from August 2005 through July 2007. It is fairly obvious the period where my usage of AUTDv1 starts and ends. &lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image1&lt;/u&gt; - Text Message Usage Per Month&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_GhRaWNC6A8Q/RqYBc0mr4LI/AAAAAAAAAFk/fo38sFCv5yw/s1600-h/TextMessaging.JPG"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_GhRaWNC6A8Q/RqYBc0mr4LI/AAAAAAAAAFk/fo38sFCv5yw/s320/TextMessaging.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5090758023457792178" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37149201-5745432030265193528?l=www.rhinomobile.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rhinomobile/~4/tp53h6g7w14" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2008-12-10T05:46:56.873-05:00</atom:updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_GhRaWNC6A8Q/RqYBc0mr4LI/AAAAAAAAAFk/fo38sFCv5yw/s72-c/TextMessaging.JPG" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.rhinomobile.net/2007/07/autdv1-text-messaging-impact.html</feedburner:origLink></item><item><title>.NET CF Custom Control: RoundedGroupBox</title><link>http://feedproxy.google.com/~r/Rhinomobile/~3/RSuDg1PjDn4/net-cf-custom-control-roundedgroupbox.html</link><category>Visual Studio</category><category>.NET Compact Framework</category><category>Windows Mobile</category><author>noreply@blogger.com (Ryan O'Neill)</author><pubDate>Wed, 02 May 2007 11:00:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-37149201.post-4639176996716849104</guid><description>The .NET Compact Framework provides an excellent abstracted interface to the Graphics Device Interface (GDI) subsystem in the same manner as the full .NET Framework. However, there are still quite a few drawing methods which are not part of the CF which if included would make the design of custom controls easier (and sometimes more fun). One of the methods missing from the Compact Framework is the &lt;a href="http://msdn2.microsoft.com/en-us/library/aa929212.aspx"&gt;RoundRect GDI function&lt;/a&gt;. According to MSDN, "This function draws a rectangle with rounded corners. The current pen outlines the rectangle and the current brush fills it." &lt;br /&gt;&lt;br /&gt;In this entry, the RoundRect function is used to create a new custom control called a RoundedGroupBox. The standard GroupBox control exists on the full framework and provides a panel with a rounded outline and a title. It logically groups controls into a designated area of the screen. An image of the GroupBox from the full framework is displayed in Image 1. The Compact Framework does not contain a GroupBox control, so this custom control, RoundedGroupBox, serves as a stand-in with a little more flare.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 1&lt;/u&gt; - GroupBox from the full .NET framework&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_GhRaWNC6A8Q/Rjiesee5L_I/AAAAAAAAAFU/Fbie2XKQn0g/s1600-h/DesktopGroupBox.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_GhRaWNC6A8Q/Rjiesee5L_I/AAAAAAAAAFU/Fbie2XKQn0g/s320/DesktopGroupBox.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5059968668284825586" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;To create the RoundedGroupBox using C# and the .NET Compact Framework, aside from the RoundRect GDI function, there are three other GDI functions which need to be P/Invoked:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://msdn2.microsoft.com/en-us/library/ms959979.aspx"&gt;CreateSolidBrush&lt;/a&gt; - This function is used to create colored brushes used to fill in the round rectangles.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://msdn2.microsoft.com/en-us/library/aa932923.aspx"&gt;SelectObject&lt;/a&gt; - This function is used to select a brush to use when drawing.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://msdn2.microsoft.com/en-us/library/aa923962.aspx"&gt;DeleteObject&lt;/a&gt; - This function deletes a drawing object and frees its associated memory.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;A fourth function, &lt;a href="http://msdn2.microsoft.com/en-us/library/aa921556.aspx"&gt;GetStockObject&lt;/a&gt; is also contained within the source code but not used within this example. GDI contains some predefined pens, brushes and fonts. This function can retrieve any of those.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;One very important point when P/Invoking these functions is that they need to be accessed at both design time and runtime. On Windows Mobile, these functions are all found in the coredll native assembly. Trying to use that assembly during design time is not going to work however, because Visual Studio will try to access a coredll.dll file on the local desktop. To work in the designer on the desktop, these functions  need to be accessed in the gdi32 assembly found in the \Windows\System32 folder. A simple wrapper function has been written that checks the current environment and decides which version of the function to use -- gdi32 on the desktop and coredll on Windows Mobile. The source code for accessing these functions is listed in Code Listing 1. Image 2 shows the RoundedGroupBox control displayed in the Visual Studio designer.&lt;br /&gt;&lt;br /&gt;&lt;a class="rgb1" href="javascript:togglecomments('rgb1')"&gt;&lt;u&gt;Code Listing 1&lt;/u&gt; - NativeMethods.cs&lt;/a&gt;&lt;br /&gt;&lt;div class="commenthidden" id="rgb1"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#region Using Directives&lt;br /&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Runtime.InteropServices;&lt;br /&gt;using System.Text;&lt;br /&gt;&lt;br /&gt;#endregion&lt;br /&gt;&lt;br /&gt;namespace Rhinomobile.ControlLibrary&lt;br /&gt;{&lt;br /&gt;    /// &amp;lt;summary&amp;gt;&lt;br /&gt;    /// Platform Invocation Methods&lt;br /&gt;    /// &amp;lt;/summary&amp;gt;&lt;br /&gt;    class NativeMethods&lt;br /&gt;    {&lt;br /&gt;        #region Windows CE Methods&lt;br /&gt;&lt;br /&gt;        [DllImport("coredll", EntryPoint = "RoundRect")]&lt;br /&gt;        private static extern bool RoundRectCE(IntPtr hdc, int nLeftRect, int nTopRect, &lt;br /&gt;            int nRightRect, int nBottomRect, int nWidth, int nHeight);&lt;br /&gt;&lt;br /&gt;        [DllImport("coredll", EntryPoint = "CreateSolidBrush")]&lt;br /&gt;        private static extern IntPtr CreateSolidBrushCE(int crColor);&lt;br /&gt;&lt;br /&gt;        [DllImport("coredll", EntryPoint = "SelectObject")]&lt;br /&gt;        private static extern IntPtr SelectObjectCE(IntPtr hdc, IntPtr hgdiobj);&lt;br /&gt;&lt;br /&gt;        [DllImport("coredll", EntryPoint = "DeleteObject")]&lt;br /&gt;        private static extern bool DeleteObjectCE(IntPtr hObject);&lt;br /&gt;&lt;br /&gt;        [DllImport("coredll", EntryPoint = "GetStockObject")]&lt;br /&gt;        private static extern IntPtr GetStockObjectCE(int fnObject);&lt;br /&gt;&lt;br /&gt;        #endregion&lt;br /&gt;&lt;br /&gt;        #region Windows Methods&lt;br /&gt;&lt;br /&gt;        [DllImport("gdi32", EntryPoint = "RoundRect")]&lt;br /&gt;        private static extern bool RoundRectWin(IntPtr hdc, int nLeftRect, int nTopRect, &lt;br /&gt;            int nRightRect, int nBottomRect, int nWidth, int nHeight);&lt;br /&gt;&lt;br /&gt;        [DllImport("gdi32", EntryPoint = "CreateSolidBrush")]&lt;br /&gt;        private static extern IntPtr CreateSolidBrushWin(int crColor);&lt;br /&gt;&lt;br /&gt;        [DllImport("gdi32", EntryPoint = "SelectObject")]&lt;br /&gt;        private static extern IntPtr SelectObjectWin(IntPtr hdc, IntPtr hgdiobj);&lt;br /&gt;&lt;br /&gt;        [DllImport("gdi32", EntryPoint = "DeleteObject")]&lt;br /&gt;        private static extern bool DeleteObjectWin(IntPtr hObject);&lt;br /&gt;&lt;br /&gt;        [DllImport("gdi32", EntryPoint = "GetStockObject")]&lt;br /&gt;        private static extern IntPtr GetStockObjectWin(int fnObject);&lt;br /&gt;&lt;br /&gt;        #endregion&lt;br /&gt;&lt;br /&gt;        #region Platform Agnostic Methods&lt;br /&gt;&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// This function draws a rectangle with rounded corners. The current pen outlines the &lt;br /&gt;        /// rectangle and the current brush fills it.&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        /// &amp;lt;param name="hdc"&amp;gt;Handle to the device context.&amp;lt;/param&amp;gt;&lt;br /&gt;        /// &amp;lt;param name="nLeftRect"&amp;gt;Specifies the x-coordinate of the upper left corner of &lt;br /&gt;        /// the rectangle.&amp;lt;/param&amp;gt;&lt;br /&gt;        /// &amp;lt;param name="nTopRect"&amp;gt;Specifies the y-coordinate of the upper left corner of &lt;br /&gt;        /// the rectangle.&amp;lt;/param&amp;gt;&lt;br /&gt;        /// &amp;lt;param name="nRightRect"&amp;gt;Specifies the x-coordinate of the lower right corner &lt;br /&gt;        /// of the rectangle.&amp;lt;/param&amp;gt;&lt;br /&gt;        /// &amp;lt;param name="nBottomRect"&amp;gt;Specifies the y-coordinate of the lower right corner&lt;br /&gt;        /// of the rectangle.&amp;lt;/param&amp;gt;&lt;br /&gt;        /// &amp;lt;param name="nWidth"&amp;gt;Specifies the width of the ellipse used to draw the &lt;br /&gt;        /// rounded corners.&amp;lt;/param&amp;gt;&lt;br /&gt;        /// &amp;lt;param name="nHeight"&amp;gt;Specifies the height of the ellipese used to draw the &lt;br /&gt;        /// rounded corners.&amp;lt;/param&amp;gt;&lt;br /&gt;        /// &amp;lt;returns&amp;gt;&lt;br /&gt;        /// Nonzero indicates success. Zero indicates failure. To get extended &lt;br /&gt;        /// error information, call GetLastError.&lt;br /&gt;        /// &amp;lt;/returns&amp;gt;&lt;br /&gt;        internal static bool RoundRect(IntPtr hdc, int nLeftRect, int nTopRect,&lt;br /&gt;     int nRightRect, int nBottomRect, int nWidth, int nHeight)&lt;br /&gt;        {&lt;br /&gt;            bool result = false;&lt;br /&gt;            if (Environment.OSVersion.Platform == PlatformID.WinCE)&lt;br /&gt;            {&lt;br /&gt;                result = RoundRectCE(hdc, nLeftRect, nTopRect, nRightRect, &lt;br /&gt;                    nBottomRect, nWidth, nHeight);&lt;br /&gt;            }&lt;br /&gt;            else&lt;br /&gt;            {&lt;br /&gt;                result = RoundRectWin(hdc, nLeftRect, nTopRect, nRightRect, &lt;br /&gt;                    nBottomRect, nWidth, nHeight);&lt;br /&gt;            }&lt;br /&gt;            return result;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// This function creates a logical brush that has the specified solid color.&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        /// &amp;lt;param name="crColor"&amp;gt;Specifies the color of the brush.&amp;lt;/param&amp;gt;&lt;br /&gt;        /// &amp;lt;returns&amp;gt;&lt;br /&gt;        /// A handle that identifies a logical brush indicates success. NULL &lt;br /&gt;        /// indicates failure. To get extended error information, call GetLastError.&lt;br /&gt;        /// &amp;lt;/returns&amp;gt;&lt;br /&gt;        internal static IntPtr CreateSolidBrush(int crColor)&lt;br /&gt;        {&lt;br /&gt;            IntPtr result = IntPtr.Zero;&lt;br /&gt;            if (Environment.OSVersion.Platform == PlatformID.WinCE)&lt;br /&gt;            {&lt;br /&gt;                result = CreateSolidBrushCE(crColor);&lt;br /&gt;            }&lt;br /&gt;            else&lt;br /&gt;            {&lt;br /&gt;                result = CreateSolidBrushWin(crColor);&lt;br /&gt;            }&lt;br /&gt;            return result;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// This function selects an object into a specified device context. The new object &lt;br /&gt;        /// replaces the previous object of the same type.&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        /// &amp;lt;param name="hdc"&amp;gt;Handle to the device context.&amp;lt;/param&amp;gt;&lt;br /&gt;        /// &amp;lt;param name="hgdiobj"&amp;gt;Handle to the object to be selected.&amp;lt;/param&amp;gt;&lt;br /&gt;        /// &amp;lt;returns&amp;gt;&lt;br /&gt;        /// If the selected object is not a region, the handle of the object being &lt;br /&gt;        /// replaced indicates success.&lt;br /&gt;        /// &amp;lt;/returns&amp;gt;&lt;br /&gt;        internal static IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj)&lt;br /&gt;        {&lt;br /&gt;            IntPtr result = IntPtr.Zero;&lt;br /&gt;            if (Environment.OSVersion.Platform == PlatformID.WinCE)&lt;br /&gt;            {&lt;br /&gt;                result = SelectObjectCE(hdc, hgdiobj);&lt;br /&gt;            }&lt;br /&gt;            else&lt;br /&gt;            {&lt;br /&gt;                result = SelectObjectWin(hdc, hgdiobj);&lt;br /&gt;            }&lt;br /&gt;            return result;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// This function deletes a logical pen, brush, font, bitmap, region, or palette, &lt;br /&gt;        /// freeing all system resources associated with the object. After the object is &lt;br /&gt;        /// deleted, the specified handle is no longer valid.&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        /// &amp;lt;param name="hObject"&amp;gt;Handle to a logical pen, brush, font, bitmap, region, &lt;br /&gt;        /// or palette.&amp;lt;/param&amp;gt;&lt;br /&gt;        /// &amp;lt;returns&amp;gt;Nonzero indicates success.&amp;lt;/returns&amp;gt;&lt;br /&gt;        internal static bool DeleteObject(IntPtr hObject)&lt;br /&gt;        {&lt;br /&gt;            bool result = false;&lt;br /&gt;            if (Environment.OSVersion.Platform == PlatformID.WinCE)&lt;br /&gt;            {&lt;br /&gt;                result = DeleteObjectCE(hObject);&lt;br /&gt;            }&lt;br /&gt;            else&lt;br /&gt;            {&lt;br /&gt;                result = DeleteObjectWin(hObject);&lt;br /&gt;            }&lt;br /&gt;            return result;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// This function retrieves a handle to one of the predefined stock pens, &lt;br /&gt;        /// brushes or fonts.&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        /// &amp;lt;param name="fnObject"&amp;gt;Specifies the type of stock object.&amp;lt;/param&amp;gt;&lt;br /&gt;        /// &amp;lt;returns&amp;gt;If the function succeeds, the return value identifies the &lt;br /&gt;        /// logical object requested.&amp;lt;/returns&amp;gt;&lt;br /&gt;        internal static IntPtr GetStockObject(int fnObject)&lt;br /&gt;        {&lt;br /&gt;            IntPtr result = IntPtr.Zero;&lt;br /&gt;            if (Environment.OSVersion.Platform == PlatformID.WinCE)&lt;br /&gt;            {&lt;br /&gt;                result = GetStockObjectCE(fnObject);&lt;br /&gt;            }&lt;br /&gt;            else&lt;br /&gt;            {&lt;br /&gt;                result = GetStockObjectWin(fnObject);&lt;br /&gt;            }&lt;br /&gt;            return result;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        #endregion&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 2&lt;/u&gt; - RoundedGroupBox control displayed in the designer&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_GhRaWNC6A8Q/RjiZaee5L8I/AAAAAAAAAE8/2IA5GmCSb-A/s1600-h/RoundedGroupBox1.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_GhRaWNC6A8Q/RjiZaee5L8I/AAAAAAAAAE8/2IA5GmCSb-A/s320/RoundedGroupBox1.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5059962861489041346" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;By default, when a P/Invoke call is made inside a .NET CF custom control, the Visual Studio designer will not attempt to draw the control properly because it believes it cannot. The attribute which controls whether Visual Studio will attempt to draw the control or not is the DesktopCompatible attribute which is placed in the DesignTimeAttributes.xmta xml file. Code Listing 2 shows the DesignTimeAttributes.xmta file. Image 3 displays two versions of the control - one with the DesktopCompatible attribute set to true in the xmta file and the other without it.&lt;br /&gt;&lt;br /&gt;&lt;a class="rgb2" href="javascript:togglecomments('rgb2')"&gt;&lt;u&gt;Code Listing 2&lt;/u&gt; - DesignTimeAttributes.xmta&lt;/a&gt;&lt;br /&gt;&lt;div class="commenthidden" id="rgb2"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="utf-16"?&amp;gt;&lt;br /&gt;&amp;lt;Classes xmlns="http://schemas.microsoft.com/VisualStudio/2004/03/SmartDevices/XMTA.xsd"&amp;gt;&lt;br /&gt;  &amp;lt;Class Name="Rhinomobile.ControlLibrary.BorderPanel"&amp;gt;&lt;br /&gt;    &amp;lt;DesktopCompatible&amp;gt;true&amp;lt;/DesktopCompatible&amp;gt;&lt;br /&gt;    &amp;lt;Property Name="BorderColor"&amp;gt;&lt;br /&gt;      &amp;lt;Category&amp;gt;Appearance&amp;lt;/Category&amp;gt;&lt;br /&gt;      &amp;lt;Description&amp;gt;The color used to draw the border of the panel.&amp;lt;/Description&amp;gt;&lt;br /&gt;    &amp;lt;/Property&amp;gt;&lt;br /&gt;    &amp;lt;Property Name="BorderWidth"&amp;gt;&lt;br /&gt;      &amp;lt;Category&amp;gt;Layout&amp;lt;/Category&amp;gt;&lt;br /&gt;      &amp;lt;Description&amp;gt;The width of the panel border.&amp;lt;/Description&amp;gt;&lt;br /&gt;    &amp;lt;/Property&amp;gt;&lt;br /&gt;  &amp;lt;/Class&amp;gt;&lt;br /&gt;  &amp;lt;Class Name="Rhinomobile.ControlLibrary.RoundedGroupBox"&amp;gt;&lt;br /&gt;    &amp;lt;DesktopCompatible&amp;gt;true&amp;lt;/DesktopCompatible&amp;gt;&lt;br /&gt;    &amp;lt;Property Name="OuterColor"&amp;gt;&lt;br /&gt;      &amp;lt;Category&amp;gt;Appearance&amp;lt;/Category&amp;gt;&lt;br /&gt;      &amp;lt;Description&amp;gt;The color user to fill the background of the title of the rounded group box.&amp;lt;/Description&amp;gt;&lt;br /&gt;    &amp;lt;/Property&amp;gt;&lt;br /&gt;    &amp;lt;Property Name="RoundedGroupBoxText"&amp;gt;&lt;br /&gt;      &amp;lt;Category&amp;gt;Appearance&amp;lt;/Category&amp;gt;&lt;br /&gt;      &amp;lt;Description&amp;gt;The text displayed in the title of the group box panel.&amp;lt;/Description&amp;gt;&lt;br /&gt;    &amp;lt;/Property&amp;gt;&lt;br /&gt;  &amp;lt;/Class&amp;gt;&lt;br /&gt;&amp;lt;/Classes&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 3&lt;/u&gt; - Two versions of RoundedGroupBox displayed - One with the DesktopCompatible attribute set to true in the DesignTimeAttributes.xmta file, the other without&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_GhRaWNC6A8Q/RjiZjOe5L-I/AAAAAAAAAFM/YQhRyXONS90/s1600-h/RoundedGroupBox3.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_GhRaWNC6A8Q/RjiZjOe5L-I/AAAAAAAAAFM/YQhRyXONS90/s320/RoundedGroupBox3.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5059963011812896738" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The RoundedGroupBox control itself is comprised of two round rectangles drawn with different colored brushes. The top is slightly offset on the inner polygon which leaves an area for the title to be written. This control is derived from a standard .NET Compact Framework System.Windows.Forms.Panel, so out of the box it provides the logical grouping functionality inherent in a panel. &lt;br /&gt;&lt;br /&gt;RoundedGroupBox provides two additional properties, OuterColor and RoundedGroupBoxText. OuterColor is the color used for the title area and the outline. The standard BackColor property is used for the area where controls are placed. RoundedGroupBoxText is a property which contains the text displayed in the title area.&lt;br /&gt;&lt;br /&gt;RoundedGroupBox also overrides two inherited methods, OnPaintBackground and OnPaint. In OnPaintBackground, the background color of the parent control is used to fill the RoundedGroupBox control. Doing this fills in the gaps left by the rounded corners of the control so that seemingly the parent control is showing through. OnPaint is more complicated and a snippet of code is displayed inline below.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;        protected override void OnPaint(PaintEventArgs e)&lt;br /&gt;        {&lt;br /&gt;            int outerBrushColor = HelperMethods.ColorToWin32(m_outerColor);&lt;br /&gt;            int innerBrushColor = HelperMethods.ColorToWin32(this.BackColor);&lt;br /&gt;&lt;br /&gt;            IntPtr hdc = e.Graphics.GetHdc();&lt;br /&gt;            try&lt;br /&gt;            {&lt;br /&gt;                IntPtr hbrOuter = NativeMethods.CreateSolidBrush(outerBrushColor);&lt;br /&gt;                IntPtr hOldBrush = NativeMethods.SelectObject(hdc, hbrOuter);&lt;br /&gt;                NativeMethods.RoundRect(hdc, 0, 0, this.Width, this.Height, DIAMETER, DIAMETER);&lt;br /&gt;                IntPtr hbrInner = NativeMethods.CreateSolidBrush(innerBrushColor);&lt;br /&gt;                NativeMethods.SelectObject(hdc, hbrInner);&lt;br /&gt;                NativeMethods.RoundRect(hdc, 0, 18, this.Width, this.Height, DIAMETER, DIAMETER);&lt;br /&gt;                NativeMethods.SelectObject(hdc, hOldBrush);&lt;br /&gt;                NativeMethods.DeleteObject(hbrOuter);&lt;br /&gt;                NativeMethods.DeleteObject(hbrInner);&lt;br /&gt;            }&lt;br /&gt;            finally&lt;br /&gt;            {&lt;br /&gt;                e.Graphics.ReleaseHdc(hdc);&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            if (!string.IsNullOrEmpty(m_roundedGroupBoxText))&lt;br /&gt;            {&lt;br /&gt;                Font titleFont = new Font("Tahoma", 9.0F, FontStyle.Bold);&lt;br /&gt;                Brush titleBrush = new SolidBrush(this.BackColor);&lt;br /&gt;                try&lt;br /&gt;                {&lt;br /&gt;                    e.Graphics.DrawString(m_roundedGroupBoxText, titleFont, titleBrush, 14.0F, 2.0F);&lt;br /&gt;                }&lt;br /&gt;                finally&lt;br /&gt;                {&lt;br /&gt;                    titleFont.Dispose();&lt;br /&gt;                    titleBrush.Dispose();&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            base.OnPaint(e);&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The first two function calls are to the ColorToWin32 method. This method converts a System.Drawing.Color value into an integer used with Windows 32 functions. It is contained in the HelperMethods class. This class can be found in Code Listing 3.&lt;br /&gt;&lt;br /&gt;Following the color conversions, a &lt;i&gt;h&lt;/i&gt;andle to the underlying GDI &lt;i&gt;d&lt;/i&gt;evice &lt;i&gt;c&lt;/i&gt;ontext is  retrieved using the GetHdc method. A solid brush of the outer color is then created using CreateSolidBrush. This brush is then selected using the SelectObject function. This is analagous to selecting a type of brush within a graphics program when drawing shapes. A handle to the previously selected brush is saved so that it can be the selected brush again when the control is finished drawing. The outer round rectangle is drawn with a call to the RoundRect function. The same steps are repeated for the inner round rectangle: creation, selection, and drawing. Both the outer and inner round rectangles are drawn using a constant value for nWidth and nHeight giving the control a circular corner. When both round rectangles have been drawn, the previously selected brush is set as the selected brush again. The two created brushes are then deleted. Finally, the handle to the device context is released. The remaining part of the OnPaint method is responsible for writing the title text in the space between the two round rectangles. The source code for RoundedGroupBox.cs is found in Code Listing 4. Image 4 shows a screenshot of a sample application which uses the RoundedGroupBox control to ask a question where a singular answer can be chosen.&lt;br /&gt;&lt;br /&gt;&lt;a class="rgb3" href="javascript:togglecomments('rgb3')"&gt;&lt;u&gt;Code Listing 3&lt;/u&gt; - HelperMethods.cs&lt;/a&gt;&lt;br /&gt;&lt;div class="commenthidden" id="rgb3"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#region Using Directives&lt;br /&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Drawing;&lt;br /&gt;using System.Text;&lt;br /&gt;&lt;br /&gt;#endregion&lt;br /&gt;&lt;br /&gt;namespace Rhinomobile.ControlLibrary&lt;br /&gt;{&lt;br /&gt;    /// &amp;lt;summary&amp;gt;&lt;br /&gt;    /// Useful methods&lt;br /&gt;    /// &amp;lt;/summary&amp;gt;&lt;br /&gt;    static class HelperMethods&lt;br /&gt;    {&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// Converts a System.Drawing.Color value into a Windows 32 color value.&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        /// &amp;lt;param name="color"&amp;gt;System.Drawing.Color value&amp;lt;/param&amp;gt;&lt;br /&gt;        /// &amp;lt;returns&amp;gt;Windows 32 integer representation of a color&amp;lt;/returns&amp;gt;&lt;br /&gt;        public static int ColorToWin32(Color color)&lt;br /&gt;        {&lt;br /&gt;            return ((color.R | (color.G &amp;lt;&amp;lt; 8)) | (color.B &amp;lt;&amp;lt; 16));&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;a class="rgb4" href="javascript:togglecomments('rgb4')"&gt;&lt;u&gt;Code Listing 4&lt;/u&gt; - RoundedGroupBox.cs&lt;/a&gt;&lt;br /&gt;&lt;div class="commenthidden" id="rgb4"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#region Using Directives&lt;br /&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Drawing;&lt;br /&gt;using System.Windows.Forms;&lt;br /&gt;using System.Text;&lt;br /&gt;&lt;br /&gt;#endregion&lt;br /&gt;&lt;br /&gt;namespace Rhinomobile.ControlLibrary&lt;br /&gt;{&lt;br /&gt;    /// &amp;lt;summary&amp;gt;&lt;br /&gt;    /// A group box panel with rounded corners and a title&lt;br /&gt;    /// &amp;lt;/summary&amp;gt;&lt;br /&gt;    public class RoundedGroupBox : Panel&lt;br /&gt;    {&lt;br /&gt;        #region Constants&lt;br /&gt;&lt;br /&gt;        private const int DIAMETER = 32;        &lt;br /&gt;&lt;br /&gt;        #endregion&lt;br /&gt;&lt;br /&gt;        #region Fields&lt;br /&gt;        &lt;br /&gt;        private Color m_outerColor = SystemColors.ActiveCaption;&lt;br /&gt;        private string m_roundedGroupBoxText = string.Empty;&lt;br /&gt;&lt;br /&gt;        #endregion&lt;br /&gt;&lt;br /&gt;        #region Protected Methods&lt;br /&gt;&lt;br /&gt;        protected override void OnPaintBackground(PaintEventArgs e)&lt;br /&gt;        {&lt;br /&gt;            if (this.Parent != null)&lt;br /&gt;            {&lt;br /&gt;                SolidBrush backBrush = new SolidBrush(this.Parent.BackColor);&lt;br /&gt;                try&lt;br /&gt;                {&lt;br /&gt;                    e.Graphics.FillRectangle(backBrush, 0, 0, this.Width, this.Height);&lt;br /&gt;                }&lt;br /&gt;                finally&lt;br /&gt;                {&lt;br /&gt;                    backBrush.Dispose();&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        protected override void OnPaint(PaintEventArgs e)&lt;br /&gt;        {&lt;br /&gt;            int outerBrushColor = HelperMethods.ColorToWin32(m_outerColor);&lt;br /&gt;            int innerBrushColor = HelperMethods.ColorToWin32(this.BackColor);&lt;br /&gt;&lt;br /&gt;            IntPtr hdc = e.Graphics.GetHdc();&lt;br /&gt;            try&lt;br /&gt;            {&lt;br /&gt;                IntPtr hbrOuter = NativeMethods.CreateSolidBrush(outerBrushColor);&lt;br /&gt;                IntPtr hOldBrush = NativeMethods.SelectObject(hdc, hbrOuter);&lt;br /&gt;                NativeMethods.RoundRect(hdc, 0, 0, this.Width, this.Height, DIAMETER, DIAMETER);&lt;br /&gt;                IntPtr hbrInner = NativeMethods.CreateSolidBrush(innerBrushColor);&lt;br /&gt;                NativeMethods.SelectObject(hdc, hbrInner);&lt;br /&gt;                NativeMethods.RoundRect(hdc, 0, 18, this.Width, this.Height, DIAMETER, DIAMETER);&lt;br /&gt;                NativeMethods.SelectObject(hdc, hOldBrush);&lt;br /&gt;                NativeMethods.DeleteObject(hbrOuter);&lt;br /&gt;                NativeMethods.DeleteObject(hbrInner);&lt;br /&gt;            }&lt;br /&gt;            finally&lt;br /&gt;            {&lt;br /&gt;                e.Graphics.ReleaseHdc(hdc);&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            if (!string.IsNullOrEmpty(m_roundedGroupBoxText))&lt;br /&gt;            {&lt;br /&gt;                Font titleFont = new Font("Tahoma", 9.0F, FontStyle.Bold);&lt;br /&gt;                Brush titleBrush = new SolidBrush(this.BackColor);&lt;br /&gt;                try&lt;br /&gt;                {&lt;br /&gt;                    e.Graphics.DrawString(m_roundedGroupBoxText, titleFont, titleBrush, 14.0F, 2.0F);&lt;br /&gt;                }&lt;br /&gt;                finally&lt;br /&gt;                {&lt;br /&gt;                    titleFont.Dispose();&lt;br /&gt;                    titleBrush.Dispose();&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            base.OnPaint(e);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        #endregion&lt;br /&gt;&lt;br /&gt;        #region Properties&lt;br /&gt;&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// The color user to fill the background of the title of the rounded group box.&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        public Color OuterColor&lt;br /&gt;        {&lt;br /&gt;            get&lt;br /&gt;            {&lt;br /&gt;                return m_outerColor;&lt;br /&gt;            }&lt;br /&gt;            set&lt;br /&gt;            {&lt;br /&gt;                m_outerColor = value;&lt;br /&gt;                this.Invalidate();&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// The text displayed in the title of the group box panel.&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        public string RoundedGroupBoxText&lt;br /&gt;        {&lt;br /&gt;            get&lt;br /&gt;            {&lt;br /&gt;                return this.m_roundedGroupBoxText;&lt;br /&gt;            }&lt;br /&gt;            set&lt;br /&gt;            {&lt;br /&gt;                m_roundedGroupBoxText = value;&lt;br /&gt;                this.Invalidate();&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        #endregion&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 4&lt;/u&gt; - RoundedGroupBox example application&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_GhRaWNC6A8Q/RjiZeee5L9I/AAAAAAAAAFE/o01TylOJTRs/s1600-h/RoundedGroupBox2.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_GhRaWNC6A8Q/RjiZeee5L9I/AAAAAAAAAFE/o01TylOJTRs/s320/RoundedGroupBox2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5059962930208518098" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37149201-4639176996716849104?l=www.rhinomobile.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rhinomobile/~4/RSuDg1PjDn4" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2008-12-10T05:46:57.513-05:00</atom:updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_GhRaWNC6A8Q/Rjiesee5L_I/AAAAAAAAAFU/Fbie2XKQn0g/s72-c/DesktopGroupBox.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://www.rhinomobile.net/2007/05/net-cf-custom-control-roundedgroupbox.html</feedburner:origLink></item><item><title>Quick Hitter: Indoor GPS Navigation</title><link>http://feedproxy.google.com/~r/Rhinomobile/~3/aJPJJ0iyj0U/quick-hitter-indoor-gps-navigation.html</link><category>Quick Hitter</category><category>GPS</category><author>noreply@blogger.com (Ryan O'Neill)</author><pubDate>Thu, 26 Apr 2007 09:24:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-37149201.post-2888570655866178916</guid><description>After working for some time on projects requiring a Global Positioning System (GPS) solution, mostly involving Windows Mobile, I have learned that there are associated headaches due to GPS not working indoors. Two of the GPS pioneers from the 70s are trying to change that with a solution using TV signals.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.businessweek.com/technology/content/apr2007/tc20070426_529453.htm?campaign_id=rss_tech"&gt;Rosum: Taking GPS Indoors&lt;/a&gt; [Business Week]&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37149201-2888570655866178916?l=www.rhinomobile.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rhinomobile/~4/aJPJJ0iyj0U" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2007-08-20T00:33:35.682-04:00</atom:updated><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.rhinomobile.net/2007/04/quick-hitter-indoor-gps-navigation.html</feedburner:origLink></item><item><title>.NET CF Custom Control: BorderPanel</title><link>http://feedproxy.google.com/~r/Rhinomobile/~3/CLsYf8G9U8M/net-cf-custom-control-borderpanel.html</link><category>Visual Studio</category><category>.NET Compact Framework</category><category>Windows Mobile</category><author>noreply@blogger.com (Ryan O'Neill)</author><pubDate>Fri, 20 Apr 2007 12:59:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-37149201.post-7690997381089598185</guid><description>Creating custom controls using the .NET Compact Framework 2.0 and Visual Studio 2005 can be a tough chore at times, but sometimes it can also be very rewarding and time saving. This entry details how to create a .NET CF BorderPanel custom control. A BorderPanel is a type of Panel which contains a border of a specified color and width. This control is used in the &lt;a href="http://rhinomobile.blogspot.com/2007/03/run-application-at-time-and-time-change.html"&gt;Run Application at Time (and Time Change)&lt;/a&gt; post to separate different sections of the demonstration application into logical groupings. &lt;br /&gt;&lt;br /&gt;Inside the Rhinomobile.ControlLibrary sample project, which is of type ControlLibrary, there are three files to note: BorderPanel.bmp, BorderPanel.cs, and DesignTimeAttributes.xmta. BorderPanel.bmp is the graphic which represents the BorderPanel when it is placed in the Toolbox. BorderPanel.cs is the source code for the BorderPanel custom control. DesignTimeAttributes.xmta is an xml file which contains information used by Visual Studio when using the control through the designer. The project layout including these three files is displayed in Image 1.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 1&lt;/u&gt; - Solution Explorer Showing BorderPanel.bmp, BorderPanel.cs, and DesignTimeAttributes.xmta Files&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_GhRaWNC6A8Q/RikdFvohiZI/AAAAAAAAADU/S8UGSC4e15Q/s1600-h/customcontrol1.JPG"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_GhRaWNC6A8Q/RikdFvohiZI/AAAAAAAAADU/S8UGSC4e15Q/s320/customcontrol1.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5055604041223080338" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;BorderPanel.bmp is a 16 x 16 bitmap added to the project with the same base name as the custom control. The Build Action for this file should be set to "Embedded Resource". The BorderPanel.bmp file used in this project is displayed in Image 2.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 2&lt;/u&gt; - BorderPanel.bmp Graphic&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_GhRaWNC6A8Q/RikdMfohiaI/AAAAAAAAADc/Wrab0cR4qmI/s1600-h/customcontrol2.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_GhRaWNC6A8Q/RikdMfohiaI/AAAAAAAAADc/Wrab0cR4qmI/s320/customcontrol2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5055604157187197346" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;BorderPanel is a .NET Compact Framework 2.0 Custom Control which behaves exactly like a Panel yet has a border of a specified color and width. BorderPanel inherits from the standard System.Windows.Forms.Panel class. By doing so, BorderPanel automatically acts in the same fashion as a Panel. The only difference with a BorderPanel is how it is drawn. &lt;br /&gt;&lt;br /&gt;Two fields are added to the BorderPanel class, one containing information about the border color and the other about the border width. Corresponding public properties are also added to the class. These are named appropriately enough BorderColor and BorderWidth. A call to &lt;a href="http://msdn2.microsoft.com/en-us/library/598t492a.aspx"&gt;Invalidate()&lt;/a&gt; is also added to the mutator (set) of the public properties. The Invalidate method with no parameters causes the entire control to be redrawn on the next painting. Changing the border color or changing the border width would both cause the visual look of the control to change and is why Invalidate is called.&lt;br /&gt;&lt;br /&gt;The OnPaint method inherited from the Panel class is overridden to draw the custom control. A new Pen object is instantiated, used to draw the border, and then disposed. It is of extreme importance to dispose of GDI objects as soon as they are finished being used on a mobile device as they are a major source of memory issues. The width of the Pen is set to the BorderWidth property and the color is set to BorderColor. &lt;br /&gt;&lt;br /&gt;Calculating where to draw the border though is an interesting issue. The drawing is covered in these two lines:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;int halfWidth = m_borderWidth / 2;&lt;br /&gt;e.Graphics.DrawRectangle(borderPen, halfWidth, halfWidth, &lt;br /&gt;    this.Width - m_borderWidth, this.Height - m_borderWidth);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The halfWidth variable is used due to the alignment of the Pen object. &lt;a href="http://msdn2.microsoft.com/en-us/library/system.drawing.pen.alignment(VS.71).aspx"&gt;Pen.Alignment&lt;/a&gt; is not a property that is supported on the .NET Compact Framework. The alignment of the Pen is therefore set to center, meaning that if the width of the pen is 10 pixels, 5 are going to be drawn on one side of the pen and 5 on the other. For this reason, half the width (halfWidth) of the Pen is calculated and used as the starting x,y coordinate for the drawing of the border. This ensures that the entire border is drawn on the viewable area. The third and fourth parameters to the &lt;a href="http://msdn2.microsoft.com/en-us/library/x6hb4eba.aspx"&gt;DrawRectangle&lt;/a&gt; method are a width and height of the rectangle which is the reason the entire width and entire height of the border are subtracted from these values respectively.&lt;br /&gt;&lt;br /&gt;The final item in OnPaint is a call to base.OnPaint(e) to ensure that other items are properly drawn. The source code for the BorderPanel is shown in Code Listing 1.&lt;br /&gt;&lt;br /&gt;&lt;a class="clbp1" href="javascript:togglecomments('clbp1')"&gt;&lt;u&gt;Code Listing 1&lt;/u&gt; - BorderPanel.cs&lt;/a&gt;&lt;br /&gt;&lt;div class="commenthidden" id="clbp1"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#region Using Directives&lt;br /&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.ComponentModel;&lt;br /&gt;using System.Drawing;&lt;br /&gt;using System.Data;&lt;br /&gt;using System.Text;&lt;br /&gt;using System.Windows.Forms;&lt;br /&gt;&lt;br /&gt;#endregion&lt;br /&gt;&lt;br /&gt;namespace Rhinomobile.ControlLibrary&lt;br /&gt;{&lt;br /&gt;    /// &amp;lt;summary&amp;gt;&lt;br /&gt;    /// A Panel with a colored sizable border&lt;br /&gt;    /// &amp;lt;/summary&amp;gt;&lt;br /&gt;    public class BorderPanel : Panel&lt;br /&gt;    {&lt;br /&gt;        #region Fields&lt;br /&gt;&lt;br /&gt;        private Color m_borderColor = SystemColors.Control;&lt;br /&gt;        private int m_borderWidth = 4;&lt;br /&gt;&lt;br /&gt;        #endregion&lt;br /&gt;&lt;br /&gt;        #region Constructor&lt;br /&gt;&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// BorderPanel Constructor&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        public BorderPanel() : base()&lt;br /&gt;        {&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        #endregion&lt;br /&gt;&lt;br /&gt;        #region Protected Methods&lt;br /&gt;&lt;br /&gt;        protected override void OnPaint(PaintEventArgs e)&lt;br /&gt;        {&lt;br /&gt;            if ((m_borderWidth &amp;gt; 0) &amp;&amp; (m_borderWidth &amp;lt; (this.Width / 2)))&lt;br /&gt;            {&lt;br /&gt;                Pen borderPen = new Pen(m_borderColor, (float)m_borderWidth);&lt;br /&gt;                try&lt;br /&gt;                {&lt;br /&gt;                    int halfWidth = m_borderWidth / 2;&lt;br /&gt;                    e.Graphics.DrawRectangle(borderPen, halfWidth, halfWidth, &lt;br /&gt;                        this.Width - m_borderWidth, this.Height - m_borderWidth);                    &lt;br /&gt;                }&lt;br /&gt;                finally&lt;br /&gt;                {&lt;br /&gt;                    borderPen.Dispose();&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            base.OnPaint(e);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        #endregion&lt;br /&gt;&lt;br /&gt;        #region Properties&lt;br /&gt;&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// Color used for drawing border on panel&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        public Color BorderColor&lt;br /&gt;        {&lt;br /&gt;            get&lt;br /&gt;            {&lt;br /&gt;                return m_borderColor;&lt;br /&gt;            }&lt;br /&gt;            set&lt;br /&gt;            {&lt;br /&gt;                m_borderColor = value;&lt;br /&gt;                this.Invalidate();&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// Width of border on panel&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        public int BorderWidth&lt;br /&gt;        {&lt;br /&gt;            get&lt;br /&gt;            {&lt;br /&gt;                return m_borderWidth;&lt;br /&gt;            }&lt;br /&gt;            set&lt;br /&gt;            {&lt;br /&gt;                m_borderWidth = value;&lt;br /&gt;                this.Invalidate();&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        #endregion&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;DesignTimeAttributes.xmta is an xml file which contains information about classes, properties, methods, and events used by Visual Studio at design time for controls. The xmta file for the BorderPanel custom control, demonstrates how to add descriptions for added properties as well as placing the properties within the proper categories in the Properties Window.&lt;br /&gt;&lt;br /&gt;Working with the DesignTimeAttributes.xmta file can be one of the flakiest and time consuming tasks when working with the .NET Compact Framework. The one for this control has been simplified to only show the simplest two elements. The DesignTimeAttributes.xmta file can be found in Code Listing 2.&lt;br /&gt;&lt;br /&gt;&lt;a class="clbp2" href="javascript:togglecomments('clbp2')"&gt;&lt;u&gt;Code Listing 2&lt;/u&gt; - DesignTimeAttributes.xmta&lt;/a&gt;&lt;br /&gt;&lt;div class="commenthidden" id="clbp2"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="utf-16"?&amp;gt;&lt;br /&gt;&amp;lt;Classes xmlns="http://schemas.microsoft.com/VisualStudio/2004/03/SmartDevices/XMTA.xsd"&amp;gt;&lt;br /&gt;  &amp;lt;Class Name="Rhinomobile.ControlLibrary.BorderPanel"&amp;gt;&lt;br /&gt;    &amp;lt;Property Name="BorderColor"&amp;gt;&lt;br /&gt;      &amp;lt;Category&amp;gt;Appearance&amp;lt;/Category&amp;gt;&lt;br /&gt;      &amp;lt;Description&amp;gt;The color used to draw the border of the panel.&amp;lt;/Description&amp;gt;&lt;br /&gt;    &amp;lt;/Property&amp;gt;&lt;br /&gt;    &amp;lt;Property Name="BorderWidth"&amp;gt;&lt;br /&gt;      &amp;lt;Category&amp;gt;Layout&amp;lt;/Category&amp;gt;&lt;br /&gt;      &amp;lt;Description&amp;gt;The width of the panel border.&amp;lt;/Description&amp;gt;&lt;br /&gt;    &amp;lt;/Property&amp;gt;&lt;br /&gt;  &amp;lt;/Class&amp;gt;&lt;br /&gt;&amp;lt;/Classes&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;At this point the project can be compiled and the control library built. The following images indicate how to go about adding the BorderPanel to the Toolbox within Visual Studio.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 3&lt;/u&gt; - Toolbox Before Adding BorderPanel&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_GhRaWNC6A8Q/RikdqPohibI/AAAAAAAAADk/drbQTCXQx1c/s1600-h/customcontrol3.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_GhRaWNC6A8Q/RikdqPohibI/AAAAAAAAADk/drbQTCXQx1c/s320/customcontrol3.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5055604668288305586" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Right click on the Toolbox and select "Choose Items..."&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 4&lt;/u&gt; - Choose Toolbox Items Dialog Before Adding BorderPanel&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_GhRaWNC6A8Q/Rikd-vohicI/AAAAAAAAADs/3qWMIVb2IZA/s1600-h/customcontrol4.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_GhRaWNC6A8Q/Rikd-vohicI/AAAAAAAAADs/3qWMIVb2IZA/s320/customcontrol4.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5055605020475623874" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Click the "Browse" button on the Choose Toolbox Items Dialog.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 5&lt;/u&gt; - Choose Toolbox Items Browse Dialog&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_GhRaWNC6A8Q/RikeTvohidI/AAAAAAAAAD0/Qyy9CA3wiNI/s1600-h/customcontrol5.JPG"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_GhRaWNC6A8Q/RikeTvohidI/AAAAAAAAAD0/Qyy9CA3wiNI/s320/customcontrol5.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5055605381252876754" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Navigate to the location of the control library assembly and select it.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 6&lt;/u&gt; - Choose Toolbox Items After Adding BorderPanel&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_GhRaWNC6A8Q/RikenvohieI/AAAAAAAAAD8/F1jDHChCtGQ/s1600-h/customcontrol6.JPG"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_GhRaWNC6A8Q/RikenvohieI/AAAAAAAAAD8/F1jDHChCtGQ/s320/customcontrol6.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5055605724850260450" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Notice the controls in the assembly have been added to the list of components and checked. Click the "Ok" button on the dialog and the controls should be added to the Toolbox.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 7&lt;/u&gt; - Toolbox After Adding BorderPanel&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_GhRaWNC6A8Q/RikfbPohifI/AAAAAAAAAEE/YvgnXSJEg18/s1600-h/customcontrol7.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_GhRaWNC6A8Q/RikfbPohifI/AAAAAAAAAEE/YvgnXSJEg18/s320/customcontrol7.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5055606609613523442" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 8&lt;/u&gt; - Form1.cs Design After Dragging Over a BorderPanel from the Toolbox&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_GhRaWNC6A8Q/RikgNvohigI/AAAAAAAAAEM/Fbkn-9rD8UE/s1600-h/customcontrol8.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_GhRaWNC6A8Q/RikgNvohigI/AAAAAAAAAEM/Fbkn-9rD8UE/s320/customcontrol8.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5055607477196917250" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 9&lt;/u&gt; - Properties Window Showing the BorderColor and BorderWidth Properties&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_GhRaWNC6A8Q/RikgovohihI/AAAAAAAAAEU/Kvr_S8GBWjc/s1600-h/customcontrol9.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_GhRaWNC6A8Q/RikgovohihI/AAAAAAAAAEU/Kvr_S8GBWjc/s320/customcontrol9.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5055607941053385234" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37149201-7690997381089598185?l=www.rhinomobile.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rhinomobile/~4/CLsYf8G9U8M" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2008-12-10T05:46:58.920-05:00</atom:updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_GhRaWNC6A8Q/RikdFvohiZI/AAAAAAAAADU/S8UGSC4e15Q/s72-c/customcontrol1.JPG" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://www.rhinomobile.net/2007/04/net-cf-custom-control-borderpanel.html</feedburner:origLink></item><item><title>Run Application at Time (and Time Change)</title><link>http://feedproxy.google.com/~r/Rhinomobile/~3/Q0r9w5RDrEk/run-application-at-time-and-time-change.html</link><category>.NET Compact Framework</category><category>Windows Mobile</category><author>noreply@blogger.com (Ryan O'Neill)</author><pubDate>Fri, 30 Mar 2007 13:47:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-37149201.post-7155353407550204222</guid><description>MSDN describes &lt;a href="http://msdn2.microsoft.com/en-us/library/ms908103.aspx"&gt;CeRunAppAtTime&lt;/a&gt; as a function which "prompts the system to start running a specified application at a specified time." This function can be extremely useful for performing scheduled tasks such as snapshots of running processes, the retrieval of device memory statistics, routine checks on security settings, or automatic device synchronization. Conversely, it can also be used to rescind the scheduling of these activities.&lt;br /&gt;&lt;br /&gt;The CeRunAppAtTime function takes two parameters: TCHAR* pwszAppName, and SYSTEMTIME* lpTime. The first parameter, pwszAppName, is the name of the application to be run (e.g. \windows\cgacutil.exe). The type of the parameter is a pointer to a TCHAR. One might ask, "What's a TCHAR?" Well, according to MSDN, a &lt;a href="http://msdn2.microsoft.com/en-us/library/ms527395.aspx"&gt;TCHAR&lt;/a&gt; is a "Win32 character string that can be used to describe ANSI, DBCS, or Unicode strings. [...] For Unicode platforms, TCHAR is defined as synonymous with the WCHAR type." With Windows CE being a Unicode platform, this makes a TCHAR a WCHAR (wide character). Further demonstrating this is that the name of the actual first parameter - pwszAppName, translates into &lt;i&gt;P&lt;/i&gt;ointer to a &lt;i&gt;W&lt;/i&gt;ide &lt;i&gt;S&lt;/i&gt;tring terminated with a &lt;i&gt;Z&lt;/i&gt;ero (null character) when broken down. Because the parameter is an input parameter, a standard C# string can be passed in as an equivalent in a P/Invoke function call.&lt;br /&gt;&lt;br /&gt;The second parameter, lpTime, is the time at which the specified application should be run. A simple C# type though won't suffice for lpTime (&lt;i&gt;L&lt;/i&gt;ong &lt;i&gt;P&lt;/i&gt;ointer to a time variable). This parameter requires a little bit more work. &lt;a href="http://msdn2.microsoft.com/en-us/library/aa450923.aspx"&gt;SYSTEMTIME&lt;/a&gt; is a structure composed of WORD representations of 8 items: year, month, day, day of week, hours, minutes, seconds, and milliseconds. A WORD is equivalent to a C# short, i.e. 2 bytes, putting the size of the structure at 16 bytes. A C# equivalent has been provided in Code Listing 1. &lt;br /&gt;&lt;br /&gt;Additionally, it is the second parameter which also controls whether CeRunAppAtTime rescinds the scheduling of an application. This is done by passing in a null parameter for lpTime. One note on cancelling an application though is that CeRunAppAtTime will return false if the application specified was not already currently specified, so do not interpret this as the function only failing to remove a scheduled instance.&lt;br /&gt;&lt;br /&gt;In the example below, because SYSTEMTIME (represented in C# as SystemTime) is a structure, two P/Invoke calls have been defined (see NativeTimeMethods.cs). The one which takes an array of bytes as the lpTime parameter is the one which can have a null value sent into it (see TimeUtilities.cs). The other one should be used for standard scheduling of applications.&lt;br /&gt;&lt;br /&gt;An interesting point requiring further discussion is what happens when the time on the device is changed. The device time could be changed by the user or by a time negotiation on synchronization, or via an NTP (Network Time Protocol) server. &lt;br /&gt;&lt;br /&gt;Images 1 through 5 show what happens when the current time on a device (March 28th, 2007) is changed to a future time (March 30th, 2007) to the point where applications would be scheduled to run in the past (March 29th, 2007). Windows CE ends up running  those scheduled applications immediately. This is demonstrated within the screenshots of the sample application.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 1&lt;/u&gt; - First "Set Date" button tapped. Date changed to March 28th, 2007&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_GhRaWNC6A8Q/Rg1346gaVtI/AAAAAAAAACE/Ci5OvFyzTXo/s1600-h/cerunappattime1.JPG"&gt;&lt;img style="cursor: pointer;" src="http://1.bp.blogspot.com/_GhRaWNC6A8Q/Rg1346gaVtI/AAAAAAAAACE/Ci5OvFyzTXo/s320/cerunappattime1.JPG" alt="" id="BLOGGER_PHOTO_ID_5047822577013774034" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 2&lt;/u&gt; - Right soft key button tapped. Application soft key menu displayed&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_GhRaWNC6A8Q/Rg1-YqgaVuI/AAAAAAAAACM/I6bP3gQo-2w/s1600-h/cerunappattime2.JPG"&gt;&lt;img style="cursor: pointer;" src="http://4.bp.blogspot.com/_GhRaWNC6A8Q/Rg1-YqgaVuI/AAAAAAAAACM/I6bP3gQo-2w/s320/cerunappattime2.JPG" alt="" id="BLOGGER_PHOTO_ID_5047829719544387298" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 3&lt;/u&gt; - Run App menu option selected. Application is run now.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_GhRaWNC6A8Q/Rg1-mKgaVvI/AAAAAAAAACU/P83bdvgjLp8/s1600-h/cerunappattime3.JPG"&gt;&lt;img style="cursor: pointer;" src="http://2.bp.blogspot.com/_GhRaWNC6A8Q/Rg1-mKgaVvI/AAAAAAAAACU/P83bdvgjLp8/s320/cerunappattime3.JPG" alt="" id="BLOGGER_PHOTO_ID_5047829951472621298" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 4&lt;/u&gt; - "Set App" button tapped. Application set to run on March 29th, 2007&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_GhRaWNC6A8Q/Rg1-wqgaVwI/AAAAAAAAACc/A8DLOZuD-NM/s1600-h/cerunappattime4.JPG"&gt;&lt;img style="cursor: pointer;" src="http://4.bp.blogspot.com/_GhRaWNC6A8Q/Rg1-wqgaVwI/AAAAAAAAACc/A8DLOZuD-NM/s320/cerunappattime4.JPG" alt="" id="BLOGGER_PHOTO_ID_5047830131861247746" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 5&lt;/u&gt; - Second "Set Date" button tapped. Date changed to March 30th, 2007&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_GhRaWNC6A8Q/Rg1_6agaVxI/AAAAAAAAACk/AEIHPgQV-qE/s1600-h/cerunappattime5.JPG"&gt;&lt;img style="cursor: pointer;" src="http://3.bp.blogspot.com/_GhRaWNC6A8Q/Rg1_6agaVxI/AAAAAAAAACk/AEIHPgQV-qE/s320/cerunappattime5.JPG" alt="" id="BLOGGER_PHOTO_ID_5047831398876600082" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;With the time now changed to March 30th, 2007, the application which was scheduled to run on March 29th, 2007 is now run immediately.&lt;br /&gt;&lt;br /&gt;&lt;a class="cl1" href="javascript:togglecomments('cl1')"&gt;&lt;u&gt;Code Listing 1&lt;/u&gt; - SystemTime.cs&lt;/a&gt;&lt;br /&gt;&lt;div class="commenthidden" id="cl1"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#region Using Directives&lt;br /&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Runtime.InteropServices;&lt;br /&gt;using System.Text;&lt;br /&gt;&lt;br /&gt;#endregion&lt;br /&gt;&lt;br /&gt;namespace Rhinomobile.ClassLibrary&lt;br /&gt;{&lt;br /&gt;    /// &amp;lt;summary&amp;gt;&lt;br /&gt;    /// This structure represents a date and time using individual members for the month,&lt;br /&gt;    /// day, year, weekday, hour, minute, second, and millisecond.&lt;br /&gt;    /// &amp;lt;/summary&amp;gt;&lt;br /&gt;    [StructLayout(LayoutKind.Sequential)]&lt;br /&gt;    public struct SystemTime&lt;br /&gt;    {&lt;br /&gt;        #region Fields&lt;br /&gt;&lt;br /&gt;        private short m_year;&lt;br /&gt;        private short m_month;&lt;br /&gt;        private short m_dayOfWeek;&lt;br /&gt;        private short m_day;&lt;br /&gt;        private short m_hour;&lt;br /&gt;        private short m_minute;&lt;br /&gt;        private short m_second;&lt;br /&gt;        private short m_milliseconds;&lt;br /&gt;&lt;br /&gt;        #endregion&lt;br /&gt;&lt;br /&gt;        #region Constructors&lt;br /&gt;&lt;br /&gt;        public SystemTime(DateTime value)&lt;br /&gt;            : this()&lt;br /&gt;        {&lt;br /&gt;            ConvertFromDateTime(value);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        #endregion&lt;br /&gt;&lt;br /&gt;        #region Properties&lt;br /&gt;&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// Specifies the current year&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        public short Year&lt;br /&gt;        {&lt;br /&gt;            get { return m_year; }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// Specifies the current month&lt;br /&gt;        /// January = 1 ... December = 12&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        public short Month&lt;br /&gt;        {&lt;br /&gt;            get { return m_month; }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// Specifies the current day of the week&lt;br /&gt;        /// Sunday = 0 ... Saturday = 6&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        public short DayOfWeek&lt;br /&gt;        {&lt;br /&gt;            get { return m_dayOfWeek; }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// Specifies the current day of the month&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        public short Day&lt;br /&gt;        {&lt;br /&gt;            get { return m_day; }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// Specifies the current hour&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        public short Hour&lt;br /&gt;        {&lt;br /&gt;            get { return m_hour; }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// Specifies the current minute&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        public short Minute&lt;br /&gt;        {&lt;br /&gt;            get { return m_minute; }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// Specifies the current second&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        public short Second&lt;br /&gt;        {&lt;br /&gt;            get { return m_minute; }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// Specifies the current millisecond&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        public short Milliseconds&lt;br /&gt;        {&lt;br /&gt;            get { return m_milliseconds; }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public DateTime DateTime&lt;br /&gt;        {&lt;br /&gt;            get { return ConvertToDateTime(); }&lt;br /&gt;            set { ConvertFromDateTime(value); }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// Gets the day of the year represented by this instance.&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        public int DayOfYear&lt;br /&gt;        {&lt;br /&gt;            get { return DateTime.DayOfYear; }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// Gets the number of ticks that represent the date and time of this instance.&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        public long Ticks&lt;br /&gt;        {&lt;br /&gt;            get { return DateTime.Ticks; }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// Gets the time of day for this instance.&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        public TimeSpan TimeOfDay&lt;br /&gt;        {&lt;br /&gt;            get { return DateTime.TimeOfDay; }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        #endregion&lt;br /&gt;&lt;br /&gt;        #region Private Methods&lt;br /&gt;&lt;br /&gt;        private void ConvertFromDateTime(DateTime value)&lt;br /&gt;        {&lt;br /&gt;            m_year = (short)value.Year;&lt;br /&gt;            m_month = (short)value.Month;&lt;br /&gt;            m_dayOfWeek = (short)value.DayOfWeek;&lt;br /&gt;            m_day = (short)value.Day;&lt;br /&gt;            m_hour = (short)value.Hour;&lt;br /&gt;            m_minute = (short)value.Minute;&lt;br /&gt;            m_second = (short)value.Second;&lt;br /&gt;            m_milliseconds = (short)value.Millisecond;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private DateTime ConvertToDateTime()&lt;br /&gt;        {&lt;br /&gt;            return new DateTime(m_year, m_month, m_day, m_hour, m_minute, m_second);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        #endregion&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;a class="cl2" href="javascript:togglecomments('cl2')"&gt;&lt;u&gt;Code Listing 2&lt;/u&gt; - NativeTimeMethods.cs&lt;/a&gt;&lt;br /&gt;&lt;div class="commenthidden" id="cl2"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#region Using Directives&lt;br /&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Runtime.InteropServices;&lt;br /&gt;using System.Text;&lt;br /&gt;&lt;br /&gt;#endregion&lt;br /&gt;&lt;br /&gt;namespace Rhinomobile.ClassLibrary&lt;br /&gt;{&lt;br /&gt;    /// &amp;lt;summary&amp;gt;&lt;br /&gt;    /// P/Invoked time related methods.&lt;br /&gt;    /// &amp;lt;/summary&amp;gt;&lt;br /&gt;    static class NativeTimeMethods&lt;br /&gt;    {&lt;br /&gt;        #region Internal Static Methods&lt;br /&gt;&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// This function sets the current local time and date.&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        /// &amp;lt;param name="lpSystemTime"&amp;gt;A pointer to a SystemTime structure that contains &lt;br /&gt;        /// the new local date and time. The DayOfWeek member of the SystemTime structure &lt;br /&gt;        /// is ignored.&amp;lt;/param&amp;gt;&lt;br /&gt;        /// &amp;lt;returns&amp;gt;Nonzero indicates success. Zero indicates failure.&amp;lt;/returns&amp;gt;&lt;br /&gt;        [DllImport("coredll")]&lt;br /&gt;        internal static extern bool SetLocalTime(ref SystemTime lpSystemTime);&lt;br /&gt;&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// This function prompts the system to start running a specified application at&lt;br /&gt;        /// a specified time.&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        /// &amp;lt;param name="pwszAppName"&amp;gt;Pointer to a null-terminated string that specifies&lt;br /&gt;        /// the name of the application to be run.&amp;lt;/param&amp;gt;&lt;br /&gt;        /// &amp;lt;param name="lpTime"&amp;gt;Long pointer to a SystemTime structure that specifies&lt;br /&gt;        /// the time when the given application is to be run. If this parameter is NULL,&lt;br /&gt;        /// the existing run request is deleted and no new request is entered. The &lt;br /&gt;        /// deleted run request must have been initiated by a call to CeRunAppAtTime.&amp;lt;/param&amp;gt;&lt;br /&gt;        /// &amp;lt;returns&amp;gt;TRUE indicates success. FALSE indicates failure.&amp;lt;/returns&amp;gt;&lt;br /&gt;        [DllImport("coredll")]&lt;br /&gt;        internal static extern bool CeRunAppAtTime(string pwszAppName, ref SystemTime lpTime);&lt;br /&gt;&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// This function prompts the system to start running a specified application at&lt;br /&gt;        /// a specified time.&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        /// &amp;lt;param name="pwszAppName"&amp;gt;Pointer to a null-terminated string that specifies&lt;br /&gt;        /// the name of the application to be run.&amp;lt;/param&amp;gt;&lt;br /&gt;        /// &amp;lt;param name="lpTime"&amp;gt;Long pointer to a SystemTime structure that specifies&lt;br /&gt;        /// the time when the given application is to be run. If this parameter is NULL,&lt;br /&gt;        /// the existing run request is deleted and no new request is entered. The &lt;br /&gt;        /// deleted run request must have been initiated by a call to CeRunAppAtTime.&amp;lt;/param&amp;gt;&lt;br /&gt;        /// &amp;lt;returns&amp;gt;TRUE indicates success. FALSE indicates failure.&amp;lt;/returns&amp;gt;&lt;br /&gt;        [DllImport("coredll")]&lt;br /&gt;        internal static extern bool CeRunAppAtTime(string pwszAppName, byte[] lpTime);&lt;br /&gt;&lt;br /&gt;        #endregion&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;a class="cl3" href="javascript:togglecomments('cl3')"&gt;&lt;u&gt;Code Listing 3&lt;/u&gt; - TimeException.cs&lt;/a&gt;&lt;br /&gt;&lt;div class="commenthidden" id="cl3"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#region Using Directives&lt;br /&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Text;&lt;br /&gt;&lt;br /&gt;#endregion&lt;br /&gt;&lt;br /&gt;namespace Rhinomobile.ClassLibrary&lt;br /&gt;{&lt;br /&gt;    /// &amp;lt;summary&amp;gt;&lt;br /&gt;    /// Represents errors that occur during time methods&lt;br /&gt;    /// &amp;lt;/summary&amp;gt;&lt;br /&gt;    public class TimeException : Exception&lt;br /&gt;    {&lt;br /&gt;        #region Constructors&lt;br /&gt;&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// Initializes a new instance of the TimeException class.&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        public TimeException()&lt;br /&gt;            : base()&lt;br /&gt;        {&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// Initializes a new instance of the TimeException class with a specified error message.&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        /// &amp;lt;param name="message"&amp;gt;The message that describes the error.&amp;lt;/param&amp;gt;&lt;br /&gt;        public TimeException(string message)&lt;br /&gt;            : base(message)&lt;br /&gt;        {&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// Initializes a new instance of the TimeException class with a specified error &lt;br /&gt;        /// message and a reference to the inner exception that is the cause of the exception.&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        /// &amp;lt;param name="message"&amp;gt;The message that describes the error.&amp;lt;/param&amp;gt;&lt;br /&gt;        /// &amp;lt;param name="innerException"&amp;gt;The exception that is &lt;br /&gt;        /// the cause of the current exception.&amp;lt;/param&amp;gt;&lt;br /&gt;        public TimeException(string message, Exception innerException)&lt;br /&gt;            : base(message, innerException)&lt;br /&gt;        {&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        #endregion&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;a class="cl4" href="javascript:togglecomments('cl4')"&gt;&lt;u&gt;Code Listing 4&lt;/u&gt; - TimeUtilities.cs&lt;/a&gt;&lt;br /&gt;&lt;div class="commenthidden" id="cl4"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#region Using Directives&lt;br /&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Runtime.InteropServices;&lt;br /&gt;using System.Text;&lt;br /&gt;&lt;br /&gt;#endregion&lt;br /&gt;&lt;br /&gt;namespace Rhinomobile.ClassLibrary&lt;br /&gt;{&lt;br /&gt;    /// &amp;lt;summary&amp;gt;&lt;br /&gt;    /// Methods for performing time based functions&lt;br /&gt;    /// &amp;lt;/summary&amp;gt;&lt;br /&gt;    public static class TimeUtilities&lt;br /&gt;    {&lt;br /&gt;        #region Static Public Methods&lt;br /&gt;&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// This function sets the current local date and time.&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        /// &amp;lt;param name="value"&amp;gt;The local date and time to set on the device.&amp;lt;/param&amp;gt;&lt;br /&gt;        /// &amp;lt;returns&amp;gt;True if date and time are successfully set&amp;lt;/returns&amp;gt;&lt;br /&gt;        public static bool SetLocalDeviceTime(DateTime value)&lt;br /&gt;        {&lt;br /&gt;            SystemTime systemTime = new SystemTime(value);&lt;br /&gt;            bool result = NativeTimeMethods.SetLocalTime(ref systemTime);&lt;br /&gt;            if (!result)&lt;br /&gt;            {&lt;br /&gt;                int errorCode = Marshal.GetLastWin32Error();&lt;br /&gt;                throw new TimeException(StandardConstants.ERROR_CODE + errorCode.ToString());&lt;br /&gt;            }&lt;br /&gt;            return result;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// This function prompts the system to start running a specified application&lt;br /&gt;        /// at a specified time.&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        /// &amp;lt;param name="application"&amp;gt;The name of the application to be run&amp;lt;/param&amp;gt;&lt;br /&gt;        /// &amp;lt;param name="value"&amp;gt;The date and time when the given application is to be run&amp;lt;/param&amp;gt;&lt;br /&gt;        /// &amp;lt;returns&amp;gt;True if the application is properly scheduled&amp;lt;/returns&amp;gt;&lt;br /&gt;        public static bool RunApplication(string application, DateTime value)&lt;br /&gt;        {&lt;br /&gt;            SystemTime systemTime = new SystemTime(value);&lt;br /&gt;            bool result = NativeTimeMethods.CeRunAppAtTime(application, ref systemTime);&lt;br /&gt;            if (!result)&lt;br /&gt;            {&lt;br /&gt;                int errorCode = Marshal.GetLastWin32Error();&lt;br /&gt;                throw new TimeException(StandardConstants.ERROR_CODE + errorCode.ToString());&lt;br /&gt;            }&lt;br /&gt;            return result;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        /// &amp;lt;summary&amp;gt;&lt;br /&gt;        /// This method deletes an existing run application request&lt;br /&gt;        /// &amp;lt;/summary&amp;gt;&lt;br /&gt;        /// &amp;lt;param name="application"&amp;gt;Application which has been requested to run&amp;lt;/param&amp;gt;&lt;br /&gt;        /// &amp;lt;returns&amp;gt;True if application is found and request is removed&amp;lt;/returns&amp;gt;&lt;br /&gt;        public static bool CancelRunApplication(string application)&lt;br /&gt;        {&lt;br /&gt;            return NativeTimeMethods.CeRunAppAtTime(application, null);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        #endregion&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37149201-7155353407550204222?l=www.rhinomobile.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rhinomobile/~4/Q0r9w5RDrEk" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2008-12-10T05:46:59.873-05:00</atom:updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_GhRaWNC6A8Q/Rg1346gaVtI/AAAAAAAAACE/Ci5OvFyzTXo/s72-c/cerunappattime1.JPG" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://www.rhinomobile.net/2007/03/run-application-at-time-and-time-change.html</feedburner:origLink></item><item><title>What's the Deal: Smart Device Project Ordering in Visual Studio 2005</title><link>http://feedproxy.google.com/~r/Rhinomobile/~3/c51dyuX19_U/whats-deal-smart-device-project.html</link><category>Visual Studio</category><author>noreply@blogger.com (Ryan O'Neill)</author><pubDate>Sat, 17 Mar 2007 13:32:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-37149201.post-1729924194662581395</guid><description>While creating an application earlier this afternoon for testing a proposed change, I went to create a new Windows Mobile 5.0 Pocket PC application using Visual Studio 2005's New Project dialog. I was curious as to why the entries underneath Visual C#\Smart Device seemed to be in alphabetical order except for Windows Mobile 6 Professional.&lt;br /&gt;&lt;br /&gt;The entries were in the following order under Smart Device:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Pocket PC 2003&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Windows Mobile 6 Professional&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Smartphone 2003&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Windows CE 5.0&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Windows Mobile 5.0 Pocket PC&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Windows Mobile 5.0 Smartphone&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Windows Mobile 6 Standard&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 1&lt;/u&gt; - New Project dialog out of order&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_GhRaWNC6A8Q/RfxQkL3lw1I/AAAAAAAAABg/44-UHf1aOnI/s1600-h/whatsthedeal1.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_GhRaWNC6A8Q/RfxQkL3lw1I/AAAAAAAAABg/44-UHf1aOnI/s320/whatsthedeal1.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5042994265339577170" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;After a little bit of digging around in the C:\Program Files\Microsoft Visual Studio 8\ directory, I found a folder structure with the hierarchy of "Common 7\IDE\ProjectTemplates\CSharp\SmartDevice". Inside the SmartDevice folder was a file named TemplateIndex.vstdir and 7 folders:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;PocketPC2003&lt;/li&gt;&lt;br /&gt;&lt;li&gt;ppc&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Smartphone2003&lt;/li&gt;&lt;br /&gt;&lt;li&gt;sp&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Windows Mobile 6 Professional&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Windows Mobile 6 Standard&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Windows CE&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 2&lt;/u&gt; - SmartDevice folder structure&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_GhRaWNC6A8Q/RfxzGL3lw2I/AAAAAAAAABo/oNN-FQ-y4Qg/s1600-h/whatsthedeal2.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_GhRaWNC6A8Q/RfxzGL3lw2I/AAAAAAAAABo/oNN-FQ-y4Qg/s320/whatsthedeal2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5043032232850473826" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I soon noticed that each of the 7 folders had their own TemplateIndex.vstdir files. I did a search on that file and discovered an excellent &lt;a href="http://blogs.msdn.com/vsdocs/archive/2006/10/30/new-project-generation-under-the-hood.aspx"&gt;blog entry entitled "New Project Generation: Under the Hood"&lt;/a&gt; by the &lt;a href="http://blogs.msdn.com/vsdocs/default.aspx"&gt;Visual Studio Documentation Team&lt;/a&gt;. It confirmed my suspicions that the SortIndex was what controlled the ordering and also brought to my attention that I needed to start visual Studio using the /installvstemplates command line parameter in order for the changes to take effect.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Entry                          Old Sort Index            New Sort Index&lt;br /&gt;Pocket PC 2003                          1100                      1100&lt;br /&gt;Smartphone 2003                         1110                      1110&lt;br /&gt;Windows CE 5.0                          1120                      1120&lt;br /&gt;Windows Mobile 5.0 Pocket PC            1150                      1130&lt;br /&gt;Windows Mobile 5.0 Smartphone           1160                      1140&lt;br /&gt;Windows Mobile 6 Professional           1100                      1150&lt;br /&gt;Windows Mobile 6 Standard               1100                      1160&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;After making the changes to the associated TemplateIndex.vstdir files, I ran Visual Studio with the /installvstemplates command line parameter.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 3&lt;/u&gt; - Visual Studio started via command line&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_GhRaWNC6A8Q/Rfx86b3lw3I/AAAAAAAAABw/mKJd4EE7K8o/s1600-h/whatsthedeal3.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_GhRaWNC6A8Q/Rfx86b3lw3I/AAAAAAAAABw/mKJd4EE7K8o/s320/whatsthedeal3.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5043043026103288690" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;When Visual Studio finished processing the template files and opened, going to the New Project dialog had things ordered alphabetically underneath SmartDevice:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Pocket PC 2003&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Smartphone 2003&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Windows CE 5.0&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Windows Mobile 5.0 Pocket PC&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Windows Mobile 5.0 Smartphone&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Windows Mobile 6 Professional&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Windows Mobile 6 Standard&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 4&lt;/u&gt; - New Project dialog in order&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_GhRaWNC6A8Q/Rfx9Tr3lw4I/AAAAAAAAAB4/QU7qseayUBI/s1600-h/whatsthedeal4.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_GhRaWNC6A8Q/Rfx9Tr3lw4I/AAAAAAAAAB4/QU7qseayUBI/s320/whatsthedeal4.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5043043459894985602" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37149201-1729924194662581395?l=www.rhinomobile.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rhinomobile/~4/c51dyuX19_U" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2008-12-10T05:47:00.522-05:00</atom:updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_GhRaWNC6A8Q/RfxQkL3lw1I/AAAAAAAAABg/44-UHf1aOnI/s72-c/whatsthedeal1.jpg" height="72" width="72" /><feedburner:origLink>http://www.rhinomobile.net/2007/03/whats-deal-smart-device-project.html</feedburner:origLink></item><item><title>Quick Hitter: Navigating Windows Folder via ActiveSync</title><link>http://feedproxy.google.com/~r/Rhinomobile/~3/JWnfHuqu-A0/quick-hitter-navigating-windows-folder.html</link><category>Quick Hitter</category><category>Windows Mobile</category><author>noreply@blogger.com (Ryan O'Neill)</author><pubDate>Fri, 16 Mar 2007 13:10:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-37149201.post-5232225362865382172</guid><description>Annoyed because the \Windows folder can't be viewed when trying to "Explore" a Windows Mobile device using Microsoft ActiveSync? Well, actually it can. Where the setting to change that behavior is though is fairly counterintuitive. In order to be able to see the \Windows folder on a Windows Mobile device, the Windows Explorer folder options of the machine ActiveSync is running on are what need to be changed.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 1&lt;/u&gt; - \Windows folder not visible through ActiveSync&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_GhRaWNC6A8Q/Rfr8db3lwyI/AAAAAAAAABI/i0iDbFK-5vY/s1600-h/activesyncNo.jpg"&gt;&lt;img style="cursor: pointer;" src="http://3.bp.blogspot.com/_GhRaWNC6A8Q/Rfr8db3lwyI/AAAAAAAAABI/i0iDbFK-5vY/s320/activesyncNo.jpg" alt="" id="BLOGGER_PHOTO_ID_5042620315422016290" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;On the window displayed in Image 1, from the main menu select Tools--&gt;Folder Options. Switch from the General tab to the View tab located at the top of the Folder Options dialog window. In the "Advanced Settings" area, there will be an option under "Files and Folders" named "Hidden files and folders".&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 2&lt;/u&gt; - Folder Options dialog with Hidden files and folders highlighted&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_GhRaWNC6A8Q/Rfr_hr3lwzI/AAAAAAAAABQ/SpbeJWsS9GQ/s1600-h/activeSyncFolder.jpg"&gt;&lt;img style="cursor: pointer;" src="http://4.bp.blogspot.com/_GhRaWNC6A8Q/Rfr_hr3lwzI/AAAAAAAAABQ/SpbeJWsS9GQ/s320/activeSyncFolder.jpg" alt="" id="BLOGGER_PHOTO_ID_5042623686971343666" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Change the "Hidden files and folders" value from "Do not show hidden files and folders" to "Show hidden files and folders". Click the "Apply" button and then click the "OK" button to close the dialog window. The explorer window should now display and allow access to the \Windows folder.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 3&lt;/u&gt; - \Windows folder visible through ActiveSync&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_GhRaWNC6A8Q/RfsAD73lw0I/AAAAAAAAABY/QyCtPTXgRLE/s1600-h/activeSyncYes.jpg"&gt;&lt;img style="cursor: pointer;" src="http://2.bp.blogspot.com/_GhRaWNC6A8Q/RfsAD73lw0I/AAAAAAAAABY/QyCtPTXgRLE/s320/activeSyncYes.jpg" alt="" id="BLOGGER_PHOTO_ID_5042624275381863234" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37149201-5232225362865382172?l=www.rhinomobile.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rhinomobile/~4/JWnfHuqu-A0" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2008-12-10T05:47:00.931-05:00</atom:updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_GhRaWNC6A8Q/Rfr8db3lwyI/AAAAAAAAABI/i0iDbFK-5vY/s72-c/activesyncNo.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.rhinomobile.net/2007/03/quick-hitter-navigating-windows-folder.html</feedburner:origLink></item><item><title>Oops, Activator.CreateInstance with a Singleton</title><link>http://feedproxy.google.com/~r/Rhinomobile/~3/5Kbq7kejXfs/oops-activatorcreateinstance-with.html</link><category>.NET Compact Framework</category><author>noreply@blogger.com (Ryan O'Neill)</author><pubDate>Wed, 07 Mar 2007 08:22:00 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-37149201.post-5675902656263911085</guid><description>The &lt;a href="http://msdn2.microsoft.com/en-us/library/ms998426.aspx"&gt;Singleton pattern&lt;/a&gt; is one of the most widely used &lt;a href="http://en.wikipedia.org/wiki/Design_Patterns"&gt;design patterns&lt;/a&gt;. The Singleton pattern ensures that exactly one and only one instance of a class is instantiated at any given time. It can also be somewhat confusing because it seems that there are multiple ways of implementing the pattern. In the article "&lt;a href="http://msdn2.microsoft.com/en-us/library/ms998558.aspx"&gt;Implementing Singleton in C#&lt;/a&gt;", MSDN recommends a slightly different approach for implementation than the &lt;u&gt;Design Patterns&lt;/u&gt; classic in order to take advantage of C#'s features.&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://msdn2.microsoft.com/en-us/library/ms998558.aspx"&gt;Activator class&lt;/a&gt; is a useful .NET class for creating types of objects as well as obtaining references to remote objects. On the .NET Compact Framework side, the method which stands out prominently is the &lt;a href="http://msdn2.microsoft.com/en-us/library/system.activator.createinstance.aspx"&gt;CreateInstance&lt;/a&gt; method. The .NET Compact Framework supports two overloads of the CreateInstance method. Both methods take a type. One takes a type as a parameter and returns an object. The other takes a type as a generic parameter and returns an object of that specific type.&lt;br /&gt;&lt;br /&gt;As part of my current project, there is a navigation component responsible for returning a user to where he or she left off within the application. At the lowest levels, this component is calling Activator.CreateInstance(Type) where Type is a type of form. Everything was working fine until yesterday, when the application would repeatedly blow up anytime it was started. The issue was traced down all the way to the Activator.CreateInstance(Type) method throwing a MissingMethodException.&lt;br /&gt;&lt;br /&gt;At first, I could not understand why a MissingMethodException was being thrown. A group of us theorized that maybe it was due to this particular form being in an assembly outside of the executing assembly. I was able to collapse the two assemblies together by adding all the files in the referenced assembly as links to the executing assembly. That did not fix the issue. The MissingMethodException was still occurring. &lt;br /&gt;&lt;br /&gt;I decided to step back and verify what I thought was true. I then looked up the particular &lt;a href="http://msdn2.microsoft.com/en-us/library/wccyzw83.aspx"&gt;CreateInstance&lt;/a&gt; method on MSDN. It was there that I realized exactly what was happening and why a MissingMethodException was being thrown. Next to MissingMethodException was the explanation of "No matching public constructor was found". At this point it was obvious what was the cause of the issue. The form type being passed to CreateInstance had no public constructor due to the fact that there should only ever be one object of that form instantiated (because it interacts with a native application's window handles). CreateInstance was failing because it had no idea how to create an instance of that type of form.&lt;br /&gt;&lt;br /&gt;This is just one of those times where the answer is blatantly obvious once found.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37149201-5675902656263911085?l=www.rhinomobile.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rhinomobile/~4/5Kbq7kejXfs" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2007-08-19T23:55:06.517-04:00</atom:updated><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://www.rhinomobile.net/2007/03/oops-activatorcreateinstance-with.html</feedburner:origLink></item><item><title>Samsung IP-830W Errors</title><link>http://feedproxy.google.com/~r/Rhinomobile/~3/hxUss7ErzUA/samsung-ip-830w-error.html</link><category>IP-830W</category><category>Sprint</category><category>Windows Mobile</category><author>noreply@blogger.com (Ryan O'Neill)</author><pubDate>Tue, 06 Mar 2007 14:05:00 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-37149201.post-788396847138572441</guid><description>With increasing frequency, I have started to receive some disturbing error messages from my Samsung IP-830w. I thought this would be a good forum to try to keep track of them. This entry will be updated from time to time with new messages I receive. It is not my intent to disparage the name of Sprint nor Samsung, just to point out the interesting messages displayed by this phone.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;March 06, 2007 -- CDMAdsatcmdp.c 806 Out of memory DS&lt;/li&gt;&lt;br /&gt;&lt;li&gt;April 03, 2007 -- CDMAhdrutil.c 1048 Failed write item to NV HDRMC&lt;/li&gt;&lt;br /&gt;&lt;li&gt;May 29, 2007 -- (This is not an error message, but a phone defect.) I changed the phone from ring mode to vibrate mode and left it alone. When I received a new message, the phone started vibrating and would not stop. Switching the phone back to ring mode, playing with settings, sliding the phone open and closed, and even turning the cellular radio on and off would not turn the vibrating off. Pulling down the little switch to turn the screen off did momentarily stop the vibrating. (It resumed immediately when turning the screen back on.) The only way to resolve the issue was to soft reset the phone.&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37149201-788396847138572441?l=www.rhinomobile.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rhinomobile/~4/hxUss7ErzUA" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2007-08-19T23:54:40.549-04:00</atom:updated><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://www.rhinomobile.net/2007/03/samsung-ip-830w-error.html</feedburner:origLink></item><item><title>Quick Hitter: Securing the Run Dialog</title><link>http://feedproxy.google.com/~r/Rhinomobile/~3/ioVXMabuxSQ/quick-hitter-securing-run-dialog.html</link><category>Quick Hitter</category><category>Windows Mobile</category><author>noreply@blogger.com (Ryan O'Neill)</author><pubDate>Sat, 24 Feb 2007 21:04:00 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-37149201.post-3293597194547252780</guid><description>The Windows Mobile taskbar provides users with an ability to run any particular program via the Run dialog. The Run dialog is accessed by pressing the action key (the center button of the directional pad) and tapping and holding (right-clicking) on the clock.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 1&lt;/u&gt; - The Run Dialog menu&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_GhRaWNC6A8Q/ReEZ6zegtwI/AAAAAAAAAAk/WhdIMR5oaUQ/s1600-h/rundialogon.JPG"&gt;&lt;img style="cursor: pointer;" src="http://3.bp.blogspot.com/_GhRaWNC6A8Q/ReEZ6zegtwI/AAAAAAAAAAk/WhdIMR5oaUQ/s320/rundialogon.JPG" alt="" id="BLOGGER_PHOTO_ID_5035334356418213634" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;When writing line of business software which should be the only application the user  should run on the device however, it may be necessary to disable the Run dialog as a security precaution. Disabling the Run dialog makes it more difficult for users to bypass the desired functionality. Access to the Run dialog can be disabled by setting a value within the HKEY_LOCAL_MACHINE\Security\Policies\Shell registry key. Inside that key, a value named NoRunDlg needs to be set as a DWORD with a value of 1.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 2&lt;/u&gt; - Remote Registry Editor showing NoRunDlg value&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_GhRaWNC6A8Q/ReEbZTegtxI/AAAAAAAAAAs/BVNy8ts_VQQ/s1600-h/norundialog.JPG"&gt;&lt;img style="cursor: pointer;" src="http://1.bp.blogspot.com/_GhRaWNC6A8Q/ReEbZTegtxI/AAAAAAAAAAs/BVNy8ts_VQQ/s320/norundialog.JPG" alt="" id="BLOGGER_PHOTO_ID_5035335979915851538" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Once the NoRunDlg value has been set, the menu showing Run and Clock is still accessible. However, the Run menu option is now disabled (indicated by it being grayed out) preventing users from running applications via that option.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 3&lt;/u&gt; - Run Dialog option grayed out&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_GhRaWNC6A8Q/ReEcFDegtyI/AAAAAAAAAA0/CEcmHeaybqs/s1600-h/rundialogoff.JPG"&gt;&lt;img style="cursor: pointer;" src="http://4.bp.blogspot.com/_GhRaWNC6A8Q/ReEcFDegtyI/AAAAAAAAAA0/CEcmHeaybqs/s320/rundialogoff.JPG" alt="" id="BLOGGER_PHOTO_ID_5035336731535128354" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37149201-3293597194547252780?l=www.rhinomobile.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rhinomobile/~4/ioVXMabuxSQ" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2008-12-10T05:47:01.386-05:00</atom:updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_GhRaWNC6A8Q/ReEZ6zegtwI/AAAAAAAAAAk/WhdIMR5oaUQ/s72-c/rundialogon.JPG" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.rhinomobile.net/2007/02/quick-hitter-securing-run-dialog.html</feedburner:origLink></item><item><title>Mobile Spy</title><link>http://feedproxy.google.com/~r/Rhinomobile/~3/7SWL2ehH7Vc/mobile-spy.html</link><category>.NET Compact Framework</category><category>Windows Mobile</category><author>noreply@blogger.com (Ryan O'Neill)</author><pubDate>Thu, 22 Feb 2007 15:54:00 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-37149201.post-683320046378239140</guid><description>Many Windows and Windows Mobile developers have at one time used the Microsoft Spy++ or the Microsoft CE Remote Spy tools. The Microsoft Spy++ tool allows a developer to view properties of selected windows, threads, processes, or messages using a graphical tree. Remote Spy displays a list of the windows that are open on a particular device that is connected. In addition to the list of windows, Remote Spy also provides the capability to view properties of a window such as the class, style, extended style, window procedure address, window positioning, and client area window positioning as well as the messages within the message queue for a selected window. &lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 1&lt;/u&gt; - Microsoft CE Remote Spy&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_GhRaWNC6A8Q/Rd4yMDegtuI/AAAAAAAAAAM/Kauxs346UEc/s1600-h/remotespy.JPG"&gt;&lt;img style="cursor: pointer;" src="http://1.bp.blogspot.com/_GhRaWNC6A8Q/Rd4yMDegtuI/AAAAAAAAAAM/Kauxs346UEc/s400/remotespy.JPG" alt="" id="BLOGGER_PHOTO_ID_5034516616119891682" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Remote Spy is an excellent application which is extremely useful for any mobile developer. What happens though if an individual wants to see the listing of top-level windows currently running on a device and does not have the ability to connect the device to another machine where Remote Spy can be run? Here's a simple application that performs that functionality.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 2&lt;/u&gt; - Mobile Spy&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_GhRaWNC6A8Q/Rd41TTegtvI/AAAAAAAAAAU/65-oKT2ALZI/s1600-h/mobilespy.JPG"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_GhRaWNC6A8Q/Rd41TTegtvI/AAAAAAAAAAU/65-oKT2ALZI/s320/mobilespy.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5034520039208826610" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This application (which has been named Mobile Spy just to differentiate) shows a listing of all the top level windows running on a device at a particular moment in time. Along side the window handle of the top-level window, Mobile Spy also displays the Window Text, and the Class Name of the class to which a window belongs. &lt;br /&gt;&lt;br /&gt;This application uses three P/Invoked methods to retrieve the window handles, the window text, and the window class names:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://msdn2.microsoft.com/en-us/library/ms960883.aspx"&gt;GetWindow&lt;/a&gt; - This function retrieves the handle to a window that has the specified relationship to the specified window.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://msdn2.microsoft.com/en-us/library/ms960894.aspx"&gt;GetWindowText&lt;/a&gt; - This function copies the text of the specified windows title bar—if it has one—into a buffer. If the specified window is a control, the text of the control is copied.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://msdn2.microsoft.com/en-us/library/ms960660.aspx"&gt;GetClassName&lt;/a&gt; - This function retrieves the name of the class to which the specified window belongs.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;(Source for all above descriptions comes directly from MSDN)&lt;br /&gt;&lt;br /&gt;The application contains a simple button and a simple list view with three columns. The "Refresh" button loads the windows in at a specific point in time. Here is code  of the method associated with the click event of the "Refresh" button as well as an associated explanation:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    lvWindows.BeginUpdate();&lt;br /&gt;    lvWindows.Items.Clear();&lt;br /&gt;    IntPtr window = GetWindow(this.Handle, GW_HWNDFIRST);&lt;br /&gt;    StringBuilder className = new StringBuilder(MAX_LENGTH);&lt;br /&gt;    StringBuilder windowText = new StringBuilder(MAX_LENGTH);&lt;br /&gt;    while (window != IntPtr.Zero)&lt;br /&gt;    {                &lt;br /&gt;        int classNameCount = GetClassName(window, className, MAX_LENGTH);&lt;br /&gt;        int windowTextCount = GetWindowText(window, windowText, MAX_LENGTH);&lt;br /&gt;        string windowTextDisplay = NO_NAME;&lt;br /&gt;        if (windowTextCount &gt; 0)&lt;br /&gt;        {&lt;br /&gt;            windowTextDisplay = windowText.ToString();&lt;br /&gt;        }&lt;br /&gt;        string hexWindow = String.Format("{0:X2}", window.ToInt32());&lt;br /&gt;        ListViewItem item = new ListViewItem(new string[] { hexWindow, &lt;br /&gt;                            windowTextDisplay, className.ToString() });&lt;br /&gt;        lvWindows.Items.Add(item);&lt;br /&gt;        window = GetWindow(window, GW_HWNDNEXT);&lt;br /&gt;    }&lt;br /&gt;    lvWindows.EndUpdate();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The method begins with a call to lvWindows.BeginUpdate() and lvWindows.Items.Clear(). lvWindows is the name of the ListView where the information is displayed. Calling BeginUpdate prevents the control from redrawing until EndUpdate is called. The next call is made to clear the items from the list view. Be cognizant of the difference between calling lvWindows.Clear() and lvWindows.Items.Clear().&lt;br /&gt;&lt;br /&gt;The next line is where it starts to get interesting with a call to GetWindow using the window handle of the Mobile Spy application and GW_HWNDFIRST (defined as 0). Using the GW_HWNDFIRST constant retrieves the handle of the window highest in the Z-order. Because GetWindow is passed a top-level window, it retrieves the topmost window in the Z-order. &lt;br /&gt;&lt;br /&gt;The application then sets up a while loop and iterates as long as the returned window handle is not zero. If the window handle is not zero, the application retrieves the Class Name and the WindowText using a StringBuilder for each call respectively. The return value of both the GetClassName and GetWindowText functions are the count of characters copied into the StringBuilder passed in. If the window text returned is a length of zero, "&amp;lt;No name&amp;gt;" is used for display purposes (just as in Remote Spy). &lt;br /&gt;&lt;br /&gt;A list view item is setup using the window handle, the window text, and the class name. The window handle is slightly modified to be displayed in its hexadecimal notation (just as in Remote Spy). The window text is displayed as explained above and the class name is displayed as returned by the GetClassName function. The list view item is added to the list view.&lt;br /&gt;&lt;br /&gt;When the application is done processing for a particular window handle, it attempts to retrieve the next window handle. The next window handle within the Z-order is retrieved via a call to GetWindow using the current window handle and GW_HWNDNEXT (defined as 2). GW_HWNDNEXT retrieves the window below the specified window in the Z-order. If this window handle retrieved is zero, the loop will exit on the next iteration. If this window handle is non-zero, the inner section of the loop will retrieve the window text and the class name and add the information to the list view.&lt;br /&gt;Finally the list view is allowed to resume drawing because of the EndUpdate() method call.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37149201-683320046378239140?l=www.rhinomobile.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rhinomobile/~4/7SWL2ehH7Vc" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2008-12-10T05:47:02.103-05:00</atom:updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_GhRaWNC6A8Q/Rd4yMDegtuI/AAAAAAAAAAM/Kauxs346UEc/s72-c/remotespy.JPG" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.rhinomobile.net/2007/02/mobile-spy.html</feedburner:origLink></item><item><title>My Mobile Application Travel Experience</title><link>http://feedproxy.google.com/~r/Rhinomobile/~3/UJe2ycuR_VI/my-mobile-application-travel-experience.html</link><category>Mobile Applications</category><author>noreply@blogger.com (Ryan O'Neill)</author><pubDate>Sun, 10 Dec 2006 13:08:00 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-37149201.post-6347221877942342809</guid><description>With a four hour layover last Sunday in Cincinnati (Northern Kentucky to be entirely accurate), I had the opportunity to look at some mobile applications with which I had not previously been acquainted. Here's the rundown:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Handango On Demand&lt;/span&gt;: The installation for this application came with my new phone (see earlier post about the Samsung IP-830W). Firstly, and most importantly, the content is actually pretty good. When I landed at my destination in Seattle, I actually used this application to find out what the score was of the Giants vs. Cowboys game. &lt;br /&gt;&lt;br /&gt;Unfortunately, the content is the only good thing about the application. The user interface is confusing and non-standard. It is completely understandable if an application follows Windows Mobile User Interface guidelines, executes in full screen mode, or executes in a kiosk like mode. Oddly enough, this application combines all three. It replaces the Windows taskbar, yet still uses soft keys. Button placements are also inconsistent, and it appeared to me that they were trying to trick me into tapping a button to buy something by constantly moving where buttons were placed. &lt;br /&gt;&lt;br /&gt;The user interface only scratches the surface though. Before installing this application, I had the .NET Compact Framework 2.0 SP1 installed. Well, Handango On Demand wouldn't install without the original 2.0 version installed. That is just plain embarrassing.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Audible Air&lt;/span&gt;: This application works in conjunction with the Audible.com book service. Audible.com provides audio books and program subscriptions for purchase and download in formats that work on portable media players such as ipods. A few years ago (when I had a little bit more free time), I had had a subscription and purchased probably about 20 books. Miraculously, I was able to remember my username and password. After logging in with my information, I was able to see the list of items that I had previously purchased and download them directly to my phone. I chose to download one of them which was very painless (and fast with EV-DO speeds). If the audible team extends the application so that new items can be purchased, I think they might get enough impulse buys from people like me to be worth it. I definitely would have bought a new audio book in that position for my flight to Seattle.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Windows Live Search for Mobile Beta&lt;/span&gt;: Wow! I downloaded and installed the cab file for this application while sitting in the airport. Being that I had booked my flight to Seattle less than a week earlier (and thus the reason for my four hour layover), I had somehow neglected to figure out how I was getting from the Seattle-Tacoma airport to my hotel in downtown Seattle. As soon as the plane landed in Seattle and it was taxi-ing to the gate, I whipped out my phone and started Windows Live Search. I was easily able to look up the address and the phone number of my hotel and even see where on the map it was located. I used this information to call them and ask, and once I had decided on taking a taxi I used the map to keep track of the route. &lt;br /&gt;&lt;br /&gt;One suggestion I would make for the future is the ability to add looked up information directly to contacts. The other little minor annoyance was that the application is added to the Programs menu with a shortcut name of "Search". On my phone, Sprint had already added one with that name which means that Windows Live Search shows up as "Search (1)". Overall though, this is an amazing application which everyone who can have it installed should have it installed.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37149201-6347221877942342809?l=www.rhinomobile.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rhinomobile/~4/UJe2ycuR_VI" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2007-08-19T23:53:17.616-04:00</atom:updated><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.rhinomobile.net/2006/12/my-mobile-application-travel-experience.html</feedburner:origLink></item><item><title>Quick Hitter: Blank Form</title><link>http://feedproxy.google.com/~r/Rhinomobile/~3/iBCSrzbbK8g/quick-hitter-blank-form.html</link><category>Quick Hitter</category><category>Visual Studio</category><category>.NET Compact Framework</category><author>noreply@blogger.com (Ryan O'Neill)</author><pubDate>Sat, 02 Dec 2006 07:30:00 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-37149201.post-6521403137478414148</guid><description>What a difference a function call makes sometimes, right?&lt;br /&gt;&lt;br /&gt;Ever start a program, go to a specific form and all the controls that were placed on the form at design time are missing? Well, some way some how, the InitializeComponent method has probably been removed from the form's constructor. The InitializeComponent method is a private void method which is placed inside the "Windows Form Designer generated code" region by Visual Studio. The attached comment even states that it is a "Required method for Designer support - do not modify the contents of this method with the code editor." This method sets all the properties of the form, initializes every control and subsequently adds each one to its parent control. Sometimes people think this is just magic that the controls get added to the form, but it's the InitializeComponent method which is doing all of the heavy lifting. So, if the controls are missing, check to verify that InitializeComponent is being called in the form's constructor.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37149201-6521403137478414148?l=www.rhinomobile.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rhinomobile/~4/iBCSrzbbK8g" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2007-08-20T00:34:12.662-04:00</atom:updated><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.rhinomobile.net/2006/12/quick-hitter-blank-form.html</feedburner:origLink></item><item><title>Performance vs. Readability</title><link>http://feedproxy.google.com/~r/Rhinomobile/~3/hlVQB_wEwZI/performance-vs-readability.html</link><category>.NET Compact Framework</category><author>noreply@blogger.com (Ryan O'Neill)</author><pubDate>Sun, 26 Nov 2006 20:21:00 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-37149201.post-7785394084367230012</guid><description>My pal &lt;a href="http://www.satter.org"&gt;Rabi&lt;/a&gt; recently analyzed Steve McConnell's updated classic &lt;u&gt;Code Complete&lt;/u&gt; from a &lt;a href="http://www.satter.org/2006/11/code_complete_2.html"&gt;mobile perspective&lt;/a&gt;. Personally, I am a huge fan of McConnell's work and credit his books and reading suggestions with tremendously improving my own professional development. However, as Rabi points out, not all suggestions work in all situations.&lt;br /&gt;&lt;br /&gt;Among many great points Rabi makes, these two stick out for me:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;"So the Compact Framework will pitch code on a per method basis to free memory unlike the full framework."&lt;/li&gt;&lt;br /&gt;&lt;li&gt;"Don't have methods just to have more readable code - more code in a method is better"&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;So how can we as managed &lt;i&gt;(sometimes)&lt;/i&gt; mobile developers fight the trade-off of performance vs. readability? Currently, I don't have a good answer. What I do have, however, is a suggestion. &lt;br /&gt;&lt;br /&gt;Bring the inline function specifier from C++ to the .NET Compact Framework. &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_pluslang_inline_specifier.asp"&gt;MSDN&lt;/a&gt; defines inline and __inline as function specifiers that "instruct the compiler to insert a copy of the function body into each place the function is called." &lt;br /&gt;&lt;br /&gt;Having the ability to use inline functions would mitigate Rabi's points above. Because code is pitched on a per method basis, the inline code would not be pitched being that the inline code is part of the actual method where it's being used. Additionally, the readability gains from having discrete methods instead of excessively long functions would be there as well.&lt;br /&gt;&lt;br /&gt;Another additional benefit would be much easier unit testing. It would be much simpler to unit test these functions by having something like the following:&lt;br /&gt;&lt;br /&gt;#if UnitTesting&lt;br /&gt;public int CalculateReturnValue(int param1, int param2, int param3)&lt;br /&gt;#else&lt;br /&gt;private inline int CalculateReturnValue(int param1, int param2, int param3)&lt;br /&gt;#endif&lt;br /&gt;... Continue method definition&lt;br /&gt;&lt;br /&gt;Therefore, from a testing and readability standpoint the benefit would be had with these methods looking and acting like methods, and from a performance standpoint the benefit would be had with these methods acting like a part of other methods.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37149201-7785394084367230012?l=www.rhinomobile.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rhinomobile/~4/hlVQB_wEwZI" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2007-08-19T23:52:14.560-04:00</atom:updated><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.rhinomobile.net/2006/11/performance-vs-readability.html</feedburner:origLink></item><item><title>Samsung IP-830W Initial Thoughts</title><link>http://feedproxy.google.com/~r/Rhinomobile/~3/KQfbiCHx83A/samsung-ip-830w-initial-thoughts.html</link><category>IP-830W</category><category>Sprint</category><category>Windows Mobile</category><author>noreply@blogger.com (Ryan O'Neill)</author><pubDate>Sun, 26 Nov 2006 18:06:00 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-37149201.post-116459495474337333</guid><description>Due to the current project I am staffed on for work, I am unable to have a cellphone with a camera within the building. Being a Sprint customer for the last 7 years or so and not having much desire to switch carriers, this left me with very few options for phones. Recently, Sprint finally came out with a Windows Mobile 5 phone without a camera - the Samsung IP-830W. The IP-830W is a dual CDMA/GSM phone (although the GSM portion is only usable with overseas frequencies). I've had the IP-830W for about two weeks now, so here are my initial thoughts.&lt;br /&gt;&lt;br /&gt;The Good:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Windows Mobile 5.0 - Being a mobile developer, it's great to finally have a Windows Mobile 5.0 phone.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;EV-DO - Major +++ - While stuck late one Monday at work, I was able to nicely stream the Giants on Monday Night Football using Orb.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;No Camera - I have always found cellphone cameras to be completely worthless and think it's a bad idea that Microsoft made them be standard on Smartphones.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Slide Down Keyboard - I also can't stand keyboards that slide out to the slide, which is the reason I never bought a PPC 6700. I have found myself using the keyboard more than I thought I would.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Regular and Extended Battery - Included in the box is an extended battery in addition to a standard battery.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Easy Speed Dial Buttons - One of my major gripes with the PPC 6600/6601 was that if the particular number button was not held down perfectly, the speed dial would not activate. The IP-830W is great on this front.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;The Bad:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Not Mini-USB - Just great, another cable to carry around in my bag.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;On/off Button - I'm not liking the slider on/off button, although this is only a slight negative.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Stick up antenna - It's just annoying to have a phone with an antenna again.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;The Ugly:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Unreliable Push Email - I've had problems with the push email constantly updating. I feel like it synchronizes when it feels like. Using AUTD with my PPC 6600 and 6601, this was never an issue.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Previous Windows Mobile Phones:&lt;br /&gt;Hitachi G1000&lt;br /&gt;Audiovox PPC 6600&lt;br /&gt;Audiovox PPC 6601 (Bought when I needed to ditch the phone with the camera)&lt;br /&gt;&lt;br /&gt;Here's a comparison photo of my current and previous Windows Mobile phones.&lt;br /&gt;(From left to right: Hitachi G1000, Audiovox PPC 6601, Samsung IP-830W)&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/x/blogger/933/4167/1600/631285/IMG_0100.jpg"&gt;&lt;img style="cursor: pointer;" src="http://photos1.blogger.com/x/blogger/933/4167/320/991084/IMG_0100.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37149201-116459495474337333?l=www.rhinomobile.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rhinomobile/~4/KQfbiCHx83A" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2007-08-19T23:51:24.636-04:00</atom:updated><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.rhinomobile.net/2006/11/samsung-ip-830w-initial-thoughts.html</feedburner:origLink></item><item><title>System Colors (Part 1)</title><link>http://feedproxy.google.com/~r/Rhinomobile/~3/dgElpGB5XLE/system-colors-part-1.html</link><category>GWES</category><category>.NET Compact Framework</category><category>Windows Mobile</category><author>noreply@blogger.com (Ryan O'Neill)</author><pubDate>Sun, 26 Nov 2006 17:10:00 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-37149201.post-116459073305523485</guid><description>While putting together what hopefully will be a future post, I came across a situation where I needed to know what the red, green, and blue values were for various system colors. On a Windows Mobile device, those values are stored in the Registry. In fact, when a user changes the Today theme via the Today Settings applet, behind the scenes that specific registry value is being changed.&lt;br /&gt;&lt;br /&gt;All the information in the following paragraph comes from &lt;a href="http://msdn2.microsoft.com/en-us/library/ms906614.aspx"&gt;this entry&lt;/a&gt; on MSDN.&lt;br /&gt;&lt;br /&gt;System Colors are stored in the SysColor registry value in the HKEY_LOCAL_MACHINE\System\GWE key. GWE is the Graphics, Windows, and Events subsystem. There are 29 different colors which are stored in a blob in the SysColor key. These values control items such as caption background and text colors, button colors, and window and menu colors.&lt;br /&gt;&lt;br /&gt;Below is a C# class which allows easy retrieval and access to those System Colors. Part 2 will extend the class to save new values to the System Colors.&lt;br /&gt;&lt;br /&gt;These are images of a simple application used to retrieve the system colors and set the foreground color of list view items to the corresponding colors.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 1&lt;/u&gt; - Before Retrieving System Colors&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/x/blogger/933/4167/1600/464053/before.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/x/blogger/933/4167/400/192205/before.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 2&lt;/u&gt; - After Retrieving System Colors&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/x/blogger/933/4167/1600/376933/afterDefault.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/x/blogger/933/4167/400/386553/afterDefault.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Image 3&lt;/u&gt; - After Changing to Guava Bubbles Today Theme and Retrieving System Colors&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/x/blogger/933/4167/1600/47274/afterGuava.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/x/blogger/933/4167/400/694565/afterGuava.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#region Using Directives&lt;br /&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Drawing;&lt;br /&gt;using System.IO;&lt;br /&gt;using System.Security;&lt;br /&gt;using System.Text;&lt;br /&gt;using Microsoft.Win32;&lt;br /&gt;&lt;br /&gt;#endregion&lt;br /&gt;&lt;br /&gt;namespace SystemColors&lt;br /&gt;{&lt;br /&gt;   public static class SystemColors&lt;br /&gt;   {&lt;br /&gt;&lt;br /&gt;       #region MSDN Information&lt;br /&gt;&lt;br /&gt;       // Taken from "Customizing System Colors" (http://msdn2.microsoft.com/en-us/library/ms906614.aspx)&lt;br /&gt;&lt;br /&gt;       //0     COLOR_SCROLLBAR     Color of the gray area of a scroll bar.&lt;br /&gt;       //1     COLOR_BACKGROUND     Background color of the desktop window.&lt;br /&gt;       //2     COLOR_ACTIVECAPTION     Color of the title bar of an active window.&lt;br /&gt;       //3     COLOR_INACTIVECAPTION     Color of the title bar of an inactive window.&lt;br /&gt;       //4     COLOR_MENU     Background color of a menu.&lt;br /&gt;       //5     COLOR_WINDOW     Background color of a window.&lt;br /&gt;       //6     COLOR_WINDOWFRAME     Color of a window frame.&lt;br /&gt;       //7     COLOR_MENUTEXT     Color of the text in a menu.&lt;br /&gt;       //8     COLOR_WINDOWTEXT     Color of the text in a window.&lt;br /&gt;       //9     COLOR_CAPTIONTEXT     Color of the text in a title bar and of the size box and scroll bar arrow box.&lt;br /&gt;       //10     COLOR_ACTIVEBORDER     Color of the border of an active window.&lt;br /&gt;       //11     COLOR_INACTIVEBORDER     Color of the border of an inactive window.&lt;br /&gt;       //12     COLOR_APPWORKSPACE     Background color of multiple document interface (MDI) applications.&lt;br /&gt;       //13     COLOR_HIGHLIGHT     Color of an item selected in a control.&lt;br /&gt;       //14     COLOR_HIGHLIGHTTEXT     Color of the text of an item selected in a control.&lt;br /&gt;       //15     COLOR_BTNFACE     Color of the face of a button.&lt;br /&gt;       //16     COLOR_BTNSHADOW     Shadow color of buttons for edges that face away from the light source.&lt;br /&gt;       //17     COLOR_GRAYTEXT     Color of shaded text. This color is set to 0 if the current display driver does not support a solid gray color.&lt;br /&gt;       //18     COLOR_BTNTEXT     Color of the text for push buttons.&lt;br /&gt;       //19     COLOR_INACTIVECAPTIONTEXT     Color of the text in the title bar of an inactive window.&lt;br /&gt;       //20     COLOR_BTNHIGHLIGHT     Highlight color of buttons for edges that face the light source.&lt;br /&gt;       //21     COLOR_3DDKSHADOW     Color of the dark shadow for three-dimensional display elements.&lt;br /&gt;       //22     COLOR_3DLIGHT     Highlight color of three-dimensional display elements for edges that face the light source.&lt;br /&gt;       //23     COLOR_INFOTEXT     Color of the text for ToolTip controls.&lt;br /&gt;       //24     COLOR_INFOBK     Background color for ToolTip controls.&lt;br /&gt;       //25     COLOR_STATIC     Background color for static controls and dialog boxes. Supported in Windows CE 2.0 and later.&lt;br /&gt;       //26     COLOR_STATICTEXT     Color of the text for static controls. Supported in Windows CE 2.0 and later.&lt;br /&gt;       //27     COLOR_GRADIENTACTIVECAPTION     Color of the title bar of an active window that is filled with a color gradient.&lt;br /&gt;       //28     COLOR_GRADIENTINACTIVECAPTION     Color of the title bar of an inactive window that is filled with a color gradient.&lt;br /&gt;&lt;br /&gt;       #endregion&lt;br /&gt;&lt;br /&gt;       #region Constants&lt;br /&gt;&lt;br /&gt;       private const string SYSTEM_SUBKEY = "SYSTEM";&lt;br /&gt;       private const string GWE_SUBKEY = "GWE";&lt;br /&gt;       private const string SYSTEM_COLORS_KEY = SYSTEM_SUBKEY + SLASH + GWE_SUBKEY;&lt;br /&gt;       private const string SLASH = @"\";&lt;br /&gt;       private const string SYSTEM_COLORS_VALUE = "SysColor";&lt;br /&gt;&lt;br /&gt;       private const int SYSTEM_COLORS_BLOB_SIZE = 116;        // 29 (# of values) * 4 (size of DWORD)&lt;br /&gt;&lt;br /&gt;       private const int SCROLLBAR_OFFSET = 0;                 //  0 (position) * 4 (size of DWORD)&lt;br /&gt;       private const int BACKGROUND_OFFSET = 4;                //  1 (position) * 4 (size of DWORD)&lt;br /&gt;       private const int ACTIVECAPTION_OFFSET = 8;             //  2 (position) * 4 (size of DWORD)&lt;br /&gt;       private const int INACTIVECAPTION_OFFSET = 12;          //  3 (position) * 4 (size of DWORD)&lt;br /&gt;       private const int MENU_OFFSET = 16;                     //  4 (position) * 4 (size of DWORD)&lt;br /&gt;       private const int WINDOW_OFFSET = 20;                   //  5 (position) * 4 (size of DWORD)&lt;br /&gt;       private const int WINDOWFRAME_OFFSET = 24;              //  6 (position) * 4 (size of DWORD)&lt;br /&gt;       private const int MENUTEXT_OFFSET = 28;                 //  7 (position) * 4 (size of DWORD)&lt;br /&gt;       private const int WINDOWTEXT_OFFSET = 32;               //  8 (position) * 4 (size of DWORD)&lt;br /&gt;       private const int CAPTIONTEXT_OFFSET = 36;              //  9 (position) * 4 (size of DWORD)&lt;br /&gt;       private const int ACTIVEBORDER_OFFSET = 40;             // 10 (position) * 4 (size of DWORD)&lt;br /&gt;       private const int INACTIVEBORDER_OFFSET = 44;           // 11 (position) * 4 (size of DWORD)&lt;br /&gt;       private const int APPWORKSPACE_OFFSET = 48;             // 12 (position) * 4 (size of DWORD)&lt;br /&gt;       private const int HIGHLIGHT_OFFSET = 52;                // 13 (position) * 4 (size of DWORD)&lt;br /&gt;       private const int HIGHLIGHTTEXT_OFFSET = 56;            // 14 (position) * 4 (size of DWORD)&lt;br /&gt;       private const int BTNFACE_OFFSET = 60;                  // 15 (position) * 4 (size of DWORD)&lt;br /&gt;       private const int BTNSHADOW_OFFSET = 64;                // 16 (position) * 4 (size of DWORD)&lt;br /&gt;       private const int GRAYTEXT_OFFSET = 68;                 // 17 (position) * 4 (size of DWORD)&lt;br /&gt;       private const int BTNTEXT_OFFSET = 72;                  // 18 (position) * 4 (size of DWORD)&lt;br /&gt;       private const int INACTIVECAPTIONTEXT_OFFSET = 76;      // 19 (position) * 4 (size of DWORD)&lt;br /&gt;       private const int BTNHIGHLIGHT_OFFSET = 80;             // 20 (position) * 4 (size of DWORD)&lt;br /&gt;       private const int THREEDDKSHADOW_OFFSET = 84;           // 21 (position) * 4 (size of DWORD)&lt;br /&gt;       private const int THREEDLIGHT_OFFSET = 88;              // 22 (position) * 4 (size of DWORD)&lt;br /&gt;       private const int INFOTEXT_OFFSET = 92;                 // 23 (position) * 4 (size of DWORD)&lt;br /&gt;       private const int INFOBK_OFFSET = 96;                   // 24 (position) * 4 (size of DWORD)&lt;br /&gt;       private const int STATIC_OFFSET = 100;                  // 25 (position) * 4 (size of DWORD)&lt;br /&gt;       private const int STATICTEXT_OFFSET = 104;              // 26 (position) * 4 (size of DWORD)&lt;br /&gt;       private const int GRADIENTACTIVECAPTION_OFFSET = 108;   // 27 (position) * 4 (size of DWORD)&lt;br /&gt;       private const int GRADIENTINACTIVECAPTION_OFFSET = 112; // 28 (position) * 4 (size of DWORD)&lt;br /&gt;&lt;br /&gt;       #endregion&lt;br /&gt;&lt;br /&gt;       #region Static Fields&lt;br /&gt;&lt;br /&gt;       private static Color m_scrollbar;&lt;br /&gt;       private static Color m_background;&lt;br /&gt;       private static Color m_activeCaption;&lt;br /&gt;       private static Color m_inactiveCaption;&lt;br /&gt;       private static Color m_menu;&lt;br /&gt;       private static Color m_window;&lt;br /&gt;       private static Color m_windowFrame;&lt;br /&gt;       private static Color m_menuText;&lt;br /&gt;       private static Color m_windowText;&lt;br /&gt;       private static Color m_captionText;&lt;br /&gt;       private static Color m_activeBorder;&lt;br /&gt;       private static Color m_inactiveBorder;&lt;br /&gt;       private static Color m_appWorkspace;&lt;br /&gt;       private static Color m_highlight;&lt;br /&gt;       private static Color m_highlightText;&lt;br /&gt;       private static Color m_buttonFace;&lt;br /&gt;       private static Color m_buttonShadow;&lt;br /&gt;       private static Color m_grayText;&lt;br /&gt;       private static Color m_buttonText;&lt;br /&gt;       private static Color m_inactiveCaptionText;&lt;br /&gt;       private static Color m_buttonHighlight;&lt;br /&gt;       private static Color m_threeDimensionalDarkShadow;&lt;br /&gt;       private static Color m_threeDimensionalLight;&lt;br /&gt;       private static Color m_infoText;&lt;br /&gt;       private static Color m_infoBackground;&lt;br /&gt;       private static Color m_static;&lt;br /&gt;       private static Color m_staticText;&lt;br /&gt;       private static Color m_gradientActiveCaption;&lt;br /&gt;       private static Color m_gradientInactiveCaption;&lt;br /&gt;&lt;br /&gt;       #endregion&lt;br /&gt;&lt;br /&gt;       #region Private Static Methods&lt;br /&gt;&lt;br /&gt;       private static Color ConvertToSystemColor(byte[] values, int offset)&lt;br /&gt;       {&lt;br /&gt;           if (values.Length &gt;= (offset + 4))&lt;br /&gt;           {&lt;br /&gt;               int r = (int)values[offset];&lt;br /&gt;               int g = (int)values[offset + 1];&lt;br /&gt;               int b = (int)values[offset + 2];&lt;br /&gt;               return Color.FromArgb(r, g, b);&lt;br /&gt;           }&lt;br /&gt;           else&lt;br /&gt;           {&lt;br /&gt;               throw new SystemColorsException("Incorrect System Color Values Received");&lt;br /&gt;           }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       private static void ParseSystemColors(byte[] systemColors)&lt;br /&gt;       {&lt;br /&gt;           // Make sure size is proper&lt;br /&gt;           if (systemColors.Length == SYSTEM_COLORS_BLOB_SIZE)&lt;br /&gt;           {&lt;br /&gt;               m_scrollbar = ConvertToSystemColor(systemColors, SCROLLBAR_OFFSET);&lt;br /&gt;               m_background = ConvertToSystemColor(systemColors, BACKGROUND_OFFSET);&lt;br /&gt;               m_activeCaption = ConvertToSystemColor(systemColors, ACTIVECAPTION_OFFSET);&lt;br /&gt;               m_inactiveCaption = ConvertToSystemColor(systemColors, INACTIVECAPTION_OFFSET);&lt;br /&gt;               m_menu = ConvertToSystemColor(systemColors, MENU_OFFSET);&lt;br /&gt;               m_window = ConvertToSystemColor(systemColors, WINDOW_OFFSET);&lt;br /&gt;               m_windowFrame = ConvertToSystemColor(systemColors, WINDOWFRAME_OFFSET);&lt;br /&gt;               m_menuText = ConvertToSystemColor(systemColors, MENUTEXT_OFFSET);&lt;br /&gt;               m_windowText = ConvertToSystemColor(systemColors, WINDOWTEXT_OFFSET);&lt;br /&gt;               m_captionText = ConvertToSystemColor(systemColors, CAPTIONTEXT_OFFSET);&lt;br /&gt;               m_activeBorder = ConvertToSystemColor(systemColors, ACTIVEBORDER_OFFSET);&lt;br /&gt;               m_inactiveBorder = ConvertToSystemColor(systemColors, INACTIVEBORDER_OFFSET);&lt;br /&gt;               m_appWorkspace = ConvertToSystemColor(systemColors, APPWORKSPACE_OFFSET);&lt;br /&gt;               m_highlight = ConvertToSystemColor(systemColors, HIGHLIGHT_OFFSET);&lt;br /&gt;               m_highlightText = ConvertToSystemColor(systemColors, HIGHLIGHTTEXT_OFFSET);&lt;br /&gt;               m_buttonFace = ConvertToSystemColor(systemColors, BTNFACE_OFFSET);&lt;br /&gt;               m_buttonShadow = ConvertToSystemColor(systemColors, BTNSHADOW_OFFSET);&lt;br /&gt;               m_grayText = ConvertToSystemColor(systemColors, GRAYTEXT_OFFSET);&lt;br /&gt;               m_buttonText = ConvertToSystemColor(systemColors, BTNTEXT_OFFSET);&lt;br /&gt;               m_inactiveCaptionText = ConvertToSystemColor(systemColors, INACTIVECAPTIONTEXT_OFFSET);&lt;br /&gt;               m_buttonHighlight = ConvertToSystemColor(systemColors, BTNHIGHLIGHT_OFFSET);&lt;br /&gt;               m_threeDimensionalDarkShadow = ConvertToSystemColor(systemColors, THREEDDKSHADOW_OFFSET);&lt;br /&gt;               m_threeDimensionalLight = ConvertToSystemColor(systemColors, THREEDLIGHT_OFFSET);&lt;br /&gt;               m_infoText = ConvertToSystemColor(systemColors, INFOTEXT_OFFSET);&lt;br /&gt;               m_infoBackground = ConvertToSystemColor(systemColors, INFOBK_OFFSET);&lt;br /&gt;               m_static = ConvertToSystemColor(systemColors, STATIC_OFFSET);&lt;br /&gt;               m_staticText = ConvertToSystemColor(systemColors, STATICTEXT_OFFSET);&lt;br /&gt;               m_gradientActiveCaption = ConvertToSystemColor(systemColors, GRADIENTACTIVECAPTION_OFFSET);&lt;br /&gt;               m_gradientInactiveCaption = ConvertToSystemColor(systemColors, GRADIENTINACTIVECAPTION_OFFSET);&lt;br /&gt;           }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       private static void LoadSystemColors(bool throwExceptions)&lt;br /&gt;       {&lt;br /&gt;           RegistryKey key = null;&lt;br /&gt;&lt;br /&gt;           try&lt;br /&gt;           {&lt;br /&gt;               key = Registry.LocalMachine.OpenSubKey(SYSTEM_COLORS_KEY);&lt;br /&gt;               byte[] value = (byte[])key.GetValue(SYSTEM_COLORS_VALUE);&lt;br /&gt;               ParseSystemColors(value);&lt;br /&gt;           }&lt;br /&gt;           catch (UnauthorizedAccessException uae)&lt;br /&gt;           {&lt;br /&gt;               if (throwExceptions)&lt;br /&gt;               {&lt;br /&gt;                   throw new SystemColorsException(uae.Message, uae);&lt;br /&gt;               }&lt;br /&gt;           }&lt;br /&gt;           catch (IOException ioe)&lt;br /&gt;           {&lt;br /&gt;               if (throwExceptions)&lt;br /&gt;               {&lt;br /&gt;                   throw new SystemColorsException(ioe.Message, ioe);&lt;br /&gt;               }&lt;br /&gt;           }&lt;br /&gt;           catch (SecurityException se)&lt;br /&gt;           {&lt;br /&gt;               if (throwExceptions)&lt;br /&gt;               {&lt;br /&gt;                   throw new SystemColorsException(se.Message, se);&lt;br /&gt;               }&lt;br /&gt;           }&lt;br /&gt;           catch (ArgumentNullException ane)&lt;br /&gt;           {&lt;br /&gt;               if (throwExceptions)&lt;br /&gt;               {&lt;br /&gt;                   throw new SystemColorsException(ane.Message, ane);&lt;br /&gt;               }&lt;br /&gt;           }&lt;br /&gt;           catch (ArgumentException ae)&lt;br /&gt;           {&lt;br /&gt;               if (throwExceptions)&lt;br /&gt;               {&lt;br /&gt;                   throw new SystemColorsException(ae.Message, ae);&lt;br /&gt;               }&lt;br /&gt;           }&lt;br /&gt;           catch (ObjectDisposedException ode)&lt;br /&gt;           {&lt;br /&gt;               if (throwExceptions)&lt;br /&gt;               {&lt;br /&gt;                   throw new SystemColorsException(ode.Message, ode);&lt;br /&gt;               }&lt;br /&gt;           }&lt;br /&gt;           catch (SystemColorsException sce)&lt;br /&gt;           {&lt;br /&gt;               if (throwExceptions)&lt;br /&gt;               {&lt;br /&gt;                   throw sce;&lt;br /&gt;               }&lt;br /&gt;           }&lt;br /&gt;           finally&lt;br /&gt;           {&lt;br /&gt;               if (key != null)&lt;br /&gt;               {&lt;br /&gt;                   try&lt;br /&gt;                   {&lt;br /&gt;                       key.Close();&lt;br /&gt;                       key = null;&lt;br /&gt;                   }&lt;br /&gt;                   catch (Exception ex)&lt;br /&gt;                   {&lt;br /&gt;                       if (throwExceptions)&lt;br /&gt;                       {&lt;br /&gt;                           throw new SystemColorsException(ex.Message, ex);&lt;br /&gt;                       }&lt;br /&gt;                   }&lt;br /&gt;               }&lt;br /&gt;           }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       #endregion&lt;br /&gt;&lt;br /&gt;       #region Public Static Methods&lt;br /&gt;&lt;br /&gt;       public static void LoadSystemColors()&lt;br /&gt;       {&lt;br /&gt;           LoadSystemColors(true);&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       public static void LoadSystemColorsSilently()&lt;br /&gt;       {&lt;br /&gt;           LoadSystemColors(false);&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       public static void SaveSystemColors()&lt;br /&gt;       {&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       #endregion&lt;br /&gt;&lt;br /&gt;       #region Static Properties&lt;br /&gt;&lt;br /&gt;       /// &lt;summary&gt;&lt;br /&gt;       /// Color of the gray area of a scroll bar.&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       public static Color Scrollbar&lt;br /&gt;       {&lt;br /&gt;           get { return m_scrollbar; }&lt;br /&gt;           set { m_scrollbar = value; }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       /// &lt;summary&gt;&lt;br /&gt;       /// Background color of the desktop window.&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       public static Color Background&lt;br /&gt;       {&lt;br /&gt;           get { return m_background; }&lt;br /&gt;           set { m_background = value; }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       /// &lt;summary&gt;&lt;br /&gt;       /// Color of the title bar of an active window.&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       public static Color ActiveCaption&lt;br /&gt;       {&lt;br /&gt;           get { return m_activeCaption; }&lt;br /&gt;           set { m_activeCaption = value; }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       /// &lt;summary&gt;&lt;br /&gt;       /// Color of the title bar of an inactive window.&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       public static Color InactiveCaption&lt;br /&gt;       {&lt;br /&gt;           get { return m_inactiveCaption; }&lt;br /&gt;           set { m_inactiveCaption = value; }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       /// &lt;summary&gt;&lt;br /&gt;       /// Background color of a menu.&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       public static Color Menu&lt;br /&gt;       {&lt;br /&gt;           get { return m_menu; }&lt;br /&gt;           set { m_menu = value; }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       /// &lt;summary&gt;&lt;br /&gt;       /// Background color of a window.&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       public static Color Window&lt;br /&gt;       {&lt;br /&gt;           get { return m_window; }&lt;br /&gt;           set { m_window = value; }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       /// &lt;summary&gt;&lt;br /&gt;       /// Color of a window frame.&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       public static Color WindowFrame&lt;br /&gt;       {&lt;br /&gt;           get { return m_windowFrame; }&lt;br /&gt;           set { m_windowFrame = value; }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       /// &lt;summary&gt;&lt;br /&gt;       /// Color of the text in a menu.&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       public static Color MenuText&lt;br /&gt;       {&lt;br /&gt;           get { return m_menuText; }&lt;br /&gt;           set { m_menuText = value; }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       /// &lt;summary&gt;&lt;br /&gt;       /// Color of the text in a window.&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       public static Color WindowText&lt;br /&gt;       {&lt;br /&gt;           get { return m_windowText; }&lt;br /&gt;           set { m_windowText = value; }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       /// &lt;summary&gt;&lt;br /&gt;       /// Color of the text in a title bar and of the size box and scroll bar arrow box.&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       public static Color CaptionText&lt;br /&gt;       {&lt;br /&gt;           get { return m_captionText; }&lt;br /&gt;           set { m_captionText = value; }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       /// &lt;summary&gt;&lt;br /&gt;       /// Color of the border of an active window.&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       public static Color ActiveBorder&lt;br /&gt;       {&lt;br /&gt;           get { return m_activeBorder; }&lt;br /&gt;           set { m_activeBorder = value; }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       /// &lt;summary&gt;&lt;br /&gt;       /// Color of the border of an inactive window.&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       public static Color InactiveBorder&lt;br /&gt;       {&lt;br /&gt;           get { return m_inactiveBorder; }&lt;br /&gt;           set { m_inactiveBorder = value; }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       /// &lt;summary&gt;&lt;br /&gt;       /// Background color of multiple document interface (MDI) applications.&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       public static Color AppWorkspace&lt;br /&gt;       {&lt;br /&gt;           get { return m_appWorkspace; }&lt;br /&gt;           set { m_appWorkspace = value; }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       /// &lt;summary&gt;&lt;br /&gt;       /// Color of an item selected in a control.&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       public static Color Highlight&lt;br /&gt;       {&lt;br /&gt;           get { return m_highlight; }&lt;br /&gt;           set { m_highlight = value; }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       /// &lt;summary&gt;&lt;br /&gt;       /// Color of the text of an item selected in a control.&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       public static Color HighlightText&lt;br /&gt;       {&lt;br /&gt;           get { return m_highlightText; }&lt;br /&gt;           set { m_highlightText = value; }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       /// &lt;summary&gt;&lt;br /&gt;       /// Color of the face of a button.&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       public static Color ButtonFace&lt;br /&gt;       {&lt;br /&gt;           get { return m_buttonFace; }&lt;br /&gt;           set { m_buttonFace = value; }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       /// &lt;summary&gt;&lt;br /&gt;       /// Shadow color of buttons for edges that face away from the light source.&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       public static Color ButtonShadow&lt;br /&gt;       {&lt;br /&gt;           get { return m_buttonShadow; }&lt;br /&gt;           set { m_buttonShadow = value; }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       /// &lt;summary&gt;&lt;br /&gt;       /// Color of shaded text. This color is set to 0 if the current display driver does not support a solid gray color.&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       public static Color GrayText&lt;br /&gt;       {&lt;br /&gt;           get { return m_grayText; }&lt;br /&gt;           set { m_grayText = value; }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       /// &lt;summary&gt;&lt;br /&gt;       /// Color of the text for push buttons.&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       public static Color ButtonText&lt;br /&gt;       {&lt;br /&gt;           get { return m_buttonText; }&lt;br /&gt;           set { m_buttonText = value; }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       /// &lt;summary&gt;&lt;br /&gt;       /// Color of the text in the title bar of an inactive window.&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       public static Color InactiveCaptionText&lt;br /&gt;       {&lt;br /&gt;           get { return m_inactiveCaptionText; }&lt;br /&gt;           set { m_inactiveCaptionText = value; }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       /// &lt;summary&gt;&lt;br /&gt;       /// Highlight color of buttons for edges that face the light source.&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       public static Color ButtonHighlight&lt;br /&gt;       {&lt;br /&gt;           get { return m_buttonHighlight; }&lt;br /&gt;           set { m_buttonHighlight = value; }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       /// &lt;summary&gt;&lt;br /&gt;       /// Color of the dark shadow for three-dimensional display elements.&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       public static Color ThreeDimensionalDarkShadow&lt;br /&gt;       {&lt;br /&gt;           get { return m_threeDimensionalDarkShadow; }&lt;br /&gt;           set { m_threeDimensionalDarkShadow = value; }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       /// &lt;summary&gt;&lt;br /&gt;       /// Highlight color of three-dimensional display elements for edges that face the light source.&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       public static Color ThreeDimensionalLight&lt;br /&gt;       {&lt;br /&gt;           get { return m_threeDimensionalLight; }&lt;br /&gt;           set { m_threeDimensionalLight = value; }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       /// &lt;summary&gt;&lt;br /&gt;       /// Color of the text for ToolTip controls.&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       public static Color InfoText&lt;br /&gt;       {&lt;br /&gt;           get { return m_infoText; }&lt;br /&gt;           set { m_infoText = value; }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       /// &lt;summary&gt;&lt;br /&gt;       /// Background color for ToolTip controls.&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       public static Color InfoBackground&lt;br /&gt;       {&lt;br /&gt;           get { return m_infoBackground; }&lt;br /&gt;           set { m_infoBackground = value; }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       /// &lt;summary&gt;&lt;br /&gt;       /// Background color for static controls and dialog boxes. Supported in Windows CE 2.0 and later.&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       public static Color Static&lt;br /&gt;       {&lt;br /&gt;           get { return m_static; }&lt;br /&gt;           set { m_static = value; }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       /// &lt;summary&gt;&lt;br /&gt;       /// Color of the text for static controls. Supported in Windows CE 2.0 and later.&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       public static Color StaticText&lt;br /&gt;       {&lt;br /&gt;           get { return m_staticText; }&lt;br /&gt;           set { m_staticText = value; }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       /// &lt;summary&gt;&lt;br /&gt;       /// Color of the title bar of an active window that is filled with a color gradient.&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       public static Color GradientActiveCaption&lt;br /&gt;       {&lt;br /&gt;           get { return m_gradientActiveCaption; }&lt;br /&gt;           set { m_gradientActiveCaption = value; }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       /// &lt;summary&gt;&lt;br /&gt;       /// Color of the title bar of an inactive window that is filled with a color gradient.&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       public static Color GradientInactiveCaption&lt;br /&gt;       {&lt;br /&gt;           get { return m_gradientInactiveCaption; }&lt;br /&gt;           set { m_gradientInactiveCaption = value; }&lt;br /&gt;       }                     &lt;br /&gt;&lt;br /&gt;       #endregion&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37149201-116459073305523485?l=www.rhinomobile.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rhinomobile/~4/dgElpGB5XLE" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2007-08-19T23:50:37.173-04:00</atom:updated><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.rhinomobile.net/2006/11/system-colors-part-1.html</feedburner:origLink></item><item><title>Programmatically Determine Windows Mobile Processor</title><link>http://feedproxy.google.com/~r/Rhinomobile/~3/76N4ICIxTjI/programmatically-determine-windows.html</link><category>KernelIoControl</category><category>.NET Compact Framework</category><category>Windows Mobile</category><author>noreply@blogger.com (Ryan O'Neill)</author><pubDate>Sat, 04 Nov 2006 15:37:00 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-37149201.post-116268368591863497</guid><description>On a Windows Mobile device, the &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcecoreos5/html/wce50lrfKernelIoControl.asp"&gt;KernelIoControl&lt;/a&gt; function can provide some rather useful information. One such piece of information is related to the processor in the device. Processor information can be retrieved from the device using the &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcehardware5/html/wce50lrfioctlprocessorinformation.asp"&gt;IOCTL_PROCESSOR_INFORMATION&lt;/a&gt; control code.&lt;br /&gt;&lt;br /&gt;Here's how ...&lt;br /&gt;&lt;br /&gt;First, some constants:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;private const int PROCESSOR_FLOATINGPOINT = 0x00000001;&lt;br /&gt;private const int PROCESSOR_DSP = 0x00000002;&lt;br /&gt;private const int PROCESSOR_16BITINSTRUCTION = 0x00000004;&lt;br /&gt;&lt;br /&gt;private const int PROCESSOR_INFORMATION_FUNCTION = 25;&lt;br /&gt;private const int FILE_DEVICE_HAL = 0x00000101;&lt;br /&gt;private const int METHOD_BUFFERED = 0;&lt;br /&gt;private const int FILE_ANY_ACCESS = 0;&lt;br /&gt;&lt;br /&gt;private const int PROCESSOR_INFORMATION_SIZE = 576;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;At this point, you might be asking yourself where these values came from. All of the values with the exception of the PROCESSOR_INFORMATION_SIZE came from Windows header files. The PROCESSOR_INFORMATION_SIZE value was calculated based on the &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcehardware5/html/wce50lrfprocessorinfo.asp"&gt;PROCESSOR_INFO&lt;/a&gt; structure which looks like this:&lt;br /&gt;&lt;br /&gt;(Source: MSDN)&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;typedef __PROCESSOR_INFO {&lt;br /&gt;  WORD wVersion; &lt;br /&gt;  WCHAR szProcessCore[40];&lt;br /&gt;  WORD wCoreRevision;&lt;br /&gt;  WCHAR szProcessorName[40];&lt;br /&gt;  WORD wProcessorRevision;&lt;br /&gt;  WCAHR szCatalogNumber[100]; [sic]&lt;br /&gt;  WCHAR szVendor[100];&lt;br /&gt;  DWORD dwInstructionSet;&lt;br /&gt;  DWORD dwClockSpeed;&lt;br /&gt;} PROCESSOR_INFO, *PPROCESSOR_INFO;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A WORD is analogous to a C# short (Int16 - 2 bytes), and a DWORD is analogous to a C# int (Int32 - 4 bytes). Because the strings are Unicode (denoted by WCHAR or Wide Char), those string byte values double when calculating the true size.&lt;br /&gt;wVersion = 2&lt;br /&gt;szProcessorCore = 80&lt;br /&gt;wCoreRevision = 2&lt;br /&gt;szProcessorName = 80&lt;br /&gt;wProcessorRevision = 2&lt;br /&gt;szCatalogNumber = 200&lt;br /&gt;szVendor = 200&lt;br /&gt;dwInstructionSet = 4&lt;br /&gt;dwClockSpeed = 4&lt;br /&gt;&lt;br /&gt;This gives us 2 + 80 + 2 + 80 + 2 + 200 + 200 + 4 + 4 = 574. So why am I using 576 above and not 574? The reason has to do with how structures are word aligned which is beyond the scope of this blog post. Just recognize that 576 is divisible by 4 and 574 isn't.&lt;br /&gt;&lt;br /&gt;Next, we define the information necessary to calculate the actual control code from the device type, function, method, and file access:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;private int IOCTL_PROCESSOR_INFORMATION = CTL_CODE(FILE_DEVICE_HAL, &lt;br /&gt;     PROCESSOR_INFORMATION_FUNCTION, METHOD_BUFFERED, FILE_ANY_ACCESS);&lt;br /&gt;&lt;br /&gt;private static int CTL_CODE(int DeviceType, int Function, int Method, int Access)&lt;br /&gt;{&lt;br /&gt;     return ((DeviceType) &lt;&lt; 16) | ((Access) &lt;&lt; 14) | ((Function &lt;&lt; 2)) | (Method);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Then, we define out P/Invoke functions:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;[DllImport("coredll", EntryPoint = "KernelIoControl", SetLastError = true)]&lt;br /&gt;private static extern bool KernelIoControlOutBytes(int dwIoControlCode, IntPtr lpInBuf, int nInBufSize, &lt;br /&gt;     byte[] lpOutBuf, int nOutBufSize, ref int lpBytesReturned);&lt;br /&gt;&lt;br /&gt;[DllImport("coredll")]&lt;br /&gt;private static extern int GetLastError();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Notice I'm using a modified version of KernelIoControl where for the out buffer I am using a byte array. Why? Because it's much easier and cleaner than marshalling structures.&lt;br /&gt;&lt;br /&gt;Next, the code to actually retrieve the values:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;private void btnGetInfo_Click(object sender, EventArgs e)&lt;br /&gt;{&lt;br /&gt;    int size = PROCESSOR_INFORMATION_SIZE;&lt;br /&gt;    byte[] processorInfo = new byte[size];&lt;br /&gt;    int bytesReturned = 0;&lt;br /&gt;    bool result = KernelIoControlOutBytes(IOCTL_PROCESSOR_INFORMATION, IntPtr.Zero, 0,&lt;br /&gt;        processorInfo, size, ref bytesReturned);&lt;br /&gt;    if (result)&lt;br /&gt;    {&lt;br /&gt;        int version = BitConverter.ToInt16(processorInfo, 0);&lt;br /&gt;        txtProcessorCore.Text = UnicodeEncoding.Unicode.GetString(processorInfo, 2, 80);&lt;br /&gt;        txtCoreRevision.Text = BitConverter.ToInt16(processorInfo, 82).ToString();&lt;br /&gt;        txtProcessorName.Text = UnicodeEncoding.Unicode.GetString(processorInfo, 84, 80);&lt;br /&gt;        txtProcessorRevision.Text = BitConverter.ToInt16(processorInfo, 164).ToString();&lt;br /&gt;        txtCatalogNumber.Text = UnicodeEncoding.Unicode.GetString(processorInfo, 166, 200);&lt;br /&gt;        txtVendor.Text = UnicodeEncoding.Unicode.GetString(processorInfo, 366, 200);&lt;br /&gt;        txtInstructionSet.Text = BitConverter.ToInt32(processorInfo, 568).ToString();&lt;br /&gt;        txtClockSpeed.Text = BitConverter.ToInt32(processorInfo, 572).ToString();&lt;br /&gt;    }&lt;br /&gt;    else&lt;br /&gt;    {&lt;br /&gt;        MessageBox.Show(GetLastError().ToString());&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Some items to recognize:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;BitConverter.ToInt16 is used to get WORD values&lt;/li&gt;&lt;br /&gt;&lt;li&gt;BitConverter.ToInt32 is used to get DWORD values&lt;/li&gt;&lt;br /&gt;&lt;li&gt;UnicodeEncoding.Unicode.GetString is used to get WCHAR values and that the number of bytes specified is double the number specified in the PROCESSOR_INFO structure&lt;/li&gt;&lt;br /&gt;&lt;li&gt;In between the WCHAR value for the vendor and the DWORD for the Instruction Set, there is a two byte gap. This is where our extra 2 bytes which take us from 574 to 576 come into play.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;When I ran this on a Pharos GPS 525 device, here are the values I received:&lt;br /&gt;Processor Core: (Empty)&lt;br /&gt;Core Revision: 0&lt;br /&gt;Processor Name: SC32442-300MHz&lt;br /&gt;Processor Revision: 0&lt;br /&gt;Catalog Number: (Empty)&lt;br /&gt;Vendor: Samsung&lt;br /&gt;Instruction Set: 4 (PROCESSOR_16BITINSTRUCTION)&lt;br /&gt;Clock Speed: 305&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37149201-116268368591863497?l=www.rhinomobile.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rhinomobile/~4/76N4ICIxTjI" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2007-08-19T23:45:58.455-04:00</atom:updated><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.rhinomobile.net/2006/11/programmatically-determine-windows.html</feedburner:origLink></item></channel></rss>

