Электронная библиотека книг Александра Фролова и Григория Фролова.
 
Библиотека
Братьев
Фроловых
Электронная библиотека книг Александра Фролова и Григория Фролова.
Библиотека системного программиста
Программирование на JAVA
ПК. Шаг за шагом
Другие книги
Восстановление данных
Антивирусная защита
Статьи для
программистов
Пользователю компьютера

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

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

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

2.1. Простейшие приемы использования Clipboard

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

Функции для работы с Clipboard

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

Перед тем как выполнить запись или чтение данных, приложение должно получить доступ к Clipboard, открыв ее при помощи функции OpenClipboard:

BOOL WINAPI OpenClipboard(HWND hwnd);

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

Если доступ к Clipboard получен, функция OpenClipboard вернет значение TRUE. Если же Clipboard уже открыт другим приложением, эта функция вернет значение FALSE.

После использования приложение должно закрыть Clipboard, вызвав функцию CloseClipboard:

BOOL WINAPI CloseClipboard(void);

Эта функция в случае успеха возвращает значение TRUE, а в случае ошибки - FALSE.

Содержимое открытого Clipboard может быть сброшено функцией EmptyClipboard:

BOOL WINAPI EmptyClipboard(void);

Функция EmptyClipboard возвращает значение TRUE при нормальном завершении или FALSE при ошибке.

Для выполнения записи данных в Clipboard приложение должно использовать функцию SetClipboardData:

HANDLE WINAPI SetClipboardData(UINT uFormat, HANDLE  hData);

Функция SetClipboardData имеет два параметра. Первый параметр определяет формат запоминаемых в Clipboard данных, через второй параметр передается идентификатор незафиксированного глобального блока памяти, содержащего запоминаемые данные.

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

Функция RegisterClipboardFormat позволяет зарегистрировать собственные форматы данных для Clipboard, мы расскажем о ней позже.

Приведем список предопределенных форматов данных для Clipboard. Соответствующие константы определены в файле windows.h.

Константа Описание формата данных
CF_TEXT Текстовые данные в виде массив символов. Каждая строка завершается комбинацией символов "\r\n", весь массив закрыт двоичным нулем
CF_OEMTEXT Аналогично предыдущему, однако буфер содержит символы в кодировке OEM
CF_BITMAP Битовое изображение в формате, который зависит от устройства отображения (DDB)
CF_METAFILEPICT Метафайл
CF_DIB Битовое изображение в формате, который не зависит от устройства отображения (DIB)
CF_PALETTE Палитра цветов. Используется при записи в Clipboard битовых изображений DIB
CF_SYLK Формат Microsoft Symbolic Link. Этот формат предназначен для передачи текстовых данных, причем каждая строка заканчивается комбинацией символов "\r\n". Используется в некоторых программных продуктах Microsoft
CF_DIF Формат Data Interchange Format. Аналогично формату CF_SYLK, формат CF_DIF предназначен для передачи текстовых данных
CF_TIFF Графическое изображение в формате Tag Image File Format, который был разработан Microsoft, Aldus Corporation и Hewlett-Packard
CF_PENDATA Этот формат данных используется в расширении операционной системы Windows, педназначенном для работы с перьевым вводом
CF_RIFF Формат Resource Interchange File Format. Мы рассказывали о нем в томе "Библиотеки системного программиста", посвященном системам мультимедиа
CF_WAVE Звуковые данные. Подмножество формата Resource Interchange File Format
CF_OWNERDISPLAY Формат данных определяется приложением, записавшим такие данные в Clipboard. Это же приложение отвечает за отображение данных
CF_DSPTEXT Текстовое представление данных, формат которых определен приложением
CF_DSPBITMAP Представление данных, формат которых определен приложением, в виде битового изображения
CF_DSPMETAFILEPICT Представление данных, формат которых определен приложением, в виде метафайла

Для чтения данных из Clipboard используется функция GetClipboardData:

HANDLE  WINAPI GetClipboardData(UINT uFormat);

Единственный параметр функции задает требуемый формат данных. Если Clipboard содержит данные в указанном формате, функция GetClipboardData возвращает идентификатор незафиксированного глобального блока памяти, содержащего требуемые данные.

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

Запись данных в Clipboard

Для того чтобы записать данные в Clipboard, вы должны выполнить следующую последовательность действий.

Открыть Clipboard функцией OpenClipboard

Сбросить содержимое Clipboard функцией EmptyClipboard

Заказать функцией GlobalAlloc глобальный блок памяти имеющий размер, достаточный для размещения записываемых в Clipboard данных

Зафиксировать полученный блок памяти функцией GlobalLock

Записать в зафиксированный блок памяти данные

Расфиксировать блок памяти функцией GlobalUnlock

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

Закрыть Clipboard функцией CloseClipboard

На первый взгляд, указанная последовательность действий понятна, однако при ее внимательном изучении возникает ряд вопросов.

Например, почему блок памяти, полученный для данных, не уничтожается функцией GlobalFree, после того как его идентификатор был использован в вызове функции SetClipboardData?

Дело в том, что при записи в Clipboard никакого перемещения данных не происходит. Функция SetClipboardData изменяет атрибуты передаваемого ей блока памяти таким образом, что этот блок памяти изменяет своего "хозяина", переходя в собственность операционной системы Windows и приобретая атрибут GMEM_DDESHARE.

Если приложение заказало глобальный блок памяти без атрибута GMEM_DDESHARE, этот блок памяти принадлежит приложению. Оно отвечает за уничтожение такого блока памяти. Если же приложение "забыло" уничтожить заказанный ей глобальный блок памяти, Windows уничтожает блок памяти сама при завершении приложения.

Напомним, что одно из требований к блоку памяти, предназначенного для хранения данных Clipboard, заключается в том, чтобы этот блок не уничтожался при завершении работы приложения, создавшего его.

Если приложение снабдит блок памяти атрибутом GMEM_DDESHARE, Windows не будет автоматически уничтожать его при завершении работы приложения. Приложение обязано уничтожить его самостоятельно, как только этот блок памяти перестанет быть нужным.

Обычно блоки памяти с атрибутом GMEM_DDESHARE используются в Windows версии 3.1 для организации общего поля памяти, доступного всем приложениям. Так как в Windows версии 3.0 и 3.1 для адресации памяти все приложения обращаются к одной локальной таблице дескрипторов LDT, они все могут адресоваться к одному блоку памяти, если будут знать его селектор.

Память Clipboard в Windows версий 3.0 и 3.1 устроена как раз в виде набора таких блоков памяти "общего пользования" (по одному на каждый формат данных). Функция SetClipboardData получает у приложения его "личный" глобальный блок памяти с данными, и отдает его в "коллективное пользование", добавляя атрибут GMEM_DDESHARE.

Из всего сказанного выше следует правило:

Если вы записали данные в Clipboard, отдав идентификатор глобального блока памяти функции SetClipboardData, больше не используйте этот идентификатор для адресации данных

Почему нельзя использовать идентификатор блока памяти, переданный функции SetClipboardData?

Дело в том, что в любой момент времени пользователь может уничтожить такой блок памяти записью в Clipboard новых данных. В процессе записи новых данных приложение вызовет функцию EmptyClipboard, которая уничтожит все блоки памяти, распределенные Clipboard раньше.

Разумеется, если операция записи данных в Clipboard выполняется при обработке одного сообщения (а именно так и рекомендуется поступать), никакое другое приложение не будет работать с Clipboard во время записи данных. Однако если этот обработчик попутно создает диалоговые панели, пользователь может записать в Clipboard содержимое, например, однострочного текстового редактора, реализованного в виде органа управления диалоговой панели.

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

Все операции с Clipboard от его открытия и до закрытия должны выполняться в одном обработчике сообщения. Нельзя открывать Clipboard в обработчике одного сообщения, а закрывать в обработчике другого сообщения. Между открытием и закрытием Clipboard нельзя создавать диалоговые панели или выполнять другие действия, которые могут повлечь за собой создание диалоговых панелей (например, вызов функций SendMessage или PeekMessage)

Еще одно замечание относительно атрибута блока памяти GMEM_DDESHARE.

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

Такой метод будет превосходно работать в Windows версии 3.1, и... не будет работать в Windows NT. Дело в том, что 32-разрядная операционная система Windows NT создает для каждого 32-разрядного приложения отдельную локальную таблицу дескрипторов LDT и, следовательно, отдельное адресное пространство. Поэтому никакое приложение ни при каких обстоятельствах не может иметь доступа к адресному пространству другого приложения.

Если же для передачи данных между приложениями вы будете использовать функции Clipboard, вам гарантирована совместимость на уровне исходных текстов с операционной системой Windows NT. И это несмотря на то, что в Windows NT работа Clipboard основана на других принципах, нежели в Windows версии 3.1.

Чтение данных из Clipboard

Рассмотрим теперь процедуру чтения данных из Clipboard. Приложение должно сделать следующее.

Открыть Clipboard функцией OpenClipboard

Вызвать функцию GetClipboardData, передав ей через единственный параметр требуемый формат данных. Если Clipboard содержит данные в указанном формате, функция GetClipboardData возвратит идентификатор незафиксированного блока памяти, содержащего нужные данные. Если в Clipboard нет данных в указанном формате, будет возвращено значение NULL

Зафиксировать блок памяти, идентификатор которого получен от функции GetClipboardData, функцией GlobalLock

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

Расфиксировать блок памяти, идентификатор которого получен от функции GetClipboardData, функцией GlobalUnlock

Закрыть Clipboard функцией CloseClipboard

Чтение содержимого Clipboard, как и запись в Clipboard, нужно выполнять в обработчике одного сообщения, руководствуясь рекомендациями, приведенными в предыдущем разделе.

Отметим также, что приложение должно переписать данные из блока памяти Clipboard в свой, созданный специально, а не пользоваться блоком памяти, идентификатор которого был получен от функции GetClipboardData. Причина очевидна - в любой момент времени пользователь может уничтожить этот блок памяти, перезаписав содержимое Clipboard новыми данными.

Приложение CLIPTXT

Работу описанных выше функций вы можете проверить при помощи приложения CLIPTXT (рис. 2.4). Главное меню этого приложения содержит временное меню "Edit". Пользуясь строками "Copy" и "Paste" этого меню вы сможете записать в Clipboard текстовую строку, заданную в приложении, а также просмотреть в главном окне приложения содержимое Clipboard в текстовом формате.

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

Файл cliptxt.cpp содержит все функции, определенные в приложении (листинг 2.1).


Листинг 2.1. Файл cliptxt/cliptxt.cpp


// ----------------------------------------
// Запись данных в текстовом формате в Clipboard
// и чтение текстовых данных из Clipboard
// ----------------------------------------
#define STRICT
#include <windows.h>
#include <mem.h>
#include "cliptxt.hpp"

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

char const szClassName[]   = "CliptxtClass";
char const szWindowTitle[] = "Clipboard Demo";
char const szClipboardText[] =
  "Этот текст будет записан\r\n"
  "в универсальный буфер обмена Clipboard\r\n"
  "приложением CLIPTXT";

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

  // Разрешаем запуск нескольких копий приложения
  if(!hPrevInstance)
    if(!InitApp(hInstance))
      return FALSE;

  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);

  while(GetMessage(&msg, 0, 0, 0))
  {
    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         = CS_HREDRAW | CS_VREDRAW;
  wc.lpfnWndProc   = (WNDPROC) WndProc;
  wc.cbClsExtra    = 0;
  wc.cbWndExtra    = 0;
  wc.hInstance     = hInstance;
  wc.hIcon         = LoadIcon(hInstance, "APP_ICON");
  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)
{
  HDC hdc;
  PAINTSTRUCT ps;
  RECT rc;

  static HGLOBAL hglbTextCopyBuf;
  LPSTR lpTextCopy;
  static HGLOBAL hglbTextPasteBuf;
  LPSTR lpTextPaste;
  static HGLOBAL hglbClipBuf;
  LPSTR lpClipBuf;

  switch (msg)
  {
    case WM_CREATE:
    {
      // Заказываем буфер для хранения текста,
      // прочитанного из Clipboard.
      // Начальный размер этого буфера - 1 байт
      hglbTextPasteBuf = GlobalAlloc(GHND, 1);
      if(hglbTextPasteBuf == NULL)
        return -1;

      // Фиксируем буфер в памяти и получаем его адрес
      lpTextPaste = (LPSTR)GlobalLock(hglbTextPasteBuf);
      if(hglbTextPasteBuf == NULL)
        return -1;

      // Записываем в буфер пустую строку
      lpTextPaste[0] = '\0';

      // Расфиксируем буфер
      GlobalUnlock(hglbTextPasteBuf);
      return 0;
    }
    case WM_PAINT:
    {
      hdc = BeginPaint(hwnd, &ps);

      // Фиксируем текстовый буфер в памяти,
      // в случае успеха отображаем его содержимое
      // во внутренней области главного окна
      lpTextPaste = (LPSTR)GlobalLock(hglbTextPasteBuf);
      if(lpTextPaste != NULL)
      {
        GetClientRect(hwnd, &rc);
        DrawText(hdc, lpTextPaste, -1, &rc,
          DT_LEFT | DT_EXPANDTABS);
        GlobalUnlock(hglbTextPasteBuf);
      }
      EndPaint(hwnd, &ps);
    }
    case WM_COMMAND:
    {
      switch (wParam)
      {
        // Копируем строку текста в Clipboard
        case CM_EDITCOPY:
        {
          // Заказываем глобальный блок памяти для строки
          hglbTextCopyBuf = GlobalAlloc(GHND,
            sizeof(szClipboardText) + 1);
          if(hglbTextCopyBuf != NULL)
          {
            // Фиксируем блок памяти
            lpTextCopy = (LPSTR)GlobalLock(hglbTextCopyBuf);
            if(lpTextCopy != NULL)
            {
              // Копируем строку текста в блок памяти
              lstrcpy(lpTextCopy, szClipboardText);

              // Расфиксируем блок памяти
              GlobalUnlock(hglbTextCopyBuf);

              // Открываем Clipboard и очищаем его
              OpenClipboard(hwnd);
              EmptyClipboard();

              // Записываем данные в Clipboard
              SetClipboardData(CF_TEXT, hglbTextCopyBuf);

              // Закрываем Clipboard
              CloseClipboard();
            }
            else
              MessageBox(hwnd, "Мало памяти",
                (LPSTR)szWindowTitle, MB_OK | MB_ICONHAND);
          }
          else
            MessageBox(hwnd, "Мало памяти",
              (LPSTR)szWindowTitle, MB_OK | MB_ICONHAND);
          return 0;
        }

        // Чтение текстовых данных из Clipboard
        case CM_EDITPASTE:
        {
          // Открываем Clipboard
          OpenClipboard(hwnd);

          // Получаем идентификатор блока памяти,
          // содержащего текстовые данные Clipboard
          hglbClipBuf = GetClipboardData(CF_TEXT);

          // Если в Clipboard есть данные в текстовом
          // формате, читаем их
          if(hglbClipBuf != NULL)
          {
            // Фиксируем блок памяти Clipboard
            lpClipBuf = (LPSTR)GlobalLock(hglbClipBuf);
            if(lpClipBuf != NULL)
            {
              // Изменяем размер буфера, предназначенного для
              // хранения данных, прочитанных из Clipboard,
              // устанавливая его равным размеру блока
              // данных Clipboard
              hglbTextPasteBuf = 
                 GlobalReAlloc(hglbTextPasteBuf,
                 GlobalSize(hglbClipBuf), GMEM_NODISCARD);

              // Фиксируем буфер в памяти и переписываем
              // в него содержимое Clipboard
              lpTextPaste =
                (LPSTR)GlobalLock(hglbTextPasteBuf);
              if(lpTextPaste != NULL)
              {
                lstrcpy(lpTextPaste, lpClipBuf);

                // Перерисовываем главное окно приложения
                InvalidateRect(hwnd, NULL, TRUE);

                // Расфиксируем буфер
                GlobalUnlock(hglbTextPasteBuf);
              }
              else
                MessageBox(hwnd, "Мало памяти",
                  (LPSTR)szWindowTitle, MB_OK | MB_ICONHAND);

              // Расфиксируем блок памяти Clipboard 
              GlobalUnlock(hglbClipBuf);
            }
            else
              MessageBox(hwnd, "Мало памяти",
                (LPSTR)szWindowTitle, MB_OK | MB_ICONHAND);
          }
          else
            MessageBox(hwnd, "Формат CF_TEXT недоступен",
            (LPSTR)szWindowTitle, MB_OK | MB_ICONHAND);

          // Закрываем Clipboard
          CloseClipboard();
          return 0;
        }

        case CM_HELPABOUT:
        {
          MessageBox(hwnd,
            "Приложение CLIPTXT\n(C) Фролов А.В., 1995",
            (LPSTR)szWindowTitle, MB_OK |
            MB_ICONINFORMATION);
          return 0;
        }
        case CM_FILEEXIT:
        {
          DestroyWindow(hwnd);
          return 0;
        }
        default:
          return 0;
      }
    }
    case WM_DESTROY:
    {
      // Освобождаем буфер, предназначенный для хранения
      // данных, прочитанных из Clipboard
      if(hglbTextPasteBuf != NULL)
        GlobalFree(hglbTextPasteBuf);

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

Обработчик сообщения WM_CREATE заказывает буфер hglbTextPasteBuf, в который будет записан текст, вставленный из Clipboard. Первоначально размер этого буфера равен 1 байту, так как при создании главного окна приложения в него записывается пустая строка, состоящая из одного нулевого байта. Впоследствии при вставке текста из Clipboard размер буфера будет изменяться таким образом, чтобы в нем можно было разместить весь текст.

После записи пустой строки буфер расфиксируется.

Задача обработчика сообщения WM_PAINT заключается в рисовании содержимого буфера hglbTextPasteBuf. Для рисования используется функция DrawText.

Заметьте, что мы фиксируем буфер hglbTextPasteBuf в памяти только на время рисования. Перед возвратом управления обработчик сообщения WM_PAINT расфиксирует буфер.

Когда пользователь выбирает строку "Copy" из меню "Edit", обработчик сообщения WM_COMMAND выполняет описанные нами ранее действия по копированию текстовой строки szClipboardText в Clipboard.

Прежде всего, он заказывает глобальный блок памяти hglbTextCopyBuf, размер которого равен размеру строки с учетом двоичного нуля, закрывающего строку. Полученный блок памяти фиксируется, после чего в него с помощью функции lstrcpy копируется содержимое строки szClipboardText. Далее блок памяти hglbTextCopyBuf расфиксируется.

Теперь блок памяти подготовлен для записи в Clipboard. Приложение открывает Clipboard и очищает его с помощью функций OpenClipboard и EmptyClipboard:

OpenClipboard(hwnd);
EmptyClipboard();

После этого блок памяти hglbTextCopyBuf передается функции SetClipboardData. Для завершения процесса Clipboard закрывается функцией CloseClipboard:

SetClipboardData(CF_TEXT, hglbTextCopyBuf);
CloseClipboard();

Все! Теперь Clipboard содержит следующий текст:

Этот текст будет записан
в универсальный буфер обмена Clipboard
приложением CLIPTXT

Вы можете убедиться в этом с помощью приложения Clipboard или ClipBook Viewer (если вы используете Windows for Workgroups).

Если пользователь выберет строку "Paste" из меню "Edit", обработчик сообщения WM_COMMAND скопирует данные из Clipboard в буфер hglbTextPasteBuf, подготовленный приложением на этапе создания главного окна.

В процессе копирования приложение открывает Clipboard функцией OpenClipboard и получает из него текстовые данные, вызывая функцию GetClipboardData:

hglbClipBuf = GetClipboardData(CF_TEXT);

Для получения адреса данных блок фиксируется функцией GlobalLock:

lpClipBuf = (LPSTR)GlobalLock(hglbClipBuf);

Перед тем как скопировать данные из Clipboard в буфер hglbTextPasteBuf его размер делается равным размеру блока памяти hglbClipBuf при помощи функции GlobalReAlloc:

hglbTextPasteBuf = 
   GlobalReAlloc(hglbTextPasteBuf,
   GlobalSize(hglbClipBuf), GMEM_NODISCARD);

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

Чтобы отразить новое содержимое блока памяти hglbTextPasteBuf, приложение перерисовывает главное окно, вызывая функцию InvalidateRect.

В завершении процесса копирования данных из Clipboard блоки памяти hglbTextPasteBuf и hglbClipBuf расфиксируются функцией GlobalUnlock. Затем Clipboard закрывается функцией CloseClipboard.

При завершении работы приложения обработчик сообщения WM_DESTROY уничтожает блок памяти hglbTextPasteBuf, который использовался для хранения данных, прочитанных из Clipboard:

if(hglbTextPasteBuf != NULL)
  GlobalFree(hglbTextPasteBuf);

Файл cliptxt.hpp (листинг 2.2) содержит определения констант для идентификации строк меню приложения CLIPTXT.


Листинг 2.2. Файл cliptxt/cliptxt.hpp


#define CM_HELPABOUT  24000
#define CM_EDITPASTE  24001
#define CM_EDITCOPY   24002
#define CM_FILEEXIT   24003

В файле cliptxt.rc (листинг 2.3) определено главное меню приложения и пиктограмма, в которую превращается главное окно приложения при свертке.


Листинг 2.3. Файл cliptxt/cliptxt.rc


#include "cliptxt.hpp"
APP_MENU MENU 
BEGIN
  POPUP "&File"
  BEGIN
    MENUITEM "E&xit",     CM_FILEEXIT
  END
  POPUP "&Edit"
  BEGIN
    MENUITEM "&Copy",     CM_EDITCOPY
    MENUITEM "&Paste",    CM_EDITPASTE
  END
  POPUP "&Help"
  BEGIN
    MENUITEM "&About...", CM_HELPABOUT
  END
END
APP_ICON ICON "cliptxt.ico"

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


Листинг 2.4. Файл cliptxt/cliptxt.def


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

Clipboard и редактор текста EDIT

Орган управления, созданный на базе предопределенного класса окна "EDIT" (редактор текста), способен обмениваться данными с Clipboard. В 12 томе "Библиотеки системного программиста" мы перечисляли сообщения, которые можно посылать редактору текста с помощью функции SendMessage. Для обмена данных между редактором текста и Clipboard приложение может посылать редактору сообщения WM_COPY, WM_CUT и WM_PASTE:

SendMessage(hEdit, WM_PASTE, 0, 0L);

Перечисленные выше сообщения не имеют параметров и используются, соответственно, для копирования выделенного фрагмента текста в Clipboard, для переноса выделенного фрагмента текста в Clipboard с последующим удалением и для вставки текста из Clipboard в редактор текста.

Пример организации взаимодействия органа управления EDIT и буфера обмена Clipboard приведен в 13 томе "Библиотеки системного программиста" в разделе "Приложение SMARTPAD".

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


Создание интернет-магазинов: http://www.shop2you.ru/ © Александр Фролов, Григорий Фролов, 1991-2016