<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>How To's</title><link>http://blogs.simplifi.com/brucet/category/8.aspx</link><description>How To's</description><managingEditor>2004-08 by Bruce Thomas. All rights reserved.</managingEditor><dc:language>en-US</dc:language><generator>.Text Version 0.95.2004.102</generator><item><dc:creator>2004-08 by Bruce Thomas. All rights reserved.</dc:creator><title>Configuring Window Mobile Smartphone Emulator for Network Access</title><link>http://blogs.simplifi.com/brucet/archive/2008/02/25/707.aspx</link><pubDate>Mon, 25 Feb 2008 12:10:00 GMT</pubDate><guid>http://blogs.simplifi.com/brucet/archive/2008/02/25/707.aspx</guid><description>&lt;P&gt;I was asked recently how to configure the &lt;S&gt;Smartphone&lt;/S&gt; (excuse me Windows Mobile Standard) device in the emulator to access network resources. Since there doesn&amp;#8217;t appear to be any clear step-by-step directions on this, I will outline the necessary steps here.&lt;/P&gt;
&lt;P&gt;First, begin by launching Visual Studio and create or open a SmartClient (SmartPhone) project and set the target platform to Windows Mobile 5.0 SmartPhone SDK. In Visual Studio, select Tools | Connect to Device&amp;#8230;&lt;BR&gt;&lt;BR&gt;&lt;/P&gt;
&lt;P align=center&gt;&lt;IMG alt="" hspace=0 src="/brucet/images/21/o_smartphone1.jpg" align=baseline border=0&gt;&lt;/P&gt;
&lt;P&gt;From the emulator window select File | Configure&amp;#8230;, then select the network tab. Select the Enable NE2000 PCMCIA network adapter and bind to: checkbox and select the Connected Network Card option or the specific network adapter in use by your workstation and click OK&amp;#8230;&lt;BR&gt;&lt;BR&gt;&lt;/P&gt;
&lt;P align=center&gt;&lt;IMG alt="" hspace=0 src="/brucet/images/21/o_smartphone2.jpg" align=baseline border=0&gt;&lt;/P&gt;
&lt;P&gt;Using the device emulator, select [Start] | 9 (Device Setting) | 6 (Connections) | 5 (Proxy) | 1 (Add). Set the description value to the workstation name, set the&amp;nbsp; Connects from field to &amp;#8220;Work&amp;#8221; and the Connects to field to &amp;#8220;Internet&amp;#8221; and select [Done] (leave the other fields to the default values). Select [Done] until returning to the Connections menu.&lt;BR&gt;&lt;BR&gt;&lt;/P&gt;
&lt;P align=center&gt;&lt;IMG alt="" hspace=0 src="/brucet/images/21/o_smartphone3.jpg" align=baseline border=0&gt;&lt;/P&gt;
&lt;P&gt; &lt;/P&gt;
&lt;P&gt;From the Connections menu, select [Menu] | 1 (Advanced) and make sure all setting are set to &amp;#8220;Automatic&amp;#8221;, then select [Menu] | 1 (Options) and scroll down to the &amp;#8220;My desktop connects to:&amp;#8221; setting and change it to &amp;#8220;The Interenet&amp;#8221;. Note: if you only want to test services that are available on your workstation then this value should be set to &amp;#8220;Work&amp;#8221;. Select [Done] until you return to the Start menu. Then select Internet Explorer to test internet browsing.&lt;BR&gt;&lt;BR&gt;&lt;/P&gt;
&lt;P align=center&gt;&lt;IMG alt="" hspace=0 src="/brucet/images/21/o_smartphone4.jpg" align=baseline border=0&gt;&lt;/P&gt;
&lt;P&gt; &lt;/P&gt;
&lt;P&gt;That&amp;#8217;s all there is to it! Of course, your could also cradle the emulator using Device Emulator Manager to connect via ActiveSync.&lt;/P&lt; P&gt;&lt;/P&gt;&lt;img src ="http://blogs.simplifi.com/brucet/aggbug/707.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>2004-06 by Bruce Thomas. All rights reserved.</dc:creator><title>ASP.NET 2.0: Developing Rich UI Custom Web Controls</title><link>http://blogs.simplifi.com/brucet/archive/2006/04/24/676.aspx</link><pubDate>Mon, 24 Apr 2006 11:01:00 GMT</pubDate><guid>http://blogs.simplifi.com/brucet/archive/2006/04/24/676.aspx</guid><description>&lt;P&gt;Here's the slides and demo code from my recent talk at the Huntsville Code Camp. In this presentation I focus on building rich custom web controls. The demo code shows how to build your own Outlook-style navigation pane.&lt;/P&gt;
&lt;P&gt;Enjoy!&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.simplifi.com/brucet/downloads/huntsvillecodecampweblive.zip"&gt;&lt;IMG alt="" hspace=0 src="/brucet/images/21/o_ASPCustomControlSlideImage.jpg" align=baseline border=0&gt;&lt;/IMG&gt;&lt;/A&gt;&lt;/P&gt;&lt;img src ="http://blogs.simplifi.com/brucet/aggbug/676.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>2004-06 by Bruce Thomas. All rights reserved.</dc:creator><title>Windows Mobile 5.0: Techniques for Building Compelling Mobile Solution</title><link>http://blogs.simplifi.com/brucet/archive/2006/04/24/675.aspx</link><pubDate>Mon, 24 Apr 2006 10:54:00 GMT</pubDate><guid>http://blogs.simplifi.com/brucet/archive/2006/04/24/675.aspx</guid><description>&lt;P&gt;Here's the slides and demo code from my recent talk at the Huntsville Code Camp. In this presentation I focus on usage patterns and key success factors for building great mobile applications. The demo code shows how to build your own custom controls to enhance the user experience.&lt;/P&gt;
&lt;P&gt;Enjoy!&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.simplifi.com/brucet/downloads/huntsvillecodecampmobile.zip"&gt;&lt;IMG alt="" hspace=0 src="/brucet/images/21/o_WindowMobileSlideImage.jpg" align=baseline border=0&gt;&lt;/IMG&gt;&lt;/A&gt;&lt;/P&gt;&lt;img src ="http://blogs.simplifi.com/brucet/aggbug/675.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>2004-06 by Bruce Thomas. All rights reserved.</dc:creator><title>Sql Server Integration Service (SSIS) Execute SQL Task ODBC Result Set Bug/Workaround</title><link>http://blogs.simplifi.com/brucet/archive/2006/01/27/668.aspx</link><pubDate>Fri, 27 Jan 2006 01:41:00 GMT</pubDate><guid>http://blogs.simplifi.com/brucet/archive/2006/01/27/668.aspx</guid><description>&lt;DIV&gt;&lt;FONT face=Arial size=2&gt;&lt;BR&gt;Recently, I&amp;nbsp;discovered an issue&amp;nbsp;with SQL Server Integration Services (SSIS)&amp;nbsp;regarding how the Execute SQL Task item handles returning a result set to the control flow.&amp;nbsp;Lets start by demonstrating&amp;nbsp;an existing issue with the Execute SQL Task using ODBC then I'll present a solution&lt;EM&gt;.&lt;/EM&gt; First, create a new DSN that points to the database using the ODBC Data Sources Administrator (Control Panel | Administrator Tools | ODBC Data Sources).&amp;nbsp;If&amp;nbsp;you are only dealing with SQL Server you can still&amp;nbsp;test this out by&amp;nbsp;creating a DSN that uses the SQL Server ODBC&amp;nbsp;driver.&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face=Arial size=2&gt;Figure 1 shows our initial control flow&amp;nbsp;that issues a query to an ODBC data source (in my initial&amp;nbsp;case a DB2 database residing on a mainframe that needs to&amp;nbsp;download data to a SQL Server 2005 and SQL Mobile database), iterates through the results, and&amp;nbsp;carries out some additional data flow based on each row in the initial&amp;nbsp;result set.&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV align=left&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG alt="figure 1" hspace=0 src="/brucet/images/21/o_ssis_odbc_fig1.gif" align=baseline border=0&gt;&lt;BR&gt;&lt;FONT size=1&gt;&lt;STRONG&gt;Figure 1. SSIS package control flow using Execute SQL Task&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face=Arial size=2&gt;In Visual Studio 2005, create a new BI Integration Services project. In the Connection Managers window right-click and select New Connection&lt;EM&gt;...&lt;/EM&gt;&amp;nbsp;From the Add SSIS Connection Manager dialog,&amp;nbsp;highlight&amp;nbsp;ODBC&amp;nbsp;and&amp;nbsp;select the Add... button to continue. In the Configure ODBC Connection Manager dialog, Select the New... button,&amp;nbsp;complete&amp;nbsp;the necessary information in the Connection Manager dialog, select Test Connection to verify your settings, then select the OK button. Your ODBC Connection is now complete and should appear similar to the screen in Figure 2.&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG alt="Figure 2" hspace=0 src="/brucet/images/21/o_ssis_odbc_fig2.gif" align=baseline border=0&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face=Arial size=2&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;&lt;FONT size=1&gt;Figure 2. Configure ODBC Connection Manager dialog&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face=Arial size=2&gt;Next, add an Execute SQL Task item to the package's control flow. Right-click the task, select the Edit... command. In the Execute SQL Task Editor dialog (Figure 3),&amp;nbsp;set the necessary properties. Since we will be issuing a Select command and want to have access to the result set, begin by setting the Result set property to&amp;nbsp;"Full result set". Next, set the ConnectionType to ODBC and&amp;nbsp;assign the previously created ODBC connection to the Connection property. In the SQLStatement property, type the SQL for the select statement.&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG alt="Figure 3" hspace=0 src="/brucet/images/21/o_ssis_odbc_fig3.gif" align=baseline border=0&gt;&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face=Arial size=1&gt;&lt;STRONG&gt;Figure 3. Execute SQL Task Editor - General Page&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face=Arial size=2&gt;In the page list of the Execute SQL Task Editor, select the Result Set page (Figure 4). Select the Add... button to create a result set mapping. Change the Result Name to "0" (zero) and add a new variable to hold the result set. But sure the variable&amp;nbsp;type is set to type Object and&amp;nbsp;has package-level scope. Select OK to continue.&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&lt;IMG alt="" hspace=0 src="/brucet/images/21/o_ssis_odbc_fig4.gif" align=baseline border=0&gt;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face=Arial&gt;&lt;STRONG&gt;&lt;FONT size=1&gt;Figure 4. Execute SQL Task Editor - Result Set Page&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face=Arial size=2&gt;Now we are ready to test the execution of the task. Simply right-click the task item and select Execute Task. The execution will produce the following error message:&lt;/FONT&gt;&lt;/DIV&gt;
&lt;BLOCKQUOTE dir=ltr style="MARGIN-RIGHT: 0px"&gt;
&lt;DIV&gt;&lt;FONT face=Arial color=#ff0000 size=2&gt;&lt;EM&gt;[Execute SQL Task] Error: Executing the query "select locationid, name from production.location" failed with the following error: "Disconnected recordsets are not available from ODBC connections.". Possible failure reasons: Problems with the query, "ResultSet" property not set correctly, parameters not set correctly, or connection not established correctly.&lt;/EM&gt;&lt;/FONT&gt;&lt;/DIV&gt;&lt;/BLOCKQUOTE&gt;
&lt;DIV&gt;&lt;FONT face=Arial size=2&gt;According to feedback I received from Microsoft support, this is completely by design. The explanation I received, suggested that because the&amp;nbsp;ODBC specs does support disconnected recordsets, the Execute SQL Task item is functioning as designed. What? Huh? Can't be? In .NET, a dataset is dataset is dataset, right?. It has no knowledge of the connection used to load it's data. That's ADO.NET 101 right? However, I must say that if you using an OLE provider the Execute SQL Task item functions as expected and returns&amp;nbsp;the result set correctly, but not with ODBC and I haven't been able to get it to return the result set&amp;nbsp;when the connection is&amp;nbsp;SQL Mobile. So, how do we work around this when we need to have access to the&amp;nbsp;result set&amp;nbsp;using ODBC or other none OLE data providers? We begin by replacing the Execute SQL Task item with a Script Task (not an ActiveX Script Task, although you could use it also and write VBScript or JScript code). Right-click the Script Task and select the Edit... command. In the Script Task Editor (Figure 5), set the ReadWriteVariables property to include the variable (in this example the variable is named varDataset)&amp;nbsp;that was previously defined to contain the result set using the Execute SQL Task.&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG alt="Figure 5" hspace=0 src="/brucet/images/21/o_ssis_odbc_fig5.gif" align=baseline border=0&gt;&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face=Arial size=1&gt;&lt;STRONG&gt;Figure 5. Script Task Editor dialog&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face=Arial size=2&gt;Next, select the Design Script... button to launch the Visual Basic for Application editor and enter the following code in Sub Main of the ScriptMain class:&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;
&lt;DIV dir=ltr align=left&gt;&lt;FONT face=Arial&gt;&lt;FONT face="Courier New" color=#008000 size=2&gt;Public Sub Main()&lt;BR&gt;&amp;nbsp;Dim connName As String = Dts.Connections(0).Name&lt;BR&gt;&amp;nbsp;Dim conn As Odbc.OdbcConnection = CType(Dts.Connections(0).AcquireConnection(Nothing), Odbc.OdbcConnection)&lt;BR&gt;&amp;nbsp;Dim da As Odbc.OdbcDataAdapter = New Odbc.OdbcDataAdapter("select locationid, name from production.location", conn)&lt;BR&gt;&amp;nbsp;Dim ds As Data.DataSet = New Data.DataSet()&lt;/FONT&gt;&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV dir=ltr align=left&gt;&lt;FONT face="Courier New" color=#008000 size=2&gt;&amp;nbsp;Try&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; da.Fill(ds)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;STRONG&gt;Dts.Variables("varDataset").Value = ds&lt;/STRONG&gt;&lt;BR&gt;&amp;nbsp;Catch ex As Exception&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dts.TaskResult = Dts.Results.Failure&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Return&lt;BR&gt;&amp;nbsp;Finally&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; da.Dispose()&lt;BR&gt;&amp;nbsp;End Try&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV dir=ltr align=left&gt;&lt;FONT face="Courier New" color=#008000 size=2&gt;&amp;nbsp;Dts.TaskResult = Dts.Results.Success&lt;BR&gt;End Sub&lt;/FONT&gt;&lt;/DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face=Arial size=2&gt;Notice that this code can reference the current DTS package directly including the connections and variables defined in the package. Don't forget to make the variables available to the script as previously described or the code will throw an exception because the variable hasn't been exposed. Our final control flow (Figure 6)&amp;nbsp;will look much like it did before only we have replaced the first Execute SQL Task item.&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG alt="Figure 6" hspace=0 src="/brucet/images/21/o_ssis_odbc_fig6.gif" align=baseline border=0&gt;&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face=Arial size=2&gt;Close the script window, select OK to continue, then right-click the Script Task and select the Execute Task command. The Script Task will execute the SQL command and assign the result set to the varDataset variable. The varDataset&amp;nbsp;variable can now be used to iterate the dataset in subsequent data flow like a Foreach Loop Task as demonstrated in this example. In my opinion, this is what the Execute SQL Task should do, and does do, except for ODBC connection types. Although we had to&amp;nbsp;do a little more work than if&amp;nbsp;the Execute SQL Task worked properly, the&amp;nbsp;real power of SSIS is demonstrated&amp;nbsp;by the fact we can jump right in and add the correct plumbing so that&amp;nbsp;data control&amp;nbsp;flow is unaffected. With the Script Task item&amp;nbsp;and ActiveX Script Task item we can create some powerful&amp;nbsp;BI integration solutions and work around some shortcoming that are sure to get corrected over time.&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;&lt;img src ="http://blogs.simplifi.com/brucet/aggbug/668.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>2004-05 by Bruce Thomas. All rights reserved.</dc:creator><title>Ajax: Creating a rich user-experience for your web-based application</title><link>http://blogs.simplifi.com/brucet/archive/2005/10/26/660.aspx</link><pubDate>Wed, 26 Oct 2005 17:13:00 GMT</pubDate><guid>http://blogs.simplifi.com/brucet/archive/2005/10/26/660.aspx</guid><description>&lt;P&gt;&lt;FONT face=Arial size=2&gt;Here's the slides and demo code from my recent talk at MADEV. The topic is "Creating a rich user experience for your web-based application" and I focus on some techniques you can use to make your web-based application more responsive and fluid using the XmlHttpRequest object, XML, javascript (better known as Ajax)&amp;nbsp;and ASP.NET.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Enjoy!&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;&lt;A href="http://blogs.simplifi.com/brucet/downloads/ajaxwebsamples.zip"&gt;&lt;IMG alt="" hspace=0 src="/brucet/images/17/ajax_thumbnail.gif" align=baseline border=0&gt;&lt;/IMG&gt;&lt;/A&gt;&lt;/FONT&gt; 
&lt;P&gt;&lt;/P&gt;&lt;img src ="http://blogs.simplifi.com/brucet/aggbug/660.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>2004-05 by Bruce Thomas. All rights reserved.</dc:creator><title>VSTO2 Code Camp Demo</title><link>http://blogs.simplifi.com/brucet/archive/2005/05/17/182.aspx</link><pubDate>Tue, 17 May 2005 13:13:00 GMT</pubDate><guid>http://blogs.simplifi.com/brucet/archive/2005/05/17/182.aspx</guid><description>&lt;P&gt;&lt;FONT face=Arial size=2&gt;Here's my demo solution and PPTs from the last MADEV meeting and Atlanta Code Camp. The demo is based VS2005 Beta 2. The solution hits all of the new VSTO 2 features (except schema-based programming). Enjoy!&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;A href="http://blogs.simplifi.com/brucet/downloads/brucethomasvsto2codecamp.zip"&gt;&lt;IMG alt="" hspace=0 src="/brucet/images/17/vsto2demo.gif" align=baseline border=0&gt;&lt;/IMG&gt;&lt;/A&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;img src ="http://blogs.simplifi.com/brucet/aggbug/182.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>2004-05 by Bruce Thomas. All rights reserved.</dc:creator><title>My MSDN Article...</title><link>http://blogs.simplifi.com/brucet/archive/2005/05/09/179.aspx</link><pubDate>Mon, 09 May 2005 13:18:00 GMT</pubDate><guid>http://blogs.simplifi.com/brucet/archive/2005/05/09/179.aspx</guid><description>&lt;P&gt;Here's a link to a recent article I did for Microsoft's Smart-Client Developer Center on MSDN. It's a very interesting topic or great sleep material, depending on your viewpoint. One thing is for sure, users are beginning to demand software that is; elegantly-simply with a range of choices on how to accomplish tasks. Enjoy!&lt;/P&gt;
&lt;P&gt;&lt;A title=http://msdn.microsoft.com/smartclient/default.aspx?pull=/library/en-us/dnwinforms/html/altinputdevices.asp href="http://msdn.microsoft.com/smartclient/default.aspx?pull=/library/en-us/dnwinforms/html/altinputdevices.asp"&gt;&lt;FONT face=Arial color=#0000ff size=2&gt;http://msdn.microsoft.com/smartclient/default.aspx?pull=/library/en-us/dnwinforms/html/altinputdevices.asp&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;img src ="http://blogs.simplifi.com/brucet/aggbug/179.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>2004-05 by Bruce Thomas. All rights reserved.</dc:creator><title>Programming for the '10 Foot Experience' via Remote Control (Part 2 of 2) </title><link>http://blogs.simplifi.com/brucet/archive/2005/02/11/164.aspx</link><pubDate>Fri, 11 Feb 2005 11:10:00 GMT</pubDate><guid>http://blogs.simplifi.com/brucet/archive/2005/02/11/164.aspx</guid><description>&lt;P&gt;In &lt;A href="http://blogs.simplifi.com/brucet/archive/2005/01/25/161.aspx"&gt;part 1&lt;/A&gt; of this post, we looked at how to capture two of the three messages generated by the remote control device.  These two messages covered most of the buttons on the remote. The remaining buttons (e.g. Guide, Recorded TV, More, etc.) will generate a WM_INPUT message.  The WM_INPUT message requires some additional steps to correctly interpret the button that was pressed.  In order for your application to receive WM_INPUT messages, it must first register the raw input devices using the RegisterRawInputDevices function.  Your application will not receive this message until this function is called.&lt;/P&gt;
&lt;P&gt;We begin by defining a RAWINPUTDEVICE structure to pass into the RegisterRawInputDevices function. The first parameter of the RegisterRawInputDevices function accepts an array RAWINPUTDEVICES to denote the exact collection usage pages and usage collection (i.e. buttons) we want to register to receive the WM_INPUT message.  In this case, I am registering two different usage pages containing three different usage collections.  &lt;/P&gt;
&lt;P&gt;&lt;FONT color=#006400&gt;&lt;FONT face="Courier New" size=2&gt;  [StructLayout(LayoutKind.Sequential)]&lt;BR&gt;  internal struct RAWINPUTDEVICE&lt;BR&gt;  {&lt;BR&gt;   [MarshalAs(UnmanagedType.U2)]&lt;BR&gt;   public ushort usUsagePage;&lt;BR&gt;   [MarshalAs(UnmanagedType.U2)]&lt;BR&gt;   public ushort usUsage;&lt;BR&gt;   [MarshalAs(UnmanagedType.U4)]&lt;BR&gt;   public int  dwFlags;&lt;BR&gt;   public IntPtr hwndTarget;&lt;BR&gt;  }&lt;BR&gt;&lt;BR&gt;   [DllImport("User32.dll")]&lt;BR&gt;  extern static bool RegisterRawInputDevices(RAWINPUTDEVICE[] pRawInputDevice, uint uiNumDevices, uint cbSize);&lt;BR&gt;  &lt;BR&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; private const int WM_INPUT  = 0x00FF;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#006400 size=2&gt;  // Buttons that generate the WM_INPUT message&lt;BR&gt;  private const int RAWINPUT_DETAILS    = 0x209;&lt;BR&gt;  private const int RAWINPUT_GUIDE    = 0x8D;&lt;BR&gt;  private const int RAWINPUT_TVJUMP    = 0x25;&lt;BR&gt;  private const int RAWINPUT_STANDBY    = 0x82;&lt;BR&gt;  private const int RAWINPUT_OEM1     = 0x80;&lt;BR&gt;  private const int RAWINPUT_OEM2     = 0x81;&lt;BR&gt;  private const int RAWINPUT_MYTV     = 0x46;&lt;BR&gt;  private const int RAWINPUT_MYVIDEOS    = 0x4A;&lt;BR&gt;  private const int RAWINPUT_MYPICTURES   = 0x49;&lt;BR&gt;  private const int RAWINPUT_MYMUSIC    = 0x47;&lt;BR&gt;  private const int RAWINPUT_RECORDEDTV   = 0x48;&lt;BR&gt;  private const int RAWINPUT_DVDANGLE    = 0x4B;&lt;BR&gt;  private const int RAWINPUT_DVDAUDIO    = 0x4C;&lt;BR&gt;  private const int RAWINPUT_DVDMENU    = 0x24;&lt;BR&gt;  private const int RAWINPUT_DVDSUBTITLE   = 0x4D;&lt;BR&gt; &lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#006400 size=2&gt;   ...&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#006400 size=2&gt;  //-------------------------------------------------------------&lt;BR&gt;  // constructors&lt;BR&gt;  //-------------------------------------------------------------&lt;BR&gt;  &lt;BR&gt;  public RemoteControlDevice()&lt;BR&gt;  { &lt;BR&gt;   // Register the input device to receive the commands from the &lt;BR&gt;   // remote device. See &lt;A href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/remote_control.asp"&gt;http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/remote_control.asp&lt;/A&gt;&lt;BR&gt;   // for the vendor defined usage page.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#006400 size=2&gt;   RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[3];&lt;BR&gt;   &lt;BR&gt;   rid[0].usUsagePage = 0xFFBC;&lt;BR&gt;   rid[0].usUsage = 0x88;&lt;BR&gt;   rid[0].dwFlags = 0;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#006400 size=2&gt;   rid[1].usUsagePage = 0x0C;&lt;BR&gt;   rid[1].usUsage = 0x01;&lt;BR&gt;   rid[1].dwFlags = 0;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#006400 size=2&gt;   rid[2].usUsagePage = 0x0C;&lt;BR&gt;   rid[2].usUsage = 0x80;&lt;BR&gt;   rid[2].dwFlags = 0;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#006400 size=2&gt;   if (!RegisterRawInputDevices(rid, &lt;BR&gt;    (uint) rid.Length, &lt;BR&gt;    (uint) Marshal.SizeOf(rid[0]))&lt;BR&gt;    )&lt;BR&gt;   {&lt;BR&gt;    throw new ApplicationException("Failed to register raw input devices.");&lt;BR&gt;   }&lt;BR&gt;  &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Once RegisterRawInputDevices is successfully called our application will now begin to receive the WM_INPUT message.  Next, once a message is generated we must use the GetRawInputData function to determine the value of the button that was actually selected.  You would think that this would be a straight-forward process, but it takes a little bit of work to the actually retrieve the data containing the button value.&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#006400 size=2&gt;  [DllImport("User32.dll")]&lt;BR&gt;  extern static uint GetRawInputData(IntPtr hRawInput, uint uiCommand, IntPtr pData, ref uint pcbSize, uint cbSizeHeader);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#006400 size=2&gt;  [StructLayout(LayoutKind.Sequential)]&lt;BR&gt;  internal struct RAWINPUTHEADER&lt;BR&gt;  {&lt;BR&gt;   [MarshalAs(UnmanagedType.U4)]&lt;BR&gt;   public int dwType;&lt;BR&gt;   [MarshalAs(UnmanagedType.U4)]&lt;BR&gt;   public int dwSize;&lt;BR&gt;   public IntPtr hDevice;&lt;BR&gt;   [MarshalAs(UnmanagedType.U4)]&lt;BR&gt;   public int wParam;&lt;BR&gt;  }&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#006400 size=2&gt;&lt;BR&gt;  [StructLayout(LayoutKind.Sequential)]&lt;BR&gt;  internal struct RAWHID&lt;BR&gt;  {&lt;BR&gt;   [MarshalAs(UnmanagedType.U4)]&lt;BR&gt;   public int dwSizHid;&lt;BR&gt;   [MarshalAs(UnmanagedType.U4)]&lt;BR&gt;   public int dwCount;&lt;BR&gt;  }&lt;BR&gt;  &lt;BR&gt;  [StructLayout(LayoutKind.Explicit)]&lt;BR&gt;  internal struct RAWINPUT&lt;BR&gt;  {&lt;BR&gt;   [FieldOffset  (0)] public RAWINPUTHEADER header;&lt;BR&gt;//   [FieldOffset (16)] public RAWMOUSE mouse;&lt;BR&gt;//   [FieldOffset (16)] public RAWKEYBOARD keyboard;&lt;BR&gt;   [FieldOffset (16)] public RAWHID hid;&lt;BR&gt;  }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#006400 size=2&gt;  private void ProcessInputCommand(ref Message message)&lt;BR&gt;  {&lt;BR&gt;   RemoteControlButton rcb = RemoteControlButton.Unknown;&lt;BR&gt;   uint dwSize = 0;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#006400 size=2&gt;   GetRawInputData(message.LParam, &lt;BR&gt;    RID_INPUT, &lt;BR&gt;    IntPtr.Zero, &lt;BR&gt;    ref dwSize,&lt;BR&gt;    (uint) Marshal.SizeOf(typeof(RAWINPUTHEADER)&lt;BR&gt;    ));&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#006400 size=2&gt;   IntPtr buffer = Marshal.AllocHGlobal((int) dwSize);&lt;BR&gt;   try&lt;BR&gt;   {&lt;BR&gt;    if(buffer == IntPtr.Zero)&lt;BR&gt;     return;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#006400 size=2&gt;    if (GetRawInputData(message.LParam,  &lt;BR&gt;     RID_INPUT, &lt;BR&gt;     buffer, &lt;BR&gt;     ref dwSize,&lt;BR&gt;     (uint) Marshal.SizeOf(typeof(RAWINPUTHEADER))) != dwSize&lt;BR&gt;     )&lt;BR&gt;    {&lt;BR&gt;     return;&lt;BR&gt;    }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#006400 size=2&gt;    RAWINPUT raw = (RAWINPUT) Marshal.PtrToStructure(buffer, typeof(RAWINPUT));&lt;BR&gt;    if(raw.header.dwType == RIM_TYPEHID)&lt;BR&gt;    {&lt;BR&gt;     byte[] bRawData = new byte[raw.hid.dwSizHid];&lt;BR&gt;     int pRawData = buffer.ToInt32() + Marshal.SizeOf(typeof(RAWINPUT)) + 1;&lt;BR&gt;    &lt;BR&gt;     Marshal.Copy(new IntPtr(pRawData), bRawData, 0, raw.hid.dwSizHid - 1);&lt;BR&gt;     int rawData = bRawData[0] | bRawData[1] &lt;&lt; 8;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#006400 size=2&gt;     switch (rawData)&lt;BR&gt;     {&lt;BR&gt;      case RAWINPUT_DETAILS:&lt;BR&gt;       rcb = RemoteControlButton.Details;&lt;BR&gt;       break;&lt;BR&gt;      case RAWINPUT_GUIDE:&lt;BR&gt;       rcb = RemoteControlButton.Guide;&lt;BR&gt;       break;&lt;BR&gt;      case RAWINPUT_TVJUMP:&lt;BR&gt;       rcb = RemoteControlButton.TVJump;&lt;BR&gt;       break;&lt;BR&gt;      case RAWINPUT_STANDBY:&lt;BR&gt;       rcb = RemoteControlButton.StandBy;&lt;BR&gt;       break;&lt;BR&gt;      case RAWINPUT_OEM1:&lt;BR&gt;       rcb = RemoteControlButton.OEM1;&lt;BR&gt;       break;&lt;BR&gt;    ...&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#006400 size=2&gt; }&lt;BR&gt;   &lt;BR&gt;     if (rcb != RemoteControlButton.Unknown &amp;&amp; this.ButtonPressed != null)&lt;BR&gt;      this.ButtonPressed(this, new RemoteControlEventArgs(rcb, GetDevice(message.LParam.ToInt32())));&lt;BR&gt;    }&lt;BR&gt;    else if(raw.header.dwType == RIM_TYPEMOUSE)&lt;BR&gt;    {&lt;BR&gt;     // do mouse handling... &lt;BR&gt;    }&lt;BR&gt;    else if(raw.header.dwType == RIM_TYPEKEYBOARD)&lt;BR&gt;    {&lt;BR&gt;     // do keyboard handling...&lt;BR&gt;    }&lt;BR&gt;   }&lt;BR&gt;   finally&lt;BR&gt;   {&lt;BR&gt;    Marshal.FreeHGlobal(buffer);&lt;BR&gt;   }&lt;BR&gt;  }&lt;/FONT&gt;&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;We began by creating the appropriate structures required or use by the GetRawInputData function. The main structure is RAWINPUT, which contains a RAWINPUTHEADER and RAWHID structure. The RAWINPUTHEADER contains all sorts of useful information but the actually button value from the remote is stored in the RAWHID structure.  Since the last member of the &lt;A href="http://msdn.microsoft.com/library/en-us/winui/winui/windowsuserinterface/userinput/rawinput/rawinputreference/rawinputstructures/rawhid.asp?frame=true"&gt;RAWHID&lt;/A&gt; structure actually expects an array of bytes, things get a little more complicated because we can't predict the actually size of bRawData member at definition.  Fortunately, all this information is passed to us from the GetRawInputData function.  The first call to the GetRawInputData function is purely informational; we need to determine the size of buffer needed to handle the entire RAWINPUT structure.  This value is returned in the dwSize param of the GetRawInputData function.  Once we know actually size of RAWINPUT we can allocate a buffer of the correct size and call GetRawInputData again this time passing in the buffer to get all the data for RAWINPUT.  The buffer is casted to a RAWINPUT structure and then we must check the header to insure the input is of RIM_TYPEHID, which the type generated by remote control devices.  Lastly, we need to create a byte array  and copy the raw data based on the value of dwSizHid and do a little bit shifting to get the actually button value.  This may seem like a long way to go the get the actual input, but if written correctly this code will work for any number of Human Inteface Devices (HIDs). &lt;/P&gt;
&lt;P&gt;A remote control device is just one of many user-input devices to consider besides the traditional keyboard and mouse.  User input can come from a joystick, touch screen, hand glove, microphone, or other specialize devices. Windows XP with Service Pack 1 or greater provides a stable and robust way for applications to leverage the flexibility of these devices.&lt;/P&gt;
&lt;P&gt;Download &lt;A href="http://blogs.simplifi.com/brucet/downloads/remotecontrolsample.zip"&gt;remotecontrolsample.zip&lt;/A&gt; &lt;/P&gt;&lt;img src ="http://blogs.simplifi.com/brucet/aggbug/164.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>2004-05 by Bruce Thomas. All rights reserved.</dc:creator><title>Programming for the '10 Foot Experience' via Remote Control (Part 1 of 2)</title><link>http://blogs.simplifi.com/brucet/archive/2005/01/25/161.aspx</link><pubDate>Tue, 25 Jan 2005 12:15:00 GMT</pubDate><guid>http://blogs.simplifi.com/brucet/archive/2005/01/25/161.aspx</guid><description>&lt;img src ="http://blogs.simplifi.com/brucet/aggbug/161.aspx" width = "1" height = "1" /&gt;</description></item></channel></rss>