ПасьянсРефераты >> Программирование и компьютеры >> Пасьянс
3.2.1.2. Описание окон, сообщений, и относящихся к ним данных и функций (сверху - вниз, начиная с наиболее крупных, заканчивая вспомогательными).
Программа состоит из главной функции WinMain, в которую входит обработчик событий switch, функции WindowFunc, DrawCards. Так же есть дополнительные функции FillCoords, Catch. Обработчик событий switch содержит следующие ветвления:
- WM_DESTROY: /* завершение программы */
- WM_VSCROLL:/*прокрутка, содержит свой обработчик событий*/
-SB_LINEDOWN://была нажата стрелка вниз
- SB_LINEUP: // вверх
- SB_PAGEUP: //было нажато над скролом
- SB_PAGEDOWN: //было нажато под скролом
- SB_THUMBTRACK: //бегунок был перетащен вручную
- WM_LBUTTONDOWN:/*нажата левая кнопка мышки*/
- WM_COMMAND:/*выбор пункта меню*/
- WM_TIMER: /* сообщение от таймера*/
- WM_PAINT: /*отрисовка клиентской области, вызывает функцию DrawCards*/
- WM_CREATE:/*была вызвана функция создания окна, здесь созданы элементы управления – поле редактора Edit box и Check Box */
Функция DrawCards:
Объявление
void DrawCards(HWND hwnd,int x,int y,char *msg, int i, int j,float sdvig);
Вызов
DrawCards(hwnd,100,10,"Откройте любую карту .",i,j,-cyChar*iVscrollInc);
hwnd- дескриптор окна;
2-й, 3-й параметры – координаты для вывода сообщения;
4-й – текст сообщения;
5-й, 6-й – индексы для доступа к каждой отдельной карте;
7-й – праметр сдвига перерисовки при прокрутке
Функция DrawCards рисует прямоугольники с помощью функции Rectangle в цикле:
for (i=0;i<16;i++)
Rectangle(hDC,x0[i],y0[i]=(y0[i]+sdvig*100),x1[i],y1[i]=(y1[i]+sdvig*100));
Sdvig- это расстояние, на которое карты должны перерисоваться с учетом скроллинга, функция DrawCards вызывается во время скроллинга, и в кач-ве параметра сдвига ей передается выражение: -cyChar*iVscrollInc где cyChar, iVscrollInc – числовые коэффициенты, положительные\отрицательные в зависимости от напрвления прокрутки.
Перерисовка при нажатии мышки происходит в ветвлении WM_LBUTTONDOWN с помощью функции BitBlt.
ФункцияFillCoords:
Текст функции
void FillCoords(int i, int X0, int Y0, int X1, int Y1)
{
x0[i] = X0;
y0[i] = Y0;
x1[i] = X1;
y1[i] = Y1;
return;
}
Заполняет массивы х0, у0, х1, у1 необходимыми координатами;
Вызов: FillCoords(0,113,157,247,322);
Функция Catch:
void Catch(int i, int j)
{
catched[i] = catched[j] = true;
}
Выполняется, если две карты оказываюся открытыми и с одинаковыми изображениями.
Сообщения программы
Программа посылает сообщения с помощью функции SendMessage в следующих местах:
1)При загрузке информации из текстового файла в поле редактора:
SendMessage(EdtHwnd, EM_REPLACESEL, FALSE, (LPARAM)(LPCTSTR)pBuffer);
EdtHwnd//дескриптор редактора- получателя
EM_REPLACESEL// позволяет к концу одной записи прибавлять другую, выводить по несколько файлов
WPARAM wParam, // первый параметр сообщения , равен нулю
pBuffer // буфер для текста
2)При завершении работы приложения, этим сообщением вызывается стандартный диалог сохранения файла
SendMessage(hwnd,WM_COMMAND,IDM_SAVE2,0);
hwnd//дескриптор окна- получателя
WM_COMMAND// посылаемое сообщение
3.2.1. Приложение под DOS 7.0.
3.2.1.1. Общий алгоритм работы программы
При загрузке программы (не важно, СОМ или ЕХЕ) перед образом программы в памяти находится область PSP (префикс программного сегмента) размером 256 байт, последние 128 байт которой называется DTA и является файловым буфером по умолчанию для устаревших файловых функций , так же она используется для хранения строки параметров командной строки. Содержимое командной строки, следующее за именем программы при ее вызове помещается в PSP, DTA со смещением 80h и максимальным размером 128. 1ый байт содержит кол-во символов параметров комстроки (длину), со второго (смещение 81h) начинаются символы параметров. Последний символ – всегда 0dh. Программа сначала копирует имя открываемого файла из PSP в сегмент данных ,а потом настраивает регистр ds на сегмент данных, т.к при старте программы загрузчик устанавливает регистры ds и es равные сегментному адресу PSP.
mov ax,@data;
mov es,ax
Ассемблер не может определить адрес data, он пределится лишь когда объектная программа будет скомпанована и загружена для выполнения. Поскольку згрузчик может расположить программу в любом месте памяти, ассемблер оставляет данный адрес открытым, компоновщик должен подставить вместо @data действительный адрес.
mov di,81h ;начало комстроки
mov al," "
mov cx,128 ;макс длина
cld ; сбрасывает флаг DF, это необходимо, чтобы на каждом шаге
; копирования происходило увеличение
; (а не уменьшение) содержимого DI на единицу.
repe scasb ;пропускает пробелы, пока не найдет символ «не пробел»,
; причем даже когда будет найден такой символ
;di увеличится на 1
dec di ;вернет значение di, так что он будет являтся смещением 1-го
;отличного от пробела символа ES:[DI]
push di
pop si ;его адрес- в si siß---diß---ES
mov ax,@data;вручную настраиваем es на сегмент данных
mov es,ax ;ax в es т.к нет команд для непосредственной пересылки
; данных из памяти в регистр es
mov cl,ds:[80h]; кол-во символов в комстроке
dec cl ; избавляемся от Enter’а , введенного пользователем
lea di,FILE ;
rep movsb ; скопировать комстроку в FILE по адресу di
push es ;было esß---@data, настроим ds на сегмент данных
pop ds ; теперь dsß---es а значит dsß-@data
Далее программа открывает файл с помощью функции 3Dh , режим доступа –только чтение. Далее создается дескриптор файла. После этого файл читается функцией 3fh, дескриптор файла заносится в регистр bx, в регистр сх- число байтов, которое нужно прочитать, в регистр dx адрес области ввода. ( сх совпадает с размером буфера для чтения). Правильно выполненная операция считывает запись в память, сбрасывает флаг CF и устанавливает в регистре ах число дейсвительно прочитанных байтов. Нулевое значение в ах означает попытку чтения после конца файла. Мы каждый раз сравниваем значение в регистрах сх и ах и , если значения совпадают, закрываем файл с помощью функции 3Еh , предварительно занеся в регистр bx дескриптор файла.
Далее мы обрабатываем массив с файла. В регистре сх записываем, сколько нам необходимо прочитать, обращение к символу в строке происходит через регистр обработки цепочечных операций si: BUFER[si]. Мы сравниваем символ и если он совпадает с нужным нам символом мы увеличиваем счетчик и продвигаемся по строке дальше, увеличивая si. Поскольку значение счетчика –число, то для вывода на экран его необходимо преобразовать в строку (ASCII-формат).В коде ASCII на каждый символ требуется 1 байт. Например, число 25 в ASCII-коде имеет внутреннее представление 3235. Значит, чтобы преобразовать двоичное число, его нужно делить на 10 пока результат не станет меньше 10. Остатки, которые лежат в границах от 0 до 9 образуют число в ASCII-формате. Последнее частное и все остатки от деления (снизу вверх) должны записываться в память с тройками: