Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ОС лабы / ОС - Лабораторная работа 1.doc
Скачиваний:
63
Добавлен:
01.06.2015
Размер:
1.18 Mб
Скачать
  1. Выполнение лабораторной работы

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

Для получения протокола следует настроить Spy++ подходящим образом и осуществить заданные действия. Можно не отслеживать не оконные типы сообщений (не имеющие префиксаWM_), сообщения, адресованные посторонним окнам, и сообщения о перемещении мыши. Допускается также удаление сообщений, не упоминавшихся ни в описании данной работы, ни в описанном ниже примере выполнения. Все оставшиеся сообщения, следует прокомментировать и понимать, в ответ на какое действие пользователя появляется то или иное сообщение (или группа сообщений).

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

Очень желательно вместе с сообщениями для окна верхнего уровня отслеживать также сообщения для всех его дочерних окон.

Информацию о сообщениях Windows, их смысле и параметрах, можно найти в справочных данных системы программирования (VisualStudio,Delphi,C++Builder) или, если есть возможность, в базе данныхMSDN(MicrosoftDevelopersNetwork). Ссылки на незнание английского языка не принимаются (пора знать).

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

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

  1. Пример выполнения задания

Рассмотрим выполнение лабораторной работы на следующем примере.

Задание. Получить и прокомментировать протокол сообщений, посылаемых окну редактораNotepad(«Блокнот») при его закрытии. Окно закрывать щелчком по кнопке закрытия. Считать, что текст в окне редактора сохранен, т.е. запрос на сохранение выдаваться не будет.

Пример выполнялся в системе WindowsXT. Для других версийWindowsпоток сообщений может несколько отличаться.

Сначала запустим Notepad, введем несколько строк текста и сохраним файл. Затем запустимSpy++ и выполним командуSpy+Log Messages. Откроется диалоговое окноMessage Options. На закладкеWindowsоттащимFinder Toolна окноNotepad. При этом можно обнаружить, чтоNotepadсодержит, как минимум, два окна: основное окно программы и вложенное в него (дочернее) окно с панелью редактора (на самом деле, имеется еще окно строки состояния, которое может быть видимым или нет, в зависимости от настройкиNotepad). Выберем главное окно, но включим переключательChild Windows, чтобы получать сообщения для всех окон Notepad. На закладкеMessagesпока оставим все сообщения.

Полезно перейти теперь в окно списка окон (через команду меню Spy++Windows), на всякий случай обновить список (командой контекстного менюRefresh) и найти в списке окнаNotepad. Это можно сделать либо просмотром всего списка, либо с помощью командыSearch+Find Window. В нашем случае список содержит главное окноNotepadс хэндлом 002702D2, дочернее окно редактирования (хэндл 001103В0) и окно строки состояния (001002B4). Разумеется, значения хэндлов при других запускахNotepadмогут быть другими.

Вернемся в окно протокола сообщений. Чтобы получить меньше ненужных сообщений, желательно расположить на экране окна таким образом, чтобы кнопка закрытия Notepadбыла как можно ближе к краю окнаSpy++. Убедимся, что протоколирование включено (ненадолго поместим курсор наNotepad, при этом в окнеSpy++ должен политься бурный поток сообщений). Удалим все сообщения командойMessages+Clear Log.

Теперь за дело: быстро переведем курсор из окна Spy++ на кнопку закрытияNotepadи щелкнем левой кнопкой мыши. Дальше можно не спешить, поскольку после закрытияNotepadпоток сообщений так или иначе прекратится.

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

<00001> 002702D2 S

WM_NCHITTEST xPos:258 yPos:191

<00002> 002702D2 R

WM_NCHITTEST nHittest:HTCLOSE

<00003> 002702D2 S

WM_SETCURSOR hwnd:002702D2 nHittest:HTCLOSE wMouseMsg:WM_MOUSEMOVE

<00004> 002702D2 R

WM_SETCURSOR fHaltProcessing:False

<00005> 002702D2 P

WM_NCMOUSEMOVE nHittest:HTCLOSE xPos:258 yPos:191

<00006> 001103D0 S

EM_GETSEL lpdwStart:0007FC74 lpdwEnd:0007FC78

<00007> 001103D0 R

EM_GETSEL wStart:0 wEnd:0 lpdwStart:0007FC74 (0) lpdwEnd:0007FC78 (0)

<00008> 001103D0 S

EM_LINEFROMCHAR ich:0

<00009> 001103D0 R

EM_LINEFROMCHAR iLine:0

<00010> 001103D0 S

EM_LINEINDEX line:0

<00011> 001103D0 R

EM_LINEINDEX ich:0

............

..................

<00094> 002702D2 S

WM_NCHITTEST xPos:256 yPos:185

<00095> 002702D2 R

WM_NCHITTEST nHittest:HTCLOSE

<00096> 002702D2 S

WM_MOUSEACTIVATE hwndTopLevel:002702D2 nHittest:HTCLOSE uMsg:WM_LBUTTONDOWN

<00097> 002702D2 R

WM_MOUSEACTIVATE fuActivate:MA_ACTIVATE

<00098> 002702D2 S

WM_WINDOWPOSCHANGING lpwp:0007FE98

<00099> 002702D2 R

WM_WINDOWPOSCHANGING

<00100> 002702D2 S

WM_NCPAINT hrgn:00000001

<00101> 002702D2 S

WM_GETTEXT cchTextMax:510 lpszText:0007F45C

<00102> 002702D2 R

WM_GETTEXT cchCopied:29 lpszText:0007F45C ("­@8<5@ ")

<00103> 002702D2 R

WM_NCPAINT

<00104> 002702D2 S

WM_ERASEBKGND hdc:67010BA7

<00105> 002702D2 R

WM_ERASEBKGND fErased:True

<00106> 002702D2 S

WM_WINDOWPOSCHANGED lpwp:0007FE98

<00107> 002702D2 R

WM_WINDOWPOSCHANGED

<00108> 002702D2 S

WM_ACTIVATEAPP fActive:True dwThreadID:00000000

<00109> 002702D2 R

WM_ACTIVATEAPP

<00110> 002702D2 S

WM_NCACTIVATE fActive:True

<00111> 002702D2 R

WM_NCACTIVATE

<00112> 002702D2 S

WM_ACTIVATE fActive:WA_ACTIVE fMinimized:False hwndPrevious:(null)

<00113> 002702D2 S

WM_SETFOCUS hwndLoseFocus:(null)

<00114> 002702D2 S

WM_KILLFOCUS hwndGetFocus:001103D0

<00115> 001103D0 S

WM_KILLFOCUS hwndGetFocus:001103D0

<00116> 002702D2 S

WM_COMMAND wNotifyCode:EN_KILLFOCUS wID:15 hwndCtl:001103D0

<00117> 002702D2 R

WM_COMMAND

<00118> 001103D0 R

WM_KILLFOCUS

<00119> 002702D2 R

WM_KILLFOCUS

<00120> 001103D0 S

WM_SETFOCUS hwndLoseFocus:002702D2

<00121> 002702D2 S

WM_CTLCOLOREDIT hdcEdit:67010BA7 hwndEdit:001103D0

<00122> 002702D2 R

WM_CTLCOLOREDIT hBrush:0110007B

<00123> 002702D2 S

WM_COMMAND wNotifyCode:EN_SETFOCUS wID:15 hwndCtl:001103D0

<00124> 002702D2 R

WM_COMMAND

<00125> 001103D0 R

WM_SETFOCUS

<00126> 002702D2 R

WM_SETFOCUS

<00127> 002702D2 R

WM_ACTIVATE

<00128> 002702D2 S

WM_SETCURSOR hwnd:002702D2 nHittest:HTCLOSE wMouseMsg:WM_LBUTTONDOWN

<00129> 002702D2 R

WM_SETCURSOR fHaltProcessing:False

<00130> 002702D2 P

WM_NCLBUTTONDOWN nHittest:HTCLOSE xPos:256 yPos:185

<00131> 001103D0 S

EM_GETSEL lpdwStart:0007FABC lpdwEnd:0007FAC0

<00132> 001103D0 R

EM_GETSEL wStart:0 wEnd:0 lpdwStart:0007FABC (0) lpdwEnd:0007FAC0 (0)

<00133> 001103D0 S

EM_LINEFROMCHAR ich:0

<00134> 001103D0 R

EM_LINEFROMCHAR iLine:0

<00135> 001103D0 S

EM_LINEINDEX line:0

<00136> 001103D0 R

EM_LINEINDEX ich:0

<00137> 002702D2 S

WM_NCHITTEST xPos:256 yPos:185

<00138> 002702D2 R

WM_NCHITTEST nHittest:HTCLOSE

<00139> 002702D2 P

WM_MOUSEMOVE fwKeys:MK_LBUTTON xPos:249 yPos:-29

<00140> 002702D2 P

WM_LBUTTONUP fwKeys:0000 xPos:249 yPos:-29

<00141> 002702D2 S

WM_CAPTURECHANGED hwndNewCapture:00000000

<00142> 002702D2 R

WM_CAPTURECHANGED

<00143> 002702D2 S

WM_SYSCOMMAND uCmdType:SC_CLOSE xPos:256 yPos:185

<00144> 002702D2 S

WM_CLOSE

<00145> 001103D0 S

EM_GETMODIFY

<00146> 001103D0 R

EM_GETMODIFY fModified:False

<00147> 002702D2 S

WM_PARENTNOTIFY fwEvent:WM_DESTROY idChild:0401 (1025) hwndChild:001002B4

<00148> 002702D2 R

WM_PARENTNOTIFY

<00149> 001002B4 S

WM_SHOWWINDOW fShow:False fuStatus:0 (ShowWindow was called)

<00150> 002702D2 S

WM_ERASEBKGND hdc:C8010B4C

<00151> 002702D2 R

WM_ERASEBKGND fErased:True

<00152> 002702D2 S

WM_WINDOWPOSCHANGING lpwp:0007F978

<00153> 002702D2 R

WM_WINDOWPOSCHANGING

<00154> 002702D2 S

WM_WINDOWPOSCHANGED lpwp:0007F978

<00155> 002702D2 R

WM_WINDOWPOSCHANGED

<00156> 002702D2 S

WM_NCACTIVATE fActive:False

<00157> 002702D2 R

WM_NCACTIVATE fDeactivateOK:True

<00158> 002702D2 S

WM_ACTIVATE fActive:WA_INACTIVE fMinimized:False hwndPrevious:(null)

<00159> 002702D2 R

WM_ACTIVATE

<00160> 002702D2 S

WM_ACTIVATEAPP fActive:False dwThreadID:00000D20

<00161> 001103D0 S

EM_GETSEL lpdwStart:0007F78C lpdwEnd:0007F790

<00162> 002702D2 R

WM_ACTIVATEAPP

<00163> 002702D2 S

WM_COMMAND wNotifyCode:EN_KILLFOCUS wID:15 hwndCtl:001103D0

<00164> 002702D2 R

WM_COMMAND

<00165> 002702D2 S

WM_DESTROY

<00166> 002702D2 R

WM_DESTROY

<00167> 002702D2 S

WM_NCDESTROY

<00168> 002702D2 R

WM_NCDESTROY

<00169> 002702D2 R

WM_CLOSE

<00170> 002702D2 R

WM_SYSCOMMAND

Прокомментируем протокол.

Строки 1-2. Система запрашивает у окна, на какой части неклиентской области находится курсор. Окно отвечает: он на кнопке закрытия (HTCLOSE).

3-4. Система предлагает окну сменить, если надо, форму курсора.

5. Асинхронное сообщение о перемещении мыши. Чаще всего оно не обрабатывается.

6-7. У дочернего окна редактирования запрашивают позицию начала и конца выделенного в окне текста (например, чтобы отобразить его другими цветами). Ответ: 0, 0 (нет выделенного текста).

8-9. Запрос номера строки, где начинается выделение. Ответ: 0.

10-11. Теперь запрашивается номер позиции в этой строке. Тоже 0.

Далее многократно повторяется та же группа сообщений, с единственным отличием – небольшими изменениями позиции мыши (xPos,yPos). Это система перепроверяет положение курсора, пока он ползет пару миллиметров по кнопке закрытия.

94-95. Еще раз проверяется положение мыши. Она все еще на кнопке закрытия окна.

96-97. Это уже интереснее. Система сообщает окну, что пользователь пытается его активизировать. И подробности: был щелчок левой кнопкой мыши на кнопке закрытия окна. Указывается также хэндл окна верхнего уровня, которое должно принимать решение, как реагировать на щелчок. Ответ: можно активизировать, окно не возражает; и, кроме того, щелчок надо передать кнопке закрытия для обработки (если бы ответ был MA_ACTIVATEANDEAT, окно бы активизировалось, но щелчок был бы «съеден», т.е. не привел бы к закрытию окна).

98-99. Окну сообщают, что его положение на экране будет изменено. Детали предстоящего изменения оконная функция может найти по указанному адресу (lpwp). Ответ не требуется, но сообщение принято к сведению.

100. Окну сообщают, что надо перерисовать неклиентскую область. Оконная функция передает это сообщение системе и та принимается за дело (см. вложенные сообщения 101-103).

101-102. Система запрашивает у программы текст заголовка окна (потому что его надо отобразить заново на синем фоне). При этом cchTextMax– размер системного буфера для приема строки текста, аlpszText– адрес этого буфера. В ответ выдается 29 символов текста, иSpy++ безуспешно пытается отобразить первое слово русского заголовка.

103. Неклиентская часть перерисована.

104-105. В связи с предстоящей перерисовкой окна требуется очистить его фон. Сделано.

106-107. Изменение положения окна завершено (в данном случае окно Notepadне сдвинулось по экрану, но разместилось поверх прочих оконWindows, а это считается «изменениемZ-порядка»).

108-109. Окну сообщают, что программа Notepadактивизируется.

110-111. Окно активизируется и, возможно, его неклиентская часть требует при этом перерисовки.

112. Окну сообщают, что оно становится активным. Сообщения 113-127 посылаются при обработке сообщения 112.

113-119. Идет малопонятная игра с передачей фокуса клавиатурного ввода сначала главному окну Notepad, затем дочернему окну редактирования, а затем этим окном самому себе! В сообщении 116 редактор даже успевает сообщить главному окну, что теряет фокус.

120. Все-таки фокус переходит к окну редактирования.

121-122. Редактор просит родителя указать, каким цветом перерисовать фон (в связи с получением фокуса). В ответ он получает хэндл соответствующей кисти.

123. Редактор радостно сообщает родителю, что фокус он в конце концов получил.

124-127. И на этом заканчивается обработка активизации окна Notepad.

128-138. Еще раз проверяется положение мыши, возможность смены курсора и границы селектированного текста. На этот раз это все делается не в связи с перемещением мыши, а вследствие нажатия левой кнопки (WM_LBUTTONDOWN).

139-140. Окно Notepadполучает асинхронные извещения о том, что после щелчка курсор еще немного передвинулся, а затем левая кнопка была отпущена. Системе не жалко известить, вдруг эти детали играют какую-то роль для окна. Отрицательная координатаyPosне должна удивлять, поскольку координаты здесь отсчитываются вниз/вправо от левого верхнего угла клиентской части окна.

141-142. Окну сообщают, что оно потеряло захват мыши.

143. Окно получает системную команду закрытия (это прямой результат щелчка на кнопке закрытия). Все дальнейшие сообщения посылаются в порядке выполнения этой команды.

144. Система говорит окну: «Закройся!». Далее идет выполнение закрытия.

145-146. У окна редактора спрашивают, не изменен ли в нем текст (т.е. требуется ли запрос о сохранении). Ответ: «Нет, не изменен».

147-148. Наконец-то как-то проявилось окно строки состояния. Оно сообщает родителю, что прекращает свое существование.

149. Окно строки состояния получает команду не отображаться.

150-151. Зачем-то вытирается главное окно.

152-155. Окно меняет свое положение (теперь оно «никакое»).

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

158-164. Окно и приложение деактивируются, редактор теряет фокус.

165-166. Окно Notepadи его дочерние окна полностью разрушаются.

167-168. Самое последнее: система освобождает память, отведенную для структур данных окна.

169-170. И на этом заканчивается обработка сообщения 144 и породившего его сообщения 143.