using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using System.Runtime.InteropServices; public sealed class Accelerometer : IDisposable { private const uint GENERIC_READ = 0x80000000; private const uint FILE_SHARE_READ = 1; private const uint FILE_SHARE_WRITE = 2; private const uint OPEN_EXISTING = 3; private readonly static IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1); private const uint IOCTL_SHOCKMGR_READ_ACCELEROMETER_DATA = 0x733fc; private const int FACILITY_WIN32 = unchecked((int)0x80070000); private IntPtr handle = INVALID_HANDLE_VALUE; private AccelerometerData sample; private static int HRESULT_FROM_WIN32(int x) { return x <= 0 ? x : ((x & 0x0000FFFF) | FACILITY_WIN32); } private struct AccelerometerData { internal int status; internal short x0; internal short y0; short x1; short y1; short x2; short y2; short x3; short y3; short x4; short y4; short x5; short y5; short x6; short y6; short x7; short y7; short x8; short y8; short x9; short y9; short x10; short y10; short x11; short y11; short x12; short y12; short x13; short y13; short unknown0; short unknown1; } [DllImport("kernel32", SetLastError = true)] private static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile); [DllImport("kernel32")] private static extern void CloseHandle(IntPtr handle); [DllImport("kernel32", SetLastError = true)] private static extern bool DeviceIoControl(IntPtr hDevice, uint dwIoControlCode, IntPtr lpInBuffer, uint nInBufferSize, ref AccelerometerData lpOutBuffer, uint nOutBufferSize, ref uint lpBytesReturned, IntPtr lpOverlapped); public Accelerometer() { handle = CreateFile(@"\\.\ShockMgr", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); if(handle == INVALID_HANDLE_VALUE) { GC.SuppressFinalize(this); Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(Marshal.GetLastWin32Error())); } } ~Accelerometer() { CloseImpl(); } private void CloseImpl() { IntPtr h = handle; if(h != INVALID_HANDLE_VALUE) { handle = INVALID_HANDLE_VALUE; CloseHandle(h); } } public void ReadSample() { uint dwRead = 0; if(!DeviceIoControl(handle, IOCTL_SHOCKMGR_READ_ACCELEROMETER_DATA, IntPtr.Zero, 0, ref sample, 0x24, ref dwRead, IntPtr.Zero)) { Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(Marshal.GetLastWin32Error())); } } public int Status { get { return sample.status; } } public int X { get { return sample.x0; } } public int Y { get { return sample.y0; } } public void Dispose() { CloseImpl(); GC.SuppressFinalize(this); } } namespace Horizon { /// /// Summary description for Form1. /// public class Form1 : System.Windows.Forms.Form { private System.ComponentModel.IContainer components; private System.Windows.Forms.Timer timer1; private Accelerometer sensor = new Accelerometer(); public Form1() { // // Required for Windows Form Designer support // InitializeComponent(); // // TODO: Add any constructor code after InitializeComponent call // } /// /// Clean up any resources being used. /// protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } } base.Dispose( disposing ); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.components = new System.ComponentModel.Container(); this.timer1 = new System.Windows.Forms.Timer(this.components); // // timer1 // this.timer1.Enabled = true; this.timer1.Tick += new System.EventHandler(this.timer1_Tick); // // Form1 // this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(292, 266); this.Name = "Form1"; this.Text = "Form1"; } #endregion /// /// The main entry point for the application. /// [STAThread] static void Main() { Application.Run(new Form1()); } private void timer1_Tick(object sender, System.EventArgs e) { sensor.ReadSample(); Invalidate(); } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); float horizontal = 640; float vertical = 800; float y = sensor.Y; float angle = 90 * (y - horizontal) / (vertical - horizontal); e.Graphics.DrawString(angle.ToString(), Font, Brushes.Black, 0, 0); e.Graphics.TranslateTransform(ClientRectangle.Width / 2, ClientRectangle.Height / 2); e.Graphics.RotateTransform(- angle); e.Graphics.DrawLine(Pens.Black, - ClientRectangle.Width / 2, 0, ClientRectangle.Width / 2, 0); } } }