Сенсорная панель Windows с использованием примера пера в режиме реального времени (C++)
В примере сенсорной панели Windows (MTScratchpadRTStylus) показано, как использовать сообщения Windows Touch для рисования трассировок точек касания в окне. След основного пальца, который был помещен на дигитайзер первым, рисуется черным цветом. Вторичные пальцы рисуются в шести других цветах: красный, зеленый, синий, голубой, пурпурный и желтый. На следующем снимке экрана показано, как приложение может выглядеть во время выполнения.
В этом примере создается объект Stylus в реальном времени (RTS) и включена поддержка нескольких точек контакта. Подключаемый модуль DynamicRenderer добавляется в RTS для отрисовки содержимого. Подключаемый модуль CSyncEventHandlerRTS реализуется для отслеживания количества пальцев и изменения цвета, который рисует динамический отрисовщик. При использовании обоих подключаемых модулей в стеке подключаемых модулей RTS приложение Windows Touch Scratchpad будет отображать основной контакт черным цветом, а остальные контакты — различными цветами.
В следующем коде показано, как создается объект RTS с поддержкой нескольких точек контакта.
IRealTimeStylus* CreateRealTimeStylus(HWND hWnd)
{
// Check input argument
if (hWnd == NULL)
{
ASSERT(hWnd && L"CreateRealTimeStylus: invalid argument hWnd");
return NULL;
}
// Create RTS object
IRealTimeStylus* pRealTimeStylus = NULL;
HRESULT hr = CoCreateInstance(CLSID_RealTimeStylus, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pRealTimeStylus));
if (FAILED(hr))
{
ASSERT(SUCCEEDED(hr) && L"CreateRealTimeStylus: failed to CoCreateInstance of RealTimeStylus");
return NULL;
}
// Attach RTS object to a window
hr = pRealTimeStylus->put_HWND((HANDLE_PTR)hWnd);
if (FAILED(hr))
{
ASSERT(SUCCEEDED(hr) && L"CreateRealTimeStylus: failed to set window handle");
pRealTimeStylus->Release();
return NULL;
}
// Register RTS object for receiving multi-touch input.
IRealTimeStylus3* pRealTimeStylus3 = NULL;
hr = pRealTimeStylus->QueryInterface(&pRealTimeStylus3);
if (FAILED(hr))
{
ASSERT(SUCCEEDED(hr) && L"CreateRealTimeStylus: cannot access IRealTimeStylus3");
pRealTimeStylus->Release();
return NULL;
}
hr = pRealTimeStylus3->put_MultiTouchEnabled(TRUE);
if (FAILED(hr))
{
ASSERT(SUCCEEDED(hr) && L"CreateRealTimeStylus: failed to enable multi-touch");
pRealTimeStylus->Release();
pRealTimeStylus3->Release();
return NULL;
}
pRealTimeStylus3->Release();
return pRealTimeStylus;
}
В следующем коде показано, как создается подключаемый модуль динамического отрисовщика и добавляется в RTS.
IDynamicRenderer* CreateDynamicRenderer(IRealTimeStylus* pRealTimeStylus)
{
// Check input argument
if (pRealTimeStylus == NULL)
{
ASSERT(pRealTimeStylus && L"CreateDynamicRenderer: invalid argument RealTimeStylus");
return NULL;
}
// Get window handle from RTS object
HWND hWnd = NULL;
HRESULT hr = pRealTimeStylus->get_HWND((HANDLE_PTR*)&hWnd);
if (FAILED(hr))
{
ASSERT(SUCCEEDED(hr) && L"CreateDynamicRenderer: failed to get window handle");
return NULL;
}
// Create DynamicRenderer object
IDynamicRenderer* pDynamicRenderer = NULL;
hr = CoCreateInstance(CLSID_DynamicRenderer, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pDynamicRenderer));
if (FAILED(hr))
{
ASSERT(SUCCEEDED(hr) && L"CreateDynamicRenderer: failed to CoCreateInstance of DynamicRenderer");
return NULL;
}
// Add DynamicRenderer to the RTS object as a synchronous plugin
IStylusSyncPlugin* pSyncDynamicRenderer = NULL;
hr = pDynamicRenderer->QueryInterface(&pSyncDynamicRenderer);
if (FAILED(hr))
{
ASSERT(SUCCEEDED(hr) && L"CreateDynamicRenderer: failed to access IStylusSyncPlugin of DynamicRenderer");
pDynamicRenderer->Release();
return NULL;
}
hr = pRealTimeStylus->AddStylusSyncPlugin(
0, // insert plugin at position 0 in the sync plugin list
pSyncDynamicRenderer); // plugin to be inserted - DynamicRenderer
if (FAILED(hr))
{
ASSERT(SUCCEEDED(hr) && L"CreateDynamicRenderer: failed to add DynamicRenderer to the RealTimeStylus plugins");
pDynamicRenderer->Release();
pSyncDynamicRenderer->Release();
return NULL;
}
// Attach DynamicRenderer to the same window RTS object is attached to
hr = pDynamicRenderer->put_HWND((HANDLE_PTR)hWnd);
if (FAILED(hr))
{
ASSERT(SUCCEEDED(hr) && L"CreateDynamicRenderer: failed to set window handle");
pDynamicRenderer->Release();
pSyncDynamicRenderer->Release();
return NULL;
}
pSyncDynamicRenderer->Release();
return pDynamicRenderer;
}
Следующий код изменяет цвет росчерка пера для обработчика событий StylusDown в CSyncEventHandlerRTS, пользовательском подключаемом модуле RTS.
HRESULT CSyncEventHandlerRTS::StylusDown(
IRealTimeStylus* /* piRtsSrc */,
const StylusInfo* /* pStylusInfo */,
ULONG /* cPropCountPerPkt */,
LONG* /* pPacket */,
LONG** /* ppInOutPkt */)
{
// Get DrawingAttributes of DynamicRenderer
IInkDrawingAttributes* pDrawingAttributesDynamicRenderer;
HRESULT hr = g_pDynamicRenderer->get_DrawingAttributes(&pDrawingAttributesDynamicRenderer);
if (FAILED(hr))
{
ASSERT(SUCCEEDED(hr) && L"CSyncEventHandlerRTS::StylusDown: failed to get RTS's drawing attributes");
return hr;
}
// Set new stroke color to the DrawingAttributes of the DynamicRenderer
// If there are no fingers down, this is a primary contact
hr = pDrawingAttributesDynamicRenderer->put_Color(GetTouchColor(m_nContacts == 0));
if (FAILED(hr))
{
ASSERT(SUCCEEDED(hr) && L"CSyncEventHandlerRTS::StylusDown: failed to set color");
pDrawingAttributesDynamicRenderer->Release();
return hr;
}
pDrawingAttributesDynamicRenderer->Release();
++m_nContacts; // Increment finger-down counter
return S_OK;
}
Когда значение m_nContacts увеличивается, цвет, заданный в динамическом отрисовщике, изменится. Штрихи, которые не являются основным контактом, будут нарисованы разными цветами.
Связанные темы
Мультисенсорное приложение (RTS/C#),мультисенсорное приложение для сенсорной панели (RTS/C++),Примеры сенсорного ввода Windows