技术开发 频道

Windows Mobile下的重力感应器开发

 这是回调函数,定义如下:

  private:

 static void GetVectorHandler(SmiAccelerometerVector accel);

 由于SmiAccelerometerRegisterHandler()注册的回调函数只能是static的,所以我在开发SamsungGSensor的时候不得不把这个类做成Singleton,否则static函数没法取出对象的实例指针了。

 运行于Samsung机器的界面

 HTC GSensor API

 目前为止(2009年7月),HTC还没有公开Sensor的APIs,所以这些API都是通过反向工程(Reverse Engineering)出来的,使用有风险,自己承担。

 API的定义生成和清理

 

 private:

 // The following PInvokes were ported from the results of the reverse engineering done

 // by Scott at scottandmichelle.net.

 // Blog post: http://scottandmichelle.net/scott/comments.html?entry=784

 typedef HANDLE (WINAPI * PFN_HTCSensorOpen)(DWORD);

 typedef void (WINAPI * PFN_HTCSensorClose)(HANDLE);

 typedef DWORD (WINAPI * PFN_HTCSensorGetDataOutput)(HANDLE, PSENSORDATA);

 PFN_HTCSensorOpen           pfnHTCSensorOpen;

 PFN_HTCSensorClose          pfnHTCSensorClose;

 PFN_HTCSensorGetDataOutput  pfnHTCSensorGetDataOutput;

 #define SENSOR_DLL      L"HTCSensorSDK.dll"

 HTCGSensor::HTCGSensor(void)

 {

 HMODULE hSensorLib = LoadLibrary(SENSOR_DLL);

 if (hSensorLib == NULL)

 {

 printf("Unable to load HTC Sensor DLL");

 throw;

 }

 pfnHTCSensorOpen = (PFN_HTCSensorOpen)

 GetProcAddress(hSensorLib, L"HTCSensorOpen");

 pfnHTCSensorClose = (PFN_HTCSensorClose)

 GetProcAddress(hSensorLib, L"HTCSensorClose");

 pfnHTCSensorGetDataOutput = (PFN_HTCSensorGetDataOutput)

 GetProcAddress(hSensorLib, L"HTCSensorGetDataOutput");

 if (pfnHTCSensorOpen == NULL ||

 pfnHTCSensorClose == NULL ||

 pfnHTCSensorGetDataOutput == NULL)

 {

 printf("Unable to find entry point");

 throw;

 }

 sensorHandle = NULL;

 sensorHandle = pfnHTCSensorOpen(HTC_GSensor);

 }

 HTCGSensor* HTCGSensor::Create()

 {

 HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, L"HTC_GSENSOR_SERVICESTART");

 if (hEvent == NULL || GetLastError() != ERROR_ALREADY_EXISTS)

 {

 printf("Unable to create Sensor Event");

 throw;

 }

 SetEvent(hEvent);

 CloseHandle(hEvent);

 return new HTCGSensor();

 }

 HTCGSensor::~HTCGSensor(void)

 {

 if(sensorHandle != NULL)

 {

 pfnHTCSensorClose(sensorHandle);

 sensorHandle = NULL;

 }

 HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, L"HTC_GSENSOR_SERVICESTOP");

 if (hEvent == NULL || GetLastError() != ERROR_ALREADY_EXISTS)

 {

 printf("Unable to stop Sensor Event");

 throw;

 }

 SetEvent(hEvent);

 CloseHandle(hEvent);

 }

 HTCGSensor()构造函数加载DLL和生成函数调用的入口指针。Create()函数启动Sensor。~HTCGSensor()释放资源。

 取GVector信息

 

 GVector HTCGSensor::GetGVector()

 {

 GVector gVector;

 SENSORDATA data;

 pfnHTCSensorGetDataOutput(sensorHandle, &data);

 // HTC's Sensor returns a vector which is around 1000 in length on average..

 // but it really depends on how the device is oriented.

 // When simply face up, my Diamond returns a vector of around 840 in length.

 // While face down, it returns a vector of around 1200 in length.

 // The vector direction is fairly accurate, however, the length is clearly not extremely precise.

 float htcScaleFactor = 1.0 / 1000.0 * 9.8;

 gVector.x = data.TiltX * htcScaleFactor;

 gVector.y = data.TiltY * htcScaleFactor;

 gVector.z = data.Orientation * htcScaleFactor;

 return gVector;

 }

 订阅GVector信息

 由于HTC的API不提供订阅功能,所以我封装了一个ThreadTask(线程任务)类,负责生成一个线程,该线程定期执行任务,在这个场景下定期任务用于取GVector信息。

 

 #include <Windows.h>

 class ThreadTask

 {

 public:

 ThreadTask();

 ~ThreadTask(void);

 private:

 HANDLE    mProcEvent;

 HANDLE    mThreadHnd;

 DWORD    mThreadId;

 bool    mThreadHalt;

 int     mInterval;

 bool    mStarted;

 public:

 void ProcessTask();

 void Start(int interval);

 void Stop();

 virtual void Process() {};

 };

 //    Thread methods

 DWORD WINAPI ProcessThread(void *param)

 {

 if (param)

 {

 ThreadTask* thread = (ThreadTask*)param;

 thread->ProcessTask();

 }

 return 0;

 }

 ThreadTask::ThreadTask() :

 mProcEvent(INVALID_HANDLE_VALUE),

 mThreadHnd(NULL),

 mThreadId(0),

 mThreadHalt(false),

 mInterval(0),

 mStarted(false)

 {

 }

 ThreadTask::~ThreadTask(void)

 {

 Stop();

 }

 void ThreadTask::Start(int interval)

 {

 if(!mStarted)

 {

 mStarted = true;

 mInterval = interval;

 mProcEvent = CreateEvent(NULL, true, false, NULL);            //    manual reset, initial state reset

 mThreadHnd = CreateThread(NULL, 0, &ProcessThread, this, CREATE_SUSPENDED, &mThreadId);

 if (mThreadHnd)

 {

 SetThreadPriority(mThreadHnd,THREAD_PRIORITY_NORMAL);

 ResumeThread(mThreadHnd);

 }

 }

 }

 void ThreadTask::Stop()

 {

 if(mStarted)

 {

 mThreadHalt = true;

 // Signal the event

 SetEvent(mProcEvent);

 // Wait for the Thread to Die

 WaitForSingleObject(mThreadHnd, INFINITE);

 CloseHandle(mThreadHnd);

 CloseHandle(mProcEvent);

 mStarted = false;

 }

 }

 void ThreadTask::ProcessTask()

 {

 while (!mThreadHalt)

 {

 WaitForSingleObject(mProcEvent, mInterval); //INFINITE

 ResetEvent(mProcEvent);

 //process by subclass

 Process();

 }

 }

 作为ThreadTask的子类只需要知道interval来启动Thread,然后重写处理定时任务函数(Override Process() )。ThreadTask可以用于Windows Mobile开发下的很多场景下。

  void HTCGSensor::Register()

 {

 Start(1000);

 }

 void HTCGSensor::Unregister()

 {

 Stop();

 }

 void HTCGSensor::Process()

 {

 GVectorChanged(GetGVector());

 }

0
相关文章