Docsity
Docsity

Подготовься к экзаменам
Подготовься к экзаменам

Учись благодаря многочисленным ресурсам, которые есть на Docsity


Получи баллы для скачивания
Получи баллы для скачивания

Заработай баллы, помогая другим студентам, или приобретай их по тарифом Премиум


Руководства и советы
Руководства и советы

Механизмы параллельных вычислений в Windows. Разработка справочной системы курсовая по программированию и компьютерам , Дипломная из Программирование

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

Вид: Дипломная

2016/2017

Загружен 11.04.2017

refbank12820
refbank12820 🇷🇺

5

(3)

27 документы

1 / 36

Toggle sidebar

Сопутствующие документы


Частичный предварительный просмотр текста

Скачай Механизмы параллельных вычислений в Windows. Разработка справочной системы курсовая по программированию и компьютерам и еще Дипломная в формате PDF Программирование только на Docsity! МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ УКРАИНЫ ХАРЬКОВСКИЙ ГОСУДАРСТВЕННЫЙ ЭКОНОМИЧЕСКИЙ УНИВЕРСИТЕТ Кафедра информационных систем Курсовой проект по дисциплине “Системное программирование и операционные системы” на тему: “ Механизмы параллельных вычислений в Windows. Разработка справочной системы” Выполнила: студентка 2 курса группы 401-2 факультета ЭИ Nils Проверил: доцент кафедры информационных систем к.т.н. Голубничий Дмитрий Юрьевич Харьков 2005 МИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ УКРАИНЫ ХАРЬКОВСКИЙ ГОСУДАРСТВЕННЫЙ ЭКОНОМИЧЕСКИЙ УНИВЕРСИТЕТ Кафедра информационных систем Дисциплина “Системное программирование и операционные системы” Специальность 8.080401-2 ЗАДАНИЕ на курсовой проект студента NILS 1. Тема проекта: “Механизмы параллельных вычислений в Windows. Разработка справочной системы” 2. Срок сдачи законченного проекта: 1.06.2005 3. Исходные данные к проекту: Разработать приложение, в котором пользователем осуществляется в диалоговом окне выбор произвольных графических примитивов (не менее 12), а также их комбинаций. Обеспечить возможность добавления/удаления примитивов из списка. После выбора осуществляется их прорисовка в клиентской области. Щелчок правой кнопки по рисунку выводит справку-описание в формате WINHELP по функциям API, использованным для создания выбранного объекта. 4. Содержание расчетно-пояснительной записки: ВВЕДЕНИЕ. 1. МЕХАНИЗМЫ ПАРАЛЛЕЛЬНЫХ ВЫЧИСЛЕНИЙ В WINDOWS. 2. РАЗРАБОТКА СПРАВОЧНОЙ СИСТЕМЫ. ВЫВОД 5. Перечень графического материала: Схема алгоритма. 6. Дата выдачи задания: 6.09.2004 РЕФЕРАТ Сведения о проекте: 39с., 2 рис., 7 источников, 2 приложения. реализующим типовые нейрооперации (взвешенное суммирование и нелинейное преобразование). Нейросетевые системы, реализованные в виде плат расширения стандартных вычислительных систем, будем называть нейроускорителями (взвешенное суммирование, как правило, реализуется аппаратно, например, на основе трансверсальных фильтров, а нелинейные преобразования — программно). Системы, реализованные в виде функционально законченных специализированных вычислительных устройств, следует относить к нейрокомпьютерам. Нейрокомпьютеры являются вычислительными системами с высоким параллелизмом, реализуемым на основе специализированной элементной базы, ориентированной на выполнение нейросетевых операций в нейросетевом логическом базисе. Эффективное применение нейрокомпьютеров характерно, в частности, для случаев, требующих резкого сокращения времени обработки при решении пространственных задач повышенной размерности, которые во множестве можно найти практически в любой области: обработка изображений, выделение и слежение за движущимися объектами, задачи распознавания и классификации. 1.1. Особенности организации параллельных вычислений При параллельных вычислениях необходимо программировать специальные действия по координации работы задач, а также следует четко определить "область деятельности" для каждой задачи. Рассмотрим здесь несколько возможных подходов для решения этих проблем. При первом варианте организации параллельных вычислений все задачи запускаются одной командой, в которой указывается имя запускаемого исполняемого файла, число запускаемых задач, а также число и тип используемых процессоров. По этой команде запускаются на указанных процессорах требуемое число копий указанного исполняемого файла. Следовательно, программные коды всех запущенных в PVM задач в данном случае одинаковы. Для того чтобы эти задачи могли выполнять разные действия, им должен быть известен признак, отличающий каждую задачу от остальных. Тогда, используя этот признак в условных операторах, легко запрограммировать выполнение задачами разных действий. Наличие такого признака предусмотрено в любой многозадачной операционной системе. Это так называемый идентификатор задачи - целое число, которое присваивается задаче при запуске. Существенно, что при запуске задача получает идентификатор, отличный от идентификаторов задач, выполняемых в данное время. Это гарантирует, что идентификаторы всех запущенных задач в PVM будут различными. Если теперь обеспечить задачи возможностью определять собственный идентификатор и обмениваться информацией с другими задачами, то ясно, что им легко распределить между собой вычислительную работу, в зависимости, например, от занимаемого места в упорядоченном наборе идентификаторов задач. Во втором обычно используемом варианте запуска задач сначала запускается одна задача (master), которая в коллективе задач будет играть функции координатора работ. Эта задача производит некоторые подготовительные действия, после чего запускает остальные задачи (slaves), которым может соответствовать либо тот же исполняемый файл, либо разные исполняемые файлы. Такой вариант организации параллельных вычислений предпочтительнее при усложнении логики управления вычислительным процессом, а также когда алгоритмы, реализованные в разных задачах, существенно различаются или имеется большой объем операций (например, ввода - вывода), которые обслуживают вычислительный процесс в целом. 1.1.1. Оптимизация параллельных вычислений Главным критерием качества распараллеливания вычислений является сокращение общего времени решения задачи. Для простоты в качестве задач будем рассматривать здесь вычисления по формулам, в которых все алгебраические операции выполняются за одинаковое время T, а используемые процессоры все имеют одинаковые характеристики. Пусть требуется вычислить величины Y1 = A * B + C * D Y2 = (A + B) * C + D. При использовании одного процессора Y1 и Y2 будут вычислены за одинаковое время 3T. При использовании двух процессоров Y1 может быть вычислено за время 2T, т.к. операции умножения могут быть выполнены параллельно. А вычисление Y2 не может быть ускорено, т.к. сама формула не допускает параллельного выполнения операций. Из рассмотренного примера следует, что возможности для распараллеливания вычислений ограничиваются не только числом имеющихся процессоров, но и особенностями вычислительного алгоритма, который может вообще не допускать распараллеливания. Кроме того, ясно, что предельный эффект от использования N процессоров может быть достигнут лишь тогда, когда общая вычислительная нагрузка может быть разделена точно на N частей, и при этом ни один из процессоров не простаивает от начала и до конца вычислений. Теперь обратим внимание на то, что в рассмотренном примере были проигнорированы затраты времени на пересылки данных между процессорами. Это отчасти правомерно, если процессоры используют общую память (следует отметить, что все процессоры имеют индивидуальную регистровую память гораздо более быстродействующую, чем ОЗУ). Если же процессоры работают с данными, хранящимися в индивидуальных ОЗУ, то обмен данными между этими ОЗУ снижает эффект от распараллеливания вычислений вплоть до того, что этот эффект может стать отрицательным. Отсюда следует, что при оптимизации распараллеливания вычислений нужно учитывать время, затрачиваемое на обмен данными между процессорами. И вообще при прочих равных условиях уменьшение числа и объемов сообщений, которыми обмениваются параллельно работающие процессоры, как правило, приводит к сокращению общего времени решения задачи. Поэтому желательно распараллеливать вычислительный процесс на уровне как можно более крупных блоков алгоритма. До сих пор мы рассматривали вычисления, производимые над одной порцией исходных данных. При этом распараллеливание базируется на декомпозиции алгоритма вычислений. Более богатые возможности для распараллеливания открываются при многократном использовании формулы для потока входных данных. При этом, как правило, удается достичь максимального эффекта от распараллеливания вычислений, что видно на примере вычислений по формулам для Y1 и Y2. Пусть каждые T секунд для вычисления очередного значения Y1 поступает новая порция исходных данных: A, B, C, D - и каждые T секунд процессор 1 и процессор 2 параллельно выполняют операции умножения, а процессор 3 в это время складывает произведения, полученные в предыдущие T секунд. Очевидно, что с увеличением массива исходных данных эффект от распараллеливания стремится к предельному значению. Более того, почти такой же эффект получается при вычислении Y2. Правда, здесь каждая порция исходных данных будет преобразовываться в результат уже в течение 3T секунд, зато в работе одновременно будут находиться не 2, а 3 порции исходных данных. Распараллеливание вычислений по потоку данных лежит в основе так называемых конвейерных вычислений и часто позволяет добиться большего эффекта, чем распараллеливание, основанное на декомпозиции алгоритма. Поэтому там, где это возможно, его желательно использовать в первую очередь. 1.2. Модели параллельных вычислений Параллельное программирование представляет дополнительные источники сложности - необходимо явно управлять работой тысяч процессоров, координировать миллионы межпроцессорных взаимодействий. Для того решить задачу на параллельном компьютере, необходимо распределить вычисления между процессорами системы, так чтобы каждый процессор был занят решением части задачи. Кроме того, желательно, чтобы как можно меньший объем данных пересылался между процессорами, поскольку коммуникации значительно больше медленные операции, чем вычисления. Часто, возникают конфликты между степенью распараллеливания и объемом коммуникаций, то есть чем между большим числом процессоров распределена задача, тем больший объем данных необходимо пересылать между ними. Среда параллельного программирования должна обеспечивать адекватное управление распределением и коммуникациями данных. Из-за сложности параллельных компьютеров и их существенного отличия от традиционных однопроцессорных компьютеров нельзя просто воспользоваться традиционными языками программирования и ожидать при реализации таких систем приходится принимать какое-либо решение в этом отношении. В таких системах каждый процесс выполняет одну и ту же программу (параметризованную относительно идентификатора либо процесса, либо процессора), но работает с разными данными, поэтому о таких системах говорят, что они реализуют SPMD (single program multiple data - одна программа много данных) модель программирования. SPMD модель приемлема и достаточно удобна для широкого диапазона приложений параллельного программирования, но она затрудняет разработку некоторых типов параллельных алгоритмов. 1.2.3. Модель параллелизм данных Модель параллелизм данных также является часто используемой моделью параллельного программирования. Название модели происходит оттого, что она эксплуатирует параллелизм, который заключается в применении одной и той же операции к множеству элементов структур данных. Например, "умножить все элементы массива M на значение x", или "снизить цену автомобилей со сроком эксплуатации более 5-ти лет". Программа с параллелизмом данных состоит из последовательностей подобных операций. Поскольку операции над каждым элементом данных можно рассматривать как независимые процессы, то степень детализации таких вычислений очень велика, а понятие "локальности" (распределения по процессам) данных отсутствует. Следовательно, компиляторы языков с параллелизмом данных часто требуют, чтобы программист предоставил информацию относительно того, как данные должны быть распределены между процессорами, другими словами, как программа должны быть разбита на процессы. Компилятор транслирует программу с параллелизмом данных в SPMD программу, генерируя коммуникационный код автоматически. 1.2.4. Модель общая память В модели программирования с общей памяти, все процессы совместно используют общее адресное пространство, к которому они асинхронно обращаются с запросами на чтение и запись. В таких моделях для управления доступом к общей памяти используются всевозможные механизмы синхронизации типа семафоров и блокировок процессов. Преимущество этой модели с точки зрения программирования состоит в том, что понятие собственности данных (монопольного владения данными) отсутствует, следовательно, не нужно явно задавать обмен данными между производителями и потребителями. Эта модель, с одной стороны, упрощает разработку программы, но, с другой стороны, затрудняет понимание и управление локальностью данных, написание детерминированных программ. В основном эта модель используется при программировании для архитектур с общедоступной памятью. 1.3. Система параллельного программирования Linda Идея построения системы Linda исключительно проста, а потому красива и очень привлекательна. Параллельная программа есть множество параллельных процессов, и каждый процесс работает согласно обычной последовательной программе. Все процессы имеют доступ к общей памяти, единицей хранения в которой является кортеж. Отсюда происходит и специальное название для общей памяти - пространство кортежей. Каждый кортеж это упорядоченная последовательность значений. Например, ( "Hello", 42, 3.14 ), ( "P", 5, FALSE, 97, 1024, 2), ( "worker", 5 ) . Первый элемент кортежа всегда является символьной строкой и выступает в роли имени кортежа. Так первый кортеж предыдущего примера состоит из имени ("Hello"), элемента целого типа (42) и вещественного числа (3.14). Во втором кортеже кроме имени "P" есть элемент целого типа (5), элемент логического типа (FALSE) и три целых числа. Последний кортеж состоит из двух элементов: имени ("worker") и целого числа (5). Количество элементов в кортеже может быть любым. Все процессы работают с пространством кортежей по принципу: поместить кортеж, забрать, скопировать. В отличие от традиционной памяти, процесс может забрать кортеж из пространства кортежей, после чего данный кортеж станет недоступным остальным процессам. В отличие от традиционной памяти, если в пространство кортежей положить два кортежа с одним и тем же именем, то не произойдет привычного для нас "обновления" значения переменной - в пространстве кортежей окажется два кортежа с одним и тем же именем. В отличие от традиционной памяти, изменить кортеж непосредственно в пространстве нельзя. Для изменения значений элементов кортежа, его нужно сначала оттуда изъять, затем процесс, изъявший кортеж, может изменить значения его элементов и вновь добавить измененный кортеж в память. В отличие от других систем программирования, процессы в системе Linda никогда не взаимодействуют друг с другом явно, и все общение всегда идет через пространство кортежей. Интересно, что с точки зрения системы Linda в любой последовательный язык достаточно добавить лишь четыре новые функции, как он становится средством параллельного программирования! Эти функции и составляют систему Linda: три для операций над кортежами и пространством кортежей и одна функция для порождения параллельных процессов. Для определенности, дальнейшее обсуждение системы и ее функций будем вести с использованием языка С. Функция OUT помещает кортеж в пространство кортежей. Например, out ( "GoProcess", 5); помещает в пространство кортежей кортеж ("GoProcess", 5). Если такой кортеж уже есть в пространстве кортежей, то появится второй, что, в принципе, позволяет иметь сколь угодно много экземпляров одинаковых кортежей. По этой же причине с помощью функции out нельзя изменить кортеж, уже находящийся в пространстве. Для этого кортеж должен быть сначала оттуда изъят, затем изменен и после этого помещен назад. Функция out никогда не блокирует выполнивший ее процесс. Функция IN ищет подходящий кортеж в пространстве кортежей, присваивает значения его элементов элементам своего параметра-кортежа и удаляет найденный кортеж из пространства кортежей. Например, in( "P", int i, FALSE ); Этой функции соответствует любой кортеж, который состоит из трех элементов: значением первого элемента является "P", второй элемент может быть любым целым числом, а третий должен иметь значение FALSE. Подходящими кортежами могут быть ( "P", 5, FALSE) или ( "P", 135, FALSE) и т.п., но не ( "P", 7.2, FALSE) или ( "Proc", 5, FALSE). Если параметру функции in соответствуют несколько кортежей, то случайным образом выбирается один из них. После нахождения кортеж удаляется из пространства кортежей, а неопределенным формальным элементам параметра-кортежа, содержащимся в вызове данной функции, присваиваются соответствующие значения. В предыдущем примере переменной i присвоится 5 или 135. Если в пространстве кортежей ни один кортеж не соответствуют функции, то вызвавший ее процесс блокируется до тех пор, пока соответствующий кортеж в пространстве не появится. Элемент кортежа в функции in считается формальным, если перед ним стоит определитель типа. Если используется переменная без определителя типа, то берется ее значение и элемент рассматривается как фактический параметр. Например, во фрагменте программы int i = 5; in( "P", i, FALSE ); функции in, в отличие от предыдущего примера, соответствует только кортеж ("P", 5, FALSE). Если переменная описана до вызова функции и ее надо использовать как формальный элемент кортежа, можно использовать ключевое слово formal или знак '?'. Например, во фрагменте программы j = 15; in( "P", formal i, j ); последнюю строку можно заменить и на оператор in("P", ?i, j). В этом примере функции in будет соответствовать, например, кортеж ("P", 6, 15), но не программы. И, наконец, для вычисления элемента Cij каждый процесс get_elem_result выполнит следующий фрагмент: read( "A", Nrow, formal row); read( "B", Ncol, formal col); out( "result", Nrow, Ncol, DotProduct(row,col) ); где DotProduct это функция, реализующая скалярное произведение. Таким образом, каждый элемент произведения окажется в отдельном кортеже в пространстве кортежей. Завершающий процесс соберет результат, поместив их в соответствующие элементы матрицы C: for ( irow = 0; irow < N; irow++) for ( icol = 0; icol < N; icol++) in( "result", irow + 1, icol + 1, formal C[irow][icol]); Не имея в системе Linda никаких явных средств для синхронизации процессов, совсем не сложно их смоделировать самому. Предположим, что в некоторой точке нужно выполнить барьерную синхронизацию N процессов. Какой-то один процесс, например, стартовый, заранее помещает в пространство кортеж ("ForBarrier", N). Подходя к точке синхронизации, каждый процесс выполняет следующий фрагмент, который и будет выполнять функции барьера: in( "ForBarrier", formal Bar); Bar = Bar - 1; if( Bar != 0 ) { out( "ForBarrier", Bar); read( "Barrier" ); } else out( "Barrier" ); Если кортеж с именем "ForBarrier" есть в пространстве, то процесс его изымает, в противном случае блокируется до его появления. Анализируя второй элемент данного кортежа, процесс выполняет одно из двух действий. Если есть процессы, которые еще не дошли до данной точки, то он возвращает кортеж в пространство с уменьшенным на единицу вторым элементом и встает на ожидание кортежа "Barrier". В противном случае он сам помещает кортеж "Barrier" в пространство, который для всех является сигналом к продолжению работы. В целом, сильные и слабые стороны системы Linda понятны. Простота и стройность концепции системы является основным козырем, однако эти же факторы оборачивается большой проблемой на практике. Если вычислительная система обладает распределенной памятью, то общение процессов через пространство кортежей заведомо будет сопровождаться большими накладными расходами. РАЗДЕЛ 2 РАЗРАБОТКА СПРАВОЧНОЙ СИСТЕМЫ В этом разделе курсового проекта рассматривается прорисовка графических примитивов и вывод справки по функциям API, использованным для создания этого объекта. 2.1. Вызов справки Вызов справки не должен вызвать затруднений, в связи с тем, что файл справки уже создан и вызывается при нажатии правой кнопки мыши. Для вызова справки используется следующие операторы: GetCurrentDirectory(256,buf); strcat(buf,"/help/Shapes.hlp"); WinHelp(hDlg,buf,HELP_CONTENTS,0); Рассмотрим более подробно синтаксис и назначение функций. Функция GetCurrentDirectory(nBufferLength: DWORD; lpBuffer: PChar): DWORD возвращает текущий каталог. Обычно это каталог в котором была запущена программа. Параметры: nBufferLength - размер буфера для принимаемой строки lpBuffer - принимый путь Возвращаемое значение: В случае успеха строка, содержащая путь, в случае неуспеха 0. Получить дополнительную информацию об ошибке исполнения можно с помощью функции GetLastError. Функция находится в файле kernel32.dll Функция strcat(buf,"/help/Shapes.hlp") копирует строку "/help/Shapes.hlp" в переменную типа char c именем buf. Функция WindHelp(Wnd: HWnd; HelpFile: PChar; Command: Word; Data: Longint) вызывает механизм Windows получения спpавочной инфоpмации с командой Command. Паpаметpы: Wnd: Идентификатор окна. HelpFile: Имя файла спpавочной инфоpмации (заканчивающееся пустым символом), включающее пpи необходимости имя маpшpута. Command: Одна из команд help_Context, help_HelpOnHelp, help_Index, help_Key, help_Quit или help_SetIndex. Data: Номеp идентификатора контекста, если Command имеет значение help_Context, или ключевое слово спpавочной темы (заканчивающееся пустым символом), если Command имеет значение help_Key. Возвращаемое значение: Не нуль в случае успешного завершения; 0 - в противном случае. 2.1. Рисование графических примитивов 0 0 1 FПри рисовании линий активно используют значение текущей пози ции пера. Чтобы узнать текущую позицию пера, вызывают функцию GetCurrentPositionEx: BOOL GetCurrentPositionEx( HDC hdc, LPPOINT IpPoint); Параметр IpPoint указывает на структуру типа POINT, 0 01 Fв которую бу дут 0 0 1 Fзаписаны логические координаты текущей позиции. В случае ус пешного выполнения функция возвращает ненулевое значение. Чтобы нарисовать прямую линию, вызывают функцию LineTo: BOOL LineTo( HDC hdc, int x, int у); В случае успешного выполнения функция LineTo 0 01 Fрисует прямую ли нию из текущей позиции до (но, не включая ее) точки с координатами (х, у). При этом текущая позиция переносится в точку (х, у), а возвращаемое значение отлично от нуля. Для рисования прямой используются текущие установки пера и, если прерывистая линия, текущие установки кисти фона вывода. При рисовании прямых линий часто приходится сначала перемещать текущую позицию в начало рисуемой прямой и, только затем, вызывать функцию LineTo. Во избежание такой "сложности" описывают функцию следующего вида: BOOL DrawLine( HDC hdc, int xO, int yO, int x, int y) { POINT pt; MoveToEx (hdc, xO, yO, &pt); return LineTo (hdc, x, y); } Эта функция рисует прямую, начиная от точки (хО, уО), до точки (х, у) и переносит текущую позицию в точку (х, у). Для рисования эллипса используют функцию Ellipse: BOOL Ellipse( HOC hdc, int I, int t, int r, int b); Параметры функции Ellipse идентичны первым пяти параметрам функции Arc 0 01 F. В случае успешного выполнения функция возвращает не нулевое значение. Функция игнорирует текущую позицию. Сегмент эллипса рисуют при помощи функции Chord: BOOL Chord(HDC hdc, int I, int t, int r, int b, int xO, int yO, int x, int у); Параметры этой функции аналогичны параметрам функции Arc. В отличие от функции Arc, функция Chord соединяет хордой точки начала и конца дуги эллипса и закрашивает выделенный таким образом сегмент 0 0 1 Fтекущей кистью. В случае успешного выполнения функция воз вращает ненулевое значение. Функция игнорирует текущую позицию. Функция RoundRect рисует прямоугольник с закругленными углами: BOOL RoundRect( HOC hdc, int I, int t, int r, int b, int w, int h); 0 0 1 FПервые 5 параметров этой функции совпадают с параметрами функ ции Rectangle. А параметры w и h 0 01 Fзадают соответственно ширину и вы соту эллипса, дуги которого закругляют углы прямоугольника. В случае успешного 0 0 1 Fвыполнения функция возвращает ненулевое значение. Функ ция игнорирует текущую позицию. СПИСОК ИСПОЛЬЗУЕМЫХ ИСТОЧНИКОВ 1. Саймон Р. Windows 2000 API. Энциклопедия программиста. – К.: ООО "ДиасофтЮП", 2002. – 1085 с. 2. http://parallel.ru/vvv/lec7.html 3. http://www.ccas.ru/paral/prog/comm_msg/intro.html 5. http://osp.admin.tomsk.ru/os/index.htm 6. http://www.csa.ru/~il/pvm_tutor/ 7. MSDN ПРИЛОЖЕНИЕ А ЛИСТИНГ ПРОГРАММЫ //Файл Shapes.cpp #define STRICT #include <windows.h> #pragma hdrstop #include <string.h> #include <windowsx.h> #include "shapes.h" char szAppName[10]; // name of application HINSTANCE hInst; // hInstance of application HWND hWndMain; // hWnd of main window HWND hQryDlgBox; // handle of modeless dialog box HWND hDlgSelect; HGLOBAL hdlgr; // handle of dialog resource FARPROC lpModelessProc; // pointer to proc for modeless box HDC hdc; PAINTSTRUCT ps; HMENU hMenu, hMenuFile, hMenuAvt; bool flag = false; int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int cmdShow); void InitMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int cmdShow); LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); void InitMainDlg(HWND hWnd); BOOL CALLBACK MainDlgBoxProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK Select(HWND, UINT, WPARAM, LPARAM); // диалог выбора фигур void fillb(HWND hDlg, int ID); void PaintShapes(HWND hDlg); //--------------------------------------------------------------------- int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int cmdShow) { MSG msg; // Go init this application. InitMain(hInstance, hPrevInstance, lpszCmdLine, cmdShow); // Get and dispatch messages for this applicaton. while (GetMessage(&msg, NULL, 0, 0)) { if(!hQryDlgBox || !IsWindow(hQryDlgBox) || !IsDialogMessage( hQryDlgBox, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return(msg.wParam); } void InitMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int cmdShow) { WNDCLASS wcMainClass; // Get string from resource with application name. LoadString(hInstance, IDS_NAME, (LPSTR)szAppName, 10); // Define the window class for this application. wcMainClass.lpszClassName = szAppName; wcMainClass.hInstance = hInstance; wcMainClass.lpfnWndProc = MainWndProc; wcMainClass.hCursor = LoadCursor(NULL, IDC_ARROW); wcMainClass.hIcon = LoadIcon(hInstance, szAppName); wcMainClass.lpszMenuName = (LPSTR) NULL; wcMainClass.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE);//GetStockObject (WHITE_BRUSH); wcMainClass.style = CS_HREDRAW | CS_VREDRAW; wcMainClass.cbClsExtra = 0; wcMainClass.cbWndExtra = 0; // Register the class RegisterClass(&wcMainClass); hInst = hInstance; // save for use by window procs // Create applications main window. hWndMain = CreateWindow( szAppName, szAppName, WS_BORDER | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, 10, 19, 256, 123, NULL, NULL, hInstance, NULL ); // Create a thunk for the main dialog box proc function. lpModelessProc = MakeProcInstance((FARPROC)MainDlgBoxProc, hInst); InitMainDlg(hWndMain); } //******************************************************************* // MainWndProc - handles messages for this application // dltp = (DLGTEMPLATE FAR *) LockResource(hdlgr); if (dltp) { // Change the number of items to display. The drive boxes are // defined last so we can truncate the ones not needed. // make a temporary copy of dialog template tempDlgPtr = (DLGTEMPLATE*) malloc((size_t)SizeofResource(hInst, resourceHndl)); #if defined(__FLAT__) memcpy((void *)tempDlgPtr, (const void *)dltp, (size_t)SizeofResource (hInst, resourceHndl)); #else _fmemcpy((void FAR *)tempDlgPtr, (const void FAR *)dltp, (size_t)SizeofResource(hInst, resourceHndl)); #endif CreateDialogIndirect(hInst, (DLGPTR)tempDlgPtr, hWnd, (DLGPROC)lpModelessProc); // free tempory copy of dialog template free(tempDlgPtr); // Unlock dialog resource we locked above. #if !defined(__FLAT__) UnlockResource(hdlgr); #endif // Free it. FreeResource(hdlgr); // Zero handle to it. hdlgr = 0; } } } //******************************************************************* // MainDlgBoxProc - handle Main dialog messages (modeless) // // This is a modeless dialog box procedure that controls this // entire application. // // paramaters: // hDlg - The window handle for this message // message - The message number // wParam - The WPARAM parameter for this message // lParam - The LPARAM parameter for this message // //******************************************************************* #pragma argsused BOOL CALLBACK MainDlgBoxProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { // static HWND hlistwnd; static RECT wrect; int index[27]; char buf[256]; int x, y, w, h, i; switch (message) { case WM_INITDIALOG: // Save the handle of this proc for use by main window proc. hQryDlgBox = hDlg; // Get position of dialog box window. GetWindowRect(hDlg, (LPRECT) &wrect); w = wrect.right - wrect.left; h = wrect.bottom - wrect.top; // Move main application window to same position. SetWindowPos(hWndMain, hDlg, wrect.left, wrect.top, w, h, 0); hMenuAvt=CreatePopupMenu(); AppendMenu(hMenuAvt,MF_ENABLED|MF_STRING,IDM_ABOUT, "&About"); hMenuFile=CreatePopupMenu(); AppendMenu(hMenuFile,MF_ENABLED|MF_STRING,IDM_EXIT, "&Выход"); hMenu = CreateMenu(); AppendMenu(hMenu, MF_ENABLED|MF_POPUP, (UINT) hMenuFile, "&Файл"); AppendMenu(hMenu, MF_ENABLED|MF_POPUP, (UINT) hMenuAvt, "&О программе"); SetMenu(hDlg, hMenu); break; case WM_MOVE: // Always keep this dialog box on top of main window. GetWindowRect(hWndMain, (LPRECT) &wrect); x = wrect.left; y = wrect.top; w = wrect.right - wrect.left; h = wrect.bottom - wrect.top; MoveWindow(hDlg, x, y, w, h, 1); break; case WM_SYSCOMMAND: // Pass WM_SYSCOMMAND messages on to main window so both // main window and dialog box get iconized, minimized etc. // in parallel. SendMessage(hWndMain, message, wParam, lParam); break; case WM_RBUTTONUP: if(flag) if(LOWORD(lParam)>290 && LOWORD(lParam)<410 && HIWORD(lParam)> 90 && HIWORD (lParam)<210){ GetCurrentDirectory(256,buf); strcat(buf,"/help/Shapes.hlp"); WinHelp(hDlg,buf,HELP_CONTENTS,0); }; break; case WM_COMMAND: switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDC_OK3: ShowWindow(hDlg,SW_HIDE); ShowWindow(hDlg,SW_SHOW); break; case IDM_EXIT: PostMessage(hWndMain, WM_CLOSE, 0, 0L); // Destroy ourseleves. DestroyWindow(hDlg); break; case IDM_ABOUT: DialogBox(hInst, (LPCTSTR)IDD_ABOUT, hDlg, (DLGPROC)About); break; case IDC_SELECT: DialogBox(hInst, (LPCTSTR)IDD_SELECT, hDlg, (DLGPROC)Select); break; default: break; } break; case WM_PAINT: hdc = BeginPaint(hDlg, &ps); // TODO: Add any drawing code here... RECT rt; GetClientRect(hDlg, &rt); //--------------------------------------- PaintShapes(hDlg); //-------------------------------- EndPaint(hDlg, &ps); break; case WM_CLOSE: // Unlock dialog resource we locked above. #if !defined(__FLAT__) UnlockResource(hdlgr); #endif // Free it. FreeResource(hdlgr); // Zero handle to it. hdlgr = 0; // Zero handle to this dialog window. hQryDlgBox = 0; // Tell main window to close. PostMessage(hWndMain, WM_CLOSE, 0, 0L); // Destroy ourseleves. DestroyWindow(hDlg); break; default: return FALSE; } return(TRUE); } const int x = 350; const int y = 150; int index[27]; char buf[256]; static COLORREF cr=RGB(200,200,200 );//цвет фона HPEN hPen, hPenOld; //перо LOGBRUSH lb; HBRUSH hBrush; //кисть HBRUSH hOldBrush; //создание контекста lb.lbStyle=PS_SOLID; lb.lbColor=RGB(255,0,0); //создание пера hPen=ExtCreatePen(PS_GEOMETRIC | PS_SOLID,1,&lb,0,NULL); hPenOld=HPEN(SelectObject(hdc,hPen)); //создание кисти hBrush=CreateSolidBrush(cr); hOldBrush=HBRUSH(SelectObject(hdc,hBrush)); flag = false; SendDlgItemMessage(hDlg, IDC_LISTBOX1, LB_GETSELITEMS, (WPARAM) 27, (LPARAM) (LPINT) index); for(int i=0;i<SendDlgItemMessage(hDlg, IDC_LISTBOX1,LB_GETSELCOUNT,0,0);i++){ SendDlgItemMessage(hDlg, IDC_LISTBOX1, LB_GETTEXT, (WPARAM) index[i], (LPARAM) (LPCTSTR) buf); if(strcmp(buf,"горизонтальная линия") == 0){ MoveToEx(hdc, x-50, y, NULL); LineTo(hdc, x+50, y); flag = true; }; if(strcmp(buf,"квадрат") == 0){ MoveToEx(hdc, x-50, y-50, NULL); LineTo(hdc, x+50, y-50); LineTo(hdc, x+50, y+50); LineTo(hdc, x-50, y+50); LineTo(hdc, x-50, y-50); flag = true; }; if(strcmp(buf,"шестиугольник") == 0){ MoveToEx(hdc,x-50,y,NULL); LineTo(hdc,x-25,y-50); LineTo(hdc,x+25,y-50); LineTo(hdc,x+50,y); LineTo(hdc,x+25,y+50); LineTo(hdc,x-25,y+50); LineTo(hdc,x-50,y); flag = true; }; if(strcmp(buf,"восьмиугольник") == 0){ MoveToEx(hdc,x-50,y-25,NULL); LineTo(hdc,x-25,y-50); LineTo(hdc,x+25,y-50); LineTo(hdc,x+50,y-25); LineTo(hdc,x+50,y+25); LineTo(hdc,x+25,y+50); LineTo(hdc,x-25,y+50); LineTo(hdc,x-50,y+25); LineTo(hdc,x-50,y-25); flag = true; }; if(strcmp(buf,"крест") == 0){ MoveToEx(hdc,x,y-50,NULL); LineTo(hdc,x,y+50); MoveToEx(hdc,x-50,y,NULL); LineTo(hdc,x+50,y); flag = true; }; if(strcmp(buf,"Х") == 0){ MoveToEx(hdc,x-50,y-50,NULL); LineTo(hdc,x+50,y+50); MoveToEx(hdc,x-50,y+50,NULL); LineTo(hdc,x+50,y-50); flag = true; }; if(strcmp(buf,"вертикальная линия") == 0){ MoveToEx(hdc, x, y-50, NULL); LineTo(hdc, x, y+50); flag = true; }; if(strcmp(buf,"ромб") == 0){ MoveToEx(hdc,x-50,y,NULL); LineTo(hdc,x,y-50); LineTo(hdc,x+50,y); LineTo(hdc,x,y+50); LineTo(hdc,x-50,y); flag = true; }; if(strcmp(buf,"Т") == 0){ MoveToEx(hdc,x-50,y-50,NULL); LineTo(hdc,x+50,y-50); MoveToEx(hdc,x,y-50,NULL); LineTo(hdc,x,y+50); flag = true; }; if(strcmp(buf,"_|_") == 0){ MoveToEx(hdc,x-50,y+50,NULL); LineTo(hdc,x+50,y+50); MoveToEx(hdc,x,y-50,NULL); LineTo(hdc,x,y+50); flag = true; }; if(strcmp(buf,"Н") == 0){ MoveToEx(hdc,x-50,y-50,NULL); LineTo(hdc,x-50,y+50); MoveToEx(hdc,x-50,y,NULL); LineTo(hdc,x+50,y); MoveToEx(hdc,x+50,y-50,NULL); LineTo(hdc,x+50,y+50); flag = true; }; if(strcmp(buf,"стрелка вверх") == 0){ MoveToEx(hdc,x-50,y,NULL); LineTo(hdc,x,y-50); LineTo(hdc,x+50,y); MoveToEx(hdc,x,y-50,NULL); LineTo(hdc,x,y+50); flag = true; }; if(strcmp(buf,"стрелка вниз") == 0){ MoveToEx(hdc,x-50,y,NULL); LineTo(hdc,x,y+50); LineTo(hdc,x+50,y); MoveToEx(hdc,x,y-50,NULL); LineTo(hdc,x,y+50); flag = true; }; if(strcmp(buf,"треугольник") == 0){ MoveToEx(hdc,x,y-50,NULL); LineTo(hdc,x+50,y+50); LineTo(hdc,x-50,y+50); LineTo(hdc,x,y-50); flag = true; }; if(strcmp(buf,"нижний левый прямоугольный треугольник") == 0){ MoveToEx(hdc,x-50,y-50,NULL); LineTo(hdc,x-50,y+50); LineTo(hdc,x,y+50); LineTo(hdc,x-50,y-50); flag = true; }; if(strcmp(buf,"нижний правый прямоугольный треугольник") == 0){ MoveToEx(hdc,x+50,y-50,NULL); LineTo(hdc,x+50,y+50); LineTo(hdc,x,y+50); LineTo(hdc,x+50,y-50); flag = true; }; if(strcmp(buf,"верхний левый прямоугольный треугольник") == 0){ MoveToEx(hdc,x-50,y-50,NULL); LineTo(hdc,x,y-50); LineTo(hdc,x-50,y+50); LineTo(hdc,x-50,y-50); flag = true; }; if(strcmp(buf,"верхний правый прямоугольный треугольник") == 0){ MoveToEx(hdc,x,y-50,NULL); LineTo(hdc,x+50,y-50); LineTo(hdc,x+50,y+50); LineTo(hdc,x,y-50); flag = true; }; if(strcmp(buf,"квадрат с диагональю верх лево - низ право") == 0){ MoveToEx(hdc, x-50, y-50, NULL); LineTo(hdc, x+50, y-50); LineTo(hdc, x+50, y+50); LineTo(hdc, x-50, y+50); LineTo(hdc, x-50, y-50); LineTo(hdc, x+50, y+50); flag = true; }; if(strcmp(buf,"квадрат с диагональю низ лево - верх право") == 0){ MoveToEx(hdc, x-50, y-50, NULL); LineTo(hdc, x+50, y-50); LineTo(hdc, x+50, y+50); LineTo(hdc, x-50, y+50); } IDD_SELECT DIALOG 0, 0, 389, 182 STYLE DS_MODALFRAME | DS_3DLOOK | DS_CONTEXTHELP | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Выбор фигур" FONT 8, "MS Sans Serif" { CONTROL "OK", IDC_OK2, "BUTTON", BS_PUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 168, 16, 52, 14 CONTROL "ListBox1", IDC_LISTBOX3, "listbox", LBS_NOTIFY | LBS_MULTIPLESEL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP, 4, 13, 156, 168 CONTROL "Добавить", IDC_ADD, "button", BS_PUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 168, 39, 52, 14 CONTROL "Удалить", IDC_DELETE, "button", BS_PUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 168, 60, 52, 13 CONTROL "ListBox2", IDC_LISTBOX2, "listbox", LBS_NOTIFY | LBS_MULTIPLESEL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP, 228, 13, 156, 168 CONTROL "<- Отчистить", IDC_CLEAR, "button", BS_PUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 168, 82, 52, 13 } ПРИЛОЖЕНИЕ Б БЛОК – СХЕМА АЛГОРИТМА Файл Shapes.rc Shapes.cpp Выбор Нарисовать Продолжение прил. Б
Docsity logo