home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Samples / Managed / DirectInput / Keyboard / Keyboard.cs next >
Encoding:
Text File  |  2004-09-27  |  28.0 KB  |  758 lines

  1. //-----------------------------------------------------------------------------
  2. // File: Keyboard.cs
  3. //
  4. // Desc: The Keyboard sample obtains and displays Keyboard data.
  5. //
  6. // Copyright (c) Microsoft Corporation. All rights reserved
  7. //-----------------------------------------------------------------------------
  8. using System;
  9. using System.Drawing;
  10. using System.Windows.Forms;
  11. using Microsoft.DirectX.DirectInput;
  12. using Microsoft.DirectX;
  13.  
  14. public class KeyboardForm : Form
  15. {
  16.     private System.ComponentModel.IContainer components;
  17.     private GroupBox staticGroupBox1;
  18.     private GroupBox staticGroupBox2;
  19.     private GroupBox staticGroupBox3;
  20.     private Label staticDataLabel;
  21.     private Label dataLabel;
  22.     private System.Windows.Forms.Button createDevice;
  23.     private System.Windows.Forms.Button cancel;
  24.     private Label behaviorLabel;
  25.     private System.Windows.Forms.Timer grabData;
  26.     private System.Windows.Forms.RadioButton immediate;
  27.     private System.Windows.Forms.RadioButton buffered;
  28.     private System.Windows.Forms.RadioButton exclusive;
  29.     private System.Windows.Forms.RadioButton nonexclusive;
  30.     private System.Windows.Forms.CheckBox windowsKey;
  31.     private System.Windows.Forms.Panel panel1;
  32.     private System.Windows.Forms.RadioButton foreground;
  33.     private System.Windows.Forms.RadioButton background;
  34.  
  35.     int sizeSampleBuffer  = 8;
  36.     Device applicationDevice = null;
  37.  
  38.  
  39.     
  40.     
  41.     public static void Main()
  42.     {
  43.         using (KeyboardForm form = new KeyboardForm())
  44.         {
  45.             Application.Run(form);
  46.         }
  47.     }
  48.     
  49.  
  50.  
  51.  
  52.     public KeyboardForm()
  53.     {
  54.         try
  55.         {
  56.             // Load the icon from our resources
  57.             System.Resources.ResourceManager resources = new System.Resources.ResourceManager(this.GetType());
  58.             this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
  59.         }
  60.         catch
  61.         {
  62.             // It's no big deal if we can't load our icons, but try to load the embedded one
  63.             try { this.Icon = new System.Drawing.Icon(this.GetType(), "directx.ico"); } 
  64.             catch {}
  65.         }
  66.         //
  67.         // Required for Windows Form Designer support.
  68.         //
  69.         InitializeComponent();
  70.     }
  71.     #region InitializeComponent code
  72.     
  73.     
  74.     
  75.     
  76.     private void InitializeComponent()
  77.     {
  78.         this.components = new System.ComponentModel.Container();
  79.         System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(KeyboardForm));
  80.         this.staticGroupBox1 = new System.Windows.Forms.GroupBox();
  81.         this.exclusive = new System.Windows.Forms.RadioButton();
  82.         this.nonexclusive = new System.Windows.Forms.RadioButton();
  83.         this.windowsKey = new System.Windows.Forms.CheckBox();
  84.         this.panel1 = new System.Windows.Forms.Panel();
  85.         this.background = new System.Windows.Forms.RadioButton();
  86.         this.foreground = new System.Windows.Forms.RadioButton();
  87.         this.staticGroupBox2 = new System.Windows.Forms.GroupBox();
  88.         this.immediate = new System.Windows.Forms.RadioButton();
  89.         this.buffered = new System.Windows.Forms.RadioButton();
  90.         this.staticDataLabel = new System.Windows.Forms.Label();
  91.         this.dataLabel = new System.Windows.Forms.Label();
  92.         this.createDevice = new System.Windows.Forms.Button();
  93.         this.cancel = new System.Windows.Forms.Button();
  94.         this.staticGroupBox3 = new System.Windows.Forms.GroupBox();
  95.         this.behaviorLabel = new System.Windows.Forms.Label();
  96.         this.grabData = new System.Windows.Forms.Timer(this.components);
  97.         this.staticGroupBox1.SuspendLayout();
  98.         this.panel1.SuspendLayout();
  99.         this.staticGroupBox2.SuspendLayout();
  100.         this.SuspendLayout();
  101.         // 
  102.         // staticGroupBox1
  103.         // 
  104.         this.staticGroupBox1.Controls.AddRange(new System.Windows.Forms.Control[] {
  105.                                                                                this.exclusive,
  106.                                                                                this.nonexclusive,
  107.                                                                                this.windowsKey,
  108.                                                                                this.panel1});
  109.         this.staticGroupBox1.Location = new System.Drawing.Point(10, 11);
  110.         this.staticGroupBox1.Name = "staticGroupBox1";
  111.         this.staticGroupBox1.Size = new System.Drawing.Size(247, 79);
  112.         this.staticGroupBox1.TabIndex = 0;
  113.         this.staticGroupBox1.TabStop = false;
  114.         this.staticGroupBox1.Text = "Cooperative Level";
  115.         // 
  116.         // exclusive
  117.         // 
  118.         this.exclusive.Checked = true;
  119.         this.exclusive.Location = new System.Drawing.Point(15, 13);
  120.         this.exclusive.Name = "exclusive";
  121.         this.exclusive.Size = new System.Drawing.Size(72, 16);
  122.         this.exclusive.TabIndex = 6;
  123.         this.exclusive.TabStop = true;
  124.         this.exclusive.Text = "Exclusive";
  125.         this.exclusive.Click += new System.EventHandler(this.ChangeProperties);
  126.         // 
  127.         // nonexclusive
  128.         // 
  129.         this.nonexclusive.Location = new System.Drawing.Point(15, 31);
  130.         this.nonexclusive.Name = "nonexclusive";
  131.         this.nonexclusive.Size = new System.Drawing.Size(96, 16);
  132.         this.nonexclusive.TabIndex = 7;
  133.         this.nonexclusive.Text = "Nonexclusive";
  134.         this.nonexclusive.Click += new System.EventHandler(this.ChangeProperties);
  135.         // 
  136.         // windowsKey
  137.         // 
  138.         this.windowsKey.Location = new System.Drawing.Point(15, 50);
  139.         this.windowsKey.Name = "windowsKey";
  140.         this.windowsKey.Size = new System.Drawing.Size(105, 16);
  141.         this.windowsKey.TabIndex = 8;
  142.         this.windowsKey.Text = "Disable Windows Key";
  143.         // 
  144.         // panel1
  145.         // 
  146.         this.panel1.Controls.AddRange(new System.Windows.Forms.Control[] {
  147.                                                                              this.background,
  148.                                                                              this.foreground});
  149.         this.panel1.Location = new System.Drawing.Point(136, 8);
  150.         this.panel1.Name = "panel1";
  151.         this.panel1.Size = new System.Drawing.Size(104, 48);
  152.         this.panel1.TabIndex = 15;
  153.         // 
  154.         // background
  155.         // 
  156.         this.background.Location = new System.Drawing.Point(8, 24);
  157.         this.background.Name = "background";
  158.         this.background.Size = new System.Drawing.Size(90, 16);
  159.         this.background.TabIndex = 12;
  160.         this.background.Text = "Background";
  161.         this.background.Click += new System.EventHandler(this.ChangeProperties);
  162.         // 
  163.         // foreground
  164.         // 
  165.         this.foreground.Checked = true;
  166.         this.foreground.Location = new System.Drawing.Point(8, 8);
  167.         this.foreground.Name = "foreground";
  168.         this.foreground.Size = new System.Drawing.Size(82, 16);
  169.         this.foreground.TabIndex = 11;
  170.         this.foreground.TabStop = true;
  171.         this.foreground.Text = "Foreground";
  172.         this.foreground.Click += new System.EventHandler(this.ChangeProperties);
  173.         // 
  174.         // staticGroupBox2
  175.         // 
  176.         this.staticGroupBox2.Controls.AddRange(new System.Windows.Forms.Control[] {
  177.                                                                                 this.immediate,
  178.                                                                                 this.buffered});
  179.         this.staticGroupBox2.Location = new System.Drawing.Point(267, 11);
  180.         this.staticGroupBox2.Name = "staticGroupBox2";
  181.         this.staticGroupBox2.Size = new System.Drawing.Size(105, 79);
  182.         this.staticGroupBox2.TabIndex = 6;
  183.         this.staticGroupBox2.TabStop = false;
  184.         this.staticGroupBox2.Text = "Data Style";
  185.         // 
  186.         // immediate
  187.         // 
  188.         this.immediate.Checked = true;
  189.         this.immediate.Location = new System.Drawing.Point(13, 22);
  190.         this.immediate.Name = "immediate";
  191.         this.immediate.Size = new System.Drawing.Size(78, 16);
  192.         this.immediate.TabIndex = 9;
  193.         this.immediate.TabStop = true;
  194.         this.immediate.Text = "Immediate";
  195.         this.immediate.Click += new System.EventHandler(this.ChangeProperties);
  196.         // 
  197.         // buffered
  198.         // 
  199.         this.buffered.Location = new System.Drawing.Point(13, 40);
  200.         this.buffered.Name = "buffered";
  201.         this.buffered.Size = new System.Drawing.Size(70, 16);
  202.         this.buffered.TabIndex = 10;
  203.         this.buffered.Text = "Buffered";
  204.         this.buffered.Click += new System.EventHandler(this.ChangeProperties);
  205.         // 
  206.         // staticDataLabel
  207.         // 
  208.         this.staticDataLabel.Location = new System.Drawing.Point(16, 347);
  209.         this.staticDataLabel.Name = "staticDataLabel";
  210.         this.staticDataLabel.Size = new System.Drawing.Size(32, 13);
  211.         this.staticDataLabel.TabIndex = 9;
  212.         this.staticDataLabel.Text = "Data:";
  213.         // 
  214.         // dataLabel
  215.         // 
  216.         this.dataLabel.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
  217.         this.dataLabel.Location = new System.Drawing.Point(48, 344);
  218.         this.dataLabel.Name = "dataLabel";
  219.         this.dataLabel.Size = new System.Drawing.Size(504, 18);
  220.         this.dataLabel.TabIndex = 10;
  221.         this.dataLabel.Text = "Device not created";
  222.         // 
  223.         // createDevice
  224.         // 
  225.         this.createDevice.Location = new System.Drawing.Point(10, 376);
  226.         this.createDevice.Name = "createDevice";
  227.         this.createDevice.Size = new System.Drawing.Size(102, 23);
  228.         this.createDevice.TabIndex = 11;
  229.         this.createDevice.Text = "Create Device";
  230.         this.createDevice.Click += new System.EventHandler(this.btnCreatedevice_Click);
  231.         // 
  232.         // cancel
  233.         // 
  234.         this.cancel.Location = new System.Drawing.Point(477, 376);
  235.         this.cancel.Name = "cancel";
  236.         this.cancel.TabIndex = 12;
  237.         this.cancel.Text = "Exit";
  238.         this.cancel.Click += new System.EventHandler(this.btnCancel_Click);
  239.         // 
  240.         // staticGroupBox3
  241.         // 
  242.         this.staticGroupBox3.Location = new System.Drawing.Point(10, 91);
  243.         this.staticGroupBox3.Name = "staticGroupBox3";
  244.         this.staticGroupBox3.Size = new System.Drawing.Size(541, 245);
  245.         this.staticGroupBox3.TabIndex = 13;
  246.         this.staticGroupBox3.TabStop = false;
  247.         this.staticGroupBox3.Text = "Expected Behavior";
  248.         // 
  249.         // behaviorLabel
  250.         // 
  251.         this.behaviorLabel.Location = new System.Drawing.Point(21, 108);
  252.         this.behaviorLabel.Name = "behaviorLabel";
  253.         this.behaviorLabel.Size = new System.Drawing.Size(519, 216);
  254.         this.behaviorLabel.TabIndex = 14;
  255.         this.behaviorLabel.Text = "Behavior";
  256.         // 
  257.         // grabData
  258.         // 
  259.         this.grabData.Interval = 83;
  260.         this.grabData.Tick += new System.EventHandler(this.GrabData_Tick);
  261.         // 
  262.         // KeyboardForm
  263.         // 
  264.         this.AcceptButton = this.createDevice;
  265.         this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
  266.         this.ClientSize = new System.Drawing.Size(562, 410);
  267.         this.Controls.AddRange(new System.Windows.Forms.Control[] {
  268.                                                                       this.behaviorLabel,
  269.                                                                       this.staticDataLabel,
  270.                                                                       this.dataLabel,
  271.                                                                       this.createDevice,
  272.                                                                       this.cancel,
  273.                                                                       this.staticGroupBox1,
  274.                                                                       this.staticGroupBox2,
  275.                                                                       this.staticGroupBox3});
  276.         this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
  277.         this.KeyPreview = true;
  278.         this.MaximizeBox = false;
  279.         this.Name = "KeyboardForm";
  280.         this.Text = "DirectInput Keyboard Sample";
  281.         this.Closing += new System.ComponentModel.CancelEventHandler(this.KeyboardForm_Closing);
  282.         this.Activated += new System.EventHandler(this.KeyboardForm_Activated);
  283.         this.staticGroupBox1.ResumeLayout(false);
  284.         this.panel1.ResumeLayout(false);
  285.         this.staticGroupBox2.ResumeLayout(false);
  286.         this.ResumeLayout(false);
  287.  
  288.     }
  289.     #endregion
  290.  
  291.     
  292.     
  293.     
  294.     private void ChangeProperties(object sender, System.EventArgs e)
  295.     {
  296.         UpdateUI();
  297.     }
  298.  
  299.     
  300.     
  301.     
  302.     private void btnCreatedevice_Click(object sender, System.EventArgs e)
  303.     {
  304.         if (null != applicationDevice)
  305.         {
  306.             FreeDirectInput();
  307.             UpdateUI();
  308.             return;
  309.         }
  310.  
  311.         CooperativeLevelFlags coopFlags;
  312.         
  313.         // Cleanup any previous call first.
  314.         grabData.Enabled = false;    
  315.         FreeDirectInput();
  316.     
  317.         if (true == exclusive.Checked)
  318.             coopFlags = CooperativeLevelFlags.Exclusive;
  319.         else
  320.             coopFlags = CooperativeLevelFlags.NonExclusive;
  321.  
  322.         if (true == foreground.Checked)
  323.             coopFlags |= CooperativeLevelFlags.Foreground;
  324.         else
  325.             coopFlags |= CooperativeLevelFlags.Background;
  326.  
  327.         // Disabling the windows key is only allowed only if we are in foreground nonexclusive.
  328.         if (true == windowsKey.Checked && !exclusive.Checked && foreground.Checked)
  329.             coopFlags |= CooperativeLevelFlags.NoWindowsKey;
  330.  
  331.         try
  332.         {
  333.             // Obtain an instantiated system keyboard device.
  334.             applicationDevice = new Device(SystemGuid.Keyboard);
  335.         }
  336.         catch(InputException)
  337.         {
  338.             FreeDirectInput();
  339.             MessageBox.Show("Unable to create device.");
  340.             return;
  341.         }
  342.  
  343.         // Set the cooperative level to let DirectInput know how
  344.         // this device should interact with the system and with other
  345.         // DirectInput applications.
  346.         try
  347.         {
  348.             applicationDevice.SetCooperativeLevel(this, coopFlags);
  349.         }
  350.         catch(InputException dx)
  351.         {
  352.             if (dx is UnsupportedException && !foreground.Checked)
  353.             {
  354.                 FreeDirectInput();
  355.                 MessageBox.Show("SetCooperativeLevel() returned UnsupportedException.\n" +
  356.                     "For security reasons, background keyboard\n" +
  357.                         "access is not allowed.", "Keyboard");
  358.                 return;
  359.             }
  360.         }
  361.  
  362.         if (false == immediate.Checked)
  363.         {
  364.             // IMPORTANT STEP TO USE BUFFERED DEVICE DATA!
  365.             //
  366.             // DirectInput uses unbuffered I/O (buffer size = 0) by default.
  367.             // If you want to read buffered data, you need to set a nonzero
  368.             // buffer size.
  369.             //
  370.             // The buffer size is an int property associated with the device.
  371.  
  372.             try
  373.             {
  374.                 applicationDevice.Properties.BufferSize = sizeSampleBuffer;
  375.             }
  376.             catch(DirectXException)
  377.             {
  378.                 return;
  379.             }
  380.         }
  381.  
  382.         applicationDevice.Acquire();
  383.         grabData.Enabled = true;
  384.         UpdateUI();
  385.     }
  386.  
  387.     
  388.     
  389.     
  390.     private void btnCancel_Click(object sender, System.EventArgs e)
  391.     {
  392.         FreeDirectInput();
  393.         this.Close();
  394.     }
  395.  
  396.     
  397.     
  398.     
  399.     private void KeyboardForm_Activated(object sender, System.EventArgs e)
  400.     {
  401.         if (null != applicationDevice)
  402.         {
  403.             try{applicationDevice.Acquire();}
  404.             catch (DirectXException){}
  405.         }
  406.     }
  407.  
  408.     
  409.     
  410.     
  411.     private void GrabData_Tick(object sender, System.EventArgs e)
  412.     {
  413.         // Update the input device every timer message.
  414.         bool isImmediate = immediate.Checked;
  415.  
  416.         if (true == isImmediate)
  417.         {
  418.             if (!ReadImmediateData())
  419.             {
  420.                 grabData.Enabled = false;
  421.                 MessageBox.Show("Error reading input state. The sample will now exit.","Keyboard");
  422.                 this.Close();
  423.             }
  424.         }
  425.         else
  426.         {
  427.             if (!ReadBufferedData())
  428.             {
  429.                 grabData.Enabled = false;
  430.                 MessageBox.Show("Error reading input state. The sample will now exit.","Keyboard");
  431.                 this.Close();
  432.             }
  433.         }       
  434.     }
  435.  
  436.     
  437.     
  438.     
  439.     private void KeyboardForm_Closing(object sender, System.ComponentModel.CancelEventArgs e)
  440.     {
  441.         grabData.Enabled = false;
  442.         FreeDirectInput();
  443.     }
  444.  
  445.     
  446.     
  447.     
  448.     private void FreeDirectInput()
  449.     {
  450.         // Unacquire the device one last time just in case 
  451.         // the app tried to exit while the device is still acquired.
  452.         if (null != applicationDevice) 
  453.         {
  454.             applicationDevice.Unacquire();
  455.             applicationDevice.Dispose();
  456.             applicationDevice = null;
  457.         }
  458.     }
  459.  
  460.     
  461.     
  462.     
  463.     ///<summary>
  464.     /// Enables/disables the UI, and sets the dialog behavior text based on the UI
  465.     ///</summary>
  466.     private void UpdateUI()
  467.     {
  468.         string strExpected = String.Empty;
  469.         bool isExclusive;
  470.         bool isForeground;
  471.         bool isImmediate;
  472.         bool DisableWindowsKey;
  473.  
  474.         // Determine where the buffer would like to be allocated.
  475.         isExclusive = exclusive.Checked;
  476.         isForeground = foreground.Checked;
  477.         isImmediate = immediate.Checked;
  478.         DisableWindowsKey = windowsKey.Checked;
  479.  
  480.         if (null != applicationDevice)
  481.         {
  482.             createDevice.Text ="Release Device";
  483.             dataLabel.Text = String.Empty;
  484.  
  485.             exclusive.Enabled = false;
  486.             foreground.Enabled = false;
  487.             nonexclusive.Enabled = false;
  488.             background.Enabled = false;
  489.             immediate.Enabled = false;
  490.             buffered.Enabled = false;
  491.             windowsKey.Enabled = false;
  492.         }
  493.         else
  494.         {
  495.             createDevice.Text ="&Create Device";
  496.             dataLabel.Text = "Device not created. Choose settings and click 'Create Device' then type to see results";
  497.  
  498.             exclusive.Enabled = true;
  499.             foreground.Enabled = true;
  500.             nonexclusive.Enabled = true;
  501.             background.Enabled = true;
  502.             immediate.Enabled = true;
  503.             buffered.Enabled = true;          
  504.  
  505.             if (!isExclusive && isForeground)
  506.                 windowsKey.Enabled = true;
  507.             else
  508.                 windowsKey.Enabled = false;
  509.         }
  510.  
  511.         // Figure what the user should expect based on the dialog choice.
  512.         if (!isForeground && isExclusive)
  513.         {
  514.             strExpected = "For security reasons, background exclusive " +
  515.                 "keyboard access is not allowed.\n\n";
  516.         }
  517.         else
  518.         {
  519.             if (isForeground)
  520.             {
  521.                 strExpected =  "Foreground cooperative level means that the " +
  522.                     "application has access to data only when in the " +
  523.                     "foreground or, in other words, has the input focus. " +
  524.                     "If the application moves to the background, " +
  525.                     "the device is automatically unacquired, or made " +
  526.                     "unavailable.\n\n";
  527.             }
  528.             else
  529.             {
  530.                 strExpected = "Background cooperative level really means " +
  531.                     "foreground and background. A device with a " +
  532.                     "background cooperative level can be acquired " +
  533.                     "and used by an application at any time.\n\n";
  534.             }
  535.  
  536.             if (isExclusive)
  537.             {
  538.                 strExpected += "Exclusive mode prevents other applications from " +
  539.                     "also acquiring the device exclusively. The fact " +
  540.                     "that your application is using a device at the " +
  541.                     "exclusive level does not mean that other " +
  542.                     "applications cannot get data from the device. " +
  543.                     "When an application has exclusive access to the " +
  544.                     "keyboard, DirectInput suppresses all keyboard " +
  545.                     "messages including the Windows key except " +
  546.                     "CTRL+ALT+DEL and ALT+TAB\n\n";
  547.             }
  548.             else
  549.             {
  550.                 strExpected += "Nonexclusive mode means that other applications " +
  551.                     "can acquire device in exclusive or nonexclusive mode. ";
  552.  
  553.                 if (true == DisableWindowsKey)
  554.                 {
  555.                     strExpected += "The Windows key will also be disabled so that " +
  556.                         "users cannot inadvertently break out of the " +
  557.                         "application. ";
  558.                 }
  559.                 strExpected += "\n\n";
  560.             }
  561.             if (true ==  isImmediate)
  562.             {
  563.                 strExpected += "immediate data is a snapshot of the current " +
  564.                     "state of a device. It provides no data about " +
  565.                     "what has happened with the device since the " +
  566.                     "last call, apart from implicit information that " +
  567.                     "you can derive by comparing the current state with " +
  568.                     "the last one. Events in between calls are lost.\n\n";
  569.             }
  570.             else
  571.             {
  572.                 strExpected += "Buffered data is a record of events that are stored " +
  573.                     "until an application retrieves them. With buffered " +
  574.                     "data, events are stored until you are ready to deal " +
  575.                     "with them. If the buffer overflows, new data is lost.\n\n";                             
  576.             }
  577.  
  578.             strExpected += "The sample will read the keyboard 12 times a second. " +
  579.                 "Typically an application would poll the keyboard " +
  580.                 "much faster than this, but this slow rate is simply " +
  581.                 "for the purposes of demonstration.";
  582.         }
  583.         behaviorLabel.Text = strExpected;
  584.     }
  585.  
  586.     
  587.     
  588.     
  589.     ///<summary>
  590.     /// Read the input device's state when in buffered mode and display it.
  591.     ///</summary>
  592.     bool ReadBufferedData()
  593.     {
  594.         BufferedDataCollection dataCollection = null;
  595.         string textNew = String.Empty;
  596.     
  597.         if (null == applicationDevice) 
  598.             return true;
  599.     
  600.         InputException ie = null;
  601.         try
  602.         {
  603.             dataCollection = applicationDevice.GetBufferedData();
  604.         }
  605.         catch(InputException)
  606.         {
  607.             // We got an error 
  608.             //
  609.             // It means that continuous contact with the
  610.             // device has been lost, either due to an external
  611.             // interruption, or because the buffer overflowed
  612.             // and some events were lost.
  613.             //
  614.             // Consequently, if a button was pressed at the time
  615.             // the buffer overflowed or the connection was broken,
  616.             // the corresponding "up" message might have been lost.
  617.             //
  618.             // But since our simple sample doesn't actually have
  619.             // any state associated with button up or down events,
  620.             // there is no state to reset.  (In a real game, ignoring
  621.             // the buffer overflow would result in the game thinking
  622.             // a key was held down when in fact it isn't; it's just
  623.             // that the "up" event got lost because the buffer
  624.             // overflowed.)
  625.             //
  626.             // If we want to be more clever, we could do a
  627.             // GetBufferedData() and compare the current state
  628.             // against the state we think the device is in,
  629.             // and process all the states that are currently
  630.             // different from our private state.
  631.         
  632.             bool loop = true;
  633.             do
  634.             {
  635.                 try
  636.                 {
  637.                     applicationDevice.Acquire();
  638.                 }
  639.                 catch(InputLostException)
  640.                 {
  641.                     loop = true;
  642.                 }
  643.                 catch(InputException inputException)
  644.                 {
  645.                     ie = inputException;
  646.                     loop = false;
  647.                 }
  648.             }while (loop);
  649.  
  650.             // Update the dialog text.
  651.             if (ie is OtherApplicationHasPriorityException || ie is NotAcquiredException) 
  652.                 dataLabel.Text = "Unacquired";
  653.  
  654.             // This
  655.             // may occur when the app is minimized or in the process of 
  656.             // switching, so just try again later.
  657.             return true;
  658.         }
  659.  
  660.         if (null != ie)
  661.             return false;
  662.  
  663.         if (null == dataCollection)
  664.             return true;
  665.  
  666.         // Study each of the buffer elements and process them.
  667.         //
  668.         // Since we really don't do anything, our "processing"
  669.         // consists merely of squirting the name into our
  670.         // local buffer.
  671.         foreach (BufferedData d in dataCollection) 
  672.         {
  673.             // this will display then scan code of the key
  674.             // plus a 'D' - meaning the key was pressed 
  675.             //   or a 'U' - meaning the key was released
  676.             textNew += String.Format("0x{0:X}", d.Offset);
  677.             textNew += (0 != (d.Data & 0x80)) ? "D " : "U ";
  678.         }
  679.  
  680.         // If nothing changed then don't repaint - avoid flicker.
  681.         if (dataLabel.Text != textNew)
  682.             dataLabel.Text = textNew;
  683.  
  684.         return true;
  685.     }
  686.  
  687.     
  688.     
  689.     
  690.     ///<summary>
  691.     /// Read the input device's state when in immediate mode and display it.
  692.     ///</summary>
  693.     bool ReadImmediateData()
  694.     {
  695.         string textNew = String.Empty;
  696.         KeyboardState state = null;
  697.  
  698.         if (null == applicationDevice) 
  699.             return true;
  700.     
  701.         // Get the input's device state, and store it.
  702.         InputException ie = null;
  703.         try
  704.         {
  705.             state = applicationDevice.GetCurrentKeyboardState();
  706.         }
  707.         catch (DirectXException)
  708.         {
  709.             // DirectInput may be telling us that the input stream has been
  710.             // interrupted.  We aren't tracking any state between polls, so
  711.             // we don't have any special reset that needs to be done.
  712.             // We just re-acquire and try again.
  713.         
  714.             // If input is lost then acquire and keep trying.
  715.             
  716.             bool loop = true;
  717.             do
  718.             {
  719.                 try
  720.                 {
  721.                     applicationDevice.Acquire();
  722.                 }
  723.                 catch(InputLostException)
  724.                 {
  725.                     loop = true;
  726.                 }
  727.                 catch(InputException inputException)
  728.                 {
  729.                     ie = inputException;
  730.                     loop = false;
  731.                 }
  732.             }while (loop);
  733.  
  734.             // Update the dialog text 
  735.             if (ie is OtherApplicationHasPriorityException || ie is NotAcquiredException) 
  736.                 dataLabel.Text = "Unacquired";
  737.  
  738.             // Exception may be OtherApplicationHasPriorityException or other exceptions.
  739.             // This may occur when the app is minimized or in the process of 
  740.             // switching, so just try again later.
  741.             return true; 
  742.         }
  743.     
  744.         // Make a string of the index values of the keys that are down.
  745.         for (Key k = Key.Escape; k <= Key.MediaSelect; k++) 
  746.         {
  747.             if (state[k])
  748.                 textNew += k.ToString() + " ";
  749.         }
  750.     
  751.         // If nothing changed then don't repaint - avoid flicker.
  752.         if (dataLabel.Text != textNew)
  753.             dataLabel.Text = textNew;
  754.     
  755.         return true;
  756.     }
  757. }
  758.