// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. // // Copyright (c) Microsoft Corporation. All rights reserved. // Stroke.h // // Definition of lightweight array template class. // Definition of helper classes for stroke storage, CStroke and // CStrokeCollection. #pragma once // C RunTime header files #include #include #define ASSERT assert /////////////////////////////////////////////////////////////////////////////// // TArray - lightweight array template class. // Arguments: T = element type, AG = allocation granularity // This template is intended to be used only with small C structs and pointers. // For simplicity, a lot of standard array functionality is omitted. template class TArray { public: TArray(); ~TArray(); // Access to the elements. int Count() const { return m_nCount; } T& operator [] (int i) { ASSERT((i >= 0) && (i TArray::TArray() : m_arrData(NULL), m_nCount(0) { } // Array destructor. template TArray::~TArray() { if (m_arrData != NULL) { free(m_arrData); } } // Adds the element to the array. // in: // t new element // returns: // success status template bool TArray::Add(const T& t) { // If there are no more unused elements in the array, allocate one more chunk of size AG. if (m_nCount % AG == 0) { T* arrDataNew = (T*) realloc(m_arrData, (m_nCount + AG)*sizeof(T)); if (arrDataNew == NULL) { if (m_arrData != NULL) { free(m_arrData); m_arrData = NULL; } m_nCount = 0; return false; } m_arrData = arrDataNew; } // Add the element to the array. m_arrData[m_nCount++] = t; return true; } // Removes the element from the array. // in: // i element index // returns: // success status template void TArray::Remove(int i) { ASSERT((i >= 0) && (i < m_nCount)); // If the element i is not the last element in the array, // shift all the elements beyond i for one place backwards. if (m_nCount - i - 1 > 0) { // Move the memory one element backwards. memmove(m_arrData + i, m_arrData + i + 1, (m_nCount - i - 1) * sizeof(T)); } // Decrement element count. --m_nCount; } /////////////////////////////////////////////////////////////////////////////// // CStroke object represents a single stroke, trajectory of the finger from // touch-down to touch-up. Object has two properties: color of the stroke, // and ID used to distinguish strokes coming from different fingers. // Stroke points are contained in the base class. class CStroke : public TArray { public: CStroke(); // Property: stroke color void SetColor(COLORREF clr) { m_clr = clr; } COLORREF GetColor() const { return m_clr; } // Property: stroke ID void SetId(int id) { m_id = id; } int GetId() const { return m_id; } // Draw the complete stroke. void Draw(HDC hDC) const; // Draw only last segment of the stroke. void DrawLast(HDC hDC) const; private: COLORREF m_clr; // Stroke color int m_id; // Stroke ID }; /////////////////////////////////////////////////////////////////////////////// // CStrokeCollection object represents a collection of the strokes. // It supports add/remove stroke operations and finding a stroke by ID. // Strokes are stored by-reference, meaning that collection does not own // the strokes and that it is not responsible for their life time. class CStrokeCollection : public TArray { public: // Search the collection for given ID. int FindStrokeById(int id) const; // Draw the collection of the strokes. void Draw(HDC hDC) const; };