Dieser Artikel wurde maschinell übersetzt.

Unterwegs

Erweiterung der Windows Touch-Anwendungen für mobile Benutzer

Gus Class

Downloaden des Codebeispiels

Windows 7 führt Windows Touch, die Fingereingabe auf fähige Hardware verbessert und bietet eine solide Plattform für das Touch-Anwendungen erstellen. Potenziell, bedeutet dies, dass Sie bemerkenswert intuitive Schnittstellen entwickeln können, die Benutzer aller Altersgruppen und Datenverarbeitung Fähigkeiten mit einer minimalen Menge an Schulungen oder Anweisung verstehen können.

Die magische hinter diese Funktionalität ist die Windows-Touch-API. Diese API verwenden, können Sie abrufen Informationen über, in denen ein Benutzer den Bildschirm berührt, und eines Benutzers auf dem Bildschirm Stiftbewegungen. Sie haben auch Zugriff auf realen Physik für Elemente der Benutzeroberfläche. Verschieben eines Objekts wird auf dem Bildschirm genauso einfach wie das Verschieben eines Objekts in der realen Welt. Strecken eines Objekts ist wie ein Stück Elastisch strecken. Wenn Benutzer mit einer well-implemented Touch-Anwendung interagieren, fühlen Sie als ob Sie mit der Technologie von morgen Interaktion sind, oder Sie nicht noch besser feststellen, dass Sie eine Anwendung überhaupt verwendet. Sie müssen eine Maus, einen Stift oder Kontextmenü Schlüssel verwenden, oder wählen Sie genau Menüelemente um Kernfunktionalität für die Anwendung zu erhalten.

Anwendungen, die auf mobilen Verwendungszweck zugeschnitten ist sollten bestimmte Anforderungen, um sicherzustellen, dass die Erfahrungen gut geeignet, um die Umgebung der Benutzerin integrieren. Eine mangelhaft implementierte Touch-Anwendung kann den Zweck der Verwendung von Windows Touch vollständig täuschen. Markieren Sie die Richtlinien Windows Touch User Experience (go.microsoft.com/fwlink/?LinkId=156610 ) Möglichkeiten, dass Entwickler die Benutzerfreundlichkeit für Benutzer unterwegs verbessern können. Diese Richtlinien behandelt verschiedene Szenarien für Entwickler von mobilen Anwendungen relevant und zur Vermeidung von potenzieller Fehlerquellen Windows Touch Entwicklung erleichtern.

Wenn Sie nur eine Sache aus diesem Artikel entziehen, denken Sie daran, dass beim Erstellen einer Anwendung, die Ziele mobile Benutzer müssen Sie Aspekte in Betracht ziehen, die für Ihre Art von Anwendung spezifisch sind. Beispielsweise wenn die Anwendung Windows-Steuerelemente verwendet, stellen Sie sicher, dass Sie eine angemessene Größe und ausreichende Abstände, damit Benutzer diese problemlos berühren können. Wenn Sie eine Anwendung erstellen, die Bewegungen nutzen können, stellen Sie sicher, dass die Bewegung Aktionen ordnungsgemäß verarbeitet werden.

Jedoch eines nach dem anderen.

In diesem Artikel werde ich eine Beispielanwendung Touch in Anspruch nehmen und es für mobile Anwendungen verbessern. Gehe ich davon aus, dass Sie sich einige Kenntnisse von COM und Windows Touch und Windows Touch-fähige Hardware. Für eine Einführung in Windows Touch wechseln Sie zu go.microsoft.com/fwlink/?LinkId=156612 , oder lesen Sie Artikel msdn.microsoft.com/magazine/ee336016.aspx-Yochay Kiriaty.

Das Beispiel ist auf der MSDN Code Gallery code.msdn.microsoft.com/ Windowstouchmanip . Die Downloads-Registerkarte enthält zwei ZIP-Dateien, die erste ohne mobilen Erweiterungen und die zweite mit Ihnen. Downloaden Sie die Datei mit dem Namen mehrere Manipulators.zip, erweitern Sie ihn, und kompilieren Sie das Projekt.

Um ehrlich zu sein, ist das Beispiel in bestimmten Situationen wie versuchen, eine einer thread während des Mittens mit: die Funktionalität ist auf einen Punkt verringert, die Benutzer frustrates. Wenn Sie versuchen, sich überlappende Objekte in einer überlappenden Bereich markieren, werden Sie z. B. markieren und verschieben beide Objekte. Sie können ein Objekt auch Größe anpassen, so dass es so klein ist, dass Sie die Größe erneut ändern nicht möglich. Ich werde zeigen, wie beheben diese Probleme und andere Änderungen, die zur Verbesserung der Benutzerfreundlichkeit in den Bereichen allgemeine Benutzerfreundlichkeit, Objektauswahl und die Verwendung einer natürliche Benutzeroberfläche vornehmen. Denken Sie daran, Überlegungen, die Sie für jede mobile Anwendung, wie Benutzer damit interagieren abhängig. Nur für diese spezielle Anwendung sollte die Probleme, die ich hier behandeln als Richtlinien verwendet werden.

Allgemeine Benutzerfreundlichkeit

Wenn ein Benutzer Bearbeiten von grafische Objekten in einer mobilen Anwendung ist, muss er Aufgaben ohne die Verwendung von Tastatur und Maus ausführen können. Sich auch, wenn ein mobiler Benutzer hohe DPI-Einstellungen unter oder mit mehreren Bildschirmen verbunden ist, muss die Anwendung konsistent Verhalten. (Hohe DPI-Anforderungen werden go.microsoft.com/fwlink/?LinkId=153387 ausführlich erläutert.)

Die Beispielanwendung Adressen für Windows Touch implizit das Problem der Erhalt der Benutzereingabe aus der Benutzer ohne Maus und Tastatur.  Benutzer können Fingereingabe für Aktionen wie z. B. Objekt Übersetzung, Skalierung und so weiter. Eine verwandte Überlegung ist Unterstützung von Maus und Tastatur Eingaben in einer Anwendung für Fingereingabe entwickelt, so dass ein Benutzer Laufwerk kann mithilfe von Eingaben, einschließlich Mauseingaben Manipulation-Prozessor. Abbildung 1 zeigt, wie Sie einen Benutzer, die Fingereingabe über Mauseingaben zu simulieren, indem Sie die Beispielanwendung zeichenbaren Klasse einige Hilfsfunktionen hinzufügen lassen konnte. Sie müssen auch WndProc Mauseingaben an den Prozessor input verknüpfen Handler hinzufügen (siehe Abbildung 2 ).

Abbildung 1 Utility-Funktionen für Nachbilden Touch Eingaben mit der Maus

VOID Drawable::FillInputData(TOUCHINPUT* inData, DWORD cursor, DWORD eType, DWORD time, int x, int y)
{
  inData->dwID = cursor;
  inData->dwFlags = eType;
  inData->dwTime = time;
  inData->x = x;
  inData->y = y;
}

void Drawable::ProcessMouseData(HWND hWnd, UINT msg, WPARAM wParam, LPARAM
  lParam){
  TOUCHINPUT tInput;
  if (this->getCursorID() == MOUSE_CURSOR_ID){    
   switch (msg){
    case WM_LBUTTONDOWN:
      FillInputData(&tInput, MOUSE_CURSOR_ID, TOUCHEVENTF_DOWN, (DWORD)GetMessageTime(),LOWORD(lParam) * 100,HIWORD(lParam) * 100);
      ProcessInputs(hWnd, 1, &tInput, 0);
      break;

    case WM_MOUSEMOVE:
      if(LOWORD(wParam) == MK_LBUTTON)
      {
       FillInputData(&tInput, MOUSE_CURSOR_ID, TOUCHEVENTF_MOVE, (DWORD)GetMessageTime(),LOWORD(lParam) * 100, HIWORD(lParam) * 100);
       ProcessInputs(hWnd, 1, &tInput, 0);
      }    
      break;

    case WM_LBUTTONUP:
      FillInputData(&tInput, MOUSE_CURSOR_ID, TOUCHEVENTF_UP, (DWORD)GetMessageTime(),LOWORD(lParam) * 100, HIWORD(lParam) * 100);    
      ProcessInputs(hWnd, 1, &tInput, 0);
      setCursorID(-1);
      break;
    default:
      break;
   } 
  }  
}

Abbildung 2 Änderungen von WndProc

case WM_LBUTTONDOWN:
  case WM_MOUSEMOVE: 
  case WM_LBUTTONUP:
   for (i=0; i<drawables; i++){
    // contact start
    if (message == WM_LBUTTONDOWN && draw[i]->IsContacted(LOWORD(lParam), HIWORD(lParam), MOUSE_CURSOR_ID)){
     draw[i]->setCursorID(MOUSE_CURSOR_ID);
    }
    // contact end
    if (message == WM_LBUTTONUP && draw[i]->getCursorID() == MOUSE_CURSOR_ID){
    draw[i]->setCursorID(-1);  
    }
    draw[i]->ProcessMouseData(hWnd, message, wParam, lParam);
   }   
   InvalidateRect(hWnd, NULL, false);
   break;

Um hohe DPI-Anforderungen zu erfüllen, können Sie die Buildeinstellungen, um die Anwendung die DPI-Einstellungen aufmerksam zu machen ein Manifest Projekt hinzufügen. Sie tun dies, damit der Koordinatenstelle steht, die bei der Arbeit auf verschiedenen Ebenen der DPI-Wert korrekt ist. (Wenn Sie möchten sehen, wie die Anwendung sich verhält, nachdem Sie die DPI-Ebene geändert haben, klicken Sie mit der rechten Maustaste auf den Desktop, klicken Sie auf personalisieren und ändern Sie dann die DPI-Ebene in der Systemsteuerung unter Anzeige.)

Das folgende XML veranschaulicht, wie dieses Manifest definiert werden kann, um Ihre Anwendung mit hohen DPI-Einstellungen kompatibel zu machen:

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" 
 xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
 <asmv3:application>
  <asmv3:windowsSettings xmlns=
"https://schemas.microsoft.com/SMI/2005/WindowsSettings">
  <dpiAware>true</dpiAware>
  </asmv3:windowsSettings>
 </asmv3:application>
</assembly>

Nachdem Sie das Projekt Manifest auf die Projekteigenschaften hinzugefügt haben, sendet die Anwendung Touch eingegebenen Informationen korrekt an den Prozessor Manipulation unabhängig von der DPI-Einstellungen des Benutzers. Sie können auch die ScreenToClient-Methode verwenden (siehe go.microsoft.com/fwlink/?LinkID=153391 für Weitere Informationen), um sicherzustellen, dass der Koordinatenstelle steht, werden festgelegt statt zu den Bildschirmkoordinaten an die Koordinaten, die Anwendung. Abbildung 3 zeigt die Änderungen der ProcessInputs-Memberfunktion der zeichenbaren-Klasse, die die Punkte Bildschirm Client Punkt zu konvertieren. Jetzt Wenn der Benutzer einen externen Monitor eine Verbindung zu einem Windows-Touch–enabled-Computer herstellt, der Koordinatenstelle steht, die Ihrer Anwendung konsistent bleibt und DPI-bewusst.

Abbildung 3 Konvertieren Bildschirm Punkte, um Client Points

POINT ptInput;
void Drawable::ProcessInputs(HWND hWnd, UINT cInputs, 
  PTOUCHINPUT pInputs, LPARAM lParam){
 for (int i=0; i < static_cast<INT>(cInputs); i++){
...
  ScreenToClient(hWnd, &ptInput);
      
  if (ti.dwFlags & TOUCHEVENTF_DOWN){
   if (IsContacted( ptInput.x, ptInput.y, ti.dwID) ){
    pManip->ProcessDownWithTime(ti.dwID, static_cast<FLOAT>
(ptInput.x), static_cast<FLOAT>( ptInput.y), ti.dwTime);      
    setCursorID(ti.dwID);      
    
    if (!CloseTouchInputHandle((HTOUCHINPUT)lParam)) {
    // Error handling      
    }
   }
  }
  if (pInputs[i].dwFlags & TOUCHEVENTF_MOVE){
   pManip->ProcessMoveWithTime(ti.dwID, static_cast<FLOAT>
(ptInput.x), static_cast<FLOAT>( ptInput.y), ti.dwTime);      
  }
  if (pInputs[i].dwFlags & TOUCHEVENTF_UP){
   pManip->ProcessUpWithTime(ti.dwID, static_cast<FLOAT>
(ptInput.x), static_cast<FLOAT>( ptInput.y), ti.dwTime);
   setCursorID(-1);
  }  
  // If you handled the message and don’t want anything else done 
  // with it, you can close it
 
 }
}

Selection-Objekt

Damit dieses Objekt Auswahl Funktionen wie der Benutzer erwartet, muss der Benutzer auf natürliche und intuitive Weise überlappende Objekte auswählen können, und der Benutzer muss sein auswählen können und zu transformieren einfach Objekte auf kleinere Formularfaktoren Bildschirme oder Bildschirme mit begrenzten Touch input Auflösung.

Wie die Anwendung derzeit, wenn ein Benutzer einem überlappenden Objekt auswählt, sendet die Anwendung Touch Daten auf alle Objekte, die unter dem Punkt, in denen der Benutzer das Fenster berührt. So ändern Sie die Anwendung beenden Behandlung Fingereingabe, nachdem das erste Objekt berührt festgestellt wird, müssen Sie das Touch-Eingabe-Handle zu schließen, wenn ein Objekt markiert ist. Abbildung 4 zeigt, wie Sie den Eingabe Touch Handler zum Beenden der Verarbeitung der Nachricht Touch nach erfolgter Kontaktaufnahme mit das erste Objekt aktualisieren können.

Abbildung 4 Aktualisieren des Handlers Touch Input

POINT ptInput;
void Drawable::ProcessInputs(HWND hWnd, UINT cInputs, 
  PTOUCHINPUT pInputs, LPARAM lParam){
 BOOL fContinue = TRUE;
 for (int i=0; i < static_cast<INT>(cInputs) && fContinue; i++){
...      
  if (ti.dwFlags & TOUCHEVENTF_DOWN){
   if (IsContacted( ptInput.x, ptInput.y, ti.dwID) ){
    pManip->ProcessDownWithTime(ti.dwID, static_cast<FLOAT>
(ptInput.x), static_cast<FLOAT>(ptInput.y), ti.dwTime);      
    setCursorID(ti.dwID);      
    
    fContinue = FALSE;
   }
  }
...
 }
 CloseTouchInputHandle((HTOUCHINPUT)lParam);

}

Nachdem Sie diese Änderung, Implementieren Wenn ein Objekt berührt kontaktiert wird, reagiert Touch Daten abrufen auf andere Objekte im Array gesendet. Um das Programm zu ändern, so dass nur das erste Objekt unter Maus input Touch empfängt Eingabe, Sie in der Verarbeitung der Anweisung für die Maus nach unten Eingabe kurzgeschlossen die Logik für Mauseingaben wird Eingabe außerhalb des Schalters unterbrechen können. Abbildung 5 veranschaulicht die Änderungen an der Switch-Anweisung in den Maus-input-Ereignishandler.

Abbildung 5 Ändern der Switch-Anweisung im Handler Mouse Input

case WM_LBUTTONDOWN:
   for (i=0; i<drawables; i++){
    if (draw[i]->IsContacted(LOWORD(lParam), HIWORD(lParam), MOUSE_CURSOR_ID)){
     draw[i]->setCursorID(MOUSE_CURSOR_ID);
     draw[i]->ProcessMouseData(hWnd, message, wParam, lParam); 
     break;
    }
   }
...

Als Nächstes sollten Sie Ihre Anwendung, um sicherzustellen, dass wenn ein Benutzer Objekte ändert, die Objekte nicht so klein werden, dass der Benutzer weder aktivieren noch deren Größe erneut ändern ändern. Sie können dieses Problem umgehen, können Sie Einstellungen in der API Manipulationen einschränken, wie klein ein Objekt sein kann Größe. Das Dienstprogramm Manipulation Prozessor des zeichenbaren-Objekts werden die folgenden Änderungen vorgenommen:

void Drawable::SetUpManipulator(void){
 pManip->put_MinimumScaleRotateRadius(4000.0f); 
}

Jetzt Wenn Sie ein Objekt skalieren, Werte Skala kleiner als 4.000 Centipixels von der Anwendung ignoriert werden. Einzelnen zeichenbaren Objekte können unique-Einschränkungen in der SetUpManipulator-Methode festgelegt wird, um sicherzustellen, dass das Objekt in einer entsprechenden Weise bearbeitet werden kann.

Natürliche Benutzeroberfläche

In einer Anwendung, die so konzipiert, dass eine natürliche Aussehen und Verhalten enthält sollte ein Benutzer auf mehrere Objekte gleichzeitige Manipulationen durchführen können. Objekte müsste einfache Physik, wenn Sie verschoben haben, über den Bildschirm, ähnlich wie Sie in der realen Welt Verhalten, und der Benutzer sollte nicht in der Lage, Objekte außerhalb des Bildschirms bearbeiten.

Konstruktionsbedingt sollten Anwendungen, die die API Manipulationen verwenden gleichzeitige Bearbeitung der Objekte unterstützen. Da in diesem Beispiel wird die Manipulationen-API verwendet, werden gleichzeitige Manipulationen automatisch aktiviert. Beim Verwenden des Stiftbewegungen-API für Windows Touch Unterstützung, gleichzeitige Bearbeitung der Objekte ist nicht möglich und zusammengesetzte Stiftbewegungen wie Schwenken + vergrößern und verkleinern + drehen sind entweder nicht. Aus diesem Grund sollten Sie die Bearbeitungen-API verwenden, wenn Sie eine Windows-Touch-Anwendung entwerfen, die mobile PCs abzielt.

Die Windows-Touch-API enthält die IInertiaProcessor-Schnittstelle zum Aktivieren der Unterstützung für einfache Physik (Inertia). IInertiaProcessor verwendet einige dieselben Methoden wie die IManipulationProcessor-Schnittstelle zum Hinzufügen von Unterstützung für Inertia, um Anwendungen zu vereinfachen, die bereits Manipulationen verwenden. Zum Aktivieren der Unterstützung für Inertia, müssen Sie die vorhandenen Ereignissenke für den Prozessor Manipulation erweitern, fügen Sie einen Verweis auf eine Schnittstelleninstanz IInertiaProcessor für das Objekt zeichenbaren, Ereignisdaten aus der Ereignissenke für das IInertiaProcessor-Objekt verbinden und einen Zeitgeber verwenden, um die IInertiaProcessor-Schnittstelle, um Trigger Manipulation Ereignisse für Inertia ausgelöst. Betrachten Sie jeden Vorgang ausführlicher Let’s ein.

Zuerst müssen Sie zum Aktivieren der Unterstützung für das Senden von Daten an eine IInertiaProcessor-Schnittstelle die Ereignissenke zu aktualisieren. Die folgenden Member und der Konstruktor Definitionen werden zur Implementierung der Ereignisvorspann-Senke hinzugefügt:

class CManipulationEventSink : _IManipulationEvents
{
public:
  CManipulationEventSink(IInertiaProcessor *inert, Drawable* d);
  CManipulationEventSink(IManipulationProcessor *manip, IInertiaProcessor *inert, Drawable* d);

...
protected:
  IInertiaProcessor*  m_pInert;
  BOOL fExtrapolating;

Sie fügen auch Mitglied und eine Zugriffsmethode an die Ereignissenke für das Festlegen einer HWND, die für den Zeitgeber, verwendet wird, wie hier gezeigt:
Öffentliche:

void SetWindow(HWND hWnd) {m_hWnd = hWnd;}
...
private:
...
HWND m_hWnd;

Als Nächstes ändern Sie den Konstruktor, der eine IManipulationProcessor-Schnittstelle um eine IInertiaProcessor-Schnittstelle akzeptieren annimmt, und fügen Sie einen Konstruktor, der nur eine IInertiaProcessor-Schnittstelle akzeptiert. Konstruktors, dem eine IManipulationProcessor-Schnittstelle verwendet den Verweis auf die IInertiaProcessor-Schnittstelle zum Inertia aus ManipulationCompleted-Ereignis auslösen. Der Konstruktor, der nur eine IInertiaProcessor Handles Schnittstellenereignisse akzeptiert, die für Inertia sind. Abbildung 6 zeigt die Implementierungen der diese Konstruktoren.

Abbildung 6 Implementierungen von IManipulationProcessor und IInertiaProcesor Konstruktoren

CManipulationEventSink::CManipulationEventSink(IManipulationProcessor *manip, IInertiaProcessor *inert, Drawable* d){
  drawable = d;
  // Yes, we are extrapolating inertia in this case
  fExtrapolating = false;

  //Set initial ref count to 1
  m_cRefCount = 1;

  m_pManip = NULL;
  m_pInert = inert;  

  m_cStartedEventCount = 0;
  m_cDeltaEventCount = 0;
  m_cCompletedEventCount = 0;

  HRESULT hr = S_OK;

  //Get the container with the connection points
  IConnectionPointContainer* spConnectionContainer;
  
  hr = manip->QueryInterface(
  IID_IConnectionPointContainer, 
  (LPVOID*) &spConnectionContainer
  );

  if (spConnectionContainer == NULL){
   // Something went wrong, try to gracefully quit   
  }

  //Get a connection point
  hr = spConnectionContainer->FindConnectionPoint
(__uuidof(_IManipulationEvents), &m_pConnPoint);

  if (m_pConnPoint == NULL){
   // Something went wrong, try to gracefully quit
  }

  DWORD dwCookie;

  //Advise
  hr = m_pConnPoint->Advise(this, &dwCookie);
}
CManipulationEventSink::CManipulationEventSink(IInertiaProcessor *inert, Drawable* d)
{
  drawable = d;
  // Yes, we are extrapolating inertia in this case
  fExtrapolating = true;

  //Set initial ref count to 1
  m_cRefCount = 1;

  m_pManip = NULL;
  m_pInert = inert;  

  m_cStartedEventCount = 0;
  m_cDeltaEventCount = 0;
  m_cCompletedEventCount = 0;

  HRESULT hr = S_OK;

  //Get the container with the connection points
  IConnectionPointContainer* spConnectionContainer;
  
  hr = inert->QueryInterface(
  IID_IConnectionPointContainer, 
  (LPVOID*) &spConnectionContainer
  );

  if (spConnectionContainer == NULL){
   // Something went wrong, try to gracefully quit   
  }

  //Get a connection point
  hr = spConnectionContainer->FindConnectionPoint
(__uuidof(_IManipulationEvents), &m_pConnPoint);
  if (m_pConnPoint == NULL){
   // Something went wrong, try to gracefully quit
  }

  DWORD dwCookie;

  //Advise
  hr = m_pConnPoint->Advise(this, &dwCookie);

Als Nächstes, aktualisieren Sie die zeichenbaren-Klasse zum Aktivieren der Unterstützung für Inertia. Die forward-Definition im Abbildung 7 angezeigt werden sowie eine Membervariable pInert hinzugefügt.

Abbildung 7 Aktualisieren zeichenbaren Class

interface IInertiaProcessor;
public:
...
  // Inertia Processor Initiation
  virtual void SetUpInertia(void);

...
protected:

  HWND m_hWnd;
  
  IManipulationProcessor* pManip;
  IInertiaProcessor*  pInert;
  CManipulationEventSink* pEventSink;

Der folgende Code zeigt die einfachste Implementierung für die SetUpInertia-Methode. Diese Methode beendet die Verarbeitung ist, setzt den Inertia-Prozessor zurück und legt anschließend alle Konfigurationseinstellungen fest:

void Drawable::SetUpInertia(void){
  // Complete any previous processing
  pInert->Complete();

  pInert->put_InitialOriginX(originX*100);
  pInert->put_InitialOriginY(originY*100);
   
  // Configure the inertia processor
  pInert->put_DesiredDeceleration(.1f); 
}

Nachdem Sie die Klasse mit zeichenbaren aktualisiert haben, ändern Sie den zeichenbaren Konstruktor neue Ereignissenke Konstruktoren, wie im Abbildung 8 integrieren.

Abbildung 8 neue Ereignis einbinden Konstruktoren Sink

Drawable::Drawable(HWND hWnd){
. . 
 
  // Initialize manipulators 
  HRESULT hr = CoCreateInstance(CLSID_ManipulationProcessor,
    NULL,
    CLSCTX_INPROC_SERVER,
    IID_IUnknown,
    (VOID**)(&pManip)
  );

  // Initialize inertia processor
  hr = CoCreateInstance(CLSID_InertiaProcessor,
    NULL,
    CLSCTX_INPROC_SERVER,
    IID_IUnknown,
    (VOID**)(&pInert)
  );

  //TODO: test HR 
  pEventSink = new CManipulationEventSink(pManip,pInert, this);
  pInertSink = new CManipulationEventSink(pInert, this);
  pEventSink->SetWindow(hWnd);
  pInertSink->SetWindow(hWnd);

  SetUpManipulator();
  SetUpInertia();
  m_hWnd = hWnd;
}

Und nun den folgenden Zeitgeber-Meldungshandler zum Programm hinzufügen:

case WM_TIMER:
   // wParam indicates the timer ID
   for (int i=0; i<drawables; i++){
    if (wParam == draw[i]->GetIndex() ){
      BOOL b;   
      draw[i]->ProcessInertia(&b);   
    }
   }
  break;

Nachdem Sie den Zeitgeber-Handler verfügen und Ihre Zeitgeber eingerichtet ist, müssen Sie es aus der abgeschlossenen Nachricht im Ereignis, in dem trigger keine Inertia vorhanden ist. Abbildung 9 zeigt Änderungen auf das abgeschlossene Ereignis, die den Zeitgeber zu, starten Wenn der Benutzer ein Objekt bearbeiten fertig ist und den Zeitgeber beenden, sobald Inertia abgeschlossen ist.

Abbildung 9 Änderungen auf das abgeschlossene Ereignis

HRESULT STDMETHODCALLTYPE CManipulationEventSink::ManipulationCompleted( 
  /* [in] */ FLOAT x,
  /* [in] */ FLOAT y,
  /* [in] */ FLOAT cumulativeTranslationX,
  /* [in] */ FLOAT cumulativeTranslationY,
  /* [in] */ FLOAT cumulativeScale,
  /* [in] */ FLOAT cumulativeExpansion,
  /* [in] */ FLOAT cumulativeRotation)
{
  m_cCompletedEventCount ++;

  m_fX = x;
  m_fY = y;


  if (m_hWnd){
   if (fExtrapolating){
    //Inertia Complete, stop the timer used for processing
    KillTimer(m_hWnd,drawable->GetIndex());
   }else{ 
    // Setup velocities for inertia processor
    float vX, vY, vA = 0.0f;
    m_pManip->GetVelocityX(&vX);
    m_pManip->GetVelocityY(&vY);
    m_pManip->GetAngularVelocity(&vA);

    drawable->SetUpInertia();

    // Set up the touch coordinate data
    m_pInert->put_InitialVelocityX(vX / 100);
    m_pInert->put_InitialVelocityY(vY / 100);   
         
    // Start a timer
    SetTimer(m_hWnd, drawable->GetIndex(), 50, 0); 
  
    // Reset sets the initial timestamp
    pInert->Reset();  
   }
  }
}

Beachten Sie, dass das Zeitgeberintervall verringern, der dritte Parameter für SetTimer, Ergebnisse in glatter Animation jedoch Trigger mehr Ereignisse, die potenziell die Ereignishandler verursacht Leistungseinbußen je nachdem welche Vorgänge aktualisiert, die ausgeführt werden. Beispielsweise führt zu sehr glatt Animation ändern dieses Wertes auf 5, aber das Fenster ist aufgrund des zusätzlichen Aufrufe von CManipulationEventSink::ManipulationDelta häufiger aktualisiert.

Jetzt können Sie erstellen und der Anwendung ausführen, jedoch ohne weitere Änderungen, werden die manipulierten Objekte außerhalb des Bildschirms Salon. Konfigurieren Sie die IInertiaProcessor-Schnittstelle Elastische Begrenzungen verwenden, um zu verhindern, dass Objekte außerhalb des Bildschirms bearbeitet wird. Abbildung 10 zeigt die Änderungen, die an die SetUpInertia-Methode für die zeichenbaren-Objekt zum Initialisieren der Bildschirm Begrenzungen erfolgen soll.

Abbildung 10 Initialisieren Bildschirm Grenzen

void Drawable::SetUpInertia(void){
(...)
       
  // Reset sets the initial timestamp   
  pInert->put_DesiredDeceleration(.1f);

  RECT rect;
  GetClientRect(m_hWnd, &rect);   

  int width = rect.right - rect.left;
  int height = rect.bottom - rect.top;

  int wMargin = width * .1;
  int hMargin = height * .1;

  pInert->put_BoundaryLeft(rect.left * 100);
  pInert->put_BoundaryTop(rect.top * 100);
  pInert->put_BoundaryRight(rect.right * 100);
  pInert->put_BoundaryBottom(rect.bottom * 100);

  pInert->put_ElasticMarginTop((rect.top - hMargin) * 100);
  pInert->put_ElasticMarginLeft((rect.left + wMargin) * 100);
  pInert->put_ElasticMarginRight((rect.right - wMargin) * 100);
  pInert->put_ElasticMarginBottom((rect.bottom + hMargin) * 100);

...
}

Ausblicke

Mithilfe der Windows-Touch-API ist eine effektive Möglichkeit zum Wert in vorhandenen Anwendungen hinzufügen und eine hervorragende Möglichkeit, Ihre Anwendungen hervorzuheben.Zusätzliche Zeit um den Kontext zu beheben, die in Ihrer Anwendung verwendet wird, können Sie die Windows-Touch-API optimal nutzen zu können.Wenn Sie die Mobilität und Benutzerfreundlichkeit Anforderungen der Anwendung berücksichtigen, die Anwendung wird intuitiver und Benutzer benötigen weniger Zeit, um seine Funktionalität entdecken.(Zusätzliche Ressourcen, einschließlich des Verweis vollständige Dokumentation für Windows Touch, auf der MSDN-Website befindet sich unter msdn.microsoft.com/library/dd562197 (VS.85) .aspx-).

Mit der Veröffentlichung von Windows Presentation Framework (WPF) und .NET 4 unterstützt Microsoft verwaltete Entwicklung mithilfe von Steuerelementen, die mehrere Punkte Kontakt zu ermöglichen.Wenn Sie ein Entwickler arbeiten mit verwaltetem Code zu suchen, um Ihre Anwendung mit mehreren Eingängen Unterstützung zu verbessern sind, ist diese Version lohnt es sich beim Auschecken.Derzeit sind verwaltete Windows Touch Wrapper für c#-Beispiele im Windows SDK enthalten.

Gus “gclassy” Class nbsp;programming Writer/Evangelist für Microsoft, wo er hat auf Windows Touch, Tablet PC und gearbeitet wird Microsoft DRMsystems. Er erläutert Entwickler Probleme und bietet Programmierbeispiele auf seinen Blog unter gclassy.com.

Dank an den folgenden technischen Experten für die Überprüfung dieses Artikels: Xiao Tu

Senden Sie Fragen und Kommentare für Gus in goplaces@microsoft.com .