Автор: Роман Панышев (irrona)


Всё об окнах

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

Окно рабочего стола системы

      При загрузке операционной системы (имеется в виду ОС Windows), автоматически создается окно рабочего стола. Это окно - определено системой (system-defined). Оно заполняет предопределенным цветом задний план экрана и служит базой (фоном) для всех других окон приложений.

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

      Для получения идентификатора окна рабочего стола используется API-функция GetDesktopWindow.

      Системное конфигурационное приложение, такое, например, как апплет панели управления, изменяет "обои рабочего стола" используя функцию SystemParametersInfo,

    invoke SystemParametersInfo, uiAction, uiParam, pvParam, fWinIni

в которой параметр uiAction установлен в значение SPI_SETDESKWALLPAPER, а параметр pvParam указывает на имя файла рисунка. Функция SystemParametersInfo загружает рисунок из указанного файла, используя его для прорисовки заднего плана экрана, и сохраняет имя файла рисунка в реестре Windows.

Окна приложений

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

      При запуске приложения, операционная система создает и ассоциирует с данным приложением специальную кнопку, располагая её на панели быстрого доступа - taskbar (обычно в нижней части экрана). На этой кнопке помещается изображение (иконка, icon) приложения и текст заголовка главного окна (window title). Когда приложение активно, т.е. находится в фокусе, его кнопка на панели быстрого доступа отображается в нажатом состоянии.

      Окно приложения включает в себя такие элементы как заголовок окна (title bar), меню (menu bar), оконное меню (обычно его называют системным меню), кнопку сворачивания окна (minimize button), кнопку разворачивания окна (maximize button), кнопку восстановления положения окна (restore button), кнопку закрытия окна (close button), границы (borders - служат для изменения размеров окна), клиентской области (client area), горизонтальной и вертикальной полос прокрутки (horizontal & vertical scroll bars). Главное окно приложения обычно включает в себя все перечисленные выше элементы. На рисунке показаны основные элементы окна приложения.

Элементы окна приложения
Элементы окна приложения

      В чем же отличие клиентской области окна приложения от области неклиентской. Давайте разбираться.

Клиентская область окна

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

Неклиентская область окна

      Заголовок окна, меню, системное меню, кнопки закрытия/сворачивания/разворачивания, границы, полосы прокрутки, строки состояния - всё это неклиентские области окна. Почти все аспекты поведения и отображения этих областей регулируются операционной системой, а приложение занимается отображением своей клиентской области.      

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

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

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

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

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

      Полосы прокрутки конвертируют нажатия кнопок "мыши" или клавиатуры в значения, которые приложение использует для смещения содержимого клиентской области по горизонтали или вертикали. Например, вертикальная полоса прокрутки в приложении MS Word позволяет прокручивать текущую страницу вверх/вниз или перемещаться между страницами документа.

Элементы управления и диалоговые окна

      В дополнение к главному окну приложение может создавать и другие типы окон, включая элементы управления и диалоговые окна.

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

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

Атрибуты окна

      При создании окна приложение должно предоставить функции создания окна следующую информацию:

      Функция создания окна возвращает идентификатор созданного окна, в случае ошибки возвращается ноль.

Имя класса окна (class name)

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

Имя окна (window name)

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

      Для изменения имени окна после его создания используется функция SetWindowText.

    invoke SetWindowText, hWnd, lpString

      Эта функция использует функции GetWindowTextLength и GetWindowText для получения имени текущего окна.

    invoke GetWindowTextLength, hWnd
    invoke GetWindowText, hWnd, lpString, nMaxCount

Стиль окна (window style)

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

    invoke SetWindowLong, hWnd, nIndex, dwNewLong

      Некоторые стили окон подходят можно устанавливать при создании любых окон. Но, в основном, стиль является специфичным для заданного класса окна. Основные стили окон представленны в виде констант с префиксом WS_. Они могут быть объединены между собой с помощью оператора OR, что позволяет создавать окна с различным поведением и интерфейсом. Например, класс окна SCROLLBAR позволяет создать полосу прокрутки. Но только указание в качестве стиля окна SBS_HORZ (0h) или SBS_VERT (1h) позволяет создать соответственно горизонтальную или вертикальную полосу прокрутки.

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

Константа Значение (Hex) Описание
WS_OVERLAPPED 0 Создает перекрываемое окно, которое обычно имеет заголовок и границу.
WS_TILED 0 То же самое, что WS_OVERLAPPED.
WS_MAXIMIZEBOX 10000 Создает окно, в заголовке которого присутствует кнопка "развернуть".
WS_TABSTOP 10000 Указывает на то, что элемент относится к группе элементов, переход по которым можно осуществлять с помощью клавиши TAB клавиатуры. Клавиша TAB перемещает фокус на следующий элемент, у которого установлен стиль WS_TABSTOP.
WS_MINIMIZEBOX 20000 Создает окно, в заголовке которого присутствует кнопка "свернуть".
WS_GROUP 20000 Указывает на первый элемент в группе элементов, перемещение между которыми можно осуществлять стрелками клавиатуры. Все элементы после текущего, у которых WS_GROUP имеет значение FALSE, входят в одну группу с текущим. Любой из последующих элементов, у которого WS_GROUP имеет значение TRUE, будет первым элементом следующей группы (т.е. одна группа элементов заканчивается там, где начинается следующая).
WS_THICKFRAME 40000 Создает окно с тонкой границей, используемой для изменения размеров окна.
WS_SIZEBOX 40000 То же самое, что WS_THICKFRAME.
WS_SYSMENU 80000 Создает окно с системным меню в области заголовка. Используется только при создании окон с заголовками.
WS_HSCROLL 100000 Создает окно с горизонтальной полосой прокрутки.
WS_VSCROLL 200000 Создает окно с вертикальной полосой прокрутки.
WS_DLGFRAME 400000 Создает окно с двойной границей, но без заголовка.
WS_BORDER 800000 Создает окно с границей.
WS_CAPTION C00000 Создает окно с заголовком (при установленном стиле WS_BORDER). Не может быть использован со стилем WS_DLGFRAME.
WS_OVERLAPPEDWINDOW CF0000 Является комбинацией стилей WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU, WS_THICKFRAME, WS_MINIMIZEBOX и WS_MAXIMIZEBOX.
WS_TILEDWINDOW CF0000 То же самое, что WS_OVERLAPPEDWINDOW.
WS_MAXIMIZE 1000000 Создает окно, развернутое на всю клиентскую область рабочего стола.
WS_CLIPCHILDREN 2000000 При перерисовке родительского окна, не перерисовывает область, занятую дочерним окном. Используется при создании родительского окна.
WS_CLIPSIBLINGS 4000000 Исключает дочерние окна, связанные друг с другом. Это означает, что когда определенное дочернее окно получает сообщение о перерисовке, установка этого стиля позволяет отсечь все другие пересекающиеся с ним дочерние окна из области перерисовки. Если дочерние окна пересекаются и данный стиль не установлен, то, когда вы рисуете в клиентской области текущего дочернего окна, будет также зарисовываться клиентская область дочернего окна, расположенного рядом. Используется только при установленном стиле WS_CHILD.
WS_DISABLED 8000000 Создает неактивное окно.
WS_VISIBLE 10000000 Создает видимое окно.
WS_MINIMIZE 20000000 Создает свернутое окно. Используется только с установленным стилем WS_OVERLAPPED.
WS_ICONIC 20000000 То же самое, что WS_MINIMIZE.
WS_CHILD 40000000 Создает дочернее окно. Не может быть использован со стилем WS_POPUP.
WS_CHILDWINDOW 40000000 То же самое, что WS_CHILD.
WS_POPUP 80000000 Создает всплывающее окно. Нельзя использовать со стилем WS_CHILD.
WS_POPUPWINDOW 80880000 Является комбинацией стилей WS_BORDER, WS_POPUP и WS_SYSMENU. Для отображения системного меню, комбинируйте со стилем WS_CAPTION.

Расширенный стиль окна (extended window style)

      Каждое создаваемое вами окно может иметь один и более расширенных стилей. Расширенным стилем окна является именованная константа, отвечающая за отображение и поведение окна, которая не является специфичной для заданного класса окна. Для изменения расширенного стиля окна после его создания, используется функция SetWindowLong. Расширенные стили окон представленны в виде констант с префиксом WS_EX_. Они могут быть объединены между собой с помощью оператора OR, что позволяет изменять отображение и поведение создаваемых окон.

      Ниже перечисленны основные константы, которые Вы можете использовать при указании расширенных стилей окон.

Константа Значение (Hex) Описание
WS_EX_LEFT 0 Задает для окна выравнивание по левому краю. Это значение по-умолчанию.
WS_EX_LTRREADING 0 Отображает в окне текст с направлением чтения слева-направо. Это значение по-умолчанию.
WS_EX_RIGHTSCROLLBAR 0 При наличие вертикальной полосы прокрутки, помещает её с правой стороны клиентской области окна. Это значение по-умолчанию.
WS_EX_DLGMODALFRAME 1 Определяет окно с двойной границей, что можно сделать с помощью заголовка окна при установке обычного стиля окна WS_CAPTION.
WS_EX_NOPARENTNOTIFY 4 Указывает на то, что дочернее окно, созданное с таким стилем, не будет посылать своему родительскому окну сообщение WM_PARENTNOTIFY при создании и уничтожении.
WS_EX_TOPMOST 8 Указывает на то, что окно, созданное с таким стилем, должно быть помещено поверх всех остальных окон на экране и оставаться таким даже при потере фокуса. Вы можете использовать также функцию SetWindowPos для установки или удаления этого стиля.
WS_EX_ACCEPTFILES 10 Указывает на то, что окно, созданное с таким стилем, позволяет обрабатывать операции "drag-and-drop".
WS_EX_TRANSPARENT 20 Указывает на то, что окно, созданное с таким стилем, должно быть прозрачным. Это означает, что любое окно, расположенное под создаваемым окном, не будет им затемнено (загорожено). Окно, созданное с использованием этого стиля, получает сообщение WM_PAINT только после того, как все дочерние окна, расположенные под ним, будут обновлены (перерисованы).
WS_EX_MDICHILD 40 Создает MDI-окно.
WS_EX_TOOLWINDOW 80 Создает окно инструментов, которое предназначено для использования в качестве "плавающего" окна инструментов. Данное окно имеет заголовок, который меньше нормального по высоте, и с текстом меньшего размера. Такое окно не имеет ассоциированной с ним кнопки на панели быстрого доступа и не отображается в списке окон при использовании клавишной комбинации ALT+TAB.
WS_EX_WINDOWEDGE 100 Указывает на то, что окно имеет "приподнятую" границу.
WS_EX_PALETTEWINDOW 108 Является комбинацией стилей WS_EX_WINDOWEDGE и WS_EX_TOPMOST.
WS_EX_CLIENTEDGE 200 Указывает на то, что окно имеет объемный (3D) вид, т.е. рисуется с "утопленной" границей.
WS_EX_OVERLAPPEDWINDOW 300 Является комбинацией стилей WS_EX_CLIENTEDGE и WS_EX_WINDOWEDGE.
WS_EX_CONTEXTHELP 400 Позволяет поместить на заголовок окна кнопку с вопросительным знаком. Когда пользователь нажимает такую кнопку, текущий курсор изменяется на курсор с вопросительным знаком и стрелкой. Если, после этого, пользователь нажимает кнопку "мыши" на дочернем окне, оно (дочернее окно) получает сообщение WM_HELP.
WS_EX_RIGHT 1000 Задает для окна выравнивание по правому краю. Зависит от класса окна.
WS_EX_RTLREADING 2000 Отображает в окне текст с направлением чтения справа-налево.
WS_EX_LEFTSCROLLBAR 4000 При наличие вертикальной полосы прокрутки, помещает её с левой стороны клиентской области окна.
WS_EX_CONTROLPARENT 10000 Позволяет пользователю перемещаться между дочерними окнами создаваемого окна при помощи клавиши TAB.
WS_EX_STATICEDGE 20000 Создает окно с трехмерной границей. Такие окна не принимают пользовательского ввода, т.е. служат только для отображения информации.
WS_EX_APPWINDOW 40000 Ассоциирует окно верхнего уровня с кнопкой на панели быстрого доступа, когда окно не скрыто.
WS_EX_LAYERED 80000 Позволяет создать прозрачное окно.
WS_EX_NOINHERITLAYOUT 100000 Позволяет дочернему окну не наследовать формат родительского окна.
WS_EX_LAYOUTRTL 400000 Окно или элемент управления будет создан в формате RTL. Указывается как для окна, так и для элементов управления.

      Если Вы присмотритесь внимательно к таблице выше, то увидите, что любое создаваемое окно по-умолчанию имеет три установленных расширенных стиля, имеющих значение 0 - WS_EX_LEFT, WS_EX_LTRREADING и WS_EX_RIGHTSCROLLBAR - что позволяет обеспечить выравнивание по левой кромке окна, задать направление текста слева-направо и поместить вертикальную полосу прокрутки (если она имеется) в правой части клиентской области окна..

Позиция окна (position)

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

      Для получения идентификатора окна, находящегося в определенной точке экрана, используйте функцию WindowFromPoint. Аналогично, для нахождения идентификатора дочернего окна, находящегося в определенной точке клиентской области родительского окна, используйте функцию ChildWindowFromPoint, либо её расширенный аналог ChildWindowFromPointEx. Отличие последней состоит в том, что она может игнорировать скрытые, неактивные и прозрачные окна.

    invoke WindowFromPoint, Point                   ; где Point - это структура POINT
    invoke ChildWindowFromPoint, hWndParent, Point
    invoke ChildWindowFromPointEx, Point, uFlags    ; uFlags - показывает какие окна игнорировать

Размеры окна (size)

      Размер окна (высота и ширина) задаются в пикселах. Окно может иметь нулевые высоту и ширину. При установке ширины и высоты окна в ноль, система устанавливает размеры окна в минимально возможные размеры заданные по-умолчанию. Для получения этих минимальных размеров, принятых по-умолчанию в системе, можно воспользоваться функцией GetSystemMetrics с установленными флагами SM_CXMIN (28) и SM_CYMIN (29).

    invoke GetSystemMetrics, nIndex

      Для получения наименьшего размера клиентской области окна, необходимого при создании окна, воспользуйтесь функциями AdjustWindowRect или AdjustWindowRectEx. Эти функции принимают размеры клиентской области и возвращают необходимые размеры окна для размещения этой клиентской области. Полученные размеры можно затем передать в функцию CreateWindow или CreateWindowEx для создания окна.

    invoke AdjustWindowRect, lpRect, dwStyle, bMenu               ; где lpRect - это структура RECT
                                                      ; dwStyle - стиль окна
                                                      ; bMenu - указывает имеет ли окно меню
    invoke AdjustWindowRectEx, lpRect, dwStyle, bMenu, dwExStyle  ; dwExStyle - расширенный стиль окна

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

Идентификатор родительского окна или владельца

      Окно может иметь родителя. Если окно имеет родителя, оно называется дочерним. Родительское окно обладает своей системой координат, относительно которой располагается дочернее окно. Наличие родительского окна влияет на поведение дочернего окна: например, дочернее окно обрезается таким образом, чтобы не выходить за границы родительского окна. Окно, не имеющее родителя, называется окном верхнего уровня (top-level window). Для перечисления всех окон верхнего уровня, находящихся в данный момент времени на экране монитора, служит функция EnumWindows, связанная с функцией обратного вызова (callback function) EnumWindowsProc, которая возвращает идентификаторы окон. Повторю, функция EnumWindows не предназначена для перечисления дочерних окон.

    invoke EnumWindows, lpEnumFunc, lParam    ; lpEnumFunc - указатель на функцию обратного 
                                              ; вызова EnumWindowsProc. lParam - дополнительный
                                              ; параметр, который можно в неё передать.

      Кроме этого, окно может быть владельцем других окон приложения, либо может принадлежать другому окну приложения. Подчинённое окно всегда отображается поверх окна-владельца, скрыто, если его окно-владелец свёрнуто, и уничтожается при уничтожении окна-владельца.

Идентификатор меню или дочернего окна

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

    invoke SetWindowLong, hWnd, nIndex, dwNewLong
    invoke GetWindowLong, hWnd, nIndex

      Каждое окно, за исключением дочернего, может иметь меню. Меню может быть ассоциированно с окном при регистрации класса окна или при создании окна.

Идентификатор экземпляра приложения

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

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

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

Идентификатор окна

      Для создания окна используются функции CreateWindow и CreateWindowEx, возвращающие идентификатор созданного окна.

    invoke CreateWindow, lpClassName, lpWindowName, dwStyle,\
            x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam

                             или

	invoke CreateWindowEx, dwExStyle, lpClassName, lpWindowName, dwStyle,\
            x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam

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

      Для проверки существования определенного окна Вы можете использовать функцию FindWindow. Она позволяет производить поиск окна по заданному имени класса или имени окна. В случае положительного результата функция возвращает идентификатор найденного окна. Для ограничения поиска дочерними окнами определённого приложения, используйте функцию FindWindowEx.

    invoke FindWindow, lpClassName, lpWindowName
    invoke FindWindowEx, hwndParent, hwndChildAfter, lpClassName, lpWindowName

      Функция IsWindow

    invoke IsWindow, hWnd

позволяет определить принадлежит ли указанный Вами идентификатор окну системы. Имеется набор констант, которые в некоторых ситуациях позволяют избежать использования идентификатора окна. Например, приложение может установить константу HWND_BROADCAST (0FFFFh) в функциях SendMessage и SendMessageTimeout для отсылки сообщения всем окнам системы. А установка константы HWND_DESKTOP (0) в функции MapWindowPoints позволяет конвертировать координаты точек в единицах экранных координат.

    invoke SendMessage, hWnd, Msg, wParam, lParam
    invoke SendMessageTimeout, hWnd, Msg, wParam, lParam, fuFlags, uTimeout, lpdwResult

    invoke MapWindowPoints, hWndFrom, hWndTo, lpPoints, cPoints    ; где lpPoints - указатель
                                                  ; на массив структур POINT (или структур RECT)
                                                  ; cPoints - количество структур в массиве.

Создание окна

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

Создание главного окна

      Каждое Win32-приложение должно иметь точку входа, каковой является функция WinMain.

    WinMain proc hInstance:DWORD, hPrevInstance:DWORD, lpCmdLine:DWORD, nCmdShow:DWORD

      WinMain выполняет несколько задач, включающих регистрацию класса главного окна приложения и создание этого окна. Регистрация класса главного окна обеспечивается вызовом функции RegisterClass, а создание главного окна - вызовом функции CreateWindowEx.

WinMain proc hInst:HINSTANCE, hPrevInst:HINSTANCE, CmdLine:LPSTR, CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND

        ; Заполнение структуры wc:WNDCLASSEX
        mov	wc.cbSize, SIZEOF WNDCLASSEX
        mov wc.style, CS_HREDRAW or CS_VREDRAW
        mov wc.lpfnWndProc, OFFSET WndProc
        mov wc.cbClsExtra, NULL
        mov wc.cbWndExtra, NULL
        push hInstance
        pop wc.hInstance
        mov wc.hbrBackground, COLOR_WINDOW + 1
        mov wc.lpszMenuName, NULL
        mov wc.lpszClassName, OFFSET ClassName
		; Загружаем в память иконку приложения
        invoke LoadIcon, NULL, IDI_APPLICATION
        mov wc.hIcon, eax
        mov wc.hIconSm, eax
		; Подгружаем в память курсор
        invoke LoadCursor, NULL, IDC_ARROW
        mov wc.hCursor, eax

		; Регистрируем класс главного окна приложения
        invoke RegisterClassEx, addr wc

		; Создаем главное окно приложения
        invoke CreateWindowEx, NULL, addr ClassName, addr AppName, WS_OVERLAPPEDWINDOW,\
		        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,\
				NULL, NULL, hInst, NULL
        mov hwnd, eax
        
		; Отображаем и перерисовываем главное окно
        invoke ShowWindow, hwnd, CmdShow
        invoke UpdateWindow, hwnd

        ; Входим в цикл обработки сообщений
        .WHILE TRUE
                invoke GetMessage, addr msg, NULL, 0, 0
        .BREAK .IF(!eax)
        invoke TranslateMessage, addr msg
        invoke DispatchMessage, addr msg
        .ENDW
        mov eax, msg.wParam
        ret
WinMain endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
        ; Здесь происходит обработка всех сообщений, посылаемых окну
        .IF uMsg == WM_DESTROY
                invoke PostQuitMessage, NULL
        .ELSE
                invoke DefWindowProc, hWnd, uMsg, wParam, lParam
                ret
        .ENDIF
        xor eax, eax
        ret
WndProc endp

      Кроме этого, WinMain может ограничить количество запускаемых экземпляров приложения. Для этого достаточно вызовом функции CreateMutex создать именованный мютекс и сразу после этого вызвать функцию GetLastError. Если последняя возвратит ошибку ERROR_ALREADY_EXISTS (183), значит один экземпляр приложения уже запущен. В этом случае Вам остаётся только завершить приложение выходом из процедуры WinMain.

        invoke CreateMutex, NULL, TRUE, addr MutexName
        invoke GetLastError
        .if eax == ERROR_ALREADY_EXISTS
                ret
        .endif

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

    invoke ShowWindow, hWnd, nCmdShow

      И еще. Если класс окна был зарегистрирован с помощью функции RegisterClassW (Юникод-версия функции RegisterClass), то такое окно сможет получать только Юникод-сообщения. Для тех, кто в танке напоминаю, что Юникод (Unicode) - это строка символов, в которой на каждый символ отводится два байта, в отличие от Анси (ANSI), где на символ отводится один байт. Для проверки того, с каким набором символов работает окно, вызовите функцию IsWindowUnicode.

    invoke IsWindowUnicode, hWnd    ; возвращает не 0, если это Юникод-окно, если Анси-окно - возвращает 0.

      Исходный код с примером создания главного окна приложения и ограничения запускаемых экземпляров находится в файле sample_3_1.asm, а скомпилированный пример в файле sample_3_1.exe.

Сообщения о создании окна

      При создании окна, операционная система посылает сообщения оконной процедуре. Система посылает сообщение WM_NCCREATE (81h) после создания неклиентской области окна, и, после этого, оконная процедура получает сообщение WM_CREATE (1h), означающая окончание создания клиентской области окна. Оба сообщения отсылаются до отображения окна на экране монитора и содержат указатель на структуру CREATESTRUCT, в которой указаны данные, использованные при вызове функции CreateWindowEx. Обычно оконная процедура, при получении этих сообщений, производит инициализацию переменных, необходимых для последующей работы приложения.

CREATESTRUCT STRUCT
  lpCreateParams    DWORD      ?
  hInstance         DWORD      ?
  hMenu             DWORD      ?
  hWndParent        DWORD      ?
  ly                DWORD      ?
  lx                DWORD      ?
  y                 DWORD      ?
  x                 DWORD      ?
  style             DWORD      ?
  lpszName          DWORD      ?
  lpszClass         DWORD      ?
  ExStyle           DWORD      ?
CREATESTRUCT ENDS

      При создании дочернего окна система посылает родительскому окну сообщение WM_PARENTNOTIFY (210h). Это сообщение посылается только после отсылки сообщений WM_NCCREATE (81h) и WM_CREATE (1h). При создании окна операционная система отсылает также множество других сообщений. Количество и последовательность этих сообщений зависят от класса окна и применяемых при создании окна стилей. А также от функции, использованной для создания окна.

Многопоточные приложения

      Win32-приложения могут иметь множество исполняемых потоков, каждый из которых может создавать дополнительные окна. Поток, создающий окно, должен содержать код оконной процедуры.

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

    invoke EnumThreadWindows, dwThreadId, lpfn, lParam    
            ; lpfn - указатель на callback фун-цию EnumThreadWndProc

      Для выполнения обратной операции, получения идентификатора потока, создавшего определённое окно, используйте функцию GetWindowThreadProcessId.

    invoke GetWindowThreadProcessId, hWnd, lpdwProcessId   ; lpdwProcessId - указатель на переменную, 
                            ; в которую копируется идентификатор процесса (потока), создавшего окно

      Для установки режима отображения окна, созданного другим потоком, используйте функцию ShowWindowAsync.

Типы окон

Перекрываемые окна (Overlapped Windows)

      Перекрываемое окно - это окно верхнего уровня (top-level), которое имеет заголовок, границу и клиентскую область (стиль WS_OVERLAPPED (0)), т.е. оно может выступать в качестве главного окна приложения. Окно этого типа также может иметь меню, кнопки сворачивания/разворачивания и полосы прокрутки (стиль WS_OVERLAPPEDWINDOW (CF0000h)). Перекрываемое окно, выполняющее роль главного окна приложения, обычно обладает всеми из указанных компонентов.

Всплывающие окна (Pop-up Windows)

      Всплывающее окно - это специальный тип перекрываемого окна, используемый для создания диалоговых окон, окон сообщений и др., которые отображаются за пределами главного окна приложения. Заголовок является необязательным аттрибутом такого окна. Всплывающее окно создается указанием стиля WS_POPUP (80000000h). Для включения заголовка, добавьте стиль WS_CAPTION (C00000h). Используйте стиль WS_POPUPWINDOW (80880000h), чтобы создать всплывающее окно с границей и меню. Для того, чтобы сделать меню видимым, необходимо комбинировать стиль WS_CAPTION (C00000h) со стилем WS_POPUPWINDOW (80880000h).

        так без меню
        invoke CreateWindowEx, NULL, addr ClassName, addr AppName,\
                WS_CAPTION or WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT,\
                250, 200, NULL, NULL, hInst, NULL
        или так с меню
        invoke CreateWindowEx, NULL, addr ClassName, addr AppName,\
                WS_CAPTION or WS_POPUPWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,\
                250, 200, NULL, NULL, hInst, NULL

      Исходный код с примером создания всплывающих окон находятся в файлах: sample_3_2a.asm (скомпилированный пример в файле sample_3_2a.exe) - всплывающее окно с заголовком без меню и sample_3_2b.asm (скомпилированный пример в файле sample_3_2b.exe) - всплывающее окно с заголовком и меню.

Прозрачные окна (Layered Windows)

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

      Для создания прозрачного окна установите его расширенный стиль WS_EX_LAYERED (80000h) при вызове функции CreateWindowEx или вызовите функцию SetWindowLong для установки этого стиля, если окно уже создано. После создания окна функцией CreateWindowEx, оно является невидимым и для отображения его на экране необходимо вызвать либо функцию SetLayeredWindowAttributes, либо функцию UpdateLayeredWindow. Например так, для того, чтобы сделать прозрачными те места формы, где присутствует белый цвет:

        invoke SetLayeredWindowAttributes, hWnd, 0FFFFFFh, NULL, LWA_COLORKEY
        ; где LWA_COLORKEY = 1

      или так, чтобы всю форму сделать прозрачной:

    .data?
        bf BLENDFUNCTION <>
		....
    .code
        mov bf.BlendOp, AC_SRC_OVER        ; значение 0
        mov bf.BlendFlags, 0
        mov bf.SourceConstantAlpha, 0FFh
        mov bf.AlphaFormat, AC_SRC_ALPHA   ; значение 1
        invoke SetLayeredWindowAttributes, hWnd, 0, addr bf, LWA_ALPHA
        ; где LWA_ALPHA = 2

      Исходный код с примером создания главного окна приложения с поддержкой прозрачности находится в файле sample_3_3.asm, а скомпилированный пример в файле sample_3_3.exe.

      Ещё один момент. Если Вы использовали функцию SetLayeredWindowAttributes, то все последующие вызовы UpdateLayeredWindow будут возвращать ошибку. Чтобы этого не происходило, перед вызовом UpdateLayeredWindow необходимо сбросить у окна расширенный стиль WS_EX_LAYERED (80000h) и установить его повторно.

Безинтерфейсные окна сообщений (Message-Only Windows)

      Окна собщений позволяют посылать и получать сообщения. Они невидимы, не входят в очередь отображения (Z-order), их нельзя посчитать (перечислить) и они не получают широковещательных (broadcast) сообщений. Окна этого типа просто обрабатывают сообщения и всё.

      Для создания окна сообщений используйте в качестве параметра hWndParent функции CreateWindowEx или константу HWND_MESSAGE (-3) , либо идентификатор существующего окна сообщений. Также Вы можете изменить тип существующего нормального окна на тип окна сообщения, указав в качестве параметра hWndNewParent функции SetParent константу HWND_MESSAGE (-3).

      Для поиска окон сообщений, используйте функцию FindWindowEx, указав в качестве параметра hwndParent функции константу HWND_MESSAGE (-3). В дополнение, FindWindowEx отыскивает окна сообщений наравне с окнами верхнего уровня, если оба параметра функции hwndParent и hwndChildAfter установлены в NULL.

      Исходный код с примером создания окна сообщений находится в файле sample_3_4a.asm, а скомпилированный пример в файле sample_3_4a.exe. После запуска программы на выполнение, вы можете убедиться в том, что окно создано с помощью диспетчера задач Windows. Теперь Вы можете запустить пример, находящийся в файле sample_3_4b.asm (скомпилированный аналог которого находится в файле sample_3_4b.exe). Этот пример производит поиск окна сообщений при помощи функции FindWindowEx и в случае успеха, выдаёт сообщение с текстом заголовка окна сообщений и, после этого, уничтожает его.

Дочерние окна (Child Windows)

      Дочернее окно имеет стиль WS_CHILD (40000000h) и ограничено клиентской областью родительского окна. Дочерние окна часто используются для разделения клиентской области родительского окна на отдельные логические функциональные области. Создается дочернее окно заданием стиля WS_CHILD (40000000h) и функции CreateWindowEx.

      Дочернее окно должно иметь родительское окно. Родительским окном может выступать перекрываемое, всплывающее окно, или другое дочернее окно. Идентификатор родительского окна должен присутствовать в вызове CreateWindowEx. Если Вы забудете его указать, операционная система не создаст дочернее окно.

      Обычно дочернее окно создается без дополнительных стилей. Вы можете их задать сами при создании окна. Единственное, чего Вы сделать не сможете, - создать дочернее окно с меню. При указании стиля WS_CHILD (40000000h), функция CreateWindowEx игнорирует параметр hMenu. Если Вы не укажете стиль WS_BORDER (800000h), операционная система создаст дочернее окно без границ. Такие окна удобны, если Вам необходимо разделить клиентскую область родительского окна на отдельные области, но при этом скрыть от пользователя границы этих областей.

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

      Исходный код с примером создания дочерних окон находится в файле sample_3_5.asm, а скомпилированный пример в файле sample_3_5.exe.

Связи и отношения между окнами

      Что касается связей и отношений между окнами, то тут можно выделить четыре различных варианта: окно может находится на заднем плане (background window), на переднем плане (foreground window), может принадлежать другому окну (owned window) и может находится на определённом уровне слоя среди других окон (т.н. Z-order).

      Если поместить на рабочем столе два окна (скажем, два окна разных приложений или два окна двух экземпляров одного приложения), то окно, имеющее в данный момент фокус (то окно с которым взаимодействует пользователь) является активным и находится на переднем плане. Такое окно на называется окном переднего плана (foreground window). Второе же окно будет неактивным и, соответственно, будет находится на заднем плане (background window).

      Поскольку с каждым окном операционная система связывает поток, обрабатывающий сообщения данного окна, то и потоки могут быть потоками переднего и заднего плана (foreground и background threads). В нормальном состоянии ОС выделяет потоку переднего плана немного больше процессорного времени. Так, приоритет потока переднего плана равен 9, а приоритет потока заднего плана - 7.

      Чтобы превратить окно заднего плана в окно переднего плана, необходимо его активировать - кликнуть по заголовку окна или использовать комбинации клавиш клавиатуры (ALT+TAB или ALT+ESC). Для получения идентификатора окна переднего плана существует функция GetForegroundWindow. С помощью неё Вы можете легко проверить, находится ли окно вашего приложения на переднем плане, сравнив идентификатор, возвращенный функцией с идентификатором вашего окна.

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

    invoke GetForegroundWindow
    invoke SetForegroundWindow, hWnd

Статусы отображения окон

      Окна в Windows могут быть активными и неактивными, скрытыми или видимыми, минимизированными (свёрнутыми) или максимизированными (развёрнутыми на весь экран). Все эти свойства окон имеют общее название - статус отображения окна.

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

      Только одно окно верхнего уровня может быть активным в заданный момент времени. Активировать окно можно кликом по заголовку окна или используя сочетания клавиш клавиатуры (ALT+ESC или ALT+TAB). Программно активировать окно верхнего уровня можно с помощью функции SetActiveWindow.

    invoke SetActiveWindow, hWnd

      Кроме этой имеются и другие функции, активирующие окна во время исполнения:

    invoke SetWindowPos, hWndInsertAfter, X, Y, cx, cy, uFlags
    invoke DeferWindowPos, hWinPosInfo, hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags
    invoke SetWindowPlacement, hWnd, lpwndpl ; где lpwndpl - структура WINDOWPLACEMENT

    WINDOWPLACEMENT STRUCT
        iLength           DWORD       ?
        flags             DWORD       ?
        showCmd           DWORD       ?
        ptMinPosition     POINT       <>
        ptMaxPosition     POINT       <>
        rcNormalPosition  RECT        <>
    WINDOWPLACEMENT ENDS

    invoke DestroyWindow, hWnd

      Для получения идентификатора активного окна верхнего уровня используйте функцию GetActiveWindow.

    invoke GetActiveWindow	; после выполнения в eax - идентификатор активного окна. 
                            ; Если активных окон в системе нет, фун-ция возвратит NULL

      Когда, после работы с активным окном одного приложения, пользователь активирует окно другого приложения, система посылает сообщение WM_ACTIVATEAPP (1Сh) обоим приложениям, сообщая им об изменениях. Когда же пользователь активирует другое окно того же самого приложения, в котором имеется активное окно, система посылает приложению сообщение WM_ACTIVATE (6h).

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

      Для создания неактивного окна либо используют стиль WS_DISABLED (8000000h) при его создании, либо, если окно уже создано, функцию EnableWindow, где первым параметром идёт идентификатор окна, а вторым - статус отображения (TRUE - окно активируется, FALSE - окно деактивируется). Для получения статуса отображения используйте функцию IsWindowEnabled. Она возвратит 0, если окно неактивно, или ненулевое значение, если окно активно. При смене активности окна система посылает приложению сообщение WM_ENABLE (0Ah).

    invoke IsWindowEnabled, hWnd

      И ещё. При потере фокуса ввода родительским окном, все дочерние окна также теряют фокус ввода (становятся неактивными). Если Вы используете функцию EnableWindow для деактивации окна, система удаляет фокус ввода из этого окна, делает его неактивным и присваивает фокусу ввода клавиатуры значение NULL.

    invoke EnableWindow, hWnd, TRUE  ; чтобы активировать окно или FALSE, чтобы скрыть.

      Только видимые (visible) окна могут быть активными. Скрытые (hidden) окна по определению всегда неактивны. скрытое окно может получать и обрабатывать сообщения от других окон и от системы, но не может взаимодействовать с пользователем посредством клавиатуры и "мыши". Функция CreateWindowEx создает окна невидимыми, несмотря на то, что Вы указали стиль WS_VISIBLE (10000000h). Этот стиль лишь позволяет системе, отправить приложению сообщение WM_SHOWWINDOW (18h), после создания окна, но до его отображения на экране.

      Чтобы узнать, видимо ли окно, используйте функцию IsWindowVisible, передав в качестве параметра идентификатор окна.

    invoke IsWindowVisible, hWnd

      Эта функция возвращает ненулевое значение, если указанное окно, либо его родительское окно, является видимым. Она просто анализирует наличие у окна стиля WS_VISIBLE (10000000h). А раз так, то может вернуть не ноль даже, если окно закрыто другими окнами. Кроме этой функции, для смены режима видимости окна подходят функции:

    invoke ShowWindow, hWnd, nCmdShow    ; где nCmdShow - бит видимости
    invoke SetWindowPos, hWndInsertAfter, X, Y, cx, cy, uFlags
    invoke DeferWindowPos, hWinPosInfo, hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags
    invoke SetWindowPlacement, hWnd, lpwndpl ; где lpwndpl - структура WINDOWPLACEMENT
    invoke SetWindowLong, hWnd, nIndex, dwNewLong

      Эти функции просто устанавливают или удаляют у окна стиль WS_VISIBLE (10000000h). После этого они заставляют систему послать окну сообщение WM_SHOWWINDOW (18h).

      При скрытии окна, система автоматически скрывает все подчинённые ему окна. Аналогично система восстанавливает все подчинённые окна (ихи видимость и позицию) при восстановлении окна-владельца. В любом случае, система посылает всем подчинённым окнам сообщение WM_SHOWWINDOW (18h), до момента их скрытия или восстановления. Иногда возникает надобность скрыть подчинённые окна не скрывая "родителя". Для этого используйте функцию ShowOwnedPopups,

    invoke ShowOwnedPopups, hWnd, fShow    ; если fShow = TRUE, все подчинённые окна будут скрыты, 
                                           ; если fShow = FALSE - окна будут восстановлены

которая выставляет или удаляет у подчинённых окон стиль WS_VISIBLE (10000000h) и заставляет систему послать им сообщение WM_SHOWWINDOW (18h).

      Максимизированное (развёрнутое) окно - это окно со стилем WS_MAXIMIZE (1000000h). По-умолчанию, операционная система разворачивает окно таким образом, чтобы оно заполнило клиентскую область рабочего стола WIndows или, применительно к дочерним окнам, клиентскую область родительского окна. Между простым выставлением размеров окна, равным размерам максимизированного окна, и максимизированным окном существует некоторая разница. При развёртывании окна система автоматически перемещает заголовок окна в верхнюю область клиентской области окна-родителя и лишает пользователя возможности менять размеры и позицию окна.

      Минимизированное (свёрнутое) окно - это окно со стилем WS_MINIMIZE (20000000h). По-умолчанию, операционная система сворачивает окно до размеров кнопки на панели быстрого доступа, ассоциированной с данным окном.

      Восстановленное окно - это окно, позиция и размеры которого восстановлены после предыдущих изменений (сворачивания или разворачивания).

      Для сворачивания окна, после его создания, используйте функцию CloseWindow.

    invoke CloseWindow, hWnd

      Для перегруппировки иконок приложений на рабочем столе WIndows или минимизированных дочерних окон в пределах клиентской области родительского окна используйте функцию ArrangeIconicWindows

    invoke ArrangeIconicWindows, hWnd

      Функция OpenIcon восстанавливает предыдущие размеры и позицию минимизированного окна.

    invoke OpenIcon, hWnd

      Проверить является ли окно свёрнутым или развёрнутым позволяют функции:

    invoke IsZoomed, hWnd    ; если окно максимизировано (развёрнуто), возвращает ненулевое значение, иначе - 0.
	invoke IsIconic, hWnd    ; если окно минимизировано (свёрнуто), возвращает ненулевое значение, иначе - 0.
    invoke GetWindowPlacement, hWnd, lpwndpl    ; где lpwndpl - структура WINDOWPLACEMENT. Позволяет узнать
                                                ; многое о статусах отображения окна.

      Перед максимизацией окна или восстановлением минимизированного окна, система посылает приложению сообщение WM_QUERYOPEN. Если оконная процедура возвратит FALSE, система проигнорирует команду максимизации или восстановления и положение окна не изменится.

      Как уже упоминалось выше, система автоматически устанавливает размеры максимизированного окна. Изменить эти размеры, конечно, можно. Для этого можно использовать функцию SetWindowPlacement,

    invoke SetWindowPlacement, hWnd, lpwndpl    ; где lpwndpl - структура WINDOWPLACEMENT.

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

Анимация окон

      Использование функции AnimateWindow, позволяет применять специальные эффекты при скрытии и восстановлении окон.

    invoke AnimateWindow, hWnd, dwTime, dwFlags

      Функция позволяет применять три типа эффектов: roll (эффект по-умолчанию), slide и fade.

      Исходный код с примером анимации окна находится в файле sample_3_6.rar.

Формат и зеркальное отражение окон

      Формат окна отвечает за то, каким образом текст и GDI-объекты будут помещены в окне. Некоторые языки, такие как русский, английский, немецкий и т.д., требуют форматирования слева-направо (left-to-right - LTR). Другие же, такие как арабский и иврит, требуют форматирования справа-налево (right-to-left - RTL). Формат окна влияет не только на направление текста, помещенного в это окно, но также на другие GDI-элементы окна, включая рисунки, иконки, кнопки, каскадные деревья элементов, и за то с какой стороны будет расположено начало координат. Например, если выставить формат окна в RTL, то начало координат будет располагаться в правом верхнем углу экрана и значение горизонтальной координаты будет увеличиваться справа-налево. Однако не все объекты на экране затрагиваются при смене формата окна. Например, форматы диалоговых окон, окон сообщений, контексты оборудования, которые не связаны с окном (метафалы и контексты принтеров), должнены устанавливаться отдельно. Смена формата с LTR на RTL ещё называют зеркальным отражением окна. Только нужно иметь в виду, что отражение не поддерживается для окон, имеющих стиль CS_OWNDC (20h) и для контекстов с графическим режимом GM_ADVANCED (2h).

      По-умолчанию Windows создаёт окна в формате LTR. Для смены формата, нужно вызывать функцию CreateFileEx с указанием расширенного стиля WS_EX_LAYOUTRTL (400000h). Все дочерние окна наследуют формат родительского окна. Чтобы предотвратить наследование при создании дочернего окна, укажите расширенный стиль WS_EX_NOINHERITLAYOUT (100000h) в вызове CreateFileEx. Подчинённые окна не наследуют формат окна-владельца. Это касается подчинённых окон, у которых не выставлен стиль WS_CHILD (40000000h) или у которых, при создании, ссылка на родительское окно была выставлена в NULL. Чтобы избежать наследования формата для отдельно взятого окна, при получении сообщения WM_NCCREATE (81h) вызовите функции GetWindowLong и SetWindowLong для отключения стиля WS_EX_LAYOUTRTL. Фрагмент кода ниже показывает как отключить стиль WS_EX_LAYOUTRTL.

    ; Удалить бит WS_EX_LAYOUTRTL расширенного стиля окна
    invoke GetWindowLong, hWnd, GWL_EXSTYLE
    mov ecx, WS_EX_LAYOUTRTL
    not ecx
    and eax, ecx 
    invoke SetWindowLong, hWnd, GWL_EXSTYLE, eax

      Сделать форматом по-умолчанию RTL можно с помощью функции SetProcessDefaultLayout,

    invoke SetProcessDefaultLayout, dwDefaultLayout

в которой dwDefaultLayout установить в значение LAYOUT_RTL (1h). После такого вызова функции все последующие окна будут созданы в формате RTL, а существующие останутся нетронутыми. Для сброса формата по-умолчанию в LTR, вызовите SetProcessDefaultLayout с dwDefaultLayout установленным в 0. И ещё, данная функция позволяет зеркалировать контексты только зеркалируемых окон. Для смены формата контекста не связанного с окном, вызовите SetLayout.

    invoke SetLayout, hdc, dwLayout    ; где hdc - идентификатор контекста, 
                                       ; dwLayout - задаваемый контексту формат (LAYOUT_RTL (1h))

      Зеркалирование затрагивает все контексты (рисунки и иконки) зеркалируемого окна. Но это не всегда нужно. Допустим, в Вашем приложении выводится логотип фирмы или аналоговые часы, которые зеркалировать нельзя. Чтобы предотвратить зеркалирование рисунков, вызывайте SetLayout с параметром LAYOUT_BITMAPORIENTATIONPRESERVED (8h). Для сброса зеркалирования контекста, используйте SetLayout с параметром dwLayout, установленным в 0.

      Для получения текущего формата окон, заданного в системе по-умолчанию, используйте функцию GetProcessDefaultLayout, которая возвращает или LAYOUT_RTL (1h) или 0.

    invoke GetProcessDefaultLayout, pdwDefaultLayout

      Для получения текущего формата определенного контекста, используйте GetLayout, которая возвращает или LAYOUT_RTL (1h), LAYOUT_BITMAPORIENTATIONPRESERVED (8h) или их комбинацию - 9h.

    invoke GetLayout, hdc

      Для установки зеркалирования созданного окна, один лишь вызов связки GetWindowLong->SetWindowLong не поможет. После этого необходимо ещё аннулировать и перерисовать окно, чтобы изменения вступили в силу. Используйте для этого функцию InvalidateRect.

    invoke InvalidateRect, hWnd, lpRect, bErase   ; lpRect - структура RECT
                                         ; bErase - указывает на необходимость перерисовки заднего плана
                                         ; (TRUE - перерисовать, FALSE - не перерисовывать).

      Диалоговые окна и окна сообщений не наследуют форматов. Для них необходимо указывать формат отдельно. Для зеркалирования окон сообщений, создаваемых функциями MessageBox и MessageBoxEx, комбинируйте параметр uType функции с битом MB_RTLREADING (100000h).

    invoke MessageBox, hWnd, lpText, lpCaption, uType
    invoke MessageBoxEx, hWnd, lpText, lpCaption, uType, wLanguageId

      Для зеркалирования диалоговых окон используйте при их создании расширенный стиль WS_EX_LAYOUTRTL (400000h). Поскольку страницы свойств (часто используются при написании различного рода мастеров) являются набором одного и более диалоговых окон, для их зеркалирования необходимо применить стиль WS_EX_LAYOUTRTL (400000h) ко всем диалоговым окнам их составляющим.

      Контексты устройств (Device context - DC), не ассоциированные с определенным окном, не наследуют форматов. Для их зеркалирования, необходимо использовать функцию SetLayout отдельно для каждого контекста.

      И последнее. После зеркалирования окна, вызов функции GetMapMode будет возвращать MM_ISOTROPIC (7) вместо MM_TEXT (1). При этом функция SetMapMode с параметром fnMapMode, установленным в MM_TEXT (1) будет отрабатывать корректно.

    invoke GetMapMode, hdc,
    invoke SetMapMode, hdc, fnMapMode

      Исходный код с примером зеркалирования окна находится в файле sample_3_7.rar.

Уничтожение окон

      Чаще всего приложение уничтожает все окна, которые оно создало во время своей работы. Делает оно это при помощи функции DestroyWindow.

    invoke DestroyWindow, hWnd

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

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

      Если окно на момент уничтожения было активным, то фокус ввода после его уничтожения перемещается в другое окно. Узнать какое окно станет активным после уничтожения активного окна легко, использовав комбинацию ALT+ESC клавиш клавиатуры.


Предыдущая страница   Следующая страница


© 2005 ironahot@idknet.com - при использовании статей просьба делать ссылку на автора