Смекни!
smekni.com

Программа демонстрирующая иерархию окон Windows (стр. 2 из 3)

;структуры wc1

<96> ;определим цвет фона окна - белый

<97> ;готовим вызов HGDIOBJ GetStockObject(int fnObject)

<98> push WHITE_BRUSH

<99> саП GetStockObject

<100> mov wcl.hbrBackground, eax

<101> mov dword ptrwcl.lpszMenuName, 0 ;без главного меню

<102> mov dwordptrwcl.lpszClassName,offsetszC1assName; имя

;класса окна

<103> mov wcl.hIconSm, 0

<104> ;регистрируем класс окна - готовим вызов RegisterClassExA (&wndclass)

<105> push offset wcl

<106> саП RegisterClassExA

<107> test ax, ах;проверить на успех регистрации класса окна

<108> jz end_cyc1_msg ;неудача

<109> ;создаем окно:

<110> ;готовим вызовHWND CreateWindowExA(DWORDdwExStyle,

LPCTSTR1pClassName,

<111> ; LPCTSTR 1pW1ndowName, DWORD dwStyle, int x, int у, int nWidth,

|;int nHeight,

<112> ; HWND hWndParent, HMENU hMenu, HANDLE hInstance, LPVOID

;lpParam)

<113> push 0 ;lpParam

<114> push hInst ;hInstance

<115> push NULL ;menu

<116> push NULL ;parent hwnd

<117> push CW_USEDEFAULT ;высота окна

<118> push CW_USEDEFAULT ;ширина окна

<119> push CW_USEDEFAULT ;координата у левого верхнего угла

;окна

<120> push CW_USEDEFAULT ;координата х левого верхнего угла

<121> push WS_OVERLAPPEDWINDOW ;стиль окна

<122> push offset szTitleName ;строка заголовка окна

<123> push offset szClassName ;имя класса окна

<124> push NULL

<125> саll CreateWindowExA

<126> mov hwnd,eax ;-дескриптор окна

<127> ;показать окно:

<128> ;готовим вызов BOOL ShowWindow( HWND hWnd, int nCmdShow )

<129> push SW_SHOWNORMAL

<130> push hwnd

<131> call ShowWindow

<132> ;перерисовываем содержимое окна

<133> ;готовим вызов BOOL UpdateWindow( HWND hWnd )

<134> push hwnd

<135> call UpdateWindow

<136> ;запускаем цикл сообщений:

<137> ;готовим вызов BOOL GetMessageA( LPMSG lpMsg, HWND hWnd,

<138> ; UINTwMsgFilterMin,UINTwMsgFilterMax)

<139> cycl_msg:

<140> push 0

<141> push 0

<142> push NULL

<143> push offset message

<144> cal 1 GetMessageA

<145> cmp ах, 0

<146> je end_cycl_msg

<147> ;трансляция ввода с клавиатуры

<148> ;готовим вызов BOOL Trans1ateMessage( CONST MSG *lpMsg )

<149> push offset message

<150> call TranslateMessage

<151> ;отправим сообщение оконной процедуре

<152> ;готовим вызов LONG D1spatchMessage( CONST MSG *lpmsg )

<153> push offset message

<154> call DispatchMessageA

<155> jmp cycl_msg

<156> end_cycl_msg:

<157>

<158> ;выход из приложения

<159> ;готовим вызов VOID ExitProcess( UINT uExitCode )

<160> push NULL

<161> call ExitProcess

<162> start endp

<163> ; - - - - - - - - - - - - --WindowProc-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

<164> WindowProc proc

<165> argP0nwnd:DWORD, PPmes:DWORD, @@wparam:DWORD, @@lparam:DWORD

<166> uses ebx, edi, es1 ;эти регистры обязательно должны сохраняться

<167> local @@hdc:DWORD

<168> cmp @@mes, WM_DESTROY

<169> je wmdestroy

<170> cmp @@mes, WM_CREATE

<171> je wmcreate

<172> cmp @@mes, WM_PAINT

<173> je wmpaint

<174> jmp default

<175> wmcreate:

<176> ;обозначим создание окна звуковым эффектом

<177> ;готовим вызов функции BOOL PlaySound(LPCSTR pszSound, HMODULE hmod, DWORD

;fdwSound )

<178> push SND_SYNC+SND_FILENAME

<179> push NULL

<180> push offset playFileCreate

<181> call PlaySoundA

<182> mov eax, О;возвращаемое значение - 0

<183> jmp exit_wndproc

<184> wmpaint:

<185> push SND_SYNC+SND_FILENAME

<186> push NULL

<187> push offset playFIilePaint

<188> call P1aySoundA

<189>;получим контекст устройства HDC BeginPaint(HWND nwnd,LPPAINTSTRUCT;LPpAINT)

<190> push offset ps

<191> push @@hwnd

<192> call BeginPaint

<193> mov @@hdc,eax

<194> ;выведем строку текста в окно BOOL TextOut( HDC hdc. int nXStart, int

:nYStart.

<195> ; LPCTSTR lpString, int cbString )

<196> push MesWindowLen

<197> push offset MesWindow

<198> push 100

<199> push 10

<200> push @@hdc

<201> call TextOutA

<202> :ocвoбoдитькoнтeкcтBOOLEndPaint( HWNDhWnd, CONSTPAINTSTRUCT*lpPai <203> push offset ps

<204> push @@hdc

<205> call EndPaint

<206> mov еах,0;возвращаемое значение-0

<207> jmp exit_wndproc

<208> wmdestroy:

<209> push SND_SYNC+SND_FILENAME

<210> push NULL

<211> push offset playFileDestroy

<212> call PlaySoundA

<213> ;послать сообщение WМ_QUIТ

<214> ;готовим вызов VOID PostQuitMessage( int nExitCode )

<215> push 0

<216> call PostQuitMessage

<217> mov eax, О;возвращаемое значение - 0

<218> jmp exit_wndproc

<219> default:

<220> ; обработка по умолчанию

<221>;готовим вызов LRESULTDefWindowProc( HWND hWnd, UINTMsg,

<222> ; WPARAMwParam,LPARAMlParam)

<223> push @@lparam

<224> push @@wparam

<225> push @@mes

<226> push @@nwnd

<227> call DefWindowProcA

<228> jmp exit_wndproc

<229> ;... ... ...

<230> exit_wndproc:

<231> ret

<232> WindowProc endp

<233> end start

3.Иерархия окон

Изучив по дисциплине «Системное программное обеспечение» написание окон Windows на языке Assembler и рассматривая графическую оконную систему нельзя обойтись без подробного рассмотрения того, какие окна можно отображать на экране.

Тип окна задается 32-битовым без знаковым целым числом, которое указывается третьим параметром вызова функции Create Window.

Существует всего лишь три основных типа окон Window.

1 тип. Перекрывающиеся окна. Флаг WS_OVERLAPPED.

2 тип. Вспомогательные окна. Флаг WS_POPUP.

3 тип. Дочерние окна. . Флаг WS_CHILD.

Для написания курсового проекта, который имеет тему «Программа демонстрирующая иерархию окон Windows» были использованы именно эти типы окон.

Нужно о них помнить следующее что:

· Перекрывающееся окно никогда не имеет родителя

· Дочернее окно всегда имеет родителя.

· Вспомогательное окно может иметь и не иметь родителя; если оно имеет родителя, то все равно это не дочернее, а вспомогательное окно.

Из всех концепций системы управления окнами наиболее фундаментальной является отношение предок/ потомок/ сосед. Как мы видели при описании структуры данных WND, каждое окно содержит логический номер окна своего предка, логический номер своего первого дочернего окна и логический номер следующего соседнего окна. Соседними являются окна, имеющие одинаковое родительское окно. В действительности значения HWND являются просто ближними указателями в локальной "куче" модуля USER, поэтому вы можете рассматривать их как указатели связного списка, которые позволяют обходить пути в иерархии окон. Иерархия окон, создаваемая модулем USER, показана на рис.1.

Иерархия окон обходится во всех трех направлениях - от предка к потомку, от потомка к предку и от соседа к соседу. Примеры обхода иерархии включают следующее:

• При уничтожении окна модуль USER должен уничтожить всех его потомков, а также их потомков. USER обходит всю иерархию, используя поля hWndChild и hWndNext- Напомним, логические номера окон являются просто ближними указателями в локальной "куче" модуля USER.

• Когда происходит передача фокуса ввода при нажатии клавиши Tab между элементами управления в окне диалога (которые являются потомками окна диалога), указатели на соседнее окна (или поле hWndNext) соединяют друг с другом элементы управления. Кроме того, упорядочение окон в списке hWndChild и hWndNext отражает Z-порядок окон на экране. Z-порядок представляет собой относительную позицию окон в третьем измерении (в направлении от экрана к вам). Если вы щелчком кнопки мыши выбираете различные основные окна;

чтобы поместить их в вершину Z-порядка, их относительные позиции в списке hWndNext сдвигаются.

Рис..1 Иерархия окон, созданная модулем USER.

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

В корне дерева окон находится desktop-окно. Это окно покрывает весь экран и всегда находится на вершине Z-порядка. Это означает, что оно всегда находится позади всех других окон. Desktop-окно является первым созданным окном, и это единственное окно в системе, которое не имеет окна родителя или владельца. (Окна-владельцы описаны далее.) Окраска окна фона отвечает за "обои" Windows.

Desktop-окно ничем особенным не выделяется в смысле установки специальных битов или т.п. Оно создается с битами стиля (обсуждаются ниже) WS_POPUP и WS_CLIPCHILDREN. Нет никакого недокументированного бита стиля WS_DESKTOP. Вместо этого логический номер desktop-окна сохраняется в глобальной переменной модуля USER с именем HWndDesktop. Когда системе управления окнами нужно знать, имеет ли она дело с desktop-окном, она просто сравнивает HWND, о котором идет речь, с HWndDesktop. Вы можете получить значение переменной HWndDesktop, используя документированную API-функцию GetDesktopWindow().

ВЛАДЕНИЕ ОКНАМИ В Windows

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

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

Особенность вышеприведенного правила относится и к окнам WS_CHILD. Для окон WS_CHILD владелец HWND в структуре WND дочернего окна равен нулю, и вместо него уведомительные сообщения посылаются родительскому окну. Например, кнопка в окне диалога является потомком главного диалогового окна. Когда вы нажимаете кнопку, окно кнопки уведомляет об этом событии своего предка, т.е. главное диалоговое окно. Вы можете считать, что для ws_child-okhb логический номер hWndOwner — то же самое, что и hWndParenfc, хотя на самом деле они различны. В Presentati

on Manager нет необходимости в битах WS_CHILD или РWS_POPUP. Заполняется как поле hWndPa-rent, так и поле hWndOwner. Это полностью определяет, кто получает уведомительные сообщения потомка, а также положение окна в иерархии. В Presentation Manager поля hWndParent и hWndOw-ner обычно содержат одно и то же значение HWND.

Кроме посылки уведомлений своему владельцу, окно, которым владеют, также всегда расположено впереди окна-владельца. Если окно превращено в пиктограмму, то же происходит и с окнами, которыми оно владеет. Если окно-владелец уничтожается, тто окна, которыми оно владеет, также уничтожаются. Так как окно не следит за окнами, которыми оно владеет, нужно просматривать списки указателей предок/сосед и сравнивать владельца каждого окна с HWND окна, которое уничтожается.