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

Операционная система Microsoft Windows 3.1 для программиста. Дополнительные главы

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

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

4.5. Функция WinHelp

Приложения Windows обращаются к справочной системе с помощью специально предназначенной для этого функции WinHelp. Когда приложение вызывает эту функцию, происходит запуск приложения winhelp.exe. Вызывая функцию WinHelp, приложение может отобразить на экране любую информацию, обычно доступную пользователю через меню или кнопки окна Toolbar приложения winhelp.exe.

Хорошо спроектированное приложение имеет меню "Help", с помощью которого пользователь может получить доступ к оглавлению и предметному указателю справочной системы. Кроме этого, обычно имеется возможность получения так называемой контекстно-зависимой справочной информации. Если вы работали со справочной системой, входящей в состав Borland C++ или Microsoft Visual C++, то вы уже знаете, что это такое.

Когда пользователь нажимает клавишу <F1> или <Shift+F1>, приложение выдает справочную информацию, которая зависит от того, в каком состоянии находятся органы управления приложения, какая строка какого меню выделена, около какого слова в редактируемом тексте находится курсор и т. п.

Например, если вы раскрыли меню "File" и выделили строку "Open...", а затем нажали клавишу <F1>, скорее всего, в любом стандартном приложении вы увидите на экране раздел справочной системы, рассказывающей о том, как пользоваться строкой "Open..." из меню "File".

И это именно такое поведение, которое пользователь ожидает от вашего приложения. Для пользователя важно получить подсказку в каждой конкретной ситуации, нажимая при этом на одну и ту же (для всех приложений Windows) функциональную клавишу <F1>. И если вместо этого пользователь каждый раз будет попадать в раздел оглавления и искать нужную информацию в дебрях гипертекстовой системы, он едва ли будет в восторге.

Функция WinHelp позволяет организовать поиск нужного раздела в справочной системе и отображение его на экране, но и только. Задача отслеживания текущего состояния органов управления и организации контекстно-зависимой подсказки целиком ложится на плечи разработчика приложения.

Прототип функции WinHelp

Прототип функции WinHelp определен в файле windows.h:

BOOL WINAPI WinHelp(
  HWND hwndMain,   // идентификатор окна
  LPCSTR lpszHelp, // путь к hlp-файлу
  UINT usCommand,  // код операции
  DWORD ulData);   // дополнительные данные

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

Через параметр lpszHelp передается указатель на текстовую строку, закрытую двоичным нулем, в которой должен быть записан путь к hlp-файлу, содержащему нужную справочную систему.

Функция WinHelp может выполнять одну из нескольких операций в зависимости от значения параметра usCommand:

Команда Описание
HELP_COMMAND0x0102 Выполнение макрокоманды, заданной параметром ulData. Этот параметр должен содержать дальний указатель на текстовую строку, содержащую макрокоманду. Перед использованием команды HELP_COMMAND необходимо, чтобы было запущено приложение winhelp.exe и чтобы нужный hlp-файл был открыт
HELP_CONTENTS0x0003 Отображение раздела, выполняющего роль оглавления справочной системы. Параметр ulData для этой команды должен быть равен нулю
HELP_CONTEXT0x0001 Отображение содержимого раздела, заданного номером контекста, определенным в разделе MAP файла проекта справочной системы. Через параметр ulData передается номер контекста отображаемого раздела
HELP_CONTEXTPOPUP0x0008 Отображение содержимого раздела, заданного номером контекста, во временном окне. Номер контекста должен быть определен в секции MAP файла проекта справочной системы и указан в параметре ulData
HELP_FORCEFILE0x0009 Если в момент вызова функции WinHelp с этим кодом операции отображается правильный hlp-файл, функция отрабатывает вхолостую. В противном случае отображается раздел оглавления, заданный в секции CONTENTS файла проекта справочной системы. Параметр ulData для этой команды должен быть равен нулю
HELP_HELPONHELP0x0004 Отображение раздела оглавления справочной системы, содержащей информацию об использовании приложения winhelp.exe. Параметр ulData должен быть равен нулю
HELP_INDEX0x0003 Синоним HELP_CONTEXT, использовался раньше в функции WinHelp для Windows версии 3.0
HELP_KEY0x0101 Отображение раздела справочной системы в соответствии с ключевым словом, передаваемым через параметр ulData. Этот параметр должен содержать дальний указатель на текстовую строку, содержащую ключевое слово
HELP_MULTIKEY0x0201 Аналогично предыдущему, но с использованием альтернативной таблицы ключей. Параметр ulData должен содержать дальний указатель на структуру MULTIKEYHELP, определяющую символ сноски для альтернативного ключа и ключевое слово
HELP_POPUPID0x0104 Отображение содержимого раздела, заданного номером контекста, во временном окне. Через параметр ulData передается номер контекста отображаемого раздела, определенный в разделе MAP файла проекта справочной системы.
HELP_PARTIALKEY0x0105 Аналогично HELP_KEY, однако отображаются разделы, для которых имеется неполное соответствие (несколько начальных символов ключевого слова)
HELP_QUIT0x0002 Завершение работы с hlp-файлом. Если ни одно другое приложение не выполняет никаких операций со справочной системой, приложение winhelp.exe завершает свою работу. Параметр ulData должен быть равен нулю
HELP_SETCONTENTS0x0005 Раздел, номер контекста которого указан в параметре ulData, будет выполнять функции оглавления справочной системы. Номер контекста раздела должен быть определен в секции MAP файла проекта справочной системы
HELP_SETINDEX0x0005 Синоним HELP_SETCONTEXT, использовался раньше в функции WinHelp для Windows версии 3.0
HELP_SETWINPOS0x0203 Изменение размеров и расположения окна приложения winhelp.exe в соответствии со значениями, определенными в структуре HELPWININFO, указатель на которую передается через параметр ulData

Структура MULTIKEYHELP определена в файле windows.h следующим образом:

typedef struct tagMULTIKEYHELP
{
    UINT    mkSize;         // размер структуры в байтах
    BYTE    mkKeylist;      // символ сноски
    BYTE    szKeyphrase[1]; // текстовая строка, содержащая
                            // ключевое слово
} MULTIKEYHELP;

Текстовая строка szKeyphrase должна быть закрыта двоичным нулем.

Структура HELPWININFO (и указатели на нее) определена также в файле windows.h:

typedef struct
{
    int  wStructSize; // размер структуры в байтах
    int  x;           // X-координата верхнего левого угла окна
    int  y;           // Y-координата верхнего левого угла окна
    int  dx;          // ширина окна
    int  dy;          // высота окна
    int  wMax;        // стиль отображения окна
    char rgchMember[2]; // имя окна
} HELPWININFO;
typedef HELPWININFO NEAR* PHELPWININFO;
typedef HELPWININFO FAR* LPHELPWININFO;

Для стиля отображения окна вы можете использовать константы с префиксом имени SW:

Константа Описание
SW_HIDE Скрыть окно
SW_SHOWNORMAL Активизировать окно и отобразить его в нормальном состоянии (не минимизированном или максимизированном)
SW_SHOWMINIMIZED Минимизировать окно
SW_SHOWMAXIMIZED Максимизировать окно
SW_SHOWNOACTIVE Использовать для окна старые размеры и расположение. Те окна, которые были активными на момент вызова функции, по-прежнему остаются активными
SW_SHOW Активизировать и отобразить окно, используя текущие размеры и расположение
SW_MINIMIZE Минимизировать окно, активизировав другое, расположенное в самом низу (т. е. окно нижнего уровня вдоль оси Z)
SW_SHOWMINNOACTIVE Отобразить окно как пиктограмму. Те окна, которые были активными на момент вызова функции, по-прежнему остаются активными
SW_SHOWNA Отобразить окно в текущем состоянии. Те окна, которые были активными на момент вызова функции, по-прежнему остаются активными
SW_RESTORE Синоним SW_SHOWNORMAL

Справочная система HELPMORE.HLP

Для иллюстрации применения стандартных и дополнительных макрокоманд, функции WinHelp, а также малоизвестных и редко используемых, но полезных встроенных окон (Embedded Windows), мы создали справочную систему helpmore.hlp (рис. 4.21). При этом мы взяли за основу подробно описанную нами ранее справочную систему hlpfile.hlp.

Рис. 4.21. Справочная система helpmore.hlp

Обратите внимание на окно Toolbar. В нем появилась новая кнопка "Calc". Если нажать на нее, будет запущено приложение calc.exe. Эта возможность реализована с помощью стандартных макрокоманд.

Выберите мышью строку "Вызов функции MsgBox из DLL". На экране появится сообщение (рис. 4.22).

Рис. 4.22. Сообщение, которое выводится при помощи специально созданной макрокоманды

Для вывода такого сообщения мы расширили стандартный набор макрокоманд приложения winhelp.exe, добавив собственную макрокоманду MsgBox, реализованную как функцию библиотеки helpmore.dll.

Если выбрать строку "Вторичное окно", на экране появится еще одно окно, которое живет самостоятельно, вне зависимости от состояния главного окна приложения winhelp.exe (рис. 4.23).

Рис. 4.23. Вторичное окно

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

Вы можете сделать щелчок левой клавишей мыши внутри встроенного окна, при этом на экране появится диалоговая панель с предложением запустить "настоящие" часы clock.exe (рис. 4.24).

Рис. 4.24. Пользователю предлагается запустить приложение clock.exe

В случае утвердительного ответа приложение clock.exe будет запущено, вслед за чем на экране появится раздел справочной системы с информацией о часах. Этот раздел будет показан во временном окне, и в нем также отображается текущее время (рис. 4.25). Таким образом, мы использовали временное окно еще и как нестандартное средство для организации гипертекстовой ссылки.

Рис. 4.25. Гипертекстовая ссылка из встроенного окна

Для экспериментов со справочной системой hlpmore.hlp лучше всего использовать ее исходные тексты и другие файлы, расположенные на дискете, продаваемой вместе с книгой в каталоге hlpmore. Для тех, кто не смог приобрести дискету, мы приведем содержимое первого раздела справочной системы (раздела оглавления) и еще одного дополнительного раздела, которого нет в предыдущей описанной нами справочной системе helpfile.hlp.

На рис. 4.26 изображено оформление раздела оглавления.

Рис. 4.26. Раздел содержания справочной системы hlpmore.hlp

Вызов созданной нами макрокоманды MsgBox выполняется следующим образом (в исходном *.rtf файле правая часть строки оформлена скрытым текстом):

Вызов функции MsgBox из DLL!MsgBox(hwndApp,"Сообщение из DLL")

Макрокоманда получает два параметра, первый из которых является внутренней глобальной переменной hwndApp (идентификатор главного окна приложения winhelp.exe), а второй представляет собой произвольную текстовую строку.

Для отображения содержимого во вторичном окне использована следующая строка:

Вторичное окноgraphics>grwnd

Здесь graphics - контекст раздела, а grwnd - название вторичного окна, определенного в файле проекта справочной системы hlpmore.hpj (будет описан позже).

Для создания встроенного окна использована следующая строка:

{ewl HLPMORE, EWHlpMoreClass, TestString}

В этой строке оператор ewl указывает, что необходимо встроить окно и расположить его в левой части основного окна (аналогично bml). Существуют также операторы ewc и ewr, с помощью которых можно задать центрирование встроенного окна и выравнивание вправо, соответственно.

Параметр HLPMORE - имя DLL-библиотеки, содержащей функцию окна для обработки сообщений встроенного окна. В данном случае используется библиотека hlpmore.dll, исходным текстом которой мы займемся чуть позже.

Параметр EWHlpMoreClass - это имя класса окна, зарегистрированное DLL-библиотекой для обработки сообщений от встроенного окна.

Строка TestString - произвольная строка, которая передается в функцию встроенного окна на этапе его создания.

Встроенными окнами мы займемся ниже в отдельном разделе.

Если вы создаете исходный текст справочной системы hlpmore.hlp на базе файла hlpfile.rtf, описанного нами ранее, добавьте в него раздел с контекстом clock (рис. 4.27). Этот раздел будет появляться во временном окне в том случае, если вы щелкните левой клавишей мыши внутри встроенного окна.

Рис. 4.27. Раздел с контекстом clock

Приведем полный список подстрочных ссылок, определенных в файле hlpmore.rtf:

$ Пример справочной системы
# cont
+ cont:010
K оглавление
$ Описание команд
# cmd
+ cont:020
K команды
$ Использование клавиатуры
# key
+ cont:030
K клавиатура
$ Графические изображения
# graphics
K графика;битовые изображения
$ Меню File
# file
+ cmd:010
K File; загрузка документа
$ Меню Edit
# edit
+ cmd:020
K edit; редактирование
$ Меню View
# view
+ cmd:030
K view
$ часы
# clock
$ Отсутствующий раздел
# missing

В файле hlpmore.hpj находится файл проекта справочной системы (листинг 4.2).


Листинг 4.2. Файл hlpmore/hlpmore.hpj


[OPTIONS]
errorlog = hlpmore.err
title = Help Sample
contents = cont
compress = 1
warning = 3
report = 1
copyright = (C) Frolov A.V., 1995
icon=hlpmore.ico

[FILES]
hlpmore.rtf

[WINDOWS]
main = "Help Sample",,,, (255,255,192 )
grwnd = "Graphics",(220,200,700,300),,,(255,255,192)

[MAP]
#define clock 200
#define cmd   201
#define key   202
#define file  203
#define edit  204
#define view  205

[CONFIG]
BrowseButtons()
CB("calc_btn","Calc","EP(`calc.exe', 0)")
RR("hlpmore.dll", "MsgBox", "US")

В секции [OPTION] добавились строки copyright и icon. Первая из них предназначена для добавления сведений о разработчиках справочной системы в диалоговую панель, отображаемую при выборе строки "About Help..." из меню "Help" приложения winhelp.exe. Вторая указывает пиктограмму, в которую превращается главное окно winhelp.exe при его минимизации. С остальными строками этой секции вы уже знакомы.

В секции [WINDOWS] помимо основного окна main описано вторичное окно grwnd, на которое есть ссылка из раздела оглавления. Помимо цвета не сворачиваемой области для вторичного окна следует указать координаты верхнего левого угла, ширину и высоту.

Секция MAP определяет номера контекста, которые будут использованы для ссылки при вызове функции WinHelp.

В секции CONFIG вызываются три макрокоманды: BrowseButtons, CB и RR.

Макрокоманда BrowseButtons добавляет кнопки просмотра последовательностей логически связанных разделов.

Макрокоманда CB (полное имя CreateButton) добавляет в окно Toolbar новую кнопку с надписью "Calc", предназначенную для запуска калькулятора calc.exe.

Макрокоманда RR (полное имя RegisterRoutine) предназначена для регистрации макрокоманды MsgBox, определенной в DLL-библиотеке hlpmore.dll.

Приложение HELPMWH

Приложение HELPMWH демонстрирует приемы работы с функцией WinHelp и один из возможных способов организации получения контекстно-зависимой справки. Меню "Help" этого приложения (рис. 4.28) открывает доступ к содержимому справочной базы данных hlpmore.hlp, описанной в предыдущем разделе.

Рис. 4.28. Меню 'Help" приложения HELPMWH

Если, запустив приложение HELPMWH, нажать комбинацию клавиш <Shift+F1>, запустится приложение winhelp.exe и в его главном окне отобразится раздел оглавления справочной системы hlpmore.hlp.

До тех пор, пока не выделена какая-нибудь строка меню, клавиша <F1> не действует. Если же выделить любую строку любого меню, кроме "Help", с помощью клавиши <F1> можно будет получить контекстно-зависимую подсказку. Например, при выделении любой строки в меню "File" с последующим нажатием на клавишу <F1> на экране появится справка об использовании меню "File". Аналогичная операция в меню "Edit" или 'View" приведет к отображению справочной информации об использовании этих меню.

Нажав на клавишу <F1> при выделенном меню "Help", вы увидите оглавление справочной системы.

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

Клавиша <F1> действует и во время отображения диалоговой панели, которая появляется на экране при выборе из меню "Help" нашего приложения строки "About..." (рис. 4.29).

Рис. 4.29. Диалоговая панель, которая появляется при выборе из меню "Help" строки "About..."

Мы организовали контекстно-чувствительную подсказку таким образом, что нажав клавишу <F1> во время отображения диалоговой панели, мы попадаем в раздел оглавления, однако вы можете выбрать любой другой раздел по вашему усмотрению, немного изменив исходные тексты приложения.

Основной файл исходных текстов приведен в листинге 4.3.


Листинг 4.3. Файл hlpmore/helpmwh.cpp


// ----------------------------------------
// Демонстрация использования функции WinHelp
// ----------------------------------------
#define STRICT
#include <windows.h>
#include <mem.h>
#include "helpmwh.hpp"

BOOL InitApp(HINSTANCE);
LRESULT CALLBACK _export WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK    _export DlgProc(HWND, UINT, WPARAM, LPARAM);

char const szClassName[]   = "HelpmWhClass";
char const szWindowTitle[] = "WinHelp Demo";
HACCEL     hAccel;
BOOL       bF1 = FALSE;
HWND       hwndDlg = NULL;
DLGPROC    lpfnDlgProc;
HINSTANCE  hInst;

// =====================================
// Функция WinMain
// =====================================
#pragma argsused
int PASCAL
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  LPSTR lpszCmdLine, int nCmdShow)
{
  MSG  msg;   // структура для работы с сообщениями
  HWND hwnd;  // идентификатор главного окна приложения

  if(!InitApp(hInstance))
      return FALSE;

  hInst = hInstance;

  hwnd = CreateWindow(
    szClassName, szWindowTitle, WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT, CW_USEDEFAULT,
    CW_USEDEFAULT,  CW_USEDEFAULT,
    0, 0, hInstance, NULL);

  if(!hwnd)
    return FALSE;

  ShowWindow(hwnd, nCmdShow);
  UpdateWindow(hwnd);

  // Загружаем таблицу акселераторов
  hAccel = LoadAccelerators(hInstance, "APP_ACCEL");

  while(GetMessage(&msg, 0, 0, 0))
  {
    if(!TranslateAccelerator(hwnd, hAccel, &msg))
    {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
  }
  return msg.wParam;
}

// =====================================
// Функция InitApp
// Выполняет регистрацию класса окна
// =====================================
BOOL InitApp(HINSTANCE hInstance)
{
  ATOM aWndClass;
  WNDCLASS wc;

  memset(&wc, 0, sizeof(wc));
  wc.lpszMenuName  = "APP_MENU";
  wc.style         = 0;
  wc.lpfnWndProc   = (WNDPROC) WndProc;
  wc.cbClsExtra    = 0;
  wc.cbWndExtra    = 0;
  wc.hInstance     = hInstance;
  wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
  wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  wc.lpszClassName = (LPSTR)szClassName;

  aWndClass = RegisterClass(&wc);
  return (aWndClass != 0);
}

// =====================================
// Функция WndProc
// =====================================
LRESULT CALLBACK _export
WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  switch (msg)
  {
    // Это сообщение поступает, если меню или модальная
    // диалоговая панель находится в состоянии ожидания
    case WM_ENTERIDLE:
    {
      // Пользователь выделил строку меню
      // Проверяем, была ли нажата клавиша <F1> 
      if((wParam == MSGF_MENU) &&
         ((GetKeyState(VK_F1) & 0x8000) != 0))
      {
        // Если была нажата клавиша <F1>, устанавливаем
        // флаг bF1, а затем имитируем нажатие
        // клавиши <Enter>
        bF1 = TRUE;
        PostMessage(hwnd, WM_KEYDOWN, VK_RETURN, 0l);
      }

      // Если клавиша <F1> была нажата во время отображения
      // диалоговой панели, вызываем раздел оглавления
      // справочной системы
      else if((wParam == MSGF_DIALOGBOX) &&
         ((GetKeyState(VK_F1) & 0x8000) != 0))
      {
        hwndDlg = (HWND)LOWORD(lParam);
        WinHelp(hwnd, "hlpmore.hlp", HELP_CONTENTS, 0L);
      }
      break;
    }

    case WM_COMMAND:
    {
      switch (wParam)
      {
        // Отображаем раздел оглавления справочной системы
        case CM_HELPINDEX:
        {
          WinHelp(hwnd, "hlpmore.hlp", HELP_CONTENTS, 0L);
          return 0L;
        }
        case CM_HELPCOMMANDS:
        {
          // Если строка меню была выбрана клавишей <F1>,
          // выводим справочную информацию, в противном
          // случае выполняем команду
          if(bF1)
          {
            WinHelp(hwnd, "hlpmore.hlp", HELP_CONTENTS, 0L);
            bF1 = FALSE;
          }
          else
            WinHelp(hwnd, "hlpmore.hlp", HELP_CONTEXT,
              (DWORD)IDN_cmd);
          return 0L;
        }

        case CM_HELPKEYBOARD:
        {
          if(bF1)
          {
            WinHelp(hwnd, "hlpmore.hlp", HELP_CONTENTS, 0L);
            bF1 = FALSE;
          }
          else
            WinHelp(hwnd, "hlpmore.hlp", HELP_CONTEXT,
              (DWORD)IDN_key);
          return 0L;
        }

        case CM_HELPUSING_HELP:
        {
          if(bF1)
          {
            WinHelp(hwnd, "hlpmore.hlp", HELP_CONTENTS, 0L);
            bF1 = FALSE;
          }
          else
            WinHelp(hwnd, "hlpmore.hlp", HELP_HELPONHELP, 0L);
          return 0L;
        }

        case CM_HELPABOUT:
        {
          if(bF1)
          {
            WinHelp(hwnd, "hlpmore.hlp", HELP_CONTENTS, 0L);
            bF1 = FALSE;
          }
          else
          {
            lpfnDlgProc = (DLGPROC)MakeProcInstance(
               (FARPROC)DlgProc, hInst);
            DialogBox(hInst, "ABOUT_DIALOG",
               hwnd, lpfnDlgProc);
          }
          return 0;
        }

        case CM_FILEPRINTER_SETUP:
        case CM_FILEPAGE_SETUP:
        case CM_FILEPRINT:
        case CM_FILESAVEAS:
        case CM_FILESAVE:
        case CM_FILEOPEN:
        case CM_FILENEW:
        {
          if(bF1)
          {
            WinHelp(hwnd,"hlpmore.hlp", HELP_CONTEXT,
              (DWORD)IDN_file);
            bF1 = FALSE;
          }
          else
            MessageBox(hwnd, "Меню File",
              "WinHelp Demo", MB_OK);
          return 0;
        }

        case CM_EDITPASTE:
        case CM_EDITCOPY:
        case CM_EDITCUT:
        case CM_EDITUNDO:
        {
          if(bF1)
          {
            WinHelp(hwnd,"hlpmore.hlp", HELP_CONTEXT,
              (DWORD)IDN_edit);
            bF1 = FALSE;
          }
          else
             MessageBox(hwnd, "Меню Edit",
               "WinHelp Demo", MB_OK);
          return 0;
        }

        case CM_VIEWNORMAL:
        case CM_VIEWZOOM:
        {
          if(bF1)
          {
            WinHelp(hwnd,"hlpmore.hlp", HELP_CONTEXT,
              (DWORD)IDN_view);
            bF1 = FALSE;
          }
          else
            MessageBox(hwnd, "Меню View",
              "WinHelp Demo", MB_OK);
          return 0;
        }

        case CM_FILEEXIT:
        {
          DestroyWindow(hwnd);
          return 0;
        }

        default:
          return 0;
      }
    }

    case WM_DESTROY:
    {
      PostQuitMessage(0);
      return 0;
    }

    default:
      break;
  }
  return DefWindowProc(hwnd, msg, wParam, lParam);
}

// =====================================
// Функция DldProc
// =====================================
#pragma argsused
BOOL CALLBACK _export
DlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
  switch(msg)
  {
    case WM_INITDIALOG:
    {
      return TRUE;
    }

    case WM_COMMAND:
    {
      switch(wParam)
      {
        case IDOK:
        case IDCANCEL:
        {
          EndDialog(hdlg, 0);
          return TRUE;
        }
      }
    }
  }
  return FALSE;
}

В функции WinMain после обычной инициализации загружается таблица акселераторов, состоящая из одного определения. Комбинации клавиш <Shift+F1> ставится в соответствие сообщение CM_HELPINDEX, попадающее в функцию окна приложения при выборе строки "Index" из меню "Help". Используя эту комбинацию клавиш, пользователь сможет отобразить раздел оглавления справочной системы.

Функция окна обрабатывает сообщение WM_ENTERIDLE, которое и помогает нам организовать контекстно-зависимую подсказку.

Это сообщение попадает в функцию окна приложения в том случае, если активизировано меню или диалоговая панель, и эти органы управления находятся в состоянии ожидания.

Если сообщение WM_ENTERIDLE попало в функцию окна в результате отображения меню, параметр wParam этого сообщения содержит значение MSGF_MENU.

Если же указанное выше сообщение явилось результатом отображения диалоговой панели, параметр wParam содержит значение MSGF_DIALOGBOX.

В обоих случаях младшее слово параметра lParam содержит идентификатор окна (при отображении меню) или диалоговой панели (при отображении диалоговой панели).

Чем же нам может помочь сообщение WM_ENTERIDLE для организации контекстно-зависимой подсказки?

При обработке этого сообщения приложение может проверить состояние клавиши <F1>. Если эта клавиша была нажата, можно установить глобальный флаг запроса подсказки и поместить в очередь приложения сообщение WM_KEYDOWN с кодом клавиши <Enter>.

Результат будет такой же, как если бы пользователь выбрал строку меню при помощи клавиатуры, вначале выделив ее, а затем нажав клавишу <Enter>. Отличие заключается в том, что теперь установлен глобальный флаг запроса подсказки. Обработчик, запускаемый при выборе строки меню, может проверить этот флаг, и если он установлен, сбросить его и запросить контекстно-зависимую подсказку. Так как каждой строке меню соответствует свой индивидуальный обработчик, с организацией контекстно-зависимой подсказки не возникнет никаких проблем.

Именно по такому алгоритму и происходит обработка сообщения WM_COMMAND в нашем приложении.

Все необходимые константы определены в файле helpmwh.hpp (листинг 4.4).


Листинг 4.4. Файл hlpmore/helpmwh.hpp


#define CM_HELPABOUT         401
#define CM_HELPUSING_HELP    402
#define CM_HELPCOMMANDS      403
#define CM_HELPKEYBOARD      404
#define CM_HELPINDEX         405

#define CM_EDITPASTE         501
#define CM_EDITCOPY          502
#define CM_EDITCUT           503
#define CM_EDITUNDO          504

#define CM_VIEWNORMAL        601
#define CM_VIEWZOOM          602

#define CM_FILEEXIT          701
#define CM_FILEPRINTER_SETUP 702
#define CM_FILEPAGE_SETUP    703
#define CM_FILEPRINT         704
#define CM_FILESAVEAS        705
#define CM_FILESAVE          706
#define CM_FILEOPEN          707
#define CM_FILENEW           708

#define IDN_cmd  201
#define IDN_key  202
#define IDN_file 203
#define IDN_edit 204
#define IDN_view 205

Обратите внимание на константы, имя которых начинается с префикса IDN. Это номера контекста разделов справочной системы hlpmore.hlp, определенные в файле проекта hlpmore.hpj (листинг 4.2).

Ресурсы приложения (меню, пиктограмма, акселераторы и диалоговая панель) определены в файле helpmwh.rc (листинг 4.5).


Листинг 4.5. Файл hlpmore/helpmwh.rc


#include "helpmwh.hpp"

APP_MENU MENU 
BEGIN
        POPUP "&File"
        BEGIN
          MENUITEM "&New",              CM_FILENEW
          MENUITEM "&Open...",          CM_FILEOPEN
          MENUITEM "&Save",             CM_FILESAVE
          MENUITEM "Save &as...",       CM_FILESAVEAS
          MENUITEM SEPARATOR
          MENUITEM "&Print...",         CM_FILEPRINT
          MENUITEM "Page se&tup...",    CM_FILEPAGE_SETUP
          MENUITEM "P&rinter setup...", CM_FILEPRINTER_SETUP
          MENUITEM SEPARATOR
          MENUITEM "E&xit",             CM_FILEEXIT
        END

        POPUP "&Edit"
        BEGIN
          MENUITEM "&Undo\tCtrl+Z",     CM_EDITUNDO
          MENUITEM "Cu&t\tCtrl+X",      CM_EDITCUT
          MENUITEM "&Copy\tCtrl+C",     CM_EDITCOPY
          MENUITEM "&Paste\tCtrl+V",    CM_EDITPASTE
        END

        POPUP "&View"
        BEGIN
          MENUITEM "&Normal",     CM_VIEWNORMAL
          MENUITEM "&Zoom...",    CM_VIEWZOOM
        END

        POPUP "&Help"
        BEGIN
          MENUITEM "&Index\tF1",  CM_HELPINDEX
          MENUITEM "&Keyboard",   CM_HELPKEYBOARD
          MENUITEM "&Commands",   CM_HELPCOMMANDS
          MENUITEM "&Using help", CM_HELPUSING_HELP
          MENUITEM SEPARATOR
          MENUITEM "&About...",   CM_HELPABOUT
        END
END

AppIcon ICON helpmwh.ico

APP_ACCEL ACCELERATORS
BEGIN
  VK_F1, CM_HELPINDEX, VIRTKEY, SHIFT
END

ABOUT_DIALOG DIALOG 25, 34, 152, 67
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "WinHelp Demo"
BEGIN
  CTEXT "WinHelp Demo\n"
        "Приложение HELPMWH\n"
         "(C) Frolov A.V., 1995", -1, 28, 9, 117, 26,
     WS_CHILD | WS_VISIBLE | WS_GROUP
   ICON "AppIcon", -1, 6, 14, 16, 16, WS_CHILD | WS_VISIBLE
   DEFPUSHBUTTON "OK", IDOK, 56, 43, 36, 14,
     WS_CHILD | WS_VISIBLE | WS_TABSTOP
END

Файл определения модуля приложения HELPMWH представлен в листинге 4.6.


Листинг 4.6. Файл hlpmore/helpmwh.def


NAME        HELPMWH
DESCRIPTION 'Приложение HELPMWH, (C) 1995, Frolov A.V.'
EXETYPE     windows
STUB        'winstub.exe'
STACKSIZE   8120
HEAPSIZE    1024
CODE        preload moveable discardable
DATA        preload moveable multiple

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