The Caret


The Caret

When a user types some text in a program, there is a vertical bar called the caret (or the cursor) that indicates where the next character will be displayed.
Cuando un usuario teclea un texto en un programa, hay una barra vertical llamada el caret (o el cursor) que indica donde la próxima letra aparecerá.

Problem 1
Create a Wintempla Window application called TypeWriter to test the caret. This program provides the basis to understand how a textbox or Microsoft Word works. After creating the application use Wintempla to set the events: Char, KillFocus, KeyDown, Open, Size, SetFocus, and Paint.
Cree una aplicación de ventana de Wintempla llamada TypeWriter para probar el caret. Este programa proporciona las bases para entender como una caja de texto o Microsoft Word trabajan. Después de crear la aplicación use Wintempla para fijar los eventos: Char, KillFocus, KeyDown, Open, Size, SetFocus, and Paint.

TypeWritterRun

TypeWriter.h
#pragma once //______________________________________ TypeWriter.h
#include "Resource.h"
#define ROW_WIDTH 256
class TypeWriter : public Win::Window
{
public:
     TypeWriter()
     {
          averageCharWidth = 0;
          charHeight = 0;
          caretX = 0;
          caretY = 0;
          rowCount = 0;
          data = NULL;
     }
     ~TypeWriter()
     {
          if (data != NULL) delete data;
     }
     int caretX;
     int caretY;
     wchar_t* data;
     CG::Font font;
     int averageCharWidth;
     int charHeight;
     int rowCount;
     ...
};


TypeWriter.cpp
// REMEMBER THAT THIS IS A WINDOW APPLICATION
...
void TypeWriter::Window_Open(Win::Event& e)
{
     font.Create(L"Courier", 14, FIXED_PITCH);
     //_____________________________________ Compute: averageCharWidth, charHeight
     CG::Gdi gdi(hWnd, false, false);
     gdi.Select(font);
     averageCharWidth = gdi.tm.tmAveCharWidth;
     charHeight = gdi.tm.tmHeight;
}

void TypeWriter::Window_Char(Win::Event& e)
{
     for (int i = 0; i < (int)LOWORD(e.lParam); i++)
     {
          switch (e.wParam)
          {
          case'\b': // backspace
               if (caretX > 0)
               {
                    caretX--;
                    this->SendMessage(WM_KEYDOWN, VK_DELETE, 1);
               }
               break;
          case'\t': // tab
               do
               {
                    this->SendMessage(WM_CHAR, ' ', 1);
               }
               while (caretX % 8 != 0);
               break;
          case'\n': // line feed
               if (caretY++ == rowCount) caretY = 0;
               break;
          case'\r': // carriage return
               caretX = 0;
               if (caretY++ == rowCount) caretY = 0;
               break;
          case'\x1B': // escape
               for (int y = 0; y < rowCount; y++)
               {
                    for (int x = 0; x < ROW_WIDTH; x++)
                    {
                         data[x + y*ROW_WIDTH] = ' ';
                    }
               }
               caretX = 0;
               caretY = 0;
               ::InvalidateRect(hWnd, NULL, FALSE);
               break;
          default:
               data[caretX + caretY*ROW_WIDTH] = (wchar_t)e.wParam;
               ::HideCaret(hWnd);
               CG::Gdi gdi(hWnd, false, false);
               gdi.Select(font);
               gdi.TextOut(caretX*averageCharWidth, caretY*charHeight, &data[caretX + ROW_WIDTH*caretY], 1);
               ::ShowCaret(hWnd);
               if (++caretX == ROW_WIDTH)
               {
                    caretX = 0;
                    if (++caretY == rowCount) caretY = 0;
               }
          }
     }
     ::SetCaretPos(caretX*averageCharWidth, caretY*charHeight);
}

void TypeWriter::Window_KeyDown(Win::Event& e)
{
     switch (e.wParam)
     {
     case VK_HOME:
          caretX = 0;
          break;
     case VK_END:
          caretX = ROW_WIDTH - 1;
          break;
     case VK_PRIOR:
          caretY = 0;
          break;
     case VK_NEXT:
          caretY = rowCount - 1;
          break;
     case VK_LEFT:
          caretX = MAXIMUM(caretX - 1, 0);
          break;
     case VK_RIGHT:
          caretX = MINIMUM(caretX + 1, ROW_WIDTH - 1);
          break;
     case VK_UP:
          caretY = MAXIMUM(caretY - 1, 0);
          break;
     case VK_DOWN:
          caretY = MINIMUM(caretY + 1, rowCount - 1);
          break;
     case VK_DELETE:
          {
               for (int x = caretX; x < ROW_WIDTH - 1; x++)
               {
                    data[x + ROW_WIDTH*caretY] = data[(x + 1) + ROW_WIDTH*caretY];
               }
               data[ROW_WIDTH - 1 + ROW_WIDTH*caretY] = ' ';
               ::HideCaret(hWnd);
               CG::Gdi gdi(hWnd, false, false);
               gdi.Select(font);
               gdi.TextOut(caretX*averageCharWidth, caretY*charHeight, &data[caretX + ROW_WIDTH*caretY], ROW_WIDTH - caretX);
               ::ShowCaret(hWnd);
          }
          break;
     }
     ::SetCaretPos(caretX*averageCharWidth, caretY*charHeight);
}

void TypeWriter::Window_KillFocus(Win::Event& e)
{
     ::HideCaret(hWnd);
     ::DestroyCaret();
     e.returnValue = 0;
}

void TypeWriter::Window_Paint(Win::Event& e)
{
     CG::Gdi gdi(hWnd, true, false);
     gdi.Select(font);
     for (int y = 0; y < rowCount; y++)
     {
          gdi.TextOut(0, y*charHeight, &data[y*ROW_WIDTH], ROW_WIDTH);
     }
}

void TypeWriter::Window_SetFocus(Win::Event& e)
{
     ::CreateCaret(hWnd, NULL, averageCharWidth, charHeight);
     ::ShowCaret(hWnd);
     e.returnValue = 0;
}

void TypeWriter::Window_Size(Win::Event& e)
{
     if (charHeight == 0) return;
     rowCount = height / charHeight;
     //_______________________________________________ Memory allocation
     if (data != NULL) delete[] data;
     data = new wchar_t[rowCount*ROW_WIDTH];
     for (int i = 0; i < rowCount*ROW_WIDTH; i++) data[i] = ' ';
     //
     caretX = 0;
     caretY = 0;
     if (hWnd == ::GetFocus()) ::SetCaretPos(0, 0);
     ::InvalidateRect(hWnd, NULL, TRUE);
}

© Copyright 2000-2021 Wintempla selo. All Rights Reserved. Jul 22 2021. Home