Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
In deze sectie wordt het Windows Touch Manipulatie-voorbeeld beschreven.
Het voorbeeld van Windows Touch-manipulatie laat zien hoe u een object kunt verplaatsen, draaien en schalen met behulp van de interface IManipulationProcessor en hoe u een _IManipulationEvents event sink implementeert. In de volgende schermafbeelding ziet u hoe het voorbeeld eruitziet wanneer het wordt uitgevoerd.
Voor dit voorbeeld wordt een CDrawingObject--klasse gemaakt die programmatisch kan worden vertaald, gedraaid of geschaald. Er wordt een IManipulationProcessor-interface geïnstantieerd. Er wordt een sink voor manipulatie-gebeurtenissen gemaakt die een aanwijzer accepteert naar de CDrawingObject-klasse klasse en de IManipulationProcessor interface op de constructor. In de implementatie van de manipulatie-gebeurtenissink wordt een verbindingspunt met IManipulationProcessor gecreëerd, zodat gebeurtenissen die door de IManipulationProcessor worden gegenereerd, worden ontvangen door de gebeurtenissink. Touch-gegevens worden doorgegeven aan de IManipulationProcessor interface en de interface genereert vervolgens _IManipulationEvent gebeurtenissen. De gebeurtenis-handlers in de CManipulationEventSink klasse werken de stand van de CDrawingObject bij door accessors aan te roepen op de aanwijzer naar de CDrawingObject.
De volgende code laat zien hoe het venster is ingesteld voor touch en hoe de CDrawingObject en IManipulationProcessor worden geïnstantieerd en doorgegeven aan de CManipulationEventSink constructor.
CDrawingObject g_cRect; // CDrawingObject class holds information about the rectangle
// and it is responsible for painting the rectangle.
(...)
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
(...)
// Register application window for receiving multi-touch input. Use default settings.
if (!RegisterTouchWindow(hWnd, 0))
{
MessageBox(hWnd, L"Cannot register application window for multi-touch input", L"Error", MB_OK);
return FALSE;
}
ASSERT(IsTouchWindow(hWnd, NULL));
// Instantiate the ManipulationProcessor object
HRESULT hr = CoCreateInstance(__uuidof(ManipulationProcessor), NULL, CLSCTX_ALL, IID_PPV_ARGS(&g_pIManipProc));
if (FAILED(hr))
{
ASSERT(SUCCEEDED(hr) && L"InitInstance: failed to instantiate the ManipulationProcessor object");
return FALSE;
}
// Instantiate the event sink with the manipulation processor and pointer to the rectangle object
g_pManipulationEventSink = new CManipulationEventSink(&g_cRect);
if (g_pManipulationEventSink == NULL)
{
ASSERT(g_pManipulationEventSink && L"InitInstance: failed to instantiate the CManipulationEventSink class");
g_pIManipProc->Release();
g_pIManipProc = NULL;
return FALSE;
}
// Establish the link between ManipulationEventSink and ManipulationProcessor
if (!g_pManipulationEventSink->Connect(g_pIManipProc))
{
ASSERT(FALSE && L"InitInstance: failed to connect ManipulationEventSink and ManipulationProcessor");
g_pIManipProc->Release();
g_pIManipProc = NULL;
g_pManipulationEventSink->Release();
g_pManipulationEventSink = NULL;
return FALSE;
}
De volgende code toont de constructor voor de sink voor manipulatie gebeurtenis, CManipulationEventSink.
CManipulationEventSink::CManipulationEventSink(CDrawingObject* pcDrawingObject)
: m_cRefCount(1),
m_pConnection(NULL),
m_dwCookie(0),
m_pcDrawingObject(pcDrawingObject)
{
ASSERT((pcDrawingObject != NULL) && L"CManipulationEventSink constructor: incorrect argument");
}
De volgende code laat zien hoe de gebeurtenissink is verbonden met de manipulatieprocessor.
bool CManipulationEventSink::Connect(IManipulationProcessor* pManipulationProcessor)
{
// Check input arguments
if (pManipulationProcessor == NULL)
{
ASSERT((pManipulationProcessor != NULL) && L"CManipulationEventSink::Create : incorrect arguments");
return false;
}
// Check object state
if ((m_dwCookie != 0) || (m_pConnection != NULL))
{
ASSERT((m_dwCookie == 0) && (m_pConnection == NULL) && L"CManipulationEventSink::Connect : connection already established");
return false;
}
// Get the container with the connection points.
IConnectionPointContainer* pConnectionContainer = NULL;
HRESULT hr = pManipulationProcessor->QueryInterface(&pConnectionContainer);
if (FAILED(hr))
{
ASSERT(SUCCEEDED(hr) && L"CManipulationEventSink::Connect : failed to get the container with the connection points");
return false;
}
// Get a connection point.
hr = pConnectionContainer->FindConnectionPoint(__uuidof(_IManipulationEvents), &m_pConnection);
if (FAILED(hr))
{
ASSERT(SUCCEEDED(hr) && L"CManipulationEventSink::Connect : failed to get a connection point");
pConnectionContainer->Release();
return false;
}
// Release the connection container.
pConnectionContainer->Release();
// Advise. Establishes an advisory connection between the connection point and the
// caller's sink object.
hr = m_pConnection->Advise(this, &m_dwCookie);
if (FAILED(hr))
{
ASSERT(SUCCEEDED(hr) && L"CManipulationEventSink::Connect : failed to Advise");
m_pConnection->Release();
m_pConnection = NULL;
return false;
}
return true;
}
De volgende code laat zien hoe aanraakgegevens worden doorgegeven aan de manipulatiegebeurtenissensink.
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
(...)
switch (message)
{
(...)
// WM_TOUCH message handlers
case WM_TOUCH:
{
// WM_TOUCH message can contain several messages from different contacts
// packed together.
// Message parameters need to be decoded:
UINT cInputs = (int) wParam; // Number of actual per-contact messages
TOUCHINPUT* pInputs = new TOUCHINPUT[cInputs]; // Allocate the storage for the parameters of the per-contact messages
if (pInputs == NULL)
{
break;
}
// Unpack message parameters into the array of TOUCHINPUT structures, each
// representing a message for one single contact.
if (GetTouchInputInfo((HTOUCHINPUT)lParam, cInputs, pInputs, sizeof(TOUCHINPUT)))
{
// For each contact, dispatch the message to the appropriate message
// handler.
for (unsigned int i = 0; i < cInputs; i++)
{
if (pInputs[i].dwFlags & TOUCHEVENTF_DOWN)
{
g_pIManipProc->ProcessDown(pInputs[i].dwID, (FLOAT)pInputs[i].x, (FLOAT)pInputs[i].y);
}
else if (pInputs[i].dwFlags & TOUCHEVENTF_MOVE)
{
g_pIManipProc->ProcessMove(pInputs[i].dwID, (FLOAT)pInputs[i].x, (FLOAT)pInputs[i].y);
}
else if (pInputs[i].dwFlags & TOUCHEVENTF_UP)
{
g_pIManipProc->ProcessUp(pInputs[i].dwID, (FLOAT)pInputs[i].x, (FLOAT)pInputs[i].y);
}
}
}
else
{
// error handling, presumably out of memory
ASSERT(FALSE && L"Error: failed to execute GetTouchInputInfo");
delete [] pInputs;
break;
}
if (!CloseTouchInputHandle((HTOUCHINPUT)lParam))
{
// error handling, presumably out of memory
ASSERT(FALSE && L"Error: failed to execute CloseTouchInputHandle");
delete [] pInputs;
break;
}
delete [] pInputs;
// Force redraw of the rectangle
InvalidateRect(hWnd, NULL, TRUE);
}
break;
De volgende code laat zien hoe de gebeurtenis-handlers de objectstand en grootte bijwerken bij manipulatie van delta-gebeurtenissen.
HRESULT STDMETHODCALLTYPE CManipulationEventSink::ManipulationDelta(
/* [in] */ FLOAT /* x */,
/* [in] */ FLOAT /* y */,
/* [in] */ FLOAT translationDeltaX,
/* [in] */ FLOAT translationDeltaY,
/* [in] */ FLOAT scaleDelta,
/* [in] */ FLOAT /* expansionDelta */,
/* [in] */ FLOAT rotationDelta,
/* [in] */ FLOAT /* cumulativeTranslationX */,
/* [in] */ FLOAT /* cumulativeTranslationY */,
/* [in] */ FLOAT /* cumulativeScale */,
/* [in] */ FLOAT /* cumulativeExpansion */,
/* [in] */ FLOAT /* cumulativeRotation */)
{
m_pcDrawingObject->ApplyManipulationDelta(translationDeltaX,translationDeltaY,scaleDelta,rotationDelta);
return S_OK;
}
De volgende code is de implementatie van ApplyManipulationDelta- in de klasse CDrawingObject.
// This function is responsible for manipulation of the rectangle.
// It is called from CManipulationEventSink class.
// in:
// translationDeltaX - shift of the x-coordinate (1/100 of pixel units)
// translationDeltaY - shift of the y-coordinate (1/100 of pixel units)
// scaleDelta - scale factor (zoom in/out)
// rotationDelta - rotation angle in radians
void CDrawingObject::ApplyManipulationDelta(
const FLOAT translationDeltaX,
const FLOAT translationDeltaY,
const FLOAT scaleDelta,
const FLOAT rotationDelta
)
{
_ptCenter.x += (LONG) (translationDeltaX / 100.0);
_ptCenter.y += (LONG) (translationDeltaY / 100.0);
_dScalingFactor *= scaleDelta;
_dRotationAngle -= rotationDelta; // we are subtracting because Y-axis is down
}
Nadat de middelpunten, schaalfactor en rotatiehoek van de CDrawingObjectzijn bijgewerkt, zal het object zichzelf getransformeerd tekenen.
Verwante onderwerpen
multi-touch manipulatietoepassing, Manipulatie en Inertie Voorbeeld, Windows Touch Voorbeelden