Ознакомление с приложениями Windows

Общая характеристика операционных систем и приложений Windows. Разделение ресурсов, работа с окнами, назначение диска, видов памяти, системы сохранения и передачи данных. История возникновения приложений, их виды и особенности, порядок написания.

Рубрика Программирование, компьютеры и кибернетика
Вид курс лекций
Язык русский
Дата добавления 24.06.2009
Размер файла 321,0 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

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

При описании панелей диалогов используется своя собственная система координат -- система координат панели диалога. В этом случае начало отсчета помещается в верхний левый угол внутренней области панели диалога Панель диалога является родительским окном для всех элементов управления, размещенных на этой панели, включая статические -- рамки, текст и прочее., ориентация осей координат сохраняется прежней, а в качестве единиц отсчета применяют по оси x -- одну четвертую от средней ширины символа шрифта, а по оси y -- одну восьмую от высоты шрифта. Обычно эти величины примерно соответствуют одному пикселю. Дополнительную информацию можно получить, например, из описания функции MapDialogUnits.

Сложность в применении этой системы координат связана с понятием средней ширины символа. Дело в том, что подавляющее большинство шрифтов является пропорциональными -- то есть каждый символ шрифта имеет свою ширину. Для вычисления «средней ширины» применяют ширины символов алфавита, взвешенные с учетом частотности встречи символов в общелитературном тексте. Как правило -- английском. Все это может привести к некоторым ошибкам в задании положения и размеров при использовании иного языка, чем английский, особенно если при этом используются нестандартные шрифты. В Windows-95 легко наблюдать этот эффект, изменяя с помощью панели управления (control panel) размеры используемых шрифтов и наблюдая за отображением стандартных диалогов.

Как построить приложение

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

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

Как строили Windows-приложения в самом начале

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

Основные сложности были связаны с двумя особенностями приложений для Windows:

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

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

Обычная DOS-задача не могла делать таких вещей. Поэтому в Windows был принят новый формат выполняемого файла, а для нормального построения образа задачи пришлось изменить стандартный компоновщик (linker) так, чтобы он мог использовать информацию об экспортируемых и импортируемых функциях и собирать выполняемые файлы в новом формате. Соответственно, такой компоновщик нуждался в информации об экспортируемых и импортируемых функциях, а также о некоторых дополнительных параметрах Windows-приложения. Чтобы предоставить эту информацию компоновщику надо было написать специальный текстовой файл -- файл описания модуля (def-файл).

В файле описания модуля перечислялись имена экспортируемых функций, имена импортируемых и библиотеки, содержащие функции, подлежащие импорту, задавался размер стека, давалось короткое описание приложения и пр. Это было не слишком удобно, так как при вызове какой-либо новой функции из Windows API (а их более 1000), необходимо было добавлять ее имя в файл описания модуля.

В тех случаях, когда приложение нуждалось в собственных ресурсах, необходимо было отдельно описать эти ресурсы в специальном текстовом файле описания ресурсов (rc-файле). Вместе с компиляторами до сих поставляется специальный компилятор ресурсов RC.EXE, который воспринимает файл описания ресурсов, компилирует его и создает файл ресурсов приложения (res-файл). Затем тот-же компилятор ресурсов может объединить уже построенный выполняемый файл с файлом ресурсов приложения.

Таким образом построение приложения состояло из следующих этапов:

разработка исходных текстов -- .c, .cpp, .h, .hpp, .rc и .def файлы;

компиляция исходного текста программы -- из .c и .cpp получаем .obj (иногда .lib);

компиляция ресурсов приложения -- из .rc получаем .res;

компоновка приложения -- из .obj и .lib получаем .exe;

встраивание ресурсов приложения в выполняемый файл -- из .exe и .res получаем рабочий .exe.

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

Следующий этап

Очевидно, что необходимость перечислять кучу имен функций в файле описания приложения никого не приводила в восторг. Поэтому на следующем этапе была включена поддержка Windows-приложений непосредственно в компиляторы Ориентировочно, начиная с компиляторов для Windows 3.0. Для этого было добавлено ключевое слово _export (иногда __export), которое применяется при описании экспортируемых функций непосредственно в тексте C-программы. Для таких функций компилятор включает в объектный файл специальную информацию, так что компоновщик может правильно собрать выполняемый файл. Так, например, было сделано в первом примере для оконной процедуры:

LRESULT WINAPI _export proc( ...

Помимо экспортированных функций, в файле описания приложения было необходимо перечислять все импортированные функции. А этот список был самым большим (Windows экспортирует более 1000 функций, которые могут импортироваться приложениями). Для решения этой задачи был изменен формат библиотек объектных файлов, так что появилась возможность описать имена функций, экспортированных другими модулями. Так компоновщик задачи может определить, какие функции импортируются и из каких модулей.

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

Библиотеки со списками функций, которые можно импортировать из Windows (то есть экспортированных компонентами Windows) входят в состав всех компиляторов. Иногда может возникнуть необходимость использования нестандартного компонента (или собственной динамически загружаемой библиотеки), для которых соответствующей библиотеки с ссылками нет. В таком случае можно воспользоваться специальным приложением -- implib.exe -- которое входит в состав большинства компиляторов (если его нет в составе компилятора, то значит его возможности реализованы в каком-либо другом инструменте, как, например, wlib.exe в Watcom C/C++). Implib позволяет по имеющемуся файлу динамически загружаемой библиотеки (.dll) или файлу описания проекта модуля библиотеки (.def), содержащему список экспортированных функций, построить библиотечный файл (.lib), с ссылками на функции библиотеки.

Первоначально, стремясь максимально уменьшить время загрузки модулей в память, при экспортировании функций им присваивались уникальные номера (назначаются разработчиком, либо просто по порядку). Конкретная функция однозначно определяется именем экспортирующей библиотеки динамической загрузки и идентификатором функции. Для задания идентификаторов экспортируемых функций используется файл описания модуля. Однако использование номеров вместо имен является не слишком удобным для человека, поэтому в Windows используются оба метода -- функции доступны как по их идентификаторам, так и по их именам. Для Windows API общепринятым методом считается использование идентификаторов -- Microsoft следит за тем, что бы все документированные функции сохраняли свои идентификаторы. А в Win32 API предполагается использование имен; более того, Microsoft не гарантирует, что идентификаторы документированных функций не будут изменяться.

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

Современные компиляторы и системы поддержки проектов фактически остались в рамках рассмотренного порядка построения приложения. Небольшие изменения реализованы в разных компиляторах независимо друг от друга. Так, иногда включение файла ресурсов приложения в выполняемый модуль выполняется не компилятором ресурсов, а непосредственно компоновщиком; в других случаях специальные редакторы ресурсов позволяют обойтись без построения файла описания ресурсов (.rc), а создать непосредственно файл ресурсов приложения (.res). Особенно часто это делается в системах визуального программирования.

Если вы используете какую-либо систему поддержки проектов (Watcom IDE, Microsoft Developer Studio, Borland IDE, Symantec IDE и пр.) -- а скорее всего это именно так -- то вы должны только проследить за тем, что бы необходимые файлы были включены в проект. Система сама отследит, как и когда должен использоваться тот или иной исходный файл.

Обычно в проект включаются следующие файлы:

исходные тексты на C и C++ -- файлы с расширениями .c, .cpp, .c++;

файл, содержащий ресурсы приложения, как правило только один, либо .rc либо .res;

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

дополнительные объектные файлы .obj -- отдельно включаются очень редко;

файл описания модуля .def, только один, часто только при желании описать нестандартные параметры компоновки (см. ниже, в описании этого файла).

Файл описания модуля (.def)

Файл описания модуля (приложения) содержит обычный текст, который можно написать любым текстовым редактором. В качестве примера рассмотрим один из файлов описания модуля, использованный для построения приложения testapp.exe:

NAME TESTAPP
DESCRIPTION 'TESTAPP - test application'
EXETYPE WINDOWS
PROTMODE
STUB 'WINSTUB.EXE'
CODE LOADONCALL MOVEABLE
DATA MOVEABLE MULTIPLE
STACKSIZE 8192
HEAPSIZE 4096

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

Большинство компиляторов могут использовать собственные директивы, а также собственные расширения для параметров, задаваемых в директивах, не описанные в общих руководствах (как, к примеру, директива PROTMODE в приведенном примере). Кроме того список возможных директив в файлах описания модулей для Windows API и для Win32 API различается.

Windows API
Первая строка обычно задает имя модуля. Если вы строите приложение, то первой должна стоять директива NAME, а если динамически загружаемую библиотеку -- LIBRARY. Указание обоих директив считается некорректным. Имя должно соответствовать имени файла, так для testapp.exe эта строка будет такой: NAME TESTAPP, а для mydll.dll -- LIBRARY MYDLL.

LIBRARY dllname
NAME exename

Обычно следующая строка -- описание данного модуля. Она начинается с директивы DESCRIPTION, за которой следует произвольный текст, заключенный в апострофы:

DESCRIPTION `description text for module'

Следующая директива, если и присутствует, то всегда определяет, что данный модуль предназначен для работы в среде Windows (аналогичные файлы описания модулей могут применяться для OS/2).

EXETYPE WINDOWS

Еще две директивы предназначены для задания размеров стека и кучи. Задание размера стека менее 5K приводит к тому, что Windows сам увеличивает его до 5K. Задание размера кучи вообще абстрактно -- главное, что бы не 0, так как Windows будет увеличивать кучу при необходимости (вплоть до наибольшего размера сегмента данных приложения -- 64K). Размер кучи 0 говорит о том, что она просто не используется..

HEAPSIZE size
STACKSIZE size

Очень любопытная директива -- STUB. О ней надо рассказать чуть подробнее. Ранее было отмечено, что для Windows-приложений был разработан собственный формат выполняемого модуля. Очевидно, что попытка запустить такой модуль на старой версии DOS, который не рассчитан на такую возможность, приведет к грубой ошибке, вплоть до зависания компьютера или порчи данных. Чтобы этого избежать, сделали так -- Windows-приложение состоит из двух частей:

Первая часть представляет собой небольшое приложение MS-DOS, называемую заглушкой (stub). Обычно это приложение просто пишет на экране фразу типа “This program must be run under Microsoft Windows.”. Заголовок этой заглушки чуть изменен, чтобы Windows мог отличить DOS-приложение от Windows-приложения, но это изменение находится в неиспользуемой MS-DOS'ом части заголовка.

STUB `stubexe.exe'

Здесь stubexe.exe -- имя приложения-заглушки (возможно полное имя, вместе с путем)

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

Разрабатывая собственную заглушку можно делать интересные приложения, работающие в DOS и в Windows. Скажем, собрать в один выполняемый файл DOS-версию приложения и Windows-версию.

Еще три директивы используются для описания параметров сегментов кода и данных. Директива CODE задает характеристики сегментов кода, DATA -- сегментов данных, а SEGMENTS позволяет описать характеристики для конкретного сегмента (в квадратные скобки [] заключены необязательные параметры, знак | разделяет возможные варианты; запись [FIXED|MOVEABLE] означает, что может быть указано либо FIXED, либо MOVEABLE, либо ничего). Более подробно о характеристиках сегментов приложения см. в описании диспетчера памяти Windows 3.x.

CODE [FIXED|MOVEABLE] [DISCARDABLE] [PRELOAD|LOADONCALL]

DATA [NONE|SINGLE|MULTIPLE] [FIXED|MOVEABLE]

SEGMENTS
segname [CLASS `clsname'] [minalloc] [FIXED|MOVEABLE] [DISCARDABLE] [SHARED|NONSHARED] [PRELOAD|LOADONCALL]
...

Могут быть указаны следующие параметры: FIXED или MOVEABLE -- сегмент фиксирован в памяти или перемещаемый; если сегмент перемещаемый, то он может быть теряемым (DISCARDABLE). Параметры PRELOAD и LOADONCALL указывают, когда сегмент должен быть загружен в оперативную память -- при загрузке приложения (PRELOAD) или при непосредственном обращении к нему (LOADONCALL). Параметры NONE, SINGLE или MULTIPLE применяются только для сегментов данных. NONE или SINGLE применяется для динамически загружаемых библиотек; NONE -- библиотека не имеет сегмента данных вообще, SINGLE -- сегмент данных присутствует в памяти в единственном экземпляре (динамические библиотеки загружаются только один раз, других копий не существует, все приложения ссылаются на одну библиотеку с единым сегментом данных). MULTIPLE -- сегмент данных загружается для каждой копии приложения, применяется только для приложений.

Директива SEGMENTS описывает характеристики конкретных сегментов; segname -- имя сегмента, clsname -- имя класса сегмента, minalloc -- минимальный размер сегмента. SHARED или NONSHARED сообщает, является ли сегмент разделяемым разными копиями приложения, либо нет. После одной директивы SEGMENTS может размещаться описание нескольких сегментов, по одному на каждой строке.

Еще две часто используемых директивы -- EXPORTS и IMPORTS. Они задают списки экспортированных и импортированных имен функций, описание каждой функции находится на своей строке. В обоих случаях надо учитывать следующую особенность -- в Windows различают внешние и внутренние имена. Внутренние имена -- это имена, использованные при разработке исходного текста программы, те которые содержаться в тексте C-программы (или в объектном файле). Внешние имена -- имена используемые при экспорте/импорте, доступные другим модулям. Внешнее и внутреннее имя могут не совпадать, поэтому предусмотрена возможность задавать оба имени.

EXPORTS
exportname [=internalname] [@id] [RESIDENTNAME] [NODATA] [argsize]
...

В разделе EXPORTS перечисляются имена функций, экспортируемых данным модулем. Параметр exportname задает внешнее имя функции, под которым она будет доступна другим модулям, параметр internalname используется, если внешнее и внутреннее имена различаются, @id задает идентификатор функции, argsize -- если указан, сообщает сколько слов в стеке занимает список аргументов функции. Параметры RESIDENTNAME и NODATA используются крайне редко; RESIDENTNAME говорит о том, что имя функции должно размещаться в так называемом резидентном списке имен (который находиться в памяти постоянно после загрузки модуля), обычно имена размещаются в нерезидентном списке, который загружается при необходимости. NODATA говорит о том, что функция использует сегмент данных вызывающего модуля, а не экспортирующего (подробнее -- при разговоре о диспетчере памяти).

IMPORTS
[internalname=] modulename.id
[internalname=] modulename.importname

Раздел IMPORTS задает соответствие внутренних имен импортируемых функций (internalname) функциям, экспортированным другими модулями. Возможно два метода связывания имен -- по идентификатору (первый пример), modulename -- имя экспортирующего модуля, id -- идентификатор; либо по именам (второй пример), importname -- внешнее имя функции, под которым она была экспортирована другим модулем.

Win32 API
Файл описания модуля в Win32 API используется для задания нестандартных характеристик динамически загружаемых библиотек. Полное описание файлов описания модуля для Win32 API надо смотреть в документации, сопровождающей применяемый компилятор.
Так как файл описания модуля используется для создания DLL, то первая директива -- LIBRARY. Часто применяется также директива EXPORTS для задания идентификаторов экспортируемых функций (обе -- см. в описании файла описания модуля для Windows API).
Для задания нестандартных параметров отдельных сегментов используется директива SECTIONS, заменяющая прежнюю директиву SEGMENTS. Синтаксис директивы SECTIONS несколько иной, хотя допускается замена слова SECTIONS на SEGMENTS:

SECTIONS
secname [CLASS `classname'] [EXECUTE] [READ] [WRITE] [SHARED]

После указания имени секции (сегмента) следует необязательное указание имени класса и атрибутов этой секции -- разрешение на выполнение (EXECUTE), на чтение (READ), на запись (WRITE) и объявление секции разделяемой (SHARED) между разными копиями модуля (загруженными в разных адресных пространствах разных приложений!).

Дополнительные разделы

В этом разделе будет рассказано о малоизвестном заголовочном файле -- windowsx.h. В некоторых случаях разработчики его, конечно, используют, но редко больше чем на 5% от его возможностей. Этот заголовочный файл был разработан специально для облегчения контроля исходного текста программы. К сожалению, в большей части документации, сопровождающей компиляторы, этот файл вообще не описан, хотя существует уже очень давно. Пожалуй впервые он описан в документации, сопровождающей Microsoft Visual C++ 4.0 (Microsoft Developer Studio, раздел “SDKs|Win32 SDK|Guides|Programming Techniques|Handling Messages with portable macros”). Однако даже там описаны только принципы его применения, но не дано подробное описание всех его макросов. Как результат -- при применении windowsx.h приходится постоянно обращаться к его исходному тексту.

Заголовочный файл WINDOWSX.H

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

Например функция DeleteObject может применяться для удаления многих объектов GDI (Graphics Devices Interface) -- карандашей, кистей, регионов и пр. По названию функции понять, какой-именно объект она удаляет нельзя, поэтому при чтении исходного кода приходится сосредотачиваться на параметрах этой функции. В windowsx.h определены макросы:

#define DeletePen(hpen) DeleteObject((HGDIOBJ)(HPEN)(hpen))
#define DeleteBrush(hbr) DeleteObject((HGDIOBJ)(HBRUSH)(hbr))
#define DeleteRgn(hrgn) DeleteObject((HGDIOBJ)(HRGN)(hrgn))

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

При включении файла windowsx.h в ваше приложение это надо делать после включения основного файла windows.h:

#define STRICT
#include <windows.h>
#include <windowsx.h>

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

макросы для работы с функциями ядра (несколько макросов для работы с глобальной памятью)

макросы для работы с объектами GDI

макросы для работы с окнами (вызовы стандартных функций)

распаковщики сообщений (самая большая часть)

макросы для работы с окнами стандартных классов (кнопки, списки и пр.)

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

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

Распаковщики сообщений

Большая часть файла windowsx.h предназначена для описания распаковщиков сообщений (message crackers). Так как в книге преимущественно будут приводятся фрагменты кода с использованием распаковщиков, то в этом месте мы с ними и познакомимся. При их использовании придется постоянно заглядывать в исходный текст windowsx.h, так как в обычной документации распаковщики не описаны. По счастью этот файл хорошо структурирован и снабжен достаточными комментариями.

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

Вполне очевиден выход -- разнести обработку сообщений по отдельным функциям, которые будут вызываться из процедуры обработки сообщений. Однако для каждого сообщения передаются свои данные, упакованные в двух параметрах -- wParam и lParam. Иногда они не используются, иногда содержат какие-либо значения, иногда -- указатели. Естественно, было бы удобным передавать в вызываемую функцию уже распакованные параметры. Затруднение здесь вызывает то, что для Windows API и для Win32 API одни и те же данные одного и того же сообщения могут быть упакованы по разному Это связано с тем, что параметр wParam имеет тип UINT -- то есть он в Windows API представляет собой 16ти разрядное слово, а в Win32 API -- 32х разрядное. Кроме того, в младшем или старшем слове lParam часто размещается хендл, который в Windows API 16ти разрядный. К сожалению в Win32 API хендлы 32х разрядные, так что уместить его на прежнем месте не представляется возможным..

При разработке windowsx.h это все было учтено (для Windows API и для Win32 API распаковщики определяются по разному). Так, для каждого сообщения WM_xxx определен свой макрос с именем HANDLE_WM_xxx. Например, для сообщения WM_CREATE определен макрос:

HANDLE_WM_CREATE(hwnd, wParam, lParam, fn)

Параметры всех макросов одинаковые, что позволяет передавать им непосредственно параметры сообщения (окно-адресат hwnd, параметры wParam и lParam), а также имя функции-обработчика fn. Этот макрос должен использоваться внутри конструкции switch для вызова нужной функции и передачи ей распакованных параметров. Например фрагмент следующего вида:

switch ( uMsg ) {
case WM_CREATE: return HANDLE_WM_CREATE(hWnd,wParam,lParam,fnOnCreate);
// ...
}

будет превращен компилятором в следующий фрагмент (подробнее см. исходный текст windowsx.h):

switch ( uMsg ) {
case WM_CREATE:
return ((fnOnCreate)((hWnd),(LPCREATESTRUCT)(lParam)) ?
0L : (LRESULT)-1L);
// ...
}

То есть при раскрытии макроса HANDLE_WM_xxx осуществляется распаковка параметров, вызов функции и анализ возвращаемого результата. Здесь, кстати, скрыта одна ловушка (по счастью крайне редкая): результат, возвращаемой функцией-обработчиком не всегда будет совпадать с результатом, описанным в справочнике для данного сообщения. Случай с WM_CREATE именно такой -- согласно описанию обработчик WM_CREATE должен вернуть 0L, если все в порядке. А, как мы видим в приведенном фрагменте, функция, вызываемая распаковщиком, должна вернуть TRUE, то есть не 0, если все в порядке (распаковщик сам заменит TRUE на 0L).

При рассмотрении этого примера возникает вопрос -- а как должна быть описана функция-обработчик, что бы распаковщик ее правильно вызывал? Ответ прост -- в самом файле windowsx.h перед определением соответствующего макроса приводится прототип этой функции. То есть нам надо сделать следующее: открыть windowsx.h, найти в нем строку, где определяется распаковщик для WM_CREATE (это легко делается поиском) и посмотреть на приведенный там текст:

/* BOOL Cls_OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct) */
#define HANDLE_WM_CREATE(hwnd, wParam, lParam, fn) \
((fn)((hwnd), (LPCREATESTRUCT)(lParam)) ? 0L : (LRESULT)-1L)
#define FORWARD_WM_CREATE(hwnd, lpCreateStruct, fn) \
(BOOL)(DWORD)(fn) ((hwnd), WM_CREATE, 0L, \
(LPARAM)(LPCREATESTRUCT)(lpCreateStruct))

Описание функции Cls_OnCreate мы и ищем. Далее нам надо его просто скопировать в наше приложение и исправить при желании имя функции. Единственное, что остается не слишком удобным -- так это вызов макроса-распаковщика -- уж очень длинная строка получается. Для этого в windowsx.h содержится отдельный небольшой макрос:

HANDLE_MSG( hWnd, uMsg, fn )

Используется он таким способом:

switch ( uMsg ) {
HANDLE_MSG( hWnd, WM_CREATE, Cls_OnCreate );
// ...
}

При этом он сам вставляет “case WM_xxx: return ...” и прочее. Важно следить, что бы в описании оконной процедуры параметры wParam и lParam назывались именно так и не иначе. Дело в том, что HANDLE_MSG при обращении к макросу HANDLE_WM_xxx указывает ему именно эти имена.

Чтобы закончить разговор о распаковщиках сообщений надо ответить только на два вопроса -- зачем нужны макросы FORWARD_WM_xxx, определенные в том-же windowsx.h и как можно добавить распаковщики для каких-либо сообщений, там не определенных (например, нестандартных).

Рассмотренные пока макросы-распаковщики позволяли нам вызвать функцию-обработчик сообщения, имея для нее данные, упакованные в wParam и lParam. Однако иногда возникает другая необходимость -- имея параметры функции передать какое-либо сообщение. Для этого предназначены макросы FORWARD_WM_xxx. Для использования этих макросов, необходимо, что-бы функция, получающая параметры сообщения, имела следующий вид:

LRESULT proc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );

Макросы FORWARD_WM_xxx получают в качестве параметров распакованные данные (как и функция-обработчик), упаковывают их в параметры сообщения и вызывают указанную функцию. По счастью практически все функции, которые придется вызывать с помощью макросов FORWARD_WM_xxx (SendMessage, PostMessage, DefWindowProc и пр.) соответствуют приведенному описанию.

Например, сообщение WM_SETFONT посылается окну (стандартного класса) для того, что бы назначить ему нужный шрифт. Параметры этого сообщения следующие: wParam содержит хендл шрифта, а младшее слово lParam указывает, надо ли перерисовывать окно сразу после смены шрифта. Предположим, что ваше окно имеет дочернее окно, и вам хочется сделать так, чтобы при смене шрифта в вашем окне одновременно менялся шрифт в дочернем. Соответственно вы должны включить в оконную процедуру обработку сообщения WM_SETFONT и в его обработчике передать такое-же сообщение дочернему окну.

void Cls_OnSetFont( HWND hwnd, HFONT hfont, BOOL fRedraw );

LRESULT WINAPI _export proc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch ( uMsg ) {
// ...
HANDLE_MSG( hWnd, WM_SETFONT, Cls_OnSetFont );
// ...
}
}

// ...

void Cls_OnSetFont( HWND hwnd, HFONT hfont, BOOL fRedraw )
{
HWND hwndChild = ...; // определение хендла дочернего окна
FORWARD_WM_SETFONT( hwndChild, hfont, fRedraw, SendMessage );
}

Здесь, кстати, можно было бы воспользоваться макросом SetWindowFont из того же windowsx.h. Этот макрос обращается к FORWARD_WM_SETFONT, как в рассмотренном примере, однако текст при этом становится более читаемым:

void Cls_OnSetFont( HWND hwnd, HFONT hfont, BOOL fRedraw )
{
HWND hwndChild = ...; // определение хендла дочернего окна
SetWindowFont( hwndChild, hfont, fRedraw );
}

Добавление собственных распаковщиков не должно вызвать больших затруднений -- достаточно только разработать реализации макросов HANDLE_WM_xxx и FORWARD_WM_xxx аналогично уже сделанному в windowsx.h.

Пример 1B -- использование распаковщиков сообщений

Этот пример иллюстрирует применение распаковщиков сообщений на примере простейшего приложения. Фактически он соответствует слегка измененному примеру 1A, в котором оконная процедура переписана для использования распаковщиков сообщений. Функция WinMain в этом примере осталась без изменений.

#define STRICT
#include <windows.h>
#include <windowsx.h>

#define UNUSED_ARG(arg) (arg)=(arg)

static char szWndClass[] = "test window";

BOOL Cls_OnCreate( HWND hwnd, LPCREATESTRUCT lpCreateStruct )
{
UNUSED_ARG( hwnd );
UNUSED_ARG( lpCreateStruct );
return TRUE;
}

void Cls_OnPaint( HWND hwnd )
{
PAINTSTRUCT ps;

BeginPaint( hwnd, &ps );
TextOut( ps.hdc, 0, 0, "Hello, world!", 13 );
EndPaint( hwnd, &ps );
}

void Cls_OnDestroy( HWND hwnd )
{
UNUSED_ARG( hwnd );

PostQuitMessage( 0 );
}

LRESULT WINAPI _export WinProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch ( uMsg ) {
HANDLE_MSG( hWnd, WM_CREATE, Cls_OnCreate );
HANDLE_MSG( hWnd, WM_PAINT, Cls_OnPaint );
HANDLE_MSG( hWnd, WM_DESTROY, Cls_OnDestroy );
default: break;
}
return DefWindowProc( hWnd, uMsg, wParam, lParam );
}

static BOOL init_instance( HINSTANCE hInstance )
{
WNDCLASS wc;

wc.style = 0;
wc.lpfnWndProc = WinProc;
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.lpszMenuName = NULL;
wc.lpszClassName = szWndClass;
return RegisterClass( &wc ) == NULL ? FALSE : TRUE;
}

int PASCAL WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszCmdLine, int nCmdShow )
{
UNUSED_ARG( lpszCmdLine );
MSG msg;
HWND hWnd;

if ( !hPrevInst ) {
if ( !init_instance( hInst ) ) return 1;
}

hWnd= CreateWindow(
szWndClass, // class name
"window header", // window name
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT,CW_USEDEFAULT, // window position
CW_USEDEFAULT,CW_USEDEFAULT, // window size
NULL, // parent window
NULL, // menu
hInst, // current instance
NULL // user-defined parameters
);

if ( !hWnd ) return 1;

ShowWindow( hWnd, nCmdShow );
UpdateWindow( hWnd );

while ( GetMessage( &msg, NULL, NULL, NULL ) ) {
TranslateMessage( &msg );
DispatchMessage( &msg );
}

return msg.wParam;
}

Немного об объектах

Здесь мы рассмотрим некоторые основные особенности реализации объектно-ориентированного программирования в Windows. В последнее время получили огромное распространение библиотеки объектов для создания приложений в среде Windows. Особенно широко они стали распространяться с развитием систем визуального программирования. Наибольшее распространение получили библиотеки объектов компаний

Borland -- Object Windows Library (OWL), поддерживается компиляторами Borland C++ (рассматривается версия v2.5, сопровождающая компилятор Borland C/C++ v4.5).

Microsoft -- Microsoft Foundation Classes (MFC), поддерживается наибольшим количеством компиляторов, среди которых Microsoft Visual C++, Watcom C++, Symantec C++ и другие (рассматривается версия v4.0, сопровождающая Visual C/C++ v4.0).

Такие библиотеки достаточно многофункциональны и громоздки, размер исполняемого файла, созданного с их помощью редко бывает меньше 300-400K. Конечно, при разработке больших систем, поддерживающих такие инструменты как OLE, DAO или WOSE, регистрирующих свои собственные типы файлов и т.д., использование этих библиотек может существенно сократить время, необходимое для разработки приложения.

Эти библиотеки объектов, хотя и имеют огромное количество различий, неизбежно имеют и много общего, что определяется платформой, на которой они работают -- Windows. Для обеспечения эффективной работы приложений эти библиотеки вынуждены предусматривать простой механизм доступа посредством методов объектов к функциям API, что их неизбежно сближает между собой. Кроме того реализация и иерархия объектов в Windows неизбежно приводит к появлению чем-то сходной иерархии классов в библиотеках ООП.

В этом разделе мы рассмотрим простейшее приложение в среде Windows, построенное средствами ООП, причем все классы будут оригинальными -- ни MFC, ни OWL не применяется. Это сделано для того, что бы “извлечь” на поверхность некоторые аспекты разработки классов для Windows-приложений. Здесь будут использоваться существенно упрощенные методы реализации объектов, по сравнению с “большими” библиотеками.

Возможно, что в некоторых частных случаях использование такого подхода может оказаться и более продуктивным, чем применение MFC или OWL. Особенно, если ваше приложение похоже на простейшее “Hello, world!” (в этом случае, правда, еще удобнее может быть обойтись совсем без классов).

Особенности ООП в Windows

На самом деле Windows не является настоящей объектно-ориентированной средой. Хотя окно и может быть названо объектом ООП, но лишь с достаточной натяжкой. Самое существенное отличие окна в Windows от объекта ООП заключается в том, что сообщение, обрабатываемое оконной функцией, во многих случаях не выполняет действий, а является “информационным”, указывая на то, что над окном выполняется та или иная операция какой-либо внешней функцией.

Поясним это на примере создания окна. В случае ООП для уничтожения объекта он должен получить сообщение “destroy”, обработка которого приведет к его уничтожению. В Windows сообщение WM_DESTROY не выполняет никаких функций по уничтожению окна. Оно только информирует окно о том, что в это время окно уничтожается средствами обычной функциональной библиотеки, например посредством функции DestroyWindow. Вы можете вообще игнорировать это сообщение, возвращать любое значение, вызывать или не вызывать функцию обработки по умолчанию -- окно все равно будет уничтожено.

С точки зрения реализации объектов это приводит к тому, что большая часть методов представлена в двух вариантах -- один вызывает соответствующую функцию API, а другой вызывается при обработке соответствующего сообщения. Так в случае функции DestroyWindow и сообщения WM_DESTROY для класса, представляющего окно, будет существовать два метода: метод Destroy и метод OnDestroy (названия методов условны, в реальных библиотеках они могут отличаться). Метод Destroy будет соответствовать вызову функции DestroyWindow, а метод OnDestroy -- обработчику сообщения WM_DESTROY.

На этом, к сожалению, сложности не кончаются. Допустим, что вы хотите сделать так, что бы окно не уничтожалось. На первый взгляд надо переопределить метод Destroy, что бы он не вызывал функцию DestroyWindow; при этом вызов метода Destroy не будет уничтожать окно. Однако все гораздо сложнее: окно по-прежнему может быть уничтожено прямым обращением к функции API -- DestroyWindow. Более того, стандартные обработчики сообщений (то есть принадлежащие Windows, а не библиотеке классов) так и делают. Так стандартная обработка сообщения WM_CLOSE приводит к вызову функции DestroyWindow (а не метода Destroy). То есть для решения подобной задачи надо переопределить все методы объекта и все обработчики сообщений, которые ссылаются на соответствующую функцию API. Задача фактически не решаемая -- особенно с учетом недостаточно подробной и точной документации.

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

Базовые классы приложения

Когда разрабатывается обычное приложение на C или C++ без использования классов, то надо разработать как функцию WinMain, определяющую работу приложения в целом, так и оконную процедуру, определяющую реакцию окна на внешние воздействия. При применении объектов эти функции возлагаются на методы классов. Естественно, что и в MFC, и в OWL существуют классы, предназначенные как для описания приложения в целом, так и для описания окон. Эти классы должны использоваться в качестве классов-предков, от которых порождаются классы, описывающие ваше приложение и его главное окно.

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

MFC
В библиотеке Microsoft Foundation Classes для описания приложения используются следующие классы:

Рисунок 5. Классы MFC, описывающие окно и приложение.

Данная версия MFC рассчитана на разработку многопотоковых приложений для Win32. Это наложило свой отпечаток на иерархию классов -- в качестве одного из базовых выступает класс CWinThread, описывающий отдельный поток. И только на его основе построен класс CWinApp, описывающий приложение (в Win32 существует понятие основного потока, который обслуживает функцию WinMain, именно он и будет представлен объектом класса CWinThread, на основе которого порождается объект класса CWinApp).

OWL
В этой библиотеке иерархия классов несколько иная -- библиотека рассчитана на разработку 16ти разрядных приложений Windows 3.x, не поддерживающую потоков.

Рисунок 6. Классы OWL, описывающие окно и приложение.

Окна ООП и окна Windows
При использовании библиотек классов надо как-то связывать экземпляры объектов, описывающих окна в приложении, с описанием того-же окна в Windows. Здесь надо учитывать, что, с одной стороны:

существуют методы классов, соответствующие вызову функций API;

существуют методы классов, соответствующие обработчикам сообщений;

а, с другой стороны:

существуют окна, созданные с помощью классов ООП;

существуют окна, созданные другими приложениями, модулями а также стандартными средствами Windows, не имеющими отношения к применяемой библиотеке.

Так, например, диалог “Открыть Файл” является стандартным диалогом Windows. Он создается и выполняется посредством вызова одной функции API -- FileOpen. Эта функция сама, независимо от приложения и его библиотеки классов, создает необходимые окна и работает с ними. Однако у программиста может возникнуть необходимость как-то взаимодействовать с этим диалогом в процессе его работы.

Можно выделить четыре возможных ситуации, с которыми придется столкнуться во время работы приложения:

должна быть вызвана функция API для окна, реализованного как объект класса;

должна быть вызвана функция API для окна, не являющегося объектом класса;

окно, реализованное как объект класса, получает сообщение -- то есть надо вызвать соответствующий метод-обработчик этого сообщения;

окно, не являющееся объектом класса, получает сообщение.

Случаи 1 и 2 решаются сравнительно просто -- среди членов-данных класса должен присутствовать член, задающий хендл окна в Windows. В таком случае вызов функций API, нуждающихся в хендле, происходи элементарно. Небольшой нюанс связан с окнами, не являющимися объектами класса. Например, диалоги, включая стандартные и их элементы управления -- кнопки, флажки и прочее, часто создаются как окна, принадлежащие Windows. То есть первоначально, в момент их создания, не существует объектов приложения, соответствующих этим окнам. Для этого в библиотеку вводятся средства создания объектов по хендлу. Эти средства могут несколько различаться в разных библиотеках.

Например метод CWnd* CWnd::FromHandle( HWND ), существующий в MFC, создает специальный объект, описывающий окно, связывает его с указанным хендлом и возвращает указатель на него. Этот объект считается “временным” -- спустя некоторое время MFC сама его уничтожит. В OWL аналогичного эффекта можно добиться используя специальную форму конструктора объекта TWindow.

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

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

находит связанное с данным хендлом окно -- для этого библиотеки классов поддерживают специальные таблицы соответствия хендлов окон описаниям этих окон в приложении

распределяет пришедшее сообщение соответствующему (обычно виртуальному) методу-обработчику этого сообщения.

Для задания методов-обработчиков конкретных сообщений вводятся специальные таблицы отклика или таблицы трансляции сообщений (response table, message map table). Когда вы разрабатываете новый класс окон, вы для него должны разработать такую таблицу, в которой должны быть указаны соответствия приходящих сообщений и вызываемых методов (конечно, если это не сделано в классе-предке).

Случай 4 вообще самый сложный -- в нормальных условиях библиотеки его не обрабатывают, так как для получения сообщений окна, не являющегося объектом класса, необходимо подменить процедуру обработки сообщений.

Это накладывает ограничения на применение методов-обработчиков сообщений -- для окон, не созданных как объекты класса, эти методы вызываться не будут. В случае MFC названия таких методов обычно начинаются на On..., например OnDestroy; а в случае OWL -- на Ev..., например EvDestroy. Часто можно так организовать приложение, что переопределять эти методы просто не потребуется, однако это не всегда удобно и возможно.

При необходимости как-либо изменить реакцию окна на внешние события (переопределить принятую обработку сообщений) надо, во-первых, создать соответствующий объект класса (как в случае 2). Во-вторых обычное окно, создаваемое Windows (например, какой-либо элемент управления диалогом -- кнопка, флажок и пр.) или другим приложением, использует собственную оконную процедуру. Эта процедура, естественно, никак не связана с библиотекой ООП, применяемой вашим приложением. Таким образом, при получении окном сообщений, вызывается только лишь его собственная оконная процедура, не обращающаяся к методам класса. То есть необходимо осуществить подмену оконной процедуры (в Windows это называется порождением подкласса окон -- subclass) с помощью специальных методов библиотек, выполняющих эту операцию: SubclassWindowFunction в OWL или SubclassWindow в MFC. После этого новая оконная функция будет обращаться к методам класса для обработки сообщений, а в качестве стандартной обработки будет использоваться та оконная функция, которая использовалась окном до ее подмены.

Однако при использовании этого приема необходимо учитывать следующие нюансы:

при создании объекта класса лучше использовать один из базовых классов (CWnd или TWindow), так как все порожденные от них классы переопределяют значительно большее число методов, предполагая стандартную обработку сообщений, реализованную в DefWindowProc, а не в той процедуре, которую вы подменили. Это может привести к конфликтам между новой обработкой событий и прежней оконной процедурой. Особенно опасна ошибка в назначении класса -- библиотека классов и компилятор никак не смогут проверить вас и предупредить, если вы, скажем, для кнопки, создадите объект класса “список” (LISTBOX). При такой ошибке конфликт практически неизбежен. В любом случае надо хорошо представлять себе, для какой стандартной оконной процедуры реализован какой класс библиотеки ООП и обработку каких сообщений он переопределяет, прежде чем решиться на подмену оконной процедуры.

в случае Win32 для окон, созданных другим приложением, оконные процедуры (используемая окном и назначаемая вами) размещается в различных адресных пространствах разных процессов. Обращение из другого процесса по новому адресу функции приведет, скорее всего, к ошибке -- так как этот адрес задан в адресном пространстве вашего приложения, а что находится в адресном пространстве другого процесса по этому адресу вам неизвестно. Решить эту проблему можно, выделяя описание объекта класса и его процедуры в отдельную DLL, а затем внедряя ее в адресное пространство процесса, создавшего окно. Однако этот прием существенно сложнее.

Пример 1C -- использование собственных классов

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

Коротко рассмотрим реализацию этого способа: вместо ведения таблиц соответствия хендлов объектам приложения можно хранить необходимые данные непосредственно в структуре описания окна в Windows (см. “Регистрация класса окон”). Так как доступ к этим данным осуществляется только с помощью функций, то размещать там все описание окна нецелесообразно, зато в этой структуре можно разместить указатель на связанный объект. Отсюда следует ограничение -- этот метод будет работать только с теми окнами, в структуре описания которых в Windows зарезервировано специальное поле для указателя. Это могут быть только окна, созданные нами.

Рисунок 7. Поиск метода-обработчика сообщения в примере.

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

Кроме того, для упрощения в примере остались некоторые следы обычного программирования -- осталась, хотя и сильно измененная, функция WinMain, в которой создается объект “приложение”.

Рассматриваемый пример состоит из 3х файлов: 1c.h -- общий заголовочный файл, содержащий описания базовых классов; 1c_cls.cpp -- методы и статические данные базовых классов; 1c_main.cpp -- собственно само приложение: описание собственных классов и их методов, а также функция WinMain.


Подобные документы

  • Основные выпуски (редакции) операционных систем Windows Vista и Windows Seven, их недостатки и преимущества. История создания, совместимость приложений с операционными системами. Новшества, которые принесла в мир компьютерных технологий каждая из систем.

    реферат [66,3 K], добавлен 17.02.2011

  • Основные понятия об операционных системах. Виды современных операционных систем. История развития операционных систем семейства Windows. Характеристики операционных систем семейства Windows. Новые функциональные возможности операционной системы Windows 7.

    курсовая работа [60,1 K], добавлен 18.02.2012

  • Назначение, классификация, состав и назначение компонентов операционных систем. Разработка сложных информационных систем, комплексов программ и отдельных приложений. Характеристика операционных систем Windows, Linux, Android, Solaris, Symbian OS и Mac OS.

    курсовая работа [2,1 M], добавлен 19.11.2014

  • Применение персональных компьютеров различных классов. Работа со встроенными программами Windows. Характеристика распространенных операционных систем (Windows 3.Х, 9Х, NT, 2000, XP, Windows7, Vista). Виды антивирусных программ и защита данных от вирусов.

    контрольная работа [32,3 K], добавлен 23.01.2011

  • История создания и общая характеристика операционных систем Windows Server 2003 и Red Hat Linux Enterprise 4. Особенности установки, файловых систем и сетевых инфраструктур данных операционных систем. Использование протокола Kerberos в Windows и Linux.

    дипломная работа [142,7 K], добавлен 23.06.2012

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

    курсовая работа [38,5 K], добавлен 08.05.2011

  • Общее понятие об оперативной системе Windows Vista. Сравнительный анализ систем Windows XP и Windows Vista. Специфика процесса установки, трехмерный интерфейс Aero Glass, действие некоторых мини-приложений. Новости управления папками, работа в интернете.

    реферат [2,4 M], добавлен 01.02.2010

  • Теоретические основы написания Windows-приложений с использованием библиотеки MFC. Основы программирования под Windows. Проектирование приложений в среде Microsoft Visual C++. Описание логической структуры приложения, его функциональное назначение.

    курсовая работа [1,3 M], добавлен 12.12.2011

  • Загрузка операционной системы Windows. Набор стандартных приложений, индикатор системных ресурсов и преобразование диска. Необходимость упаковщиков и функция "Архивация", таблица символов, графический редактор Paint и текстовый редактор WordPad.

    контрольная работа [355,9 K], добавлен 18.04.2009

  • Использование операционных систем Microsoft Windows. Разработка операционной системы Windows 1.0. Возможности и характеристика последующих версий. Выпуск пользовательских операционных систем компании, доработки и нововведения, версии Windows XP и Vista.

    реферат [23,3 K], добавлен 10.01.2012

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.