netlib.narod.ru< Назад | Оглавление | Далее >

Просмотр клавиш

Возможно, вас заинтересует, откуда я получал информацию о событиях клавиатуры, которой делился с вами, поскольку ее источник явно не в документации по Windows Forms. Большую часть того, что я знаю о клавиатуре, мне помогла узнать следующая программа. Она выводит сведения о клавишах при их нажатии и запоминает в массиве последние 25 событий клавиатуры (KeyDown, KeyUp и KeyPress).

KeyExamine.cs

  //-------------------------------------------
  // KeyExamine.cs (C) 2001 by Charles Petzold
  //-------------------------------------------
  using System;
  using System.Drawing;
  using System.Windows.Forms;

  public class KeyExamine: Form 
  {
      public static void Main() 
      {
          Application.Run(new KeyExamine());
      }

      // Определение перечислений и структур
      // для хранения событий клавиш

      enum EventType
      {
          None,
          KeyDown,
          KeyUp,
          KeyPress
      }
      struct KeyEvent
      {
          public EventType evttype;
          public EventArgs evtargs;
      }

      // Хранилище для событий клавиш

      const int  iNumLines    = 25;
      int        iNumValid    = 0;
      int        iInsertIndex = 0;
      KeyEvent[] akeyevt = new KeyEvent[iNumLines];

      // Позиционирование текста

      int xEvent, xChar, xCode, xMods, xData, 
          xShift, xCtrl, xAlt, xRight;
     
      public KeyExamine() 
      {
          Text = "Key Examine";
          BackColor = SystemColors.Window;
          ForeColor = SystemColors.WindowText;

          xEvent = 0;
          xChar  = xEvent + 5 * Font.Height;
          xCode  = xChar  + 5 * Font.Height;
          xMods  = xCode  + 8 * Font.Height;
          xData  = xMods  + 8 * Font.Height;
          xShift = xData  + 8 * Font.Height;
          xCtrl  = xShift + 5 * Font.Height;
          xAlt   = xCtrl  + 5 * Font.Height;
          xRight = xAlt   + 5 * Font.Height;

          ClientSize  = new Size(xRight, Font.Height * (iNumLines + 1));
          FormBorderStyle = FormBorderStyle.Fixed3D;
          MaximizeBox = false;
      }
      protected override void OnKeyDown(KeyEventArgs kea)
      {
          akeyevt[iInsertIndex].evttype = EventType.KeyDown;
          akeyevt[iInsertIndex].evtargs = kea;
          OnKey();
      }
      protected override void OnKeyUp(KeyEventArgs kea)
      {
          akeyevt[iInsertIndex].evttype = EventType.KeyUp;
          akeyevt[iInsertIndex].evtargs = kea;
          OnKey();
      }
      protected override void OnKeyPress(KeyPressEventArgs kpea)
      {
          akeyevt[iInsertIndex].evttype = EventType.KeyPress;
          akeyevt[iInsertIndex].evtargs = kpea;
          OnKey();
      }
      void OnKey()
      {
          if(iNumValid < iNumLines)
          {
              Graphics grfx = CreateGraphics();
              DisplayKeyInfo(grfx, iInsertIndex, iInsertIndex);
              grfx.Dispose();
          }
          else
          {
              ScrollLines();
          }
          iInsertIndex = (iInsertIndex + 1) % iNumLines;
          iNumValid = Math.Min(iNumValid + 1, iNumLines);
      }
      protected virtual void ScrollLines()
      {
          Rectangle rect = new Rectangle(0, Font.Height, 
                                         ClientSize.Width,
                                         ClientSize.Height - Font.Height);

          // Здесь хорошо бы иметь возможность прокрутки!

          Invalidate(rect);
      }
      protected override void OnPaint(PaintEventArgs pea)
      {
          Graphics grfx = pea.Graphics;

          BoldUnderline(grfx, "Event",     xEvent, 0);
          BoldUnderline(grfx, "KeyChar",   xChar,  0);
          BoldUnderline(grfx, "KeyCode",   xCode,  0);
          BoldUnderline(grfx, "Modifiers", xMods,  0);
          BoldUnderline(grfx, "KeyData",   xData,  0);
          BoldUnderline(grfx, "Shift",     xShift, 0);
          BoldUnderline(grfx, "Control",   xCtrl,  0);
          BoldUnderline(grfx, "Alt",       xAlt,   0);

          if(iNumValid < iNumLines)
          {
              for (int i = 0; i < iNumValid; i++)
                  DisplayKeyInfo(grfx, i, i);
          }
          else
          {
              for (int i = 0; i < iNumLines; i++)
                  DisplayKeyInfo(grfx, i,(iInsertIndex + i) % iNumLines);
          }
      }
      void BoldUnderline(Graphics grfx, string str, int x, int y)
      {
          // Рисуем полужирный текст

          Brush brush = new SolidBrush(ForeColor);
          grfx.DrawString(str, Font, brush, x, y);
          grfx.DrawString(str, Font, brush, x + 1, y);

          // Подчеркивание текста

          SizeF sizef = grfx.MeasureString(str, Font);
          grfx.DrawLine(new Pen(ForeColor), x, y + sizef.Height,
                                        x + sizef.Width, y + sizef.Height);
      }
      void DisplayKeyInfo(Graphics grfx, int y, int i)
      {
          Brush br = new SolidBrush(ForeColor);
          y = (1 + y) * Font.Height;    // Преобразуем y в координаты пикселя

          grfx.DrawString(akeyevt[i].evttype.ToString(),
                          Font, br, xEvent, y);

          if(akeyevt[i].evttype == EventType.KeyPress)
          {
              KeyPressEventArgs kpea = 
                                 (KeyPressEventArgs) akeyevt[i].evtargs;

              string str = String.Format("\x202D{0} (0x{1:X4})",
                                        kpea.KeyChar, (int) kpea.KeyChar);
              grfx.DrawString(str, Font, br, xChar, y);
          }
          else
          {
              KeyEventArgs kea = (KeyEventArgs) akeyevt[i].evtargs;

              string str = String.Format("{0} ({1})", 
                                        kea.KeyCode, (int) kea.KeyCode);
              grfx.DrawString(str, Font, br, xCode, y);
              grfx.DrawString(kea.Modifiers.ToString(), Font, br, xMods, y);
              grfx.DrawString(kea.KeyData.ToString(), Font, br, xData, y);
              grfx.DrawString(kea.Shift.ToString(), Font, br, xShift, y);
              grfx.DrawString(kea.Control.ToString(), Font, br, xCtrl,  y);
              grfx.DrawString(kea.Alt.ToString(), Font, br, xAlt,   y);
          }
      }
  }

Довольно большая программа для этой книги. В начале листинга класса находятся определения закрытого перечисления EventType и структуры KeyEvent, используемых для хранения данных KeyEventArgs и KeyPressEventArgs, связанных с каждой нажатой клавишей. Программа создает массив из 25 подобных структур. Целочисленные поля с префиксом х используются для размещения информации по столбцам.

По мере того как происходят события KeyDown, KeyUp и KeyPress, данные каждого из них записываются в массив и выводятся в клиентской области программы при помощи DisplayKeyInfo — самого длинного метода класса KeyExamine. Метод OnPaint также использует DisplayKeyInfo и выводит заголовки столбцов полужирным подчеркнутым шрифтом. В главе 9 я покажу другой, гораздо лучший способ получения полужирного подчеркнутого шрифта, но эта программа просто дважды прорисовывает текст, второй раз смещая его на один пиксел относительно текста, нарисованного в первый раз. Затем при помощи метода DrawLine программа рисует линию ниже текста. Вот как выглядит результат работы программы, если набрать на клавиатуре «Hello!»:


Рис. 6.1.

Проблема здесь в том, что по достижении нижнего края клиентской области программа должна прокрутить ее содержимое до конца вверх. Если бы я писал Win32-код, то вызвал бы для этого ScrollWindow. Однако в Windows Forms нет ничего подобного этой функции. Поэтому вместо прокрутки программа просто делает часть клиентской области ниже заголовков столбцов недействительной, заставляя метод OnPaint перерисовывать все строки. Мне стыдно применять этот далеко не лучший прием, но не так, как должно быть стыдно субъекту из Microsoft, забывшему реализовать ScrollWindow в Windows Forms!


netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz