这是回调函数,定义如下:
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());
}