使用感應器 API 事件
感應器 API 會透過回呼介面提供事件通知。
若要接收事件通知,您的程式必須實作必要的 COM 回呼介面。 若要從感應器接收事件,您必須實 作 ISensorEvents 。 若要從感應器管理員接收事件,您必須實 作 ISensorManagerEvents 。
下列範例程式碼會建立實作 ISensorEvents 的 類別。
class CMyEvents : public ISensorEvents
{
public:
STDMETHODIMP QueryInterface(REFIID iid, void** ppv)
{
if (ppv == NULL)
{
return E_POINTER;
}
if (iid == __uuidof(IUnknown))
{
*ppv = static_cast<IUnknown*>(this);
}
else if (iid == __uuidof(ISensorEvents))
{
*ppv = static_cast<ISensorEvents*>(this);
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
STDMETHODIMP_(ULONG) AddRef()
{
return InterlockedIncrement(&m_cRef);
}
STDMETHODIMP_(ULONG) Release()
{
ULONG count = InterlockedDecrement(&m_cRef);
if (count == 0)
{
delete this;
return 0;
}
return count;
}
//
// ISensorEvents methods.
//
STDMETHODIMP OnEvent(
ISensor *pSensor,
REFGUID eventID,
IPortableDeviceValues *pEventData)
{
HRESULT hr = S_OK;
// Handle custom events here.
return hr;
}
STDMETHODIMP OnDataUpdated(
ISensor *pSensor,
ISensorDataReport *pNewData)
{
HRESULT hr = S_OK;
if(NULL == pNewData ||
NULL == pSensor)
{
return E_INVALIDARG;
}
ULONG ulHour = 0;
ULONG ulMinute = 0;
ULONG ulSecond = 0;
PROPVARIANT var = {};
hr = pNewData->GetSensorValue(SAMPLE_SENSOR_DATA_TYPE_HOUR, &var);
if(SUCCEEDED(hr))
{
if(var.vt == VT_UI4)
{
// Get the hour value.
ulHour = var.ulVal;
}
}
PropVariantClear(&var);
if(SUCCEEDED(hr))
{
hr = pNewData->GetSensorValue(SAMPLE_SENSOR_DATA_TYPE_MINUTE, &var);
}
if(SUCCEEDED(hr))
{
if(var.vt == VT_UI4)
{
// Get the hour value.
ulMinute = var.ulVal;
}
}
PropVariantClear(&var);
if(SUCCEEDED(hr))
{
hr = pNewData->GetSensorValue(SAMPLE_SENSOR_DATA_TYPE_SECOND, &var);
}
if(SUCCEEDED(hr))
{
if(var.vt == VT_UI4)
{
// Get the hour value.
ulSecond = var.ulVal;
}
}
PropVariantClear(&var);
if(SUCCEEDED(hr))
{
// Print
wprintf_s(L"Current local time is: \n");
wprintf_s(L"%02d:%02d:%02d (asynchronous)\n", ulHour, ulMinute, ulSecond);
}
return hr;
}
STDMETHODIMP OnLeave(
REFSENSOR_ID sensorID)
{
HRESULT hr = S_OK;
// Peform any housekeeping tasks for the sensor that is leaving.
// For example, if you have maintained a reference to the sensor,
// release it now and set the pointer to NULL.
return hr;
}
STDMETHODIMP OnStateChanged(
ISensor* pSensor,
SensorState state)
{
HRESULT hr = S_OK;
if(NULL == pSensor)
{
return E_INVALIDARG;
}
if(state == SENSOR_STATE_READY)
{
wprintf_s(L"\nTime sensor is now ready.");
}
else if(state == SENSOR_STATE_ACCESS_DENIED)
{
wprintf_s(L"\nNo permission for the time sensor.\n");
wprintf_s(L"Enable the sensor in the control panel.\n");
}
return hr;
}
private:
long m_cRef;
};
實作回呼介面之後,您可以為特定感應器提供回呼類別實例的指標,以開始接收來自感應器的事件通知。
下列範例程式碼會建立回呼類別的實例,然後從感應器要求事件通知。
CMyEvents* pEventClass = NULL;
ISensorEvents* pMyEvents = NULL;
if(SUCCEEDED(hr))
{
// Create an instance of the event class.
pEventClass = new(std::nothrow) CMyEvents();
}
if(SUCCEEDED(hr))
{
// Retrieve the pointer to the callback interface.
hr = pEventClass->QueryInterface(IID_PPV_ARGS(&pMyEvents));
}
if(SUCCEEDED(hr))
{
// Start receiving events.
hr = pSensor->SetEventSink(pMyEvents);
}
您可以撰寫類似的程式碼,以接收來自感應器管理員的事件。
下列範例程式碼示範如何停止接收事件通知。
if(SUCCEEDED(hr))
{
hr = pSensor->SetEventSink(NULL);
}
要求報表間隔
您可以建議應用程式接收資料更新事件的頻率值。 不過,感應器不需要以任何特定間隔提供事件。 您應該知道,建議的值可能不符合感應器用來引發事件的實際報告間隔。 若要知道實際的報表間隔,請擷取SENSOR_PROPERTY_CURRENT_REPORT_INTERVAL屬性的值,如擷取和設定感應器屬性 中所述 。
下列範例程式碼會建立協助程式函式,要求SENSOR_PROPERTY_CURRENT_REPORT_INTERVAL屬性的新值。 函式會取得要設定屬性之感應器的指標,以及 指出要設定之新報表間隔的 ULONG 值。
HRESULT SetCurrentReportInterval(ISensor* pSensor, ULONG ulNewInterval)
{
assert(pSensor);
HRESULT hr = S_OK;
IPortableDeviceValues* pPropsToSet = NULL; // Input
IPortableDeviceValues* pPropsReturn = NULL; // Output
// Create the input object.
hr = CoCreateInstance(__uuidof(PortableDeviceValues),
NULL,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&pPropsToSet));
if(SUCCEEDED(hr))
{
// Add the current report interval property.
hr = pPropsToSet->SetUnsignedIntegerValue(SENSOR_PROPERTY_CURRENT_REPORT_INTERVAL, ulNewInterval);
}
if(SUCCEEDED(hr))
{
// Only setting a single property, here.
hr = pSensor->SetProperties(pPropsToSet, &pPropsReturn);
}
// Test for failure.
if(hr == S_FALSE)
{
HRESULT hrError = S_OK;
// Check results for failure.
hr = pPropsReturn->GetErrorValue(SENSOR_PROPERTY_CURRENT_REPORT_INTERVAL, &hrError);
if(SUCCEEDED(hr))
{
// Print an error message.
wprintf_s(L"\nSetting current report interval failed with error 0x%X\n", hrError);
// Return the error code.
hr = hrError;
}
}
else if(hr == E_ACCESSDENIED)
{
// No permission. Take appropriate action.
}
SafeRelease(&pPropsToSet);
SafeRelease(&pPropsReturn);
return hr;
}
相關主題