Четвертый Borland C++ и его окружение

       

Написание переносимого кода Windows


В данном разделе обсуждаются конструкции (введенные в

Windows 3.1), обеспечивающие переносимость кода Windows. Существующий 16-разрядный код Windows можно переносить с минимальными

изменениями в Win32 и Windows NT. Большинство изменений предусматривают подстановку вместо старых новых макрокоманд и типов и

замену специфических 16-разрядных вызовов API аналогичными API

Win32. После внесения этих изменений ваш программный код сможет

компилироваться и выполняться в 16-разрядной и 32-разрядной среде

Windows.

Чтобы облегчить создание переносимого кода, предусмотрена

переменная среду этапа компиляции STRICT. Windows 3.1 поддерживает определение STRICT в windows.h. Например, если не определена

переменная STRICT, то передача HWND функции, требующей HDC, не

приведет к выводу компилятором предупреждающего сообщения. Если

вы определите STRICT, то получите ошибку компиляции.

Использование STRICT позволяет:



  • выполнять строгую проверку типов;
  • корректировать и согласовывать описания типа параметра и

    возвращаемого значения;

  • создавать прототипы определений типов для функций обратного вызова (оконные, диалоговые и специальные процедуры);
  • согласовывать с ANSI описания структур COMM, DCB и

    COMSTAT.

  • STRICT обладает обратной совместимостью с Windows 3.0, то

    есть ее можно использовать для создания приложений, работающих в

    Windows 3.0. Определение STRICT поможет вам находить и корректировать несовместимость типов при переносе программ в 32-разрядную среду и поможет обеспечить переносимость между 16- и 32-разрядной Windows.

    Чтобы вы могли изменить свою программу в соответствии со

    STRICT, предусмотрены новые типы, константы и макрокоманды

    Типы и константы Описание

    CALLBACKИспользуется вместо FAR PASCAL в подпрограммах обратного вызова (например, оконных и диалоговых процедурах).
    LPARAM Описывает все 32-разрядные полиморфические параметры.
    LPCSTR То же, что LPSTR, но используется для доступ-

    ных только по чтению строковых указателей.

    LRESULT Описывает все 32-разрядные возвращаемые значения.
    UINT Переносимый беззнаковый целочисленный тип,

    размер которого определяется целевой средой.

    (В Windows 3.1 представляет 16-битовое значение, а в Win32 - 32-битовое.)

    WINAPI Используется вместо FAR PASCAL для описаний API. Если вы пишете DLL с экспортируемыми точками входа API, то можете использовать ее для описаний API.
    WPARAM Описывает 16-битовые полиморфические параметры.
    <


    Макрокоманда Описание






    RELDOFFSET(тип, поле) Вычисляет смещение поля в структуре. "Тип" - это тип структуры, а "поле" - это имя поля.
    WAKELP(селект,смещ) Воспринимая селектор и смещение, создает FAR VOID*.
    WAKELPARAM(мин,макс) Из двух 16-битовых значений создает LPARAM.
    WAKELRESULT(мин,макс) Из двух 16-битовых значений создает LRESULT.
    OFFSETOF(указ) Выделяет из дальнего указателя смещение и возвращает UINT.
    SELECTOROF(указ) Выделяет из дальнего указателя селектор и возвращает UINT.
    Описатели Значение












    HACCEL Описатель таблицы акселератора.
    HDRVR Описатель драйвера (Windows 3.1).
    HDWP Описатель DeferWindowPost().
    HFILE Описатель файла.
    HGDIOBJ Общий описатель объекта GDI.
    HGLOBAL Глобальный описатель.
    HINSTANCE Описатель экземпляра.
    HLOCAL Локальный описатель.
    HMETAFILE Описатель метафайла.
    HMODULE Описатель модуля.
    HPSRC Описатель ресурса.
    HTASK Описатель задачи.
    Чтобы сделать ваше приложение согласованным со STRICT, нужно:

  • Определить, какой программный код вы хотите согласовать

    со STRICT.


  • Включить наивысший уровень вывода ошибок/предупреждений.

    В IDE используйте команду

    Options Compiler Messages Display All. В BCC32 укажите

    параметр -w.


  • Перед включением windows.h и компиляцией определить

    STRICT с помощью #define или использовать в командной

    строке параметр -DSTRICT.


  • Перечислим некоторые рекомендации, которые могут оказаться

    полезными при преобразовании вашего программного кода в соответствии со STRICT:

  • Измените HANDLE на соответствующий тип описателя, например, HMODULE, HINSTANCE и др.


  • Измените WORD на UINT (за исключением тех мест, где вы

    хотите получить 16-битовое значение на 32-разрядной платформе).


  • Измените WORD на WPARAM.


  • Измените LONG на LPARAM или LRESULT.


  • Измените FARPROC на WNDPROC, DLGPROC или HOOKPROC.


  • В 16-разрядной Windows всегда описывайте указатели функций

    с помощью подходящего типа функции, а не с помощью

    FARPROC. При использовании MakeProcInstance,

    FreeProcInstance и других функций, воспринимающих или



    возвращающих FARPROC, вам нужно приводить типы указателей

    функции, например:

    BOOL CALLBACK DlgProc(HWND hwnd, UINT msg,

    WPARAM wParam,

    LPARAM lParam);

    DLGPROC lpfnDlg;

    lpfnDlg=(DLGPROC)MakeProcInstance(DlgProc, hinst);

    ...

    FreeProcInstance((FARPROC)lpfnDlg);


  • Особое внимание обратите на HMODULE и HINSTANCE. Функции

    ядра, осуществляющие управление модулями, обычно используют HINSTANCE, но некоторые API возвращают или воспринимают

    только HMODULE.


  • Если вы копируете какие-то описания функций API из

    WINDOWS.H, они могут быть изменены, и ваши описания могут

    оказаться устаревшими. Удалите локальные описания.


  • Приведите тип результата LocalLock и GlobalLock к соответствующему виду указателя данных. Параметры этих и других функций управления памятью должны при необходимости

    приводиться к LOCALHANDLE или GLOBALHADLE.


  • Приведите результат GetWindowWord и GetWindowLong и параметры к SetWindowWord и SetWindowsLong.


  • При приведении типа SendMessage, DefWinmdowProc и

    SendDlgItemMsg или любых других функций, которые возвращают LRESULT или LONG к какому-либо описателю вы должны сначала привести результат к UINT:

    HBRUSH hbr;

    hbr = (HBRUSH)(UINR)

    SendMessage(hwnd WM_CTLCOLOR, ..., ...);


  • Параметр CreateWindow и CreateWindowEx функции hmenu иногда используются для передачи целочисленного управляющего

    идентификатора. В этом случае вы должны привести тип к

    HMENU:

    HWND hwmd;

    int id;

    hwnd = CreateWindow("Button", "Ok", BS_PUSBUTTON,

    x, y, cx, cy, hwndParent,

    (HMENU)id, // здесь требуется приведение типа

    hinst, NULL);


  • Полиморфические типы данных (WPARAM, LPARAM, LRESULT, void

    FAR*) следует возможно скорее присваивать переменным. Избегайте использовать их в своих программах, когда тип значения известен. Это минимизирует число потенциально небезопасных и непереносимых в 32-разрядный режим преобразований типов. Макрокоманды API и механизмы обработки сообщений, предусмотренные в windowsx.h, будут выполнять практически всю упаковку и распаковку этих типов данных способом, обеспечивающим переносимость в 32-разрядный режим.


  • Ознакомьтесь с наиболее общими предупреждениями и ошибками

    компилятора, которые вы можете обнаружить при переходе к

    STRICT.



  • Содержание раздела