Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

Операционная система Microsoft Windows 3.1 для программиста

© Александр Фролов, Григорий Фролов
Том 11 М.: Диалог-МИФИ, 1993, 269 стр.

[Назад] [Содеожание] [Дальше]

8.5. Интерфейс EasyWin

Посмотрите на исходный текст приложения Windows, приведенный в листинге 8.1. Не торопитесь делать вывод, что эта программа попала сюда случайно из учебника по языку программирования Си Кернигана и Риччи. То, что вы видите, и в самом деле приложение Windows. Вы можете легко в этом убедиться, если запустите exe-файл этого приложения, который есть на дискете (дискета продается вместе с книгой). Главное окно приложения изображено на рис. 8.2.


Листинг 8.1. Файл easywin\easywin1.cpp


#include <stdio.h>
int main(void)
{
   printf("Hello, world!");
   return 0;
}

Рис. 8.2. Окно приложения EASYWIN1

Но есть одна маленькая тонкость. В проекте должно быть указано, что данная программа есть не что иное, как приложение Windows.

Если вы не купили дискету, прилагаемую к книге, и набрали приведенный выше текст программы самостоятельно, выберите из меню "Options" среды Borland C++ for Windows строку "Application...". На экране появится диалоговая панель "Application Options" (рис. 8.3).

Рис. 8.3. Диалоговая панель "Application Options"

В этой диалоговой панели вам надо нажать кнопку с надписью "Windows App".

Когда вы собираете загрузочный модуль приложения, компилятор находит там вместо функции WinMain функцию main. Так как в проекте указано, что данное приложение является приложением Windows, компилятор автоматически подключает к приложению функции интерфейса EasyWin и оно становится приложением Windows.

А как же, спросите вы, быть без функции WinMain? Очень просто - эта функция есть, она определена в подключаемых к вашему приложению функциях EasyWin.

Фактически интерфейс EasyWin полностью скрывает от программиста интерфейс Windows, предоставляя ему взамен старый добрый интерфейс консольного ввода/вывода. В программах EasyWin вы можете пользоваться всеми стандартными функциями ввода/вывода, такими, как printf, gets, getch и т. д. Дополнительно можно вызывать функции gotoxy, wherex, wherey, clrscr и clreol, которые входят в стандартную библиотеку Borland C++ для MS-DOS.

Аналогичный интерфейс предусмотрен и в системе разработки Microsoft Visual C++. Этот интерфейс называется QuickWin. Он позволяет использовать практически любые функции стандартной библиотеки транслятора для MS-DOS, в том числе графические. Создаваемое с помощью этого интерфейса приложение может работать в среде Windows в полноэкранном режиме, внешне не отличаясь от своего варианта для MS-DOS.

Зачем все это нужно? Мы так долго говорили о преимуществах Windows, а теперь снова возвратились к MS-DOS?

Возвратились, но не совсем.

Мы можем использовать функции консольного ввода/вывода, но этот вывод выполняется не на экран реального видеомонитора, а в обычное окно Windows. Наше приложение работает в защищенном режиме и может использовать все преимущества адресации расширенной памяти, доступные стандартному приложению Windows. Кроме того, в приложении можно вызывать и обычные функции программного интерфейса Windows.

Для чего же обычно используют интерфейс EasyWin?

Во-первых, для переноса старых программ в среду Windows. Если у вас есть исходные тексты программ MS-DOS, составленных на языке программирования Си, которыми вы продолжаете пользоваться и которые для ввода/вывода на экран используют только функции консольного ввода/вывода, вы сможете без особого труда сделать из этих программ приложения Windows. Для этого вам достаточно перетранслировать их в среде Borland C++ for Windows версии 3.1, указав в проекте, что нужно сделать приложение Windows. Скорее всего вам не придется менять ни одной строчки исходного кода.

Во-вторых, интерфейс EasyWin удобно использовать для создания небольших тестовых приложений, когда нужно быстро получить результат.

В качестве примера такого приложения приведем второй вариант приложения TMETRICS, предназначенного для просмотра пространственных характеристик шрифта, выбранного в контекст отображения (листинг 8.2).


Листинг 8.2. Файл easywin\easywin2.cpp


#include <windows.h>
#include <stdio.h>
#include <conio.h>

// Прототип функции
void Print(int, char *);

// ==============================================
// Функция main
// ==============================================

int main(void)
{
  HDC hdc;
  TEXTMETRIC tm; // структура для записи метрик шрифта

  printf("Нажмите любую клавишу...");

  // Ожидаем ввода с клавиатуры любого символа
  getch();

  printf("\nПараметры шрифта:\n"
           "-----------------\n");

  // Создаем контекст отображения,
  // необходимый для определения метрик шрифта
  hdc = CreateDC("DISPLAY", NULL, NULL, NULL);

  // Заполняем структуру информацией
  // о метрике шрифта, выбранного в
  // контекст отображения
  GetTextMetrics(hdc, &tm);

  // Выводим параметры шрифта
  Print(tm.tmHeight,          "tmHeight");
  Print(tm.tmAscent,          "tmAscent");
  Print(tm.tmDescent,         "tmDescent");
  Print(tm.tmInternalLeading, "tmInternalLeading");
  Print(tm.tmExternalLeading, "tmExternalLeading");
  Print(tm.tmAveCharWidth,    "tmAveCharWidth");
  Print(tm.tmMaxCharWidth,    "tmMaxCharWidth");
  Print(tm.tmWeight,          "tmWeight");
  Print(tm.tmItalic,          "tmItalic");
  Print(tm.tmUnderlined,      "tmUnderlined");
  Print(tm.tmStruckOut,       "tmStruckOut");
  Print(tm.tmFirstChar,       "tmFirstChar");
  Print(tm.tmLastChar,        "tmLastChar");
  Print(tm.tmDefaultChar,     "tmDefaultChar");
  Print(tm.tmBreakChar,       "tmBreakChar");
  Print(tm.tmPitchAndFamily,  "tmPitchAndFamily");
  Print(tm.tmCharSet,         "tmCharSet");
  Print(tm.tmOverhang,        "tmOverhang");
  Print(tm.tmDigitizedAspectX,"tmDigitizedAspectX");
  Print(tm.tmDigitizedAspectY,"tmDigitizedAspectY");

  // Уничтожаем созданный нами контекст
  DeleteDC(hdc);

  // Выводим сообщение о завершении работы программы
  MessageBox(NULL,"Работа программы закончена, "
     "для просмотра результатов нажмите кнопку OK",
     "Демонстрация EASYWIN", MB_OK | MB_ICONINFORMATION);

  return 0;
}

// ==========================================
// Функция для вывода параметров шрифта
// в окно
// ==========================================
void Print(int tmValue, char *str)
{
  printf("%-20s\t= %d\n", str, tmValue);
}

В этом приложении мы создаем контекст отображения, вызывая функцию программного интерфейса Windows CreateDC. Затем мы вызываем знакомую вам функцию GetTextMetrics, определяющую метрики шрифта. Названия метрик и соответствующие численные значения выводятся в окно приложения функцией Print. Функция Print определена в нашем приложении и выглядит чрезвычайно просто благодаря применению для вывода функции printf.

Главное окно приложения изображено на рис. 8.4.

Рис. 8.4. Главное окно приложения EASYWIN2

Без малейших усилий с нашей стороны у окна появились вертикальная и горизонтальная полосы просмотра, с помощью которых можно увидеть целиком окно "виртуальной консоли".

Обратите внимание также на то, что мы вызываем в этой программе функцию программного интерфейса MessageBox.

А можно ли поступить наоборот - из обычного приложения Windows инициализировать интерфейс EasyWin и воспользоваться функциями консольного ввода/вывода?

Можно, именно так мы и поступили в нашем следующем приложении, которое выполняет такие нетипичные для приложений задачи, как перезагрузка компьютера или перезапуск операционной системы Windows (листинг 8.3).


Листинг 8.3. Файл easywin\easywin3.cpp


#define STRICT
#include <windows.h>
#include <stdio.h>
#include <conio.h>

// ===========================================
// Функция WinMain
// ===========================================
#pragma argsused
int PASCAL
WinMain(HINSTANCE hInstance,
        HINSTANCE hPrevInstance,
        LPSTR     lpszCmdLine,
        int       nCmdShow)
{
   BYTE szBuf[128];
   int  cbBufSize;
   BYTE ch;

  // Инициализация интерфейса EasyWin
  _InitEasyWin();

  // Получаем путь к каталогу, в котором
  // установлена Windows
  GetWindowsDirectory(szBuf, cbBufSize);

  printf("Каталог Windows: %s\n\n", szBuf);

  printf("Нажмите:\n\n"
         "R - перезапуск системы\n"
         "W - перезапуск Windows\n"
         "N - запуск Norton Commander и возврат в Windows\n\n"
         "или любую другую клавишу ->\n" );

  ch = getch();

  if(ch == 'R' || ch == 'r')
  {
    // Перезагрузка компьютера
    if(!ExitWindows(EW_REBOOTSYSTEM, 0))
    {
      printf("Ошибка при завершении работы Windows");
    }
  }

  else if(ch == 'W' || ch == 'w')
  {
    // Перезапуск Windows
    if(!ExitWindows(EW_RESTARTWINDOWS, 0))
    {
      printf("Ошибка при завершении работы Windows");
    }
  }
  else if(ch == 'N' || ch == 'n')
  {
    // Временное завершение работы Windows,
    // запуск программы MS-DOS, затем
    // снова запуск Windows
    if(!ExitWindowsExec("g:\\nc\\nc.exe", NULL))
    {
      printf("Ошибка при завершении работы Windows");
    }
  }
  return 0;
}

Это приложение содержит стандартную для Windows функцию WinMain. Для инициализации интерфейса EasyWin вызывается функция _InitEasyWin, описанная в файлах stdio.h, io.h, iostream.h:

void _Cdecl _InitEasyWin(void);

После вызова этой функции появляется окно и вы можете вызывать стандартные функции консольного ввода/вывода.

В качестве примера мы вызываем функцию GetWindowsDirectory, которая возвращает полный путь к каталогу, содержащему файлы операционной системы Windows:

UINT WINAPI GetWindowsDirectory(LPSTR lpszSysPath, 
     UINT cbSysPath);

Параметр lpszSysPath является указателем на буфер, в который будет записан путь к каталогу Windows. Длина буфера должна быть не менее 144 символов, она задается параметром cbSysPath.

Функция GetWindowsDirectory возвращает длину строки записанной в буфер, без учета закрывающего строку двоичного нуля. Если вы не предусмотрели буфер достаточного размера, функция возвратит требуемый размер буфера. В случае ошибки возвращается нулевое значение.

Получив строку пути к каталогу Windows, приложение отображает его на экране и предлагает меню (рис. 8.5).

Рис. 8.5. Главное окно приложения EASYWIN3

В этом меню вам предлагается три возможности. Нажав клавишу <R>, вы сможете завершить работу Windows и перезагрузить компьютер. При этом будет выполнена загрузка MS-DOS.

Если вы нажмете клавишу <W>, произойдет перезапуск Windows без перезагрузки компьютера.

Если нажать клавишу <N>, работа Windows будет завершена и запустится Norton Commander (если он есть на диске вашего компьютера). После завершения работы программы Norton Commander произойдет автоматический запуск Windows.

Для перезапуска Windows и перезагрузки компьютера мы использовали функцию программного интерфейса Windows с именем ExitWindows:

BOOL WINAPI ExitWindows(DWORD dwReturnCode, UINT wReserved);

Старший байт параметра dwReturnCode должен быть равен нулю, младший байт должен содержать код возврата, передаваемый MS-DOS при завершении работы Windows:

Параметр Описание
EW_RESTARTWINDOWS Перезапуск Windows
EW_REBOOTSYSTEM Завершение работы Windows и перезапуск системы. Этот код допустим только для Windows версии 3.1 и более старших версий

Параметр wReserved зарезервирован и должен быть равен нулю.

Функция ExitWindowsExec определена в программном интерфейсе Windows версии 3.1. Она завершает работу Windows, передавая управление указанной в параметре программе MS-DOS. После завершения работы этой программы Windows запускается вновь. Приведем прототип функции ExitWindowsExec:

BOOL WINAPI ExitWindowsExec(LPCSTR lpszExe, 
      LPCSTR lpszParams);

Параметр lpszExe является дальним указателем на строку символов, закрытую двоичным нулем, содержащую путь к запускаемой программе MS-DOS. Через параметр lpszParams запускаемой программе можно передать строку параметров. Это значение можно задать как NULL.

При невозможности завершить работу Windows или в случае появления других ошибок функция возвращает значение FALSE.

Как правило, функции ExitWindowsExec и ExitWindows используются в программах установки программного обеспечения для Windows (в инсталляторах). О том, как создавать собственные инсталляторы, мы расскажем в отдельной главе в одной из следующих книг серии "Библиотека системного программиста".

[Назад] [Содеожание] [Дальше]