引发传感器事件
有关传感器事件工作原理的详细信息,请参阅 关于传感器驱动程序事件。
下面的代码示例演示一个类,该类引发数据更新和状态更改事件。 类名为 CSensorManager。
成员变量
此类定义以下成员变量。
// Smart pointer to the sensor class extension object.
CComPtr<ISensorClassExtension> m_spSensorCXT;
// Pointer to the callback class that the class extension calls.
CSensorDdi* m_pDdi;
// The event thread handle
HANDLE m_hEventThread;
// Handle to an event used to signal the thread to close.
HANDLE m_hCloseThread;
// The current report interval.
DWORD m_dwInterval;
全局变量
驱动程序将定义此类使用的以下全局变量。
// Sensor ID
static const LPWSTR g_wszSensorID = L"My Sensor ID";
// Default event interval
static const DWORD g_dwDefaultInterval = 1000; // one second
生存期管理
名为 CSensorDdi 的回调类实现 ISensorDriver,在第一个客户端订阅事件时创建 CSampleEvents 事件类的实例。 当客户端不再订阅事件时,回调类会销毁 CSampleEvents 实例。
CSampleEvents 调用回 CSensorDdi,以使用类扩展使用的相同方法(例如 ISensorDriver::OnGetDataFields)检索最新数据。
下面的代码示例包含 CSampleEvents 事件类的方法实现。
CSampleEvents::CSampleEvents()
{
// Initialize member variables.
m_hEventThread = NULL;
m_hCloseThread = NULL;
m_dwInterval = g_dwDefaultInterval;
};
CSampleEvents::~CSampleEvents()
{
};
// Initialize
// Sets the pointers to the class extension and the callback class.
HRESULT CSampleEvents::Initialize(ISensorClassExtension *pSensorCXT, CSensorDdi* pDdi)
{
HRESULT hr = S_OK;
if(NULL == pSensorCXT || NULL == pDdi)
{
return E_POINTER;
}
// Cache the pointers to the class extension and DDI callback class.
m_spSensorCXT = pSensorCXT;
m_pDdi = pDdi;
// Create the event used to close the thread.
m_hCloseThread = ::CreateEvent(NULL, FALSE, FALSE, TEXT("CloseThreadEvent"));
if(NULL == m_hCloseThread)
{
hr = E_UNEXPECTED;
}
if(SUCCEEDED(hr))
{
m_hEventThread = ::CreateThread(NULL, // Cannot be inherited by child process
0, // Default stack size
&CSampleEvents::_EventThreadProc, // Thread proc
(LPVOID)this, // Thread proc argument
0, // Starting state = running
NULL); // No thread identifier
if(NULL == m_hEventThread)
{
hr = E_UNEXPECTED;
}
}
return hr;
};
// Uninitializes the event class.
HRESULT CSampleEvents::Uninitialize()
{
HRESULT hr = S_OK;
// Stop the event thread.
::SetEvent(m_hCloseThread);
// Wait for the thread to end.
::WaitForSingleObject(m_hEventThread, INFINITE);
if (NULL != m_hEventThread)
{
CloseHandle(m_hEventThread);
m_hEventThread = NULL;
}
if(NULL != m_hCloseThread)
{
CloseHandle(m_hCloseThread);
m_hCloseThread = NULL;
}
// After Uninitialize, clients must call Initialize to set new pointers.
m_pDdi = NULL;
m_spSensorCXT.Release();
return hr;
};
// Post a state change event
HRESULT CSampleEvents::PostStateEvent()
{
HRESULT hr = (NULL == m_spSensorCXT) ? E_UNEXPECTED : S_OK ;
if (SUCCEEDED(hr))
{
SensorState st;
hr = m_pDdi->GetSensorState(&st);
if (SUCCEEDED(hr))
{
// Post the state change event.
hr = m_spSensorCXT->PostStateChange(g_wszSensorID, st);
}
}
return hr;
}
// Post a data updated event
HRESULT CSampleEvents::PostDataEvent(IPortableDeviceValues* pValues)
{
HRESULT hr = (NULL == m_spSensorCXT) ? E_UNEXPECTED : S_OK ;
if (SUCCEEDED(hr))
{
CComPtr<IPortableDeviceValuesCollection> spValuesCollection;
hr = spValuesCollection.CoCreateInstance(CLSID_PortableDeviceValuesCollection);
if (SUCCEEDED(hr))
{
hr = spValuesCollection->Add(pValues);
if (SUCCEEDED(hr))
{
hr = m_spSensorCXT->PostEvent(g_wszSensorID, spValuesCollection);
}
}
}
return hr;
}
线程过程
以下示例代码演示使用 CSampleEvents 类引发数据更新事件的线程过程。
DWORD WINAPI CSampleEvents::_EventThreadProc(__in LPVOID pvData)
{
// Cast the argument to the correct type.
CSampleEvents* pThis = static_cast<CSampleEvents*>(pvData);
// New threads must always CoInitialize...
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (SUCCEEDED(hr))
{
// Wait loop timed to use current report interval.
while (WAIT_TIMEOUT == WaitForSingleObject(pThis->m_hCloseThread, pThis->m_dwInterval))
{
if(NULL == pThis->m_pDdi ||
NULL == pThis->m_spSensorCXT.p)
{
Trace(TRACE_LEVEL_ERROR, "%!FUNC!: NULL pointer in helper function.");
hr = E_POINTER;
}
CComPtr<IPortableDeviceValues> spEventParams;
CComPtr<IPortableDeviceKeyCollection> spKeys;
if(SUCCEEDED(hr))
{
// Use the Ddi class to create the key collection.
hr = pThis->m_pDdi->OnGetSupportedDataFields(g_wszSensorID, &spKeys);
}
if(SUCCEEDED(hr))
{
CComPtr<IWDFFile> spTemp;
// Get the data fields.
// Note that we're using a DDI call as a helper function, here.
// Setting the first parameter to NULL will be problematic if you
// choose to track or use IWDFFile pointers in OnGetDataFields.
// This sample does not do so, therefore this is a safe thing to do
// in this code.
hr = pThis->m_pDdi->OnGetDataFields(spTemp, g_wszSensorID, spKeys,
&spEventParams);
}
if(SUCCEEDED(hr))
{
// Add the data event property key.
hr = spEventParams->SetGuidValue(SENSOR_EVENT_PARAMETER_EVENT_ID,
SENSOR_EVENT_DATA_UPDATED);
if(SUCCEEDED(hr))
{
// Post the event.
hr = pThis->PostDataEvent(spEventParams);
}
}
}
}
CoUninitialize();
return SUCCEEDED(hr) ? 0 : 1;
};
相关主题
反馈
https://aka.ms/ContentUserFeedback。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈