Сказки дядюшки Римуса о x64

Тема в разделе "WASM.ARTICLES", создана пользователем Mikl___, 19 дек 2016.

Метки:
  1. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.709
    Фокус ввода
    По умолчанию, после инициализации диалоговой панели фокус ввода имеет первая кнопка. Вы можете определить в качестве кнопки, используемой "по умолчанию" любую из четырех кнопок с помощью следующих констант:
    hexbin
    MB_DEFBUTTON10XX000000000000000000000000 MB_08.png
    MB_DEFBUTTON21XX000000000000000100000000 MB_09.png
    MB_DEFBUTTON32XX000000000000001000000000 MB_10.png
    MB_DEFBUTTON43XX000000000000001100000000 MB_11.png
    MB_DEFMASKFXX000000000000111100000000для программного определения кнопки обладающей фокусом
    Модальность окна сообщения
    Немодальный диалог (MessageBox со стилем MB_APPLMODAL) пользователь должен ответить MessageBox'у, прежде чем продолжать работу в текущем окне. Пользователь может перейти на окна других приложений и работать в этих окнах. Немодальный диалог не задерживает выполнение программы, для продолжения работы программы не требуется завершение диалога MessageBox. Разрешается переключаться между диалогом MessageBox и другими приложениями.
    Модальный диалог. (MessageBox со стилем MB_SYSTEMMODAL) все приложения приостанавливаются, пока пользователь не ответит в окне MessageBox. Система модальных диалогов используется для уведомления пользователя о серьезных или потенциально опасных ошибках, которые требуют немедленного внимания и следует использовать этот стиль с осторожностью. Модальный диалог не позволит переключить ввод на другие окна, порожденные приложением.
    MessageBox со стилем MB_TASKMODAL аналогичен MessageBox со стилем MB_APPLMODAL. Эта константа зарезервирован для вызывающего приложения или библиотеки, которые не имеет доступа к дескриптору окна MessageBox.
    Чтобы понять что такое модальный или немодальный диалог, просто запустите какую-нибудь программу а затем выведите на экран MessageBox со стилем MB_SYSTEMMODAL, а теперь попробуйте переключиться на основное меню другой программы. Вы обнаружите, что не можете это сделать, потому что MessageBox блокирует фокус окна. MessageBox как бы говорит пользователю: "Сперва разберись со мной, а потом уже и все остальные программы" вы будете должны закрыть MessageBox, прежде чем сможете продолжить работу с остальными программами.
    Противоположностью ему является MessageBox со стилем MB_APPLMODAL, когда он появится на экране, вы имеете доступ и к ней, и к главному окну другой программы.
    Диалоги бывают двух видов:
    • модальные
    • немодальные
    Модальный диалог характерен тем, что после открытия MessageBox MB_SYSTEMMODAL пользователь может работать только с его элементами управления, а все остальные окна приложения блокируются до тех пор, пока модальный диалог не будет закрыт. Модальные диалоги рекомендуется использовать в тех случаях, когда без информации, вводимой через окно диалога, программа не может больше работать. Если, например, программа на некотором этапе должна ввести данные из того или иного файла, то выбор конкретного файла естественно выполнить с помощью модального диалогового окна. Нормальное состояние модального диалога ― закрытое.
    Немодальный диалог не препятствует пользователю работать с любыми элементами главного окна приложеия или его внутренних окон. С помощью немодальных диалогов задают масштаб, цвет и другие свойства приложения. Нормальное состояние немодального диалога ― открытое.
    Другой вид диалоговых панелей ― это немодальные диалоговые панели. В отличие от модальных диалоговых панелей блокирующих при своем появлении родительское окно и все дочерние окна родительского окна, немодальные диалоговые панели работают параллельно с другими окнами приложения без взаимных блокировок. Вы можете работать как с главным окном приложения, так и окном немодальной диалоговой панели. Немодальные диалоговые панели очень удобны для объединения различных инструментальных средств, предназначенных для работы с объектом, расположенным в главном окне или в дочернем окне, созданным главным окном приложения.(Фроловы)
    С помощью бит 12 и 13 вы можете влиять на модальность MessageBox

    Прочее
    Кроме перечисленных выше флагов, объединенных в группы, пользователь может использовать следующие флаги

    hexbinОписание
    MB_HELP4000h000000000100000000000000
    MB_NOFOCUS8000h000000001000000000000000 FOCUS.png NOFOCUS.png
    MB_MISCMASK0C000h000000001100000000000000используется для программного определения типа MessageBox
    Z-последовательность

    Z-последовательность (Z order) окна обозначает позицию окна в стеке перекрывающихся окон. Этот оконный стек ориентируется по воображаемой оси, z-оси (оси аппликат), уходящей за пределы экрана. Окно наверху Z-последовательности перекрывает все другие окна. Окно внизу Z-последовательности перекрыто всеми другими окнами.
    Windows Z-последовательность сохраняет в обычном списке. Добавляя окна в Z-последовательность, она основывается на том, что в любом случае они самые верхние окна, окна верхнего уровня или дочерние окна. Самое верхнее окно (topmost window) накладывается на все другие не самые верхние окна, независимо от того, является ли они активными или приоритетными окнами. Самое верхнее окно имеет стиль WS_EX_TOPMOST. Все самые верхние окна появляются в Z-последовательности перед любыми не самыми верхними окнами. Дочернее окно сгруппировано со своим родителем в Z-последовательности.
    Когда прикладная программа создает окно, Windows помещает его наверху Z-последовательности для окон того же самого типа. Вы можете использовать функцию BringWindowToTop, чтобы перенести окно в верхнюю часть Z-последовательности для окон того же самого типа. Вы можете перестраивать Z-последовательность, используя функции SetWindowPos и DeferWindowPos.
    Пользователь изменяет порядок Z-последовательности, активизируя различные окна. Windows устанавливает активное окно наверху Z-последовательности для окон того же самого типа. Когда окно переходит в верхнюю часть Z-последовательности, его дочерние окна делают это также. Вы можете использовать функцию GetTopWindow, чтобы отыскать все дочерние окна родительского окна и возвратить дескриптор дочернего окна, которое является самым высоким в Z-последовательности. Функция GetNextWindow извлекает данные о дескрипторе следующего или предыдущего окна в Z-последовательности.
    В Windows используется Z-порядок окон. Окна располагаются одно над другим по вертикали. Окно на верху лежит поверх всех. Нижнее окно в самом низу, остальные в промежутке. Для этого в Windows существует специальный список, в котором эти окна расположены. Важность окна зависит от стиля окна. Самую высокую важность имеет стиль WS_EX_TOPMOST.
    Когда система создает окно она помещает это окно на самом верху относительно окон того же самого типа. Вы можете использовать функцию BringWindowToTop, чтобы вывести окно наверх относительно окон того же самого типа. Вы можете реорганизовать порядок, используя функции DeferWindowPos и SetWindowPos.
    Функция GetNextWindow возвращает указатель к следующему или предыдущему окну в Z-порядке. Для поиска подчиненных окон используется функция GetTopWindow.
    Окно поверх всех остальных
    Вы наверно сталкивались с программами, которые всегда поверх остальных окон.
    MB_TOPMOST.png
    Если Вы запустите диалоговое приложение и нажмете на его кнопки, ваше диалоговое окно будет поверх всех остальных.
    Определите один из следующих флажков, чтобы указать модальность диалогового окна:
    Замечания
    Приоритетное окно ― окно наверху Z-последовательности. Это ― окно, с которым пользователь работает. В среде приоритетной многозадачности, Вы должны вообще дать возможность управления пользователю, окно которого является приоритетным окном. Однако прикладная программа может вызывать функцию SetForegroundWindow, если требуется перевести себя в активный режим, чтобы отобразить критическую ошибку или информацию, которая требует непосредственного внимания пользователя. Хороший пример ― это отладчик, когда он обнаруживает контрольную точку останова программы. Система назначает немного более высокий приоритет потоку, который создал приоритетное окно, чем она делает это по отношению к другим потокам.
    Если закрыть окно-хозяин (Parent window), то все MessageBox исчезают. После закрытия окна MessageBox со стилем MB_SERVICE_NOTIFICATION и MessageBox со стилем MB_DEFAULT_DESKTOP_ONLY остаются на экране
    Отобразить сообщение MessageBox может любая служба, для этого нужно в функцию MessageBox помимо прочих флагов передать MB_SERVICE_NOTIFICATION или MB_DEFAULT_DESKTOP_ONLY. Флаг MB_SERVICE_NOTIFICATION заставит функцию вывести сообщение на экран, даже если пользователь ещё не вошёл в систему.
    Если установлен флаг MB_DEFAULT_DESKTOP_ONLY, сообщение появится только на "нормальном" рабочем столе. MB_SERVICE_NOTIFICATION заставляет сообщение появиться на текущем активном desktop-е, а MB_DEFAULT_DESKTOP_ONLY только на "нормальном".
    MB_SERVICE_NOTIFICATION.png
    ПриоритетСтильbin
    1MB_SERVICE_NOTIFICATION001000000000000000000000
    1MB_DEFAULT_DESKTOP_ONLY000000100000000000000000
    2MB_TOPMOST000001000000000000000000
    2MB_SYSTEMMODAL000000000001000000000000
    3MB_SETFOREGROUND000000010000000000000000
    3MB_TASKMODAL000000000010000000000000
    3MB_OK/MB_APPLMODAL000000000000000000000000
    • если первым запущен MessageBox со стилем MB_SERVICE_NOTIFICATION, то запущенный после него MessageBox со стилем MB_DEFAULT_DESKTOP_ONLY окажется под MessageBox со стилем MB_SERVICE_NOTIFICATION
    • если первым запущен MessageBox со стилем MB_DEFAULT_DESKTOP_ONLY, то запущенный после него MessageBox со стилем MB_SERVICE_NOTIFICATION окажется под MessageBox со стилем MB_DEFAULT_DESKTOP_ONLY
    • несколько запущенных MessageBox со стилем MB_DEFAULT_DESKTOP_ONLY окажутся друг под другом
    • несколько запущенных MessageBox со стилем MB_SERVICE_NOTIFICATION окажутся друг под другом
    hexbinОписание
    MB_SETFOREGROUND10000h000000010000000000000000Панель MessageBox становится окном переднего плана. При появлении окна со стилем MB_SETFOREGROUND операционная система вызывает функцию SetForegroundWindow для MessageBox'а. Информацию о мерах безопасности при использовании этого флага смотрите в разделе "Интерактивные службы". Этот флаг может создавать интерактивный контент на заблокированном рабочем столе и должен использоваться только для очень ограниченного набора сценариев, таких как исчерпание ресурсов.
    Функция SetForegroundWindow переводит поток, который создало определяемое окно в приоритетный режим и активизирует окно. Ввод с клавиатуры направлен в окно, а различные визуальные ориентиры изменяются для пользователя.
    Код (C):
    1. BOOL SetForegroundWindow
    2. ( HWND hWnd /* дескриптор окна, которое
    3. переводится в приоритетный режим */);
    hWnd идентифицирует окно, которое должно быть активизировано и переведено в приоритетный режим. Если функция завершилась успешно, возвращается значение отличное от нуля
    MB_DEFAULT_DESKTOP_ONLY20000h000000100000000000000000Если текущий рабочий стол ввода не является рабочим столом по умолчанию, MessageBox не возвращается, пока пользователь не переключится на рабочий стол по умолчанию. "Заданный по умолчанию" рабочий стол ― первая запущенная прикладная программа, после того, как пользователь вошел в систему.
    MB_TOPMOST40000h000001000000000000000000MessageBox создается со стилем окна WS_EX_TOPMOST Рабочий стол, получивший фокус ввода должен быть рабочим столом, выбираемым по умолчанию. В противном случае функция завершается с ошибкой. Под рабочим столом, выбираемым по умолчанию, понимается рабочий стол, появляющийся после загрузки системы;
    MB_SERVICE_NOTIFICATION_NT3X40000h000001000000000000000000Вызывающая программа является обслуживающей по уведомлению пользователя о событии. Функция отображает MessageBox на текущем активном рабочем столе, даже если никто из пользователей не вошел в систему компьютера. Если этот флажок установлен, параметр hwndParent должен быть равным NULL. MessageBox с флагом MB_SERVICE_NOTIFICATION_NT3X может появляться на другом рабочем столе, а не только на том, которое соответствует hwndParent.
    MB_RIGHT80000h000010000000000000000000Обычный текст
    MB_18.png
    MessageBox с выравниванием текста в правую сторону
    MB_19.png
    MB_RTLREADING100000h000100000000000000000000Предназначен для работы с текстом на иврите или арабском. "Зеркалит" текст сообщения и расположение кнопок и иконки. Довольно интересный эффект ― обратное расположение слов в тексте сообщения
    MB_20.png
    MB_SERVICE_NOTIFICATION200000h001000000000000000000000Для Windows NT версии 4.0, значение MB_SERVICE_NOTIFICATION изменилось. Смотрите winuser.h для старых и новых значений. Windows NT 4.0 обеспечивает совместимость вниз для существующих ранее услуг, при помощи преобразования данных старых значений в новых значениях при реализации MessageBox и MessageBoxEx. Это преобразование данных делается только для исполнимых программ (.exe), которые имеют номер версии, как установлено компоновщиком, меньше чем 4.0.
    Чтобы сформировать обслуживание, которое использует MB_SERVICE_NOTIFICATION и возможность запускать, и Windows NT 3.x и Windows NT 4.0, у вас два варианта:
    1. Во время компоновки, определите номер версии меньше чем 4.0; или
    2. Во время компоновки, определите версию 4.0.
    Во время запуска, используйте функцию GetVersionEx, чтобы проверить системную версию. Тогда при продолжении запуска Windows NT 3.x, используйте MB_SERVICE_NOTIFICATION_NT3X; а для Windows NT 4.0, используйте MB_SERVICE_NOTIFICATION.
    Возвращаемые значения
    Функция MessageBox возвращает нулевое значение при ошибке или одну из следующих констант, в зависимости от того, какую кнопку нажал пользователь.
    КонстантаЗначениеНазвание
    кнопки
    Примечание
    IDOK
    1​
    [​IMG]
    IDCANCEL
    2​
    [​IMG]
    IDABORT
    3​
    [​IMG]
    IDRETRY
    4​
    [​IMG]
    IDIGNORE
    5​
    [​IMG]
    IDYES
    6​
    [​IMG]
    IDNO
    7​
    [​IMG]
    IDCANCEL
    2​
    [​IMG]
    Если у MessageBox стиль MB_OK, тогда будет возвращено IDOK, хотя есть стиль IDCLOSE=8
    IDHELP
    9​
    [​IMG]Если у MessageBox MB_HELP
    IDTRYAGAIN
    10​
    [​IMG]
    IDCONTINUE
    11​
    [​IMG]


    © Mikl___ 2019
     

    Вложения:

    • MB_29.png
      MB_29.png
      Размер файла:
      717 байт
      Просмотров:
      2.295
    • MB_28.png
      MB_28.png
      Размер файла:
      432 байт
      Просмотров:
      2.260
    • 89.png
      89.png
      Размер файла:
      7,8 КБ
      Просмотров:
      2.356
    rasstriga нравится это.
  2. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.709
    Глава шестая. Братец Кролик выводит MessageBox всеми возможными способами
    «. . в желудке слона бегемот, в бегемоте ― лев,
    внутри льва ― гиена, в гиене ― кролик, в кролике ―
    утка, в утке ― яйцо, в яйце ― игла, а на конце иглы
    смерть злого колдуна Чомбе. . .»

    Одна из сказок дядюшки Римуса​

    Казалось бы, что может быть проще функции MessageBox? Но Братец Кролику, в погоне за минимальным размером, захотелось узнать, а что находится внутри MessageBox? Может быть это поможет ему сделать программы еще меньше? Братец Кролик запустил программу, выводящую MessageBox на экран, в дебаггере x64dbg и в тот момент, когда курсор дошел до строки call MessageBoxA нажал не на F8 (Step over), а на клавишу F7 (Step into) и оказался внутри функции MessageBoxA ― оказывается здесь происходит перекодировка ASCII-строк заголовка и текста сообщений в UNICODE и вызов функции MessageBoxW. Братец Кролик снова нажал на F7 ― оказывается внутри MessageBoxW функция MessageBoxExA которая имеет на один параметр больше, чем MessageBoxA и MessageBoxW и этот параметр (dwLanguageId) равен 0 (LANG_NEUTRAL), остальные же параметры совпадают полностью. Внутри MessageBoxExA находится функция MessageBoxExW. Внутри MessageBoxExW ― функция MessageBoxTimeoutA у которой на один параметр больше, чем у MessageBoxExW и этот параметр (Timeout) равен -1 (INFINITE). Внутри MessageBoxTimeoutA, (как можно было догадаться :) ) MessageBoxTimeoutW. Внутри MessageBoxTimeoutWMessageBoxIndirectA эта функция позволяет поменять иконку у MessageBox и может вызвать Справку, но мы оставляем эти параметры с нулевым значением. Внутри MessageBoxIndirectA находится точно такая же, но с UNICODE-строками функция MessageBoxIndirectW внутри которой SoftModalMessageBox внутри которой NtRaiseHardError ― вызов MessageBox на уровне ядра
    Традиционный способ определения Unicode-строки:
    Код (ASM):
    1. usz dw 'U', 'n', 'i', 'c', 'o', 'd', 'e', ' ', 's', 't', 'r', 'i', 'n', 'g', 0
    Братца Кролика этот способ не устраивал, поэтому, он написал для этой цели макрос du (define unicode string), чтобы без проблем переводить ASCII-строки в UNICODE-строки
    Код (ASM):
    1. du    macro string
    2. local bslash
    3. bslash = 0
    4. irpc c,<string>
    5. if bslash eq 0
    6.     if '&c' eq '\' ;управляющая последовательность символов
    7.     bslash = 1
    8.     elseif '&c' eq "ё"
    9.     db 51h,4
    10.     elseif '&c' eq "Ё"
    11.     db 1,4
    12.     elseif '&c' gt 127
    13.     db ('&c'- 0B0h),4;;кириллица
    14.     else
    15.     dw '&c'          ;;латиница
    16.     endif
    17. else
    18. bslash = 0
    19.     if '&c' eq "n"    ;;  \n = новая строка
    20.         DW 0Dh,0Ah
    21.         elseif '&c' eq "\";;  \\ = обратная косая черта (\)
    22.         dw '\'
    23.         elseif '&c' eq "r";;  \r = возврат каретки
    24.         dw 0Dh
    25.         elseif '&c' eq "l";;  \l = LF
    26.         dw 0Ah
    27.         elseif '&c' eq "s"
    28.         dw 20h
    29.         elseif '&c' eq "c"
    30.         dw 3Bh
    31.         elseif '&c' eq "t";;  \t = табуляция
    32.         dw 9
    33.     endif
    34. endif
    35. endm
    36. dw 0
    37. endm
    этот макрос превращает ASCII-символы латиницы в UNICODE-символы добавлением после кода символа нуля, а для кириллицы заменяет 0 на 4 и сдвигает код символа на 176, в конце UNICODE-строки ставится ноль, терминирующий строку. Всё, что требуется от пользователя ― после du написать строку в угловых скобках. То есть представить Unicode-строку так:
    Код (ASM):
    1. usz: du <Unicode string>
    обратите внимание, что после названия строки стоит двоеточие.
    MessageBoxEx

    Функция MessageBoxEx создает, отображает на экране и оперирует окном сообщений. Окно сообщений содержит определяемое программой сообщение и заголовок, плюс любую комбинацию предопределенных пиктограмм и командных кнопок. Параметр wLanguageId определяет, какой устанавливается ресурс языка, который используется для предопределенных командных кнопок.
    Синтаксис
    Код (C):
    1. int MessageBoxEx
    2. (
    3.     HWND hWnd,        // дескриптор окна владельца
    4.     LPCTSTR lpText,        // адрес текста в окне сообщений
    5.     LPCTSTR lpCaption,    // адрес заголовка в окне сообщений
    6.     UINT uType,         // стиль окна сообщений
    7.     DWORD dwLanguageId    // идентификатор языка
    8. );
    Параметры

    hWnd
    Идентифицирует окно владельца блока сообщений, которым оно было создано. Если этот параметр имеет значение NULL, у блока сообщения нет окна владельца.​
    lpText
    Указывает на строку с символом нуля в конце, содержащую сообщение, которое должно быть отражено на экране.​
    lpCaption
    Указывает на строку с символом нуля в конце, используемую для заголовка диалогового окна. Если этот параметр значение NULL, то по умолчанию используется заголовок "Ошибка" ("Error").​
    uType
    Определяет установку битов флажков, которые обуславливают содержание и поведение диалогового окна. Этот параметр может быть комбинацией флажков.​
    dwLanguageId
    Определяет язык, на котором будет отображаться текст, содержащийся в предопределенных командных кнопках.​
    Каждый выпуск Windows обычно содержит ресурсы только для ограниченного набора языков. Английская версия предлагает LANG_ENGLISH, французская ― LANG_FRENCH, немецкая ― LANG_GERMAN и японская ― LANG_JAPANESE. Каждая версия предлагает LANG_NEUTRAL. Это ограничивает установку значений, которые могут использоваться с параметром dwLanguageId.
    Замечания

    Когда Вы используете системно-модальное окно сообщений, чтобы указать, что система имеет мало памяти, строки, переданные как параметры lpText и lpCaption не должны быть приняты из файла ресурса, так как попытка загрузить ресурс может потерпеть неудачу.
    Когда прикладная программа вызывает MessageBoxEx и устанавливает флажки MB_ICONHAND и MB_SYSTEMMODAL в параметре uType, Win32 API отображает на экране законченное окно сообщений независимо от доступной памяти. Когда эти флажки установлены, Windows ограничивает длину текста окна сообщений до одной строки.
    Если Вы создаете окно сообщений, в то время когда присутствует диалоговое окно, дескриптор блока диалога используется как параметр hWnd. Параметр hWnd не должен идентифицировать дочернее окно, типа диалогового окна.
    MessageBoxTimeout
    Синтаксис

    Код (C):
    1. int MessageBoxTimeout
    2. (
    3.     HWND hWnd,        // дескриптор окна владельца
    4.     LPCTSTR lpText,        // адрес текста в окне сообщений
    5.     LPCTSTR lpCaption,    // адрес заголовка в окне сообщений
    6.     UINT uType,         // стиль окна сообщений
    7.     DWORD dwLanguageId,    // идентификатор языка
    8.     DWORD Timeout        // время
    9. );
    Вызов аналогичен функции MessageBox, только добавляются два дополнительных параметра ― идентификатор языка и таймаут в миллисекундах.
    Код (ASM):
    1. ; MessageBox закроется автоматически через 5 секунд
    2.  invoke MessageBoxTimeout,HWND_DESKTOP,&szMess,&szTitle,MB_OK,0,5000
    По истечении отведенного времени окно сообщения закрывается с кодом возврата MB_TIMEDOUT.

    MessageBoxIndirect
    Функция MessageBoxIndirect создает, отображает и оперирует окном сообщений. Окно сообщений содержит определяемый программой текст сообщения и заголовок, любую пиктограмму, и любую комбинацию предопределенных командных кнопок.
    Синтаксис
    Код (C):
    1. int MessageBoxIndirect
    2. (
    3.     LPMSGBOXPARAMS lpMsgBoxParams    // адрес структуры для параметров
    4.             // окна сообщений
    5. );
    Параметры

    lpMsgBoxParams
    Указатель на структуру MSGBOXPARAMS, которая содержит информацию, используемую для показа на экране окна сообщений.​
    Замечания

    Когда Вы используете системно-модальное окно сообщений, чтобы указать, что у системы мало памяти, строки, указанные элементами lpszText и lpszCaption структуры MSGBOXPARAMS не должны быть приняты из файла ресурса, потому что попытка загрузить ресурс может потерпеть неудачу.
    Когда прикладная программа вызывает MessageBoxIndirect и устанавливает флажки MB_ICONHAND и MB_SYSTEMMODAL в элементе dwStyle структуры MSGBOXPARAMS, Windows показывает на экране законченное окно сообщений независимо от доступной памяти. Когда эти флажки установлены, Windows ограничивает длину текста в окне сообщений до трех строк. Windows автоматически не разрывает строки, чтобы подстроить их под окно сообщений, такая строка сообщения должна содержать символы перевода каретки, чтобы разрывать строки в соответствующих местах.
    Если Вы создаете окно сообщений, в то время, когда присутствует диалоговое окно, используйте дескриптор блока диалога как параметр hWnd. Параметр hWnd не должен идентифицировать дочернее окно, типа органа управления в диалоговом окне.
    SoftModalMessageBox
    Функция SoftModalMessageBox создает, отображает и оперирует окном сообщений. Окно сообщений содержит определяемый программой текст сообщения и заголовок, любую пиктограмму, и любую комбинацию предопределенных командных кнопок, любое количество кнопок и любые надписи на кнопках.
    [​IMG]
    Синтаксис
    Код (C):
    1. int SoftModalMessageBox
    2. (
    3.     LPMSGBOXDATA lpMsgBoxData    // адрес структуры для параметров
    4.             // окна сообщений
    5. );
    Параметры
    lpMsgBoxData

    Указатель на структуру MSGBOXDATA, которая содержит информацию, используемую для показа на экране окна сообщений.​
    Код (ASM):
    1. MSGBOXPARAMS STRUCT
    2.   cbSize                DWORD      ?,?;размер структуры
    3.   hwndOwner             QWORD      ?;
    4.   hInstance             QWORD      ?;
    5.   lpszText              QWORD      ?;адрес текста в окне сообщений
    6.   lpszCaption           QWORD      ?;адрес заголовка в окне сообщений
    7.   dwStyle               DWORD      ?,?;
    8.   lpszIcon              QWORD      ?;
    9.   dwContextHelpId       DWORD      ?,?;
    10.   lpfnMsgBoxCallback    QWORD      ?;
    11.   dwLanguageId          DWORD      ?,?;идентификатор языка
    12. MSGBOXPARAMS ENDS
    13.  
    14. MSGBOXDATA struct
    15.      params              MSGBOXPARAMSA <>
    16.      pwndOwner           QWORD ?
    17.      wLanguageId         DWORD ?,?
    18.      pidButton           QWORD ?         ; // Array of button IDs
    19.      ppszButtonText      QWORD ?         ; // Array of button text strings
    20.      cButtons            DWORD ?
    21.      DefButton           DWORD ?
    22.      CancelId            DWORD ?
    23.      Timeout             DWORD ?
    24. MSGBOXDATA ends
    NtRaiseHardError

    статус ошибки
    маска, единичные биты которой соответствуют тем параметрам, которые имеют тип PUNICODE_STRING, а нули ― остальным параметрам
    общее число параметров
    указатель на массив параметров
    варианты ответов
    двойное слово, куда функция запишет выбранный пользователем ответ (если тип, переданный в следующем параметре, предполагает выбор ответа пользователем)
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. MSGBOXDATA struct
    4.      params              MSGBOXPARAMS <>
    5.     pwndOwner           QWORD ?
    6.     wLanguageId         DWORD ?,?
    7.      pidButton           QWORD ?         ; // Array of button IDs
    8.      ppszButtonText      QWORD ?         ; // Array of button text strings
    9.      cButtons            DWORD ?
    10.      DefButton           DWORD ?
    11.      CancelId            DWORD ?
    12.      Timeout             DWORD ?
    13. MSGBOXDATA ends
    14. .code
    15. MsgBoxText      db "Win64 Assembly is Great!",0
    16. MsgBoxText1     dw 'W','i','n','6','4',' ','A','s','s','e','m','b','l','y',' ','i','s',' ','G','r','e','a','t','!',10
    17. dw 'W','i','n','6','4',27719,32534,31243,24207,24456,26834,'!',0;du <Win64 Assembly is Great>
    18. MsgCaption0     db "MessageBoxA",0
    19. MsgCaption1:    du <MessageBoxW>
    20. MsgCaption2     db "MessageBoxExA",0
    21. MsgCaption3:    du <MessageBoxExW>
    22. MsgCaption4     db "MessageBoxTimeoutA",0
    23. MsgCaption5:    du <MessageBoxTimeoutW>
    24. MsgCaption6     db "MessageBoxIndirectA",0
    25. MsgCaption7:    du <MessageBoxIndirectW>
    26. MsgCaption8:    du <SoftModalMessageBox>
    27.  
    28. sBTN1: du <OK>
    29.  
    30. dwBtnIds  dd 1
    31. dwTxtTbl  dq sBTN1
    32. x    dq ?
    33. align 16
    34. WinMain proc
    35. local mbxData:MSGBOXDATA
    36. Local MessageBuffer[50h]:WCHAR;в Num+Num1 в вордах
    37. Local Message[2]:UNICODE_STRING
    38. Local HardErrorPointer[3]:PVOID
    39.  
    40. ;MessageBoxA----------------------------------------
    41.     mov edx,offset MsgBoxText
    42.     lea r8,[rdx+MsgCaption0-MsgBoxText]
    43.     invoke MessageBox,0,,,MB_OK+10h
    44.     mov edx,offset MsgBoxText
    45.     lea r8,[rdx+MsgCaption0-MsgBoxText]
    46.     invoke MessageBox,0,,,MB_OK+20h
    47.     mov edx,offset MsgBoxText
    48.     lea r8,[rdx+MsgCaption0-MsgBoxText]
    49.     invoke MessageBox,0,,,MB_OK+30h
    50.     mov edx,offset MsgBoxText
    51.     lea r8,[rdx+MsgCaption0-MsgBoxText]
    52.     invoke MessageBox,0,,,MB_OK+40h
    53.     mov edx,offset MsgBoxText
    54.     lea r8,[rdx+MsgCaption0-MsgBoxText]
    55.     invoke MessageBox,0,,,MB_OK+90h
    56.     mov edx,offset MsgBoxText
    57.     lea r8,[rdx+MsgCaption0-MsgBoxText]
    58.     invoke MessageBox,0,,,MB_OK+0A0h
    59.     mov edx,offset MsgBoxText
    60.     lea r8,[rdx+MsgCaption0-MsgBoxText]
    61.     invoke MessageBox,0,,,MB_OK+0B0h
    62. ;MessageBoxW----------------------------------------
    63.     mov edx,offset MsgBoxText1
    64.     lea r8,[rdx+MsgCaption1-MsgBoxText1]
    65.     invoke MessageBoxW,0,,,MB_OK; or MB_ICONASTERISK
    66. ;MessageBoxExA--------------------------------------
    67.     xor ecx,ecx
    68.     mov [rsp+20h],rcx    ;wLanguageId
    69.     mov edx,offset MsgBoxText
    70.     lea r8,[rdx+MsgCaption2-MsgBoxText]
    71.         invoke MessageBoxEx,,,,MB_OK; or MB_ICONASTERISK
    72. ;MessageBoxExW--------------------------------------
    73.     xor ecx,ecx
    74.     mov [rsp+20h],rcx    ;wLanguageId=LANG_NEUTRAL=0
    75.     mov edx,offset MsgBoxText1
    76.     lea r8,[rdx+MsgCaption3-MsgBoxText1]
    77.         invoke MessageBoxExW,,,,MB_OK; or MB_ICONASTERISK
    78. ;MessageBoxTimeoutA---------------------------------
    79.     xor ecx,ecx
    80.     mov [rsp+20h],rcx       ;wLanguageId=LANG_NEUTRAL
    81.     or dword ptr [rsp+28h],INFINITE;-1 или время в миллисекундах
    82.     mov edx,offset MsgBoxText
    83.     lea r8,[rdx+MsgCaption4-MsgBoxText]
    84.     invoke MessageBoxTimeout,,,,MB_OK; or MB_ICONASTERISK
    85. ;MessageBoxTimeoutW---------------------------------
    86.     xor ecx,ecx
    87.     mov [rsp+20h],rcx       ;wLanguageId=LANG_NEUTRAL
    88.     or dword ptr [rsp+28h],INFINITE;-1
    89.     mov edx,offset MsgBoxText1
    90.     lea r8,[rdx+MsgCaption5-MsgBoxText1]
    91.     invoke MessageBoxTimeoutW,,,,MB_OK; or MB_ICONASTERISK
    92. ;MessageBoxIndirectA-------------------------------
    93.     xor eax,eax
    94.     mov mbxData.params.cbSize,sizeof MSGBOXPARAMS
    95.     mov mbxData.params.hwndOwner,rax;0
    96.     mov mbxData.params.hInstance,400000h
    97.     mov mbxData.params.dwStyle,MB_OK or MB_USERICON
    98.  
    99.          mov mbxData.params.lpszIcon,1000
    100.          mov mbxData.params.dwContextHelpId,eax;0
    101.       mov mbxData.params.lpfnMsgBoxCallback,rax;0
    102.       mov mbxData.params.dwLanguageId,eax;LANG_NEUTRAL;0
    103.     lea ecx,mbxData.params
    104.         movr mbxData.params.lpszText,MsgBoxText
    105.     movr mbxData.params.lpszCaption,MsgCaption6
    106.     invoke MessageBoxIndirect
    107. ;MessageBoxIndirectW--------------------------------
    108.         movr mbxData.params.lpszText,MsgBoxText1
    109.     movr mbxData.params.lpszCaption,MsgCaption7
    110.     lea ecx,mbxData.params
    111.     invoke MessageBoxIndirectW
    112. ;SoftModalMessageBox--------------------------------
    113.       movr mbxData.params.lpszCaption,MsgCaption8;адрес заголовка в окне сообщений   8
    114.     movr mbxData.pidButton,dwBtnIds
    115.         movr mbxData.ppszButtonText,dwTxtTbl
    116.         mov mbxData.cButtons,1;4
    117.         and qword ptr mbxData.DefButton,0;        and mbxData.DefButton,0
    118.                      ;        and mbxData.CancelId,0;2
    119.         or mbxData.Timeout,-1
    120.     lea ecx,mbxData
    121.           invoke SoftModalMessageBox
    122. ;NtRaiseHardError-----------------------------------
    123.     ;первый параметр
    124.         lea edi,MessageBuffer
    125.         mov Message.Buffer+(sizeof UNICODE_STRING)*0,rdi
    126.         mov dword ptr Message.woLength+(sizeof UNICODE_STRING)*0,30002Eh
    127.         lea edx,Message+(sizeof UNICODE_STRING)*0
    128.         mov HardErrorPointer+(sizeof PVOID)*0,rdx;pwText
    129.         mov esi,offset MessageText
    130.         mov ecx,(Num+Num1+2)/4
    131.         rep movsd
    132. ;второй параметр
    133.         lea edi,MessageBuffer+Num
    134.         mov Message.Buffer+(sizeof UNICODE_STRING)*1,rdi
    135.         mov dword ptr Message.woLength+(sizeof UNICODE_STRING)*1,220020h
    136.         lea edx,Message+(sizeof UNICODE_STRING)*1
    137.         mov HardErrorPointer+(sizeof PVOID)*1,rdx;pwCaption
    138. ;третий параметр
    139.         mov HardErrorPointer+(sizeof PVOID)*2,MB_OK or MB_ICONASTERISK;uType
    140.         lea r9d,HardErrorPointer;указатель на массив параметров
    141.     movr qword ptr [rsp+28h],x;куда функция запишет выбранный юзером ответ (если тип,
    142. ;переданный в следующем параметре, предполагает выбор ответа пользователем)
    143.         mov qword ptr [rsp+20h],1
    144.     mov edx,4
    145.     mov r8d,3
    146.         mov ecx,50000018h;STATUS_SERVICE_NOTIFICATION;статус ошибки
    147.         call NtRaiseHardError
    148. ;syscall-------------------------------------------
    149. ;первый параметр
    150.     lea edi,MessageBuffer
    151.     mov Message.Buffer+(sizeof UNICODE_STRING)*0,rdi
    152.     mov dword ptr Message.woLength+(sizeof UNICODE_STRING)*0,30002Eh
    153.     lea edx,Message+(sizeof UNICODE_STRING)*0
    154.     mov HardErrorPointer+(sizeof PVOID)*0,rdx;pwText
    155.     mov esi,offset MessageText
    156.     mov ecx,(Num1+Num3)/4
    157.     rep movsd
    158. ;второй параметр
    159.     lea edi,MessageBuffer+Num
    160.     mov Message.Buffer+(sizeof UNICODE_STRING)*1,rdi
    161.     mov dword ptr Message.woLength+(sizeof UNICODE_STRING)*1,10000Eh
    162.     lea edx,Message+(sizeof UNICODE_STRING)*1
    163.     mov HardErrorPointer+(sizeof PVOID)*1,rdx;pwCaption
    164. ;третий параметр
    165.         mov HardErrorPointer+(sizeof PVOID)*2,MB_ICONASTERISK+MB_OK;uType
    166.         lea r9d,HardErrorPointer;указатель на массив параметров
    167. ;переданный в следующем параметре, предполагает выбор ответа пользователем);
    168.     movr qword ptr [rsp+28h],x;куда функция запишет выбранный юзером ответ (если тип,
    169.         mov qword ptr [rsp+20h],1
    170.     mov edx,4
    171.     mov r8d,3
    172. ;параметрам, которые имеют тип PUNICODE_STRING, а нули -- остальным параметрам
    173.     mov ecx,50000018h;STATUS_SERVICE_NOTIFICATION;статус ошибки
    174.     mov r10,rcx
    175.     mov eax,130h
    176.     push rbx
    177.     syscall
    178.     pop rbx
    179.     invoke RtlExitUserProcess,NULL
    180. WinMain endp
    181. MessageText dw 'W','i','n','6','4',27719,32534,31243,24207,24456,26834,'!',0
    182. Num = $-MessageText
    183. TitleText: du <NtRaiseHardError>
    184. Num1 = $-TitleText
    185. dw 0
    186. TitleText1: du <syscall>
    187. Num3 = $-TitleText1
    188. end
    Здесь rc-/asm-/exe-файлы и иконка


    © Mikl___ 2021
     

    Вложения:

    • 33.png
      33.png
      Размер файла:
      358,5 КБ
      Просмотров:
      2.285
    • 22.zip
      Размер файла:
      6,2 КБ
      Просмотров:
      788
    kero, rasstriga, Коцит и ещё 1-му нравится это.
  3. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.709
    Глава девятая. Как Братец Кролик создал «генератор окошек»

    Когда вы начнете осваивать хитрости программирования под Windows, то вам поможет учебная программа для экспериментов с многочисленными параметрами используемых функций ― чтобы не надо было каждый раз редактировать и компилировать заново исходный код проекта, а можно было бы выбрать необходимые опции прямо в диалоговом окне и тут же увидеть результат
    При запуске программы появится новое окно с текстом минимальной программы под х64 в рабочей области главного окна приложения. После компиляции будет получено полноценное окно с заголовком, имеющее в левом верхнем углу свой значок, при щелчке по которому появляется системное меню; в правом верхнем углу кнопки «свертнуть», «восстановить» и «развернуть»; размеры самого окна можно изменять, перетаскивая его рамку. Параметры окна заданы программой «Simple Windows Creator» по умолчанию. Для компиляции нужно выбрать «Файл» →«Создать окно»
    83.png
    приложение появится в той же папке, в которой находится программа «Simple Windows Creator». Вам остается только запустить программу, код которой вы получили в рабочей области главного окна приложения.
    84.png
    С текстом программы можно работать используя пункты «Копировать», «Вставить», «Удалить», «Сохранить», «Выделить все»
    85.png
    Основной пункт меню для наших экспериментов ― «Параметры». Содержит следующие пункты:
    1. «Windows Class Styles...»
    2. «Иконки...»
    3. «Курсоры...»
    4. «Стили Окна...»
    5. «Расширенные Стили Окна...»
    6. «Фон Окна...»
    7. «Дополнительно...»
    Каждый из них вызывает диалоговое окно, позволяющее настроить значения полей структуры WNDCLASSEX, параметров функций CreateWindowEx. Далее приводятся описания используемых структур, функций и возможностей по настройке.
    77.png
    В winuser.h описаны пятнадцать стилей окна. Для стиля окна из 32 битов отведено 18 и только один из этих битов установлен в единицу
    Стиль классаЗначениеОписание
    binhex
    1CS_VREDRAW00000000000000000000000000000001
    1​
    Перерисовывать окно при изменении вертикальных размеров
    2CS_HREDRAW00000000000000000000000000000010
    2​
    Перерисовывать все окно при изменении ширины
    3CS_KEYCVTWINDOW00000000000000000000000000000100
    4​
    Будет выполняться преобразование виртуальных клавиш
    4CS_DBLCLKS00000000000000000000000000001000
    8​
    Посылать сообщение от мыши при двойном щелчке в пределах окна
    500000000000000000000000000010000
    10​
    6CS_OWNDC00000000000000000000000000100000
    20​
    У каждого окна уникальный контекст устройства
    7CS_CLASSDC00000000000000000000000001000000
    40​
    Один и тот же контекст устройства разделяться всеми окнами этого класса. При нескольких потоках операционная система разрешит доступ только одному потоку
    8CS_PARENTDC00000000000000000000000010000000
    80​
    Дочерние окна наследуют контекст родительского окна. У дочернего окна будет область отсечки от родительского. Повышает производительность
    9CS_NOKEYCVT00000000000000000000000100000000
    100​
    Отключается преобразование виртуальных клавиш
    10CS_NOCLOSE00000000000000000000001000000000
    200​
    Убрать команду «Close» из системного меню. Отключить команду закрыть
    1100000000000000000000010000000000
    400​
    12CS_SAVEBITS00000000000000000000100000000000
    800​
    Позволяет сохранять область экрана в виде битовой матрицы закрытую в данный момент другим окном, используется для восстановления экрана
    13CS_BYTEALIGNCLIENT00000000000000000001000000000000
    1000​
    (по горизонтали) выравнивание рабочей области окна по границе байта. Влияет на ширину окна и его горизонтальное положение на экране
    14CS_BYTEALIGNWINDOW00000000000000000010000000000000
    2000​
    (по вертикали) выравнивает окна по границе байта
    15CS_GLOBALCLASS,
    CS_PUBLICCLASS
    00000000000000000100000000000000
    4000​
    Разрешается создавать глобальный класс, не зависящего от текущего hInstance, который можно поместить в динамическую библиотеку dll.
    1600000000000000001000000000000000
    8000​
    17CS_IME0000000000000001000000000000000010000Редактор метода ввода (IME ― Input Method Editor) ― программа или компонент операционной системы, позволяющий пользователям вводить символы, которых нет на клавиатуре. Используется для ввода текста на восточно-азиатских языках (китайский, японский или корейский) требующих поддержки многобайтовых кодировок и специальных методов ввода. Окно, созданное на основе этого класса, всегда можно найти с именем класса «IME», независимо от фактического имени класса
    18CS_DROPSHADOW0000000000000010000000000000000020000Включает эффект тени в окне. Эффект включается и выключается через SPI_SETDROPSHADOW. Как правило, это разрешено для небольших короткоживущих окон, таких как меню, чтобы подчеркнуть их отношение Z-порядка к другим окнам. Windows, созданная из класса с таким стилем, должна быть окон верхнего уровня; Они не могут быть дочерними окнами.
    78.png
    1. можно выбрать стандартные иконки. В качестве первого параметра функции LoadIcon можно передать NULL; в этом случае система использует один из стандартных встроенных значков. Описание соответствующего значка отображается в диалоговом окне в виде всплывающей подсказки.
    2. можно выбрать иконку из файла ― в этом случае нужно выбрать имя файла с иконкой из каталога и указать «Иконка из файла», если в файле несколько иконок, то придется указать еще и индекс иконки.
    79.png
    1. Если параметр hInstance функции LoadCursor равен NULL, в зависимости от значения второго параметра загружается один из системных курсоров. Описание соответствующего курсора отображается во всплывающей подсказке диалогового окна.
    2. можно выбрать курсор из файла ― в этом случае нужно выбрать имя файла с курсором из каталога и указать «Курсор из файла»
    80.png
    Основной стиль окна задается в диалоге «Стили окна»
    Этот параметр может быть комбинацией стилей, приведенных в диалоге «Стили окна», и дополнительных стилей элементов управления, которые здесь не рассматриваются.
    СтильЗначениеОписание
    binhex
    WS_OVERLAPPED,
    WS_TILED
    0000.0000.0000.0000.0000.0000.0000.0000
    0​
    Перекрывающееся окно, имеющее заголовок и обрамление
    WS_ACTIVECAPTION0000.0000.0000.0000.0000.0000.0000.0001
    1​
    The window is active
    WS_TABSTOP0000.0000.0000.0001.0000.0000.0000.0000
    10000​
    Определяет элемент управления, на который можно переместиться нажатием клавиши . Нажатие данной клавиши перемещает фокус ввода на следующий элемент управления, имеющий стиль WS_TABSTOP
    WS_MAXIMIZEBOX0000.0000.0000.0001.0000.0000.0000.0000
    10000​
    Создает окно с кнопкой максимизации. Должен быть указан также стиль WS_SYSMENU. Не может быть использован со стилем WS_EX_CONTEXTHELP
    WS_MINIMIZEBOX0000.0000.0000.0010.0000.0000.0000.0000
    20000​
    Создает окно с кнопкой минимизации. Должен быть указан также стиль WS_SYSMENU. Не может быть использован со стилем WS_EX_CONTEXTHELP
    WS_GROUP0000.0000.0000.0010.0000.0000.0000.0000
    20000​
    Определяет первый управляющий элемент в группе, причем в группу входит данный элемент и все последующие до следующего управляющего элемента со стилем WS_GROUP. Обычно первый элемент в группе имеет также стиль WS_TABSTOP, чтобы пользователь мог перемещаться от одной группы к другой. Внутри группы пользователь может перемещаться от одного элемента управления к другому с использованием клавиш перемещения курсора
    WS_THICKFRAME,
    WS_SIZEBOX
    0000.0000.0000.0100.0000.0000.0000.0000
    40000​
    Создает окно, имеющее a sizing border
    WS_SYSMENU00000000000010000000000000000000
    80000​
    Создает окно, имеющее системное меню в заголовке. Должен быть также указан стиль WS_CAPTION
    WS_HSCROLL00000000000100000000000000000000
    100000​
    Создает окно, имеющее a horizontal scroll bar
    WS_VSCROLL00000000001000000000000000000000
    200000​
    Создает окно, имеющее a vertical scroll bar
    WS_DLGFRAME00000000010000000000000000000000
    400000​
    Создает окно, имеющее a border of a style typically used with dialog boxes. A window with this style cannot have a title bar
    WS_BORDER00000000100000000000000000000000
    800000​
    Создает окно, имеющее a thin-line border
    WS_CAPTION00000000110000000000000000000000
    0C00000​
    Окно с заголовком (включает в себя также стиль WS_BORDER)
    WS_OVERLAPPEDWINDOW,
    WS_TILEDWINDOW
    00000000110011110000000000000000
    0CF0000​
    Создает перекрывающееся окно с заголовком, системным меню, перемещаемым обрамлением и кнопками минимизации и максимизации (комбинация стилей WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU, WS_THICKFRAME, WS_MINIMIZEBOX и WS_MAXIMIZEBOX)
    WS_MAXIMIZE00000001000000000000000000000000
    1000000​
    Creates a window that is initially maximized
    WS_CLIPCHILDREN00000010000000000000000000000000
    2000000​
    Исключает область дочернего окна при рисовании в родительском окне. Этот стиль используется при создании родительского окна.
    WS_CLIPSIBLINGS00000100000000000000000000000000
    4000000​
    Исключение областей дочерних окон друг относительно друга, т.е. при получении дочерним окном сообщения WM_PAINT стиль WS_CLIPSIBLINGS исключает области всех других дочерних окон из зоны рисования. Если стиль WS_CLIPSIBLINGS не указан, а дочерние окна перекрываются, при рисовании в области пользователя дочернего окна возможен заход в область пользователя соседнего дочернего окна.
    WS_DISABLED00001000000000000000000000000000
    8000000​
    Создает окно, доступ к которому запрещен (окно, которое не может получать ввод от пользователя).
    WS_VISIBLE0001.0000.0000.0000.0000.0000.0000.000010000000Creates a window that is initially visible
    WS_MINIMIZE,
    WS_ICONIC
    0010.0000.0000.0000.0000.0000.0000.000020000000Creates a window that is initially minimized
    WS_CHILD,
    WS_CHILDWINDOW
    0100.0000.0000.0000.0000.0000.0000.000040000000Creates a child window. This style cannot be used with the WS_POPUP style.Excludes the area occupied by child windows when drawing occurs within the parent window. This style is used when creating the parent window.
    WS_POPUP1000.0000.0000.0000.0000.0000.0000.000080000000Creates a pop-up window. This style cannot be used with the WS_CHILD style
    WS_POPUPWINDOW1000000010001000000000000000000080880000Создает всплывающее окно с обрамлением и системным меню (комбинация стилей WS_BORDER, WS_POPUP и WS_SYSMENU). Чтобы меню окна было видимым, необходимо комбинировать данный стиль со стилем WS_CAPTION
    81.png
    Расширенные стили окна можно задать на одноименной вкладке диалогового окна «Параметры функции CreateWindowEx»
    Этот параметр может принимать значения, указанные на вкладке «Расширенные стили». Дополнительные сведения для некоторых из них приведены в таблице 3.
    СтильЗначениеОписание
    binhex
    WS_EX_LEFT0000000000000000000000000000
    0​
    Окно имеет общий стиль «левостороннего» (по умолчанию) выравнивания
    WS_EX_LTRREADING0000000000000000000000000000
    0​
    Текст окна отображается слева направо (по умолчанию)
    WS_EX_RIGHTSCROLLBAR0000000000000000000000000000
    0​
    Вертикальная полоса прокрутки (при ее наличии) размещается в правой (по умолчанию) части рабочей области окна соответственно
    WS_EX_DLGMODALFRAME0000000000000000000000000001
    1​
    Создает окно, которое имеет двойную рамку; окно может быть создано (необязательно) со строкой заголовка, которую определяет стиль WS_CAPTION в параметре dwStyle
    0000000000000000000000000010
    2​
    WS_EX_NOPARENTNOTIFY0000000000000000000000000100
    4​
    Определяет, что дочернее окно, созданное с этим стилем не посылает сообщение WM_PARENTNOTIFY родительскому окну, когда оно создается или разрушается
    WS_EX_TOPMOST0000000000000000000000001000
    8​
    Окно, созданное с этим стилем, остается поверх всех других окон без данного стиля, даже если фокус ввода принадлежит другому окну
    Определяет, что окно, созданное с этим стилем должно быть размещено выше всех, не самых верхних окон и должно стоять выше их, даже тогда, когда окно дезактивировано. Чтобы добавить или удалить этот стиль, используйте функцию SetWindowPos
    The window should be placed above all non-topmost windows and should stay above them, even when the window is deactivated. To add or remove this style, use the SetWindowPos function
    WS_EX_ACCEPTFILES0000000000000000000000010000
    10​
    Определяет, что окно, созданное с этим стилем принимает файлы при помощи информационной технологии «перетащи и вставь»
    WS_EX_TRANSPARENT0000000000000000000000100000
    20​
    Specifies that a window created with this style is to be transparent. That is, any windows that are beneath the window are not obscured by the window. A window created with this style receives WM_PAINT messages only after all sibling windows beneath it have been update
    Определяет, что окно, созданное с этим стилем должно быть прозрачным. То есть любые окна, которые появляются из-под окна, не затеняются им. Окно, созданное с этим стилем принимает WM_PAINT сообщения только после того, как все сестринские окна под ним модифицировались
    The window should not be painted until siblings beneath the window (that were created by the same thread) have been painted. The window appears transparent because the bits of underlying sibling windows have already been painted. To achieve transparency without these restrictions, use the SetWindowRgn function
    WS_EX_MDICHILD0000000000000000000001000000
    40​
    Создает дочернее MDI-окно
    WS_EX_TOOLWINDOW0000000000000000000010000000
    80​
    Creates a tool window; that is, a window intended to be used as a floating toolbar. A tool window has a title bar that is shorter than a normal title bar, and the window title is drawn using a smaller font. A tool window does not appear in the task bar or in the window that appears when the user presses ALT+TAB
    Создает окно инструментальных средств; то есть окно предполагается использовать как плавающую инструментальную панель. Окно инструментальных средств имеет строку заголовка, которая является короче, чем нормальная строка заголовка, а заголовок окна выводится, с использованием меньшего шрифта. Окно инструментальных средств не появляется в панели задач или в диалоговом окне, которое появляется, когда пользователь нажимает ALT+TAB
    The window is intended to be used as a floating toolbar. A tool window has a title bar that is shorter than a normal title bar, and the window title is drawn using a smaller font. A tool window does not appear in the taskbar or in the dialog that appears when the user presses ALT+TAB. If a tool window has a system menu, its icon is not displayed on the title bar. However, you can display the system menu by right-clicking or by typing ALT+SPACE
    WS_EX_WINDOWEDGE0000000000000000000100000000
    100​
    Определяет, что окно имеет рамку с выпуклым краем
    WS_EX_PALETTEWINDOW0000000000000000000110001000
    188​
    Объединяет стили WS_EX_WINDOWEDGE, WS_EX_TOOLWINDOW и WS_EX_TOPMOST The window is palette window, which is a modeless dialog box that presents an array of commands
    WS_EX_CLIENTEDGE0000000000000000001000000000
    200​
    Определяет, что окно имеет рамку с углубленным краем
    WS_EX_OVERLAPPEDWINDOW0000000000000000001100000000
    300​
    Объединяет стили WS_EX_WINDOWEDGE и WS_EX_CLIENTEDGE The window is an overlapped window
    WS_EX_CONTEXTHELP0000000000000000010000000000
    400​
    Включает вопросительный знак в строку заголовка окна. Когда пользователь щелкает мышью по вопросительному знаку, курсор меняется на вопросительный знак с указателем. Если пользователь затем щелкает мышью по дочернему окну, потомок принимает сообщение WM_HELP. Дочернее окно должно передать сообщение родительской оконной процедуре, которая должна вызваться функцией WinHelp, использующей команду HELP_WM_HELP. Прикладная программа Справки показывает выскакивающее окно, которое обычно содержит справку для дочернего окна. WS_EX_CONTEXTHELP не может использоваться со стилями WS_MAXIMIZEBOX или WS_MINIMIZEBOX
    0000000000000000100000000000
    800​
    WS_EX_RIGHT0000000000000001000000000000
    1000​
    Окно имеет общий стиль «правостороннего» выравнивания. «Правосторонний» стиль действует лишь, когда установлен язык с обратным порядком чтения (справа налево)
    Using the WS_EX_RIGHT style for static or edit controls has the same effect as using the SS_RIGHT or ES_RIGHT style, respectively. Using this style with button controls has the same effect as using BS_RIGHT and BS_RIGHTBUTTON styles
    WS_EX_RTLREADING0000000000000010000000000000
    2000​
    Текст окна отображается справа налево. Стиль действует лишь в случае, если установлен язык с порядком чтения справа налево.
    WS_EX_LEFTSCROLLBAR0000000000000100000000000000
    4000​
    Вертикальная полоса прокрутки (при ее наличии) размещается в левой части рабочей области окна. Слева полоса прокрутки может размещаться, если установлен язык с порядком чтения справа налево
    0000000000001000000000000000
    8000​
    WS_EX_CONTROLPARENT0000000000010000000000000000
    10000​
    Позволяет пользователю передвигаться среди дочерних окон основного окна, используя клавишу табуляции (TAB)
    The window itself contains child windows that should take part in dialog box navigation. If this style is specified, the dialog manager recurses into children of this window when performing navigation operations such as handling the TAB key, an arrow key, or a keyboard mnemonic
    WS_EX_STATICEDGE0000000000100000000000000000
    20000​
    Создает окно с трехмерным стилем рамки, предполагается использовать для элементов, которые не принимают вводимую информацию от пользователя
    WS_EX_APPWINDOW0000000001000000000000000000
    40000​
    Активизирует окно верхнего уровня на панель задач, когда окно свернуто
    WS_EX_LAYERED0000000010000000000000000000
    80000​
    The window is a layered window. This style cannot be used if the window has a class style of either CS_OWNDC or CS_CLASSDC. Windows 8: The WS_EX_LAYERED style is supported for top-level windows and child windows. Previous Windows versions support WS_EX_LAYERED only for top-level windows
    WS_EX_NOINHERITLAYOUT0000000100000000000000000000
    100000​
    The window does not pass its window layout to its child windows
    WS_EX_NOREDIRECTIONBITMAP0000001000000000000000000000
    200000​
    The window does not render to a redirection surface. This is for windows that do not have visible content or that use mechanisms other than surfaces to provide their visual
    WS_EX_LAYOUTRTL0000010000000000000000000000
    400000​
    If the shell language is Hebrew, Arabic, or another language that supports reading order alignment, the horizontal origin of the window is on the right edge. Increasing horizontal values advance to the left
    0000100000000000000000000000
    800000​
    00010000000000000000000000001000000
    WS_EX_COMPOSITED00100000000000000000000000002000000Paints all descendants of a window in bottom-to-top painting order using double-buffering. For more information, see Remarks. This cannot be used if the window has a class style of either CS_OWNDC or CS_CLASSDC. Windows 2000: This style is not supported
    01000000000000000000000000004000000
    WS_EX_NOACTIVATE10000000000000000000000000008000000A top-level window created with this style does not become the foreground window when the user clicks it. The system does not bring this window to the foreground when the user minimizes or closes the foreground window. The window should not be activated through programmatic access or via keyboard navigation by accessible technology, such as Narrator. To activate the window, use the SetActiveWindow or SetForegroundWindow function. The window does not appear on the taskbar by default. To force the window to appear on the taskbar, use the WS_EX_APPWINDOW style
    Фон окна можно выбрать на одноименном диалоге через
    1. Системные цвета
    2. GetStockObject
    3. CreateSolidBrush
    82.png
    Здесь asm- и rc-файлы, иконки и ехе-файл


    © Mikl___ 2019
     

    Вложения:

    • 31.png
      31.png
      Размер файла:
      393,5 КБ
      Просмотров:
      2.258
    • 07.zip
      Размер файла:
      81 КБ
      Просмотров:
      717
    kero, rasstriga и Коцит нравится это.
  4. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.709
    Глава сорок восьмая. Братец Кролик и немного БСДМ MSDN'a

    Типы окон

    Overlapped окна

    Overlapped окно ("перекрывающее окно") - это окно верхнего уровня (top-level window), у которого есть заголовок (title bar), рамка (border) и клиентская область (client area); предполагается, что окно этого типа будет использоваться в качестве главного окна приложения. У него также могут быть системное меню, кнопки максимизации и минимизации и полосы прокрутки. Overlapped окно обычно включает в себя все эти компоненты, когда используется в качестве главного окна приложения.
    Приложение может создать overlapped окно, указывая стиль WS_OVERLAPPED или WS_OVERLAPPEDWINDOW в функции CreateWindowEx. Если вы использовали стиль WS_OVERLAPPED, то окно будет также иметь заголовок и рамку. Если вы использовали стиль WS_OVERLAPPEDWINDOW, то окно будет иметь заголовок, изменяющую размеры рамку, системное меню и кнопки минимизации и максимизации.
    флаг WS_OVERLAPPED равен нулю, поэтому если вы не укажете иной стиль, то окно по умолчанию будет иметь стиль WS_OVERLAPPED. Стиль WS_OVERLAPPEDWINDOW - это не самостоятельный стиль, он является простой комбинацией стилей WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU, WS_THICKFRAME, WS_MINIMIZEBOX и WS_MAXIMIZEBOX.
    Pop-up окна

    Pop-up окно ("всплывающее окно") - это разновидность overlapped окна, используемая для диалоговых окон, окон-сообщений и других аналогичных временных окон, которые появляются вне главного окна приложения. Для них заголовок не обязателен; в противном случае pop-up окна не отличаются от overlapped окон со стилем WS_OVERLAPPED.
    Вы можете создать pop-up окно, указывая стиль WS_POPUP в функции CreateWindowEx. Чтобы окно имело заголовок, вам нужно отдельно указать стиль WS_CAPTION. Для создания pop-up окна с рамкой и системным меню используйте стиль WS_POPUPWINDOW. Чтобы системное меню можно было увидеть, вам также нужно включить стиль WS_CAPTION вместе со стилем WS_POPUPWINDOW.
    стиль WS_POPUPWINDOW - это не самостоятельный стиль, он является простой комбинацией стилей WS_POPUP, WS_BORDER и WS_SYSMENU.
    Child окна

    Child окно ("дочернее окно") - имеет установленный стиль WS_CHILD и ограничивается клиентской областью его родительского окна (parent window). Как правило, child окна используются приложением, чтобы разделить клиентскую область окна по функциональным зонам. Вы можете создать child окно, указывая стиль WS_CHILD в функции CreateWindowEx.
    У child окна обязательно должно быть родительское окно. Родительское окно может быть overlapped окном, pop-up окном или даже другим child окном. Вы указываете его во время вызова функции CreateWindowEx в параметре hWndParent. Если же вы укажете стиль WS_CHILD в CreateWindowEx, но не укажете родительское окно, то система откажется создавать окно.
    Child окно имеет клиентскую область, но больше никаких других дополнительных возможностей, если только вы их явно не запросите. Вы можете добавить заголовок, системное меню, кнопки минимизации и максимизации, рамку и полосы прокрутки, но child окно не может иметь меню. Если вы укажете меню при создании child окна - оно будет проигнорировано. Если вы не укажете тип рамки, то система создаст окно вообще без рамки (borderless window). Приложение может использовать такие окна для разделения клиентской области родительского окна на части без видимого указания разделения пользователю.
    Примером child окон могут служить фреймы (TFrame), панели (TPanel) и вообще практически любые другие оконные компоненты - например, кнопка (TButton). Тут нужно помнить, что "окно" в смысле пользователя - это "форма" в Delphi. Но термин "окно" в смысле системы - это вовсе не обязательно "окно" в смысле пользователя, это вообще некоторый элемент управления. Все элементы управления в Windows являются окнами в смысле системы. Кнопки, списки, строки ввода, полосы прокрутки, панели и тулбары - всё это "окна".
    Позиционирование

    Система всегда размещает child окно, используя относительные координаты - относительно левого-верхнего угла клиентской области родительского окна. Child окно не может выступать за границы своего родительского окна. Если приложение создаёт child окно больше размеров своего родительского окна, либо же размещает его так, что какая-то его часть выходит за границы родителя, то система обрезает child окно так, что часть child окна вне его родительского окна будет просто невидима.
    Кроме того, действия с родительским окном также будут иметь эффект на все его child окна, как указано в следующей таблице:
    Parent окноChild окно
    УничтожаетсяУничтожается непосредственно перед удалением своего родительского окна.
    СкрываетсяСкрывается непосредственно перед скрытием своего родительского окна. Всякое child окно видимо только если его родительское окно тоже видимо.
    ПеремещаетсяПеремещается вместе с клиентской областью своего родителя так, что его относительное положение сохраняется. Child окно ответственно за перерисовку своей клиентской области после перемещения.
    ПоказываетсяПоказывается сразу после показа своего родителя
    Обрезание
    По умолчанию система не обрезает child окно, если оно размещено вне клиентской области своего родителя (если клиентская область родителя меньше размеров самого родительского окна, поскольку система всегда обрезает child окно, вылезающее за размеры своего родителя, как указано выше). Это означает, что родительское окно будет рисовать поверх child окна, если оно производит любую операцию рисования в той же области, что и child окно. Однако систему можно попросить обрезать child окно по клиентской области своего родителя, указав стиль WS_CLIPCHILDREN родительскому окну (не дочернему). Если child окно обрезается, то родительское окно не будет рисовать поверх его.
    Child окно может пересекать другие child окна в той же клиентской области. Child окна, которые разделяют одного родителя, называются sibling окнами ("братские окна"). Пересекающиеся sibling окна могут рисовать в клиентской области друг друга, если только одно из child окон не имеет стиль WS_CLIPSIBLINGS. Если child окно указывает этот стиль, то любая часть любого другого sibling окна, лежащая в рамках этого child окна, будет обрезаться.
    Установка стилей WS_CLIPCHILDREN или WS_CLIPSIBLINGS приводит к небольшому падению производительности. Каждое окно занимает системные ресурсы, так что приложение не должно использовать дочерние окна без разбора. Для достижения оптимальной производительности приложения, которые должны логически разделять своё главное окно, должны делать это в оконной процедуре главного окна, а не с помощью дочерних окон.
    Отношение с родительским окном

    Приложение может изменить родительское окно уже созданного child окна вызовом функции SetParent. В этом случае система удаляет child окно из клиентской области старого родительского окна и размещает его в клиентской области нового родительского окна. Если в SetParent указать 0 в качестве родителя, то новым родительским окном станет рабочий стол (desktop window). В этом случае child окно рисуется на рабочем столе, вне границ любого другого окна. Функция GetParent возвращает описатель родительского окна child окна.
    Родительское окно уступает часть своей клиентской области child окну, и child окно получает весь ввод (input) с этой области. Родительское и child окно не обязаны иметь один и тот же оконный класс (window class). Это означает, что приложение может заполнить родительское окна child окнами, которые выглядят по-разному и выполняют разные задачи. Например, диалоговое окно может содержать несколько типов элементов управления, каждый из которых является child окном, которое принимает различные типы данных от пользователя.
    Child окно имеет одно и только одно родительское окно, но родительское окно может иметь сколько угодно child окон. Каждое child окно, в свою очередь, тоже может иметь сколько угодно child окон. В такой цепочке окон каждое child окно называется descendant окном (окном-потомком) исходного родительского окна. Приложение может использовать функцию IsChild, чтобы определить, является ли заданное окно child окном или descendant окном другого окна.
    Функция EnumChildWindows перечисляет все дочерние окна родительского окна. Функция EnumChildWindows передаёт описатель каждого найденного child окна в функцию обратного вызова приложения. Функция работает рекурсивно, поэтому она также перечисляет все descendant окна заданного родительского окна.
    Сообщения

    Система передаёт все сообщения ввода для child окна самому child окну напрямую, минуя окно родителя. Исключением для этого правила является случай, если дочернее окно было отключено вызовом функции EnableWindow. В этом случае система передаёт сообщения, предназначенные child окну, его родителю. Это позволяет родительскому окну проверить сообщения ввода и при необходимости включить child окно.
    Child окно также может иметь уникальный числовой идентификатор. Идентификаторы child окон важны, если вы работаете с сообщениями. Приложение управляет элементами управления, отправляя им сообщения. Приложение может использовать идентификатор child окна для отправки в него сообщений. Кроме того, если элемент управления шлёт сообщения-уведомления своему родителю, то эти сообщения будут включать в себя идентификатор child-окна, что позволит родителю идентифицировать отправителя сообщения. Приложение указывает идентификатор child окна установкой параметра hMenu функции CreateWindowEx в число - значение идентификатора (а не описатель меню).
    Layered окна

    Использование layered окна ("окна со слоями") может здорово улучшить производительность и визуальные эффекты для окон, которые имеют сложную форму, анимацию или применяют альфа-каналы. Система автоматически производит композицию и перерисовку layered окон и окон под ним. В результате layered окна рисуются гладко, без эффектов мерцания на сложных регионах. Кроме того, layered окна могут быть сделаны частично прозрачными.
    Чтобы создать layered окно, вам нужно указать флаг WS_EX_LAYERED расширенного стиля окна при вызове функции CreateWindowEx или вызвать функцию SetWindowLong уже после создания окна. После вызова CreateWindowEx layered окно не будет видимо до тех пор, пока вы не вызовите для него функцию SetLayeredWindowAttributes или функцию UpdateLayeredWindow.
    Начиная с Windows 8 WS_EX_LAYERED может использоваться как для окон верхнего уровня, так и для дочерних окон (child окон). Предыдущие версии Windows поддерживают стиль WS_EX_LAYERED только для окон верхнего уровня.
    Чтобы установить степень непрозрачности (opacity level) или цвет-маску (transparency color key) для заданного layered окна - вызовите функцию SetLayeredWindowAttributes. После этого вызова система всё ещё может запросить окно нарисовать себя при показе или перемещении. Однако, поскольку система запоминает растровое содержимое layered окна, то она не будет просить окно перерисовать себя при частичном перекрытии окна другими окнами или при его перемещении по рабочему столу. При этом устаревшим приложениям не нужно переделывать их код рисования, если они хотят добавить прозрачность или эффекты - потому что система перенаправляет рисование на окнах, которые вызвали SetLayeredWindowAttributes, на внеэкранный растр.
    Чтобы реализовать более эффективную анимацию или если вам нужно попиксельное альфа-смешение цветов - вы можете вызвать UpdateLayeredWindow. UpdateLayeredWindow следует использовать, когда приложение хочет работать напрямую с формой и содержимым layered окна, минуя внеэкранный буфер, который система предоставляет через вызов SetLayeredWindowAttributes. Кроме того, использование UpdateLayeredWindow более эффективно, потому что системе не нужно выделять дополнительную память для хранения изображения перенаправленного окна. Обратите внимание, что если вы вызвали SetLayeredWindowAttributes, то все последующие вызовы UpdateLayeredWindow завершатся с ошибкой - до тех пор, пока вы не переустановите (сбросите и заново установите) флаг WS_EX_LAYERED.
    Тестирование на попадание мышью (hit testing) для layered окна основывается на форме и прозрачности окна. Это означает, что зоны окна, которые раскрашены цветовым ключом или же их альфа-канал равен нулю, пропустят щелчки мыши мимо себя. Однако если в окне дополнительно установлен флаг WS_EX_TRANSPARENT, то всё окно целиком будет пропускать щелчки мыши сквозь себя.
    Message-Only окна

    Message-only окно ("окно для сообщений") позволяет вам принимать и отправлять оконные сообщения. Оно не видимо, не имеет Z-порядка, не появляется в перечислениях (enum) и не принимает широковещательные сообщения. Это окно просто диспетчеризирует сообщения.
    Чтобы создать message-only окно, укажите константу HWND_MESSAGE или описатель на другое message-only окно в параметре hWndParent функции CreateWindowEx. Вы также можете сконвертировать любое существующее окно в message-only окно, указав HWND_MESSAGE в качестве параметра hWndNewParent функции SetParent.
    Чтобы найти message-only окна - укажите HWND_MESSAGE в параметре hwndParent функции FindWindowEx. Кроме того, функция FindWindowEx будет искать message-only окна наравне с окнами верхнего уровня, если оба параметра hwndParent и hwndChildAfter будут равны нулю.
    Отношения между окнами

    Существует много способов, которыми одно окно может относится к пользователю или другому окну. Окно может быть владеемым, окном переднего или заднего плана, а также у него может быть задан Z-порядок по отношению к другим окнам:
    Окна первого и заднего плана

    Каждый процесс может иметь несколько потоков для выполнения, и каждый поток может создавать окна. Поток, который создал окно, с которым сейчас работает пользователь, называется потоком первого плана (foreground thread), а окно называется foreground окном (окном первого плана). Все прочие потоки называются потоками заднего плана (background thread), а все прочие окна - окнами заднего плана (background окнами).
    Каждый поток имеет уровень приоритета, который определяет количество времени процессора, получаемое этим потоком. Хотя приложение может менять уровень приоритета своих потоков, обычно поток первого плана получает небольшую прибавку приоритета по отношению к потокам заднего плана. Поэтому поток первого плана будет получать больше процессорного времени, чем потоки заднего плана. Обычно поток первого плана имеет приоритет 9, в то время как обычное значение приоритета потока заднего плана - 7.
    Пользователь задаёт окно переднего плана, щёлкая по окну, либо используя комбинации клавиш ALT+TAB или ALT+ESC. Чтобы получить описатель окна переднего плана - используйте функцию GetForegroundWindow.
    Приложение может установить окно переднего плана, используя функцию SetForegroundWindow.
    Система ограничивает процессы, которым разрешено менять окно переднего плана. Процесс сможет сделать это только если верны условия ниже:
    • процесс является процессом первого плана (т.е. окно первого плана принадлежит ему).
    • процесс был запущен процессом переднего плана.
    • процесс получил последнее сообщение ввода.
    • в системе нет процесса переднего плана.
    • процесс первого плана сейчас отлаживается.
    • смена окна первого плана не заблокирована (функцией LockSetForegroundWindow).
    • истёк таймаут блокировки окна (параметр SPI_GETFOREGROUNDLOCKTIMEOUT в SystemParametersInfo).
    • нет активных меню.
    Процесс, которому разрешено менять окно первого плана, может передать это право другому процессу вызовом функции AllowSetForegroundWindow или функции BroadcastSystemMessage с флагом BSF_ALLOWSFW. Процесс первого плана также может отключить вызовы SetForegroundWindow, вызвав функцию LockSetForegroundWindow .
    Owned окна

    Overlapped или pop-up окно может владеть другим overlapped или pop-up окном. Отношение "владелец - owned окно" накладывают ограничения на последнее:
    • Owned окно всегда находится поверх своего владельца в Z-порядке.
    • Система автоматически уничтожает owned окна при уничтожении их владельца.
    • Owned окно скрывается при минимизации своего владельца.
    Владельцем может быть только overlapped или pop-up окно; child окна владельцами быть не могут. Приложение может создать owned окно указанием описателя окна-владельца в параметре hwndParent функции CreateWindowEx, когда она создаёт окно со стилями WS_OVERLAPPED или WS_POPUP. Параметр hwndParent должен идентифицировать overlapped или pop-up окно. После создания owned окна приложение не может передать отношение владения другому окну.
    Диалоговые окна и окна-сообщения (message box) являются owned окнами. Приложение указывает окно-владельца при вызове функции, создающей диалог или окно-сообщение.
    Приложение может использовать функцию GetWindow с флагом GW_OWNER, чтобы получить описатель окна-владельца.
    Z-порядок

    Z-order (Z-порядок) окна указывает положение окна в стопке overlapped окон. Эта стопка окон ориентируется вдоль воображаемой оси (оси Z), идущей от экрана. Окно на вершине Z оси (Z-порядка) перекрывает все прочие окна. Окно на дне Z-порядка может быть перекрыто любым другим окном.
    Система хранит Z-порядок в едином списке. Она добавляет окна в список в зависимости от их типа: topmost окна, top-level окна и child окна. Окно "поверх всех" (topmost окно) перекрывает все прочие окна (не topmost окна), вне зависимости от того, является ли topmost окно активным. У topmost окон устанавливается стиль WS_EX_TOPMOST. Все topmost окна всегда располагаются в списке Z-порядка перед любыми другими не topmost окнами. Child окна группируются вместе с их родителями.
    Когда приложение создаёт окно, система помещает окно в список Z-order - на вершину цепочки окон того же типа. Вы можете использовать функцию BringWindowToTop, чтобы переместить окно на вершину списка Z-order (но только в рамках окон того же типа). Вы можете переупорядочивать окна, используя функции SetWindowPos или DeferWindowPos.
    Пользователь может изменить Z-порядок активируя различные окна. Система перемещает активное окно на вершину Z-порядка для окон того же типа. Child окна перемещаются на вершину вместе со своим родителем. Вы можете использовать функцию GetTopWindow для поиска всех child окон родительского окна и получения описателя child окна на вершине Z-порядка. Функция GetNextWindow возвращает описатель следующего или предыдущего окна в Z-порядке.
    Состояния отображения окон

    В любой момент времени произвольное окно может быть активным или не активным; скрытым или видимым; и либо минимизированным, либо максимизированным, либо развёрнутым. Все эти характеристики называются window show state (состояния отображения окон). Они обсуждаются ниже:
    • Активное окно
    • Отключенные окна
    • Видимость окон
    • Минимизированные, максимизированные и развёрнутые окна
    Активное окно

    Активное окно (active window) - это окно верхнего уровня (top-level) приложения, с которым сейчас работает пользователь. Чтобы пользователь мог опознать активное окно, система размещает активное окно на вершине Z-порядка, а также изменяет вид заголовка (выделяя его) и рамки окна. Активным окном может быть только окно верхнего уровня. Если пользователь работает с child окном, то система активирует окно верхнего уровня, ассоциированное с текущим child окном.
    В любой момент времени в системе может быть только одно активное окно. Пользователь может активировать окно (верхнего уровня) просто щёлкая по нему (или по одному из его child окон), либо используя комбинации клавиш для переключения окон (например, ALT+ESC или ALT+TAB). Приложение может сделать окно (верхнего уровня) активным, вызывая функцию SetActiveWindow. Активация окна также может происходить при использовании других функций, включая SetWindowPos, DeferWindowPos, SetWindowPlacement и DestroyWindow. Хотя приложение может менять активное окно в любое время, но чтобы не смущать пользователя, лучше всего это делать в ответ на действия пользователя. Приложение может узнать текущее активное окно вызовом функции GetActiveWindow.
    Когда активное окно изменяется с окна одного приложения на окно другого приложения, система посылает сообщение WM_ACTIVATEAPP обоим приложениям, уведомляя их об изменении активного окна. Если же активное окно изменяется с одного окна приложения на другое окно этого же приложения, то система посылает сообщение WM_ACTIVATE обоим окнам этого приложения.
    Отключенные окна

    Окно может быть отключено. Отключенное окно (disabled window) не может получать ввод пользователя (сообщения клавиатуры и мыши), но может получать сообщения от других окон, приложений и системы. Обычно приложение отключает окно для предотвращения взаимодействия с ним пользователя. К примеру, приложение может отключить кнопку в диалоге, чтобы не дать пользователю на неё нажать. Приложение может включить (enable) отключенное окно в любое время; включение окна восстановит возможность ввода.
    По умолчанию окно создаётся в доступном состоянии. Но приложение может указать стиль WS_DISABLED для создания окна в отключенном состоянии. Приложение может включить или отключить окно вызовом функции EnableWindow. Непосредственно перед изменением состояния окна система отправляет ему сообщение WM_ENABLE. Приложение может узнать статус окна вызовом функции IsWindowEnabled.
    Когда child окно отключается, система передаёт сообщения мыши от child окна его родителю. Родительское окно может использовать эти сообщения для определения того, не нужно ли включить child окно.
    В каждый момент времени только одно окно в системе может принимать клавиатурный ввод; говорят, что такое окно имеет фокус (keyboard focus). Если приложение использует функцию EnableWindow для отключения окна, которое имеет фокус ввода, то, кроме собственно отключения, окно также потеряет фокус ввода. Функция EnableWindow установит клавиатурный фокус в 0, что означает, что в системе нет окна с фокусом ввода. Аналогично, если фокус имеет child окно или descendant окно, а родитель отключается, то descendant окно теряет фокус ввода.
    Видимость окон

    Окно может быть либо видимым, либо невидимым (скрытым). Система показывает на экране только видимые окна (visible window). Все скрытые окна (hidden window) не отображаются (не рисуются). Если окно видимо, то пользователь может взаимодействовать с окном (ввод и чтение содержимого). Если окно скрыто, то оно отключается. Скрытое окно может получать сообщения от других окон, приложений или системы, но оно не может получать ввод от пользователя или отображать себя на экране (рисовать). Приложение указывает видимость окон на экране при их создании. Приложение также может менять видимость окон после создания.
    Окно видимо, если у него установлен стиль WS_VISIBLE. По умолчанию функция CreateWindowEx создаёт скрытое окно, если только приложение явно не укажет стиль WS_VISIBLE. Обычно приложение создаёт окна скрытыми, а затем показывает их - после настройки окна, чтобы пользователь не видел процесс создания окна. Если при вызове функции CreateWindowEx указан стиль WS_VISIBLE, то система отправляет окну сообщение WM_SHOWWINDOW после его создания, но до отображения на экране.
    Приложение может определить, видимо ли окно, используя функцию IsWindowVisible. Приложение может изменить видимость окон вызовом функций ShowWindow, SetWindowPos, DeferWindowPos, SetWindowPlacement или SetWindowLong. Любая из этих функций может скрыть или показать окно - удалением или добавлением стиля WS_VISIBLE. Они также отправят окну сообщение WM_SHOWWINDOW непосредственно перед его показом или скрытием.
    Когда окно-владелец (owner) минимизируется, система автоматически скрывает ассоциированные с ним owned окна. Аналогично, когда owner окно восстанавливается, система автоматически показывает ассоциированные owned окна. В обоих случаях система посылает owned окнам сообщения WM_SHOWWINDOW. Иногда приложению может понадобится скрыть owned окна не минимизируя владельца. В этом случае приложение может использовать функцию ShowOwnedPopups. Эта функция устанавливает или удаляет стиль WS_VISIBLE для всех owned окон, а также рассылает им сообщения WM_SHOWWINDOW. Учтите, что скрытие окна-владельца не влияет на видимость ассоциированных с ним owned окон.
    Когда родительское окно видимо, то его child окна также видимы. Если родительское окно скрывается, то дочерние окна также скрываются. Минимизация родительского окна не влияет на видимость дочерних окон; то есть child окна исчезают с экрана вместе с родителем, но стиль WS_VISIBLE для них не удаляется.
    Даже если у окна есть стиль WS_VISIBLE, пользователь может не видеть окна на экране; окно может быть перекрыто другими окнами или быть расположено за границами экрана. Кроме того, видимое child окно может обрезаться, как того диктуют отношения с родительским окном. И если родительское окно не видимо, то child окно также не будет видимо. Если родительское окно будет расположено за границами экрана, то его child окна также будут расположены за границами экрана, потому что child окно перемещается вместе с родительским окном, ограничен им и располагается в относительных координатах.
    Минимизированные, максимизированные и развёрнутые окна

    Максимизированное окно (maximized window) - это окно, у которого установлен стиль WS_MAXIMIZE. По умолчанию система увеличивает максимизированное окно так, чтобы оно заполняло экран или, в случае child окна, клиентскую область родительского окна. Хотя вы также можете установить размеры и положение окна так, чтобы они совпали с положением максимизированного окна, эти состояния отличаются. Система отключает возможность перемещения окна и изменения его размера для максимизированных окон. Кроме того, кнопка максимизации изменяется на кнопку восстановления размера.
    Минимизированное окно (minimized window) - это окно, у которого установлен стиль WS_MINIMIZE. По умолчанию система уменьшает окно до размеров его кнопки на панели задач и перемещает окно на панель задач.
    Развёрнутое окно (restored window) - это окно, которое было восстановлено в исходные размер и положение после минимизации или максимизации.
    Если приложение укажет стили WS_MAXIMIZE или WS_MINIMIZE в функции CreateWindowEx, окно создастся изначально максимизированным или минимизированным. После создания окна приложение может использовать функцию CloseWindow для минимизации окна. Функция ArrangeIconicWindows упорядочивает свёрнутые окна на рабочем столе или в родительском окне. Функция OpenIcon восстанавливает минимизированное окно.
    Функция ShowWindow может минимизировать, максимизировать и восстанавливать окна. Она также может менять видимость окон и задавать активное окно. Функция SetWindowPlacement содержит ту же функциональность, что и ShowWindow, но она также может менять размещение окна по умолчанию в положениях минимизации, максимизации и восстановления.
     

    Вложения:

    • 30.png
      30.png
      Размер файла:
      495,6 КБ
      Просмотров:
      842
    • 00.png
      00.png
      Размер файла:
      251,5 КБ
      Просмотров:
      2.138
    • 00.jpg
      00.jpg
      Размер файла:
      165,9 КБ
      Просмотров:
      201
    kero нравится это.
  5. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.709
    Функции IsZoomed и IsIconic определяют, является ли заданное окно максимизированным или минимизированным соответственно. Функция GetWindowPlacement может получить положения минимизации, максимизации и восстановления для окна, а также определить состояние отображения окна.
    Когда система получает команду на максимизацию или восстановление минимизированного окна, она отправляет окну сообщение WM_QUERYOPEN. Если оконная процедура вернёт 0, то система проигнориует команду максимизации или восстановления.
    Система автоматически устанавливает размеры и положение максимизированного окна. Чтобы изменить системные умолчания, приложение может либо использовать функцию SetWindowPlacement, либо обрабатывать сообщение WM_GETMINMAXINFO, которое отправляется окну непосредственно перед максимизацией. Сообщение WM_GETMINMAXINFO содержит указатель на запись MINMAXINFO, содержащую значения размера и положения окна, присвоенные системой. Приложение может изменить эти значения.
    Размер и положение окна

    Размер и положение окна выражаются как ограничивающий прямоугольник (bounding rectangle), задавая его координаты относительно экрана (для окон верхнего уровня) или родительского окна (для child окон). Приложение указывает размер и положение окна при его создании, но может изменить их в любое время.
    В этой секции также рассматриваются:
    • Размеры и положение по умолчанию
    • Отслеживание размера
    • Системные команды
    • Функции для размера и положения
    • Сообщения для размера и положения
    Размеры и положение по умолчанию

    Приложение может разрешить системе задать начальные положение и размер окна верхнего уровня, указав CW_USEDEFAULT в функции CreateWindowEx. Если приложение установит координаты окна в значение CW_USEDEFAULT, то если приложение не создало других окон верхнего уровня, то система будет размещать окно относительно экрана; в противном случае система будет размещать окно относительно последнего созданного окна верхнего уровня. Если приложение также укажет CW_USEDEFAULT для ширины и высоты окна, то размеры окна будут определяться системой. Если приложение до этого создавало окна верхнего уровня, то система будет определять размер окна по последнему созданному окну верхнего уровня. Указание CW_USEDEFAULT для child или pop-up окна создаст окно с минимальным размером.
    Отслеживание размера

    Система хранит максимальный и минимальный размеры окон со стилем WS_THICKFRAME; окно с этим стилем имеет рамку с возможностью изменения размера. Минимальный размер (minimum tracking size) - это наименьший размер окна, который пользователь сможет задать, перетаскивая рамку окна. Аналогично максимальный размер (maximum tracking size) - это наибольший размер окна, который сможет получить пользователь при изменении размеров окна.
    Минимальные и максимальные размеры окна устанавливаются в системные значения по умолчанию при создании окна. Приложение может узнать эти значения и заместить их на свои при обработке сообщения WM_GETMINMAXINFO.
    Системные команды

    Приложение, которое имеет оконное меню ("системное меню"), может изменить размеры окна отправкой системный команд. Системные команды отправляются, когда пользователь выбирает команды из оконного меню. Приложение может эмулировать действия пользователя отправкой сообщения WM_SYSCOMMAND окну. Следующие системные команды влияют на размер и положение окна:
    КомандаОписание
    SC_CLOSEЗакрывает окно. Эта команда отправляет сообщение WM_CLOSE окну. Дальнейшие действия зависят от окна (обработчика сообщения WM_CLOSE).
    SC_MAXIMIZEМаксимизирует окно.
    SC_MINIMIZEМинимизирует окно.
    SC_MOVEПеремещает окно.
    SC_RESTOREВосстанавливает минимизированное или максимизированное окно на его исходные положение и размер.
    SC_SIZEНачинает процедуру изменения размера. Для изменения размера окна можно использовать мышь или стрелки на клавиатуре.
    Функции для размера и положения

    После создания окна приложение может установить размер или положение окна вызовом одной из следующих функций: SetWindowPlacement, MoveWindow, SetWindowPos и DeferWindowPos. SetWindowPlacement может установить минимизированный размер, максимизированный размер, обычный размер и положение окна, а также состояние видимости. Функции MoveWindow и SetWindowPos похожи; они обе устанавливают размер или положение одного окна в приложении. Но функция SetWindowPos допускает изменение видимости окна; а MoveWindow - нет. Используя функции BeginDeferWindowPos, DeferWindowPos и EndDeferWindowPos, приложение может одновременно изменить атрибуты нескольких окон сразу - включая положение, размеры, Z-порядок и видимость.
    Приложение может получить ограничивающий прямоугольник вызовом функции GetWindowRect. GetWindowRect заполняет запись TRect координатами левого-верхнего и правого-нижнего углов окна. Координаты вычисляются относительно левого-верхнего угла экрана - даже для child окон (позиционирование которых осуществляется относительно родительского окна). Функции ScreenToClient или MapWindowPoints могут быть использованы для перевода экранных координат в относительные координаты для child окон.
    Функция GetClientRect возвращает координаты клиентской области окна. GetClientRect заполняет TRect координатами левого-верхнего и правого-нижнего углов клиентской области окна, но координаты считаются относительно самой клиентской области окна. То есть левый-верхний угол всегда имеет координаты (0, 0), а координаты правого-нижнего угла - это ширина и высота клиентской области окна.
    Функция CascadeWindows раскладывает каскадом (cascade) окна на рабочем столе или child окна в родительском окне. Функция TileWindows раскладывает окна черепицей (tiles).
    Сообщения для размера и положения

    Окну, чьё положение должно измениться, система отправляет сообщение WM_GETMINMAXINFO. К примеру, это сообщение будет отправлено, если пользователь щёлкнул по командам Переместить или Изменить размер из оконного меню или щёлкает по рамке окна или заголовку; также это сообщение будет отправлено, если приложение вызовет функцию SetWindowPos для перемещения или изменения размера окна. Сообщение WM_GETMINMAXINFO передаёт указатель на запись TMinMaxInfo, которая содержит размер и положение максимизированного окна по умолчанию, равно как и минимальные и максимальные размеры окна. Приложение может изменить эти значения, обрабатывая сообщение WM_GETMINMAXINFO. Чтобы получать сообщения WM_GETMINMAXINFO, окно должно иметь стиль WS_THICKFRAME или WS_CAPTION. Окно со стилем WS_THICKFRAME получит это сообщение во время создания окна, а также при изменениях размера и положения.
    Окну, чьи размеры, положение, Z-порядок или видимость должны измениться, система отправит сообщение WM_WINDOWPOSCHANGING. Это сообщение содержит указатель на запись TWindowsPos, которая указывает новые положения, размер, Z-порядок и видимость окна. Изменяя поля записи TWindowsPos, приложение может изменить способ отображения окна.
    После того, как изменились размер, положение, Z-порядок или видимость окна, система отправляет окну сообщение WM_WINDOWPOSCHANGED. Это сообщение содержит указатель на запись TWindowPos, которая информирует окно о его новых атрибутах. Изменение этой записи не приведёт к изменению атрибутов окна. Окно, которому нужно обрабатывать сообщения WM_SIZE и WM_MOVE, должно передавать сообщение WM_WINDOWPOSCHANGED в функцию DefWindowProc; иначе система не будет рассылать сообщения WM_SIZE и WM_MOVE.
    Когда окно создаётся или изменяет размер, система также отправляет окну сообщение WM_NCCALCSIZE. Это сообщение используется системой для вычисления размера и относительного положения клиентской области окна (относительно левого-верхнего угла самого окна). Как правило, окно просто передаёт это сообщение обработчику по умолчанию; однако это сообщение может быть использовано приложениями, которые хотят изменить размеры клиентской области окна.
    Анимация окон

    Вы можете создавать специальные эффекты при показе или скрытии окон, используя функцию AnimateWindow. При использовании этой функции вы можете указать эффекты roll, slide, collapse, expand или fade.
    По умолчанию система использует анимацию roll. При этой анимации окно "раскатывается" от одного края до противоположного. Вы можете указать в флагах направление анимации: горизонтально, вертикально или по диагонали.
    С флагом AW_SLIDE система использует анимацию slide. При этом окно "выезжает". Анимация похожа на roll анимацию. roll анимация использует сглаженный край окна, имитируя рулон, а slide использует чёткие края, имитируя плоское окно. Аналогично, вы можете указать в флагах направление анимации: горизонтально, вертикально или по диагонали.
    Флаг AW_BLEND задаёт анимацию alpha-blended fade. При этом окно постепенно "проявляется" или исчезает. У этой анимации нет направления.
    Вы также можете использовать флаг AW_CENTER для анимации разворота окна из центра окна. Анимация похожа на roll анимацию, но roll анимация показывает окно от границы к границе окна, а center анимация - от центра окна до его границ. У этой анимации нет направления.
    Компоновка и отражение

    Компоновка окна (window layout) определяет способ размещения в окне или контексте устройства (DC - Device Context) текста и объектов GDI. Некоторые языки (вроде английского, французского, русского и немецкого) требуют компоновку left-to-right (LTR) - "слева направо". Другие языки (арабский, иврит) требуют компоновки right-to-left (RTL) - "справа налево". Компоновка окна применяется к тексту, но она также влияет и на другие элементы окна, включая растры, значки, расположение кнопок, многоуровневых деревьев, то, будет ли увеличиваться или уменьшаться горизонтальная координата при сдвиге вправо и т.п. К примеру, после того, как приложение установит компоновку RTL, начало координатной сетки в окне будет расположено в правом-верхнем углу окна (или контекста устройства) - в то время как обычно точка отсчёта располагается в левом-верхнем угле; а горизонтальная координата будет увеличиваться при движении влево, а не вправо, как это было с LTR. Однако не все объекты подчиняются компоновке окна. К примеру, компоновки диалоговых окон, окон-сообщений (message box) и контекстов устройств, не ассоциированных с окном (метафайлы, принтеры и другие) - обрабатываются отдельно. Некоторые такие особенности также упомянуты ниже.
    Оконные функции позволяют вам указать или изменить компоновку окна. Заметьте, что изменение компоновки на RTL (этот процесс также называется зеркалированием или отражением окна - mirroring) не поддерживается окнами, которые установили стиль CS_OWNDC, а также контекстами устройств в режиме GM_ADVANCED.
    По умолчанию окно и контексты устройств имеют компоновку left-to-right (LTR). Чтобы изменить компоновку окна на RTL - вызовите функцию CreateWindowEx с флагом WS_EX_LAYOUTRTL. Также, по умолчанию, child окна (т.е. окна, создаваемые со стилем WS_CHILD) будут иметь ту же компоновку, что и их родитель. Чтобы отключить наследование зеркалирования для child окон и задавать компоновку явно - добавьте стиль WS_EX_NOINHERITLAYOUT в вызове CreateWindowEx. Заметьте, что компоновка не наследуется owned окнами (создаваемыми без стиля WS_CHILD) или окнами, чей параметр hWnd в функции CreateWindowEx был установлен в 0. Чтобы отключить наследование зеркалирования в отдельном окне, обработайте сообщение WM_NCCREATE, где используйте функции GetWindowLong и SetWindowLong для замены флага WS_EX_LAYOUTRTL.
    Вы также можете изменить умолчание для всего процесса вызовом функции SetProcessDefaultLayout. Все окна, создаваемые после вызова SetProcessDefaultLayout (LAYOUT_RTL), будут создаваться зеркалированными (без указания флага), но уже существующие окна не изменятся. Чтобы отключить зеркалирование по умолчанию - используйте SetProcessDefaultLayout(0).
    Заметьте, что функция SetProcessDefaultLayout отразит контексты устройств только в отзеркалированных окнах. Чтобы отразить произвольный DC - вызовите функцию SetLayout.
    Растры (bitmap) и значки (icon) в отражённом окне также по умолчанию зеркалируются. Однако это не всегда бывает необходимо. Чтобы отключить зеркалирование растра, вызовите функцию SetLayout с установленным флагом LAYOUT_BITMAPORIENTATIONPRESERVED в dwLayout. Чтобы отключить зеркалирование в DC, вызовите SetLayout(DC, 0).
    Чтобы узнать текущую компоновку по умолчанию, вызовите функцию GetProcessDefaultLayout. При успешном вызове pdwDefaultLayout будет содержать LAYOUT_RTL или 0. Чтобы узнать компоновку контекста устройства, вызовите функцию GetLayout. При успешном вызове она вернёт набор флагов, управляющих компоновкой, которые вы можете проверить на LAYOUT_RTL и LAYOUT_BITMAPORIENTATIONPRESERVED.
    Изменить компоновку после создания окна можно функцией SetWindowLong. К примеру, это может понадобится при смене языка UI в run-time. Однако при этом вы также должны обновить (перерисовать) содержимое окна.
    При отражении окна вы должны думать в терминах "ближе" и "дальше", а не "левее" и "правее". Иначе у вас могут быть проблемы. Частой ошибкой является сценарий конвертирования координат между экранными и клиентскими. К примеру, приложение может использовать такой код для расположения элемента управления в окне:
    Код (Pascal):
    1. // КОД НИЖЕ - ОШИБОЧЕН
    2.  
    3. // Получаем координаты окна в экранных координатах
    4. GetWindowRect(hControl, rControlRect);
    5.  
    6. // Проецируем координаты экрана в клиентские координаты диалога
    7. ScreenToClient(hDialog, rControlRect.left);
    8. ScreenToClient(hDialog, rControlRect.right);
    Этот код вызовет проблемы в отзеркалированных окнах, потому что в них "лево" становится "право" и наоборот. Чтобы избежать этой проблемы, замените вызовы функции ScreenToClient на вызовы MapWindowPoints:
    Код (Pascal):
    1. // Корректный код
    2. GetWindowRect(hControl, ControlRect);
    3. MapWindowPoints(0, hDialog, rControlRect, 2);
    Этот код будет работать корректно, потому что функция MapWindowPoints умеет работать с прямоугольниками (ScreenToClient и ClientToScreen работают только с точками), поэтому она может учесть зеркалированность окон и поменять местами левые и правые грани прямоугольника при необходимости.
    Ещё одна практика, которая может вызвать проблемы в отзеркалированных окнах - позиционирование элементов управления, используя экранные координаты вместо клиентских. К примеру, код ниже использует разницу в экранных коодинатах для размещения элемента управления в диалоговом окне:
    Код (Pascal):
    1. // КОД НИЖЕ - ОШИБОЧЕН
    2. var
    3.   rdDialog: TRect;
    4.   rcControl: TRect;
    5.   hControl: HWND;
    6. begin
    7.   GetWindowRect(hDlg, rcDialog);              // Получение прямоугольника в экранных координатах
    8.   GetWindowRect(hControl, rcControl);
    9.   MoveWindow(hControl,
    10.              rcControl.left - rcDialog.left,  // Получение позиции x в клиентских координатах
    11.              rcControl.top - rcDialog.top,
    12.              nWidth,
    13.              nHeight,
    14.              False);
    Этот код будет работать для диалогового окна с компоновкой left-to-right (LTR) и режимом проецирования (mapping mode) элемента управления MM_TEXT, потому что новая позиция по X в клиентских координатах соответствует разнице в левых краях элемента управления и диалога в экранных координатах. Но для отзеркалированного диалога вам нужно использовать MapWindowPoints, как показано ниже:
    Код (Pascal):
    1. // Корректный код
    2. var
    3.   rcDialog: TRect;
    4.   rcControl: TRect;
    5.   hControl: HWND;
    6. begin
    7.   ..
    8.   GetWindowRect(hControl, rcControl);
    9.  
    10.   // MapWindowPoints работает корректно в обоих режимах (прямом и зеркальном)
    11.   MapWindowPoints(0, hDlg, rcControl, 2);
    12.  
    13.   // Теперь rcControl - в клиентских координатах
    14.   MoveWindow(hControl, rcControl.left, rcControl.top, nWidth, nHeight, False);
    Отражение диалоговых окон и окон-сообщений

    Диалоговые окна и окна-сообщения (message box) не наследуют компоновку окна, поэтому вам нужно устанавливать компоновку явно. Чтобы отразить окно-сообщени, используйте флаг MB_RTLREADING при вызове функций MessageBox или MessageBoxEx. Чтобы изменить компоновку диалога - укажите стиль WS_EX_LAYOUTRTL в шаблоне диалога. Вкладки свойств (property sheets) являются частным случаем диалогов. Каждая вкладка трактуется как отдельный диалог, поэтому вам нужно включать стиль WS_EX_LAYOUTRTL для каждой вкладки отдельно.
    Отражение контекстов устройств, не ассоциированных с окном

    Контексты устройств (DC), которые не ассоциированы с окном, не наследуют компоновку, поэтому вам нужно указывать её явно. Для изменения компоновки контекста устройства используйте функцию SetLayout.
    Функция SetLayout редко используется с окнами. Как правило, окна получают ассоциированный DC только при обработке сообщения WM_PAINT. Иногда приложение может создавать DC для окна вызовом GetDC. В любом случае, компоновка этих DC устанавливается в соответствии с компоновкой целевого окна.
    Вызов функции SetLayout не влияет на значения, возвращаемые функциями GetWindowOrgEx, GetWindowExtEx, GetViewportOrgEx и GetViewportExtEx.
    При RTL компоновке функция GetMapMode вернёт MM_ANISOTROPIC вместо MM_TEXT. Вызов SetMapMode с MM_TEXT будет работать корректно; будет изменено только возвращаемое значение GetMapMode. Аналогично, вызов SetLayout(hdc, LAYOUT_RTL) при режиме MM_TEXT приведёт к смене режима на MM_ANISOTROPIC.
    Уничтожение окна

    В целом, приложение должно уничтожать все окна, которые оно создало. Оно может сделать это вызывая функцию DestroyWindow. Когда окно уничтожается, система скрывает окно (если оно было видимо), а затем удаляет все внутренние данные, ассоциированные с окном. Описатель окна (handle) становится недопустимым и не должен более использоваться приложением.
    Обычно приложения удаляет окна вскоре после их создания. К примеру, приложение удаляет диалоговое окно со всеми дочерними окнами как только оно получит достаточно информации от пользователя. В конечном итоге приложение уничтожит и главное окно (непосредственно перед выходом).
    Перед уничтожением окна приложение должно удалить любые данные, ассоциированные с окном (если они есть), а также освободить системные ресурсы, выделенные для окна. Если приложение не освободит ресурсы, то они будут освобождены системой при завершении приложения.
    Уничтожение окна не влияет на оконный класс этого окна. Приложение может создавать окна данного оконного класса и после удаления окна этого класса, равно как и продолжить использование других окон этого класса. Уничтожение окна также уничтожит все его descendant окна (т.е. все child окна, child окна child окон и так далее). Функция DestroyWindow отправляет сообщение WM_DESTROY сначала самому окну, затем всем его child окнам, а затем, аналогично, и descendant окнам.
    Окно с оконным меню также получит сообщение WM_CLOSE, когда пользователь щёлкнет по Закрыть. Приложение может запросить у пользователя подтверждение закрытия окна в обработчике этого сообщения. Если пользователь согласен с закрытием окна, то приложение может вызвать функцию DestroyWindow для уничтожения окна.
    Если уничтожаемое окно является активным, то активным окном становится другое окно. Оно же получает фокус ввода. Окно, которое станет активным, определяется по порядку окон в списке ALT+ESC.
     
    Последнее редактирование: 23 мар 2019
    kero нравится это.
  6. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.709
    Глава сорок девятая. Память Братца Кролика
    . . . Так-то Братец Кролик был не злой, но память у него была хорошая.
    И уж если Братца Кролика кто-то обидит ― жди беды . . .

    (Джоэль Чандлер Харрис "Неопубликованные сказки дядюшки Римуса")
    Сегментированная память

    Windows 1.0 была разработана для 16-разрядных микропроцессоров, способных адресовать 1024 Кб = 1 Мб памяти. Верхние 384 Кб памяти резервировались для видеоадаптера и системного BIOS. Для программ и данных оставалось 1024Кб - 384Кб = 640Кб.
    Чтобы адресовать 1 Мб требуется 20-разрядный адрес (220= 1.048.576), который формировался из двух 16-разрядных значений: сегмента и смещения внутри сегмента. Микропроцессор имел четыре сегментных регистра: кода (CS=Code Segment), данных (DS=Data Segment), стека (SS=Stack Segment) и дополнительный (ES=Extra Segment) сегментный регистр. 20-разрядный физический адрес получался сдвигом содержимого сегментного регистра влево на 4 разряда и добавлением к полученной величине смещения внутри сегмента:
    00.png
    Прикладные программы становились более сложными и большими по объему, появлялась необходимость во множестве сегментов для кода и данных. Были определены близкие (near) указатели, имевшие величину 16 бит, и используемые для доступа к сегментам кода и данных по умолчанию, и дальние (far) указатели, которые имели ширину 32 бита, и состоявшие из смещения и сегмента. С помощью этого 32-разрядного адреса нельзя было адресовать память непосредственно. Нельзя было увеличить адрес на 1 без учета логики, обрабатывающей переполнение смещения и установку сегментного адреса. Были определены различные модели программирования:
    • model tiny (один сегмент, совмещающий данные и код),
    • model small (один сегмент для кода, один сегмент для данных),
    • model medium (один сегмент данных, много сегментов кода),
    • model compact (один сегмент кода, много сегментов данных),
    • model large (много сегментов кода и данных),
    • model huge (аналогично large, но со встроенной логикой обработки увеличения адреса).
    MS DOS не имела достаточно большой поддержки управления памятью. Программы определяли, какое количество памяти имеется в их распоряжении, и использовали ее всю целиком.
    Windows 1.0 была многозадачной средой, появилась необходимость расширить возможности управления памятью. Множество программ загружаются в память, позднее освобождают ее, память становится фрагментированной. Операционная система должна перемещать блоки памяти, чтобы объединить свободное пространство. Многозадачность без управления памятью существовать не может.
    Нельзя перемещать блоки кода и данных в памяти безотносительно прикладной программы. Так она будет содержать неправильный адрес. Но если программа использует только смещения, то сегменты могут быть изменены операционной системой.
    Программы для Windows были ограничены использованием только small и medium моделями памяти с одним 64-килобайтным сегментом для данных. Программы использовали близкие указатели для ссылок на свой сегмент данных; адрес сегмента данных для конкретного процесса устанавливался операционной системой при передаче управления программе. Это позволяло Windows перемещать сегмент данных программы и переустанавливать адрес сегмента. Все дальние вызовы функций, выполняемые программой (включая вызовы функций операционной системы), выполнялись когда сегменты кода, используемые программой, были перемещены в память.
    Программа, выполнявшаяся в 16-разрядной версии Windows, могла либо выделять память из собственного сегмента данных (локальная память, адресуемой с помощью 16-разрядного указателя смещения), либо за пределами своего сегмента данных (глобальная память адресуемая с помощью 32-разрядных адресов). В обоих случаях функции выделения памяти возвращали описатель блока памяти. Программы должны были фиксировать блок в памяти. Функции фиксации возвращали дальний указатель. После использования памяти следовало снять фиксацию с блока памяти. Это давало Windows возможность перемещать блоки памяти при необходимости. Процесс фиксации и снятия фиксации часто выполнялся в процессе обработки одного сообщения, и часто приводил к многочисленным ошибкам.
    Описатели памяти ― указатели на таблицу в ядре Windows. Ранние версии Windows содержали сегмент памяти, который содержал главную таблицу описателей памяти.
    В современной Windows содержатся некоторые части схемы адресации Windows 1.0. Архитектура Windows скрывает это, но это проявляется в структуре и синтаксисе вызовов функций.
    Проблемы с ближними и дальними адресами в 16-разрядных версиях Windows переносились и на файловый ввод/вывод. Во многих случаях программа получала от диалогового окна имя файла, которое являлось дальним указателем. Но в model small и modal medium моделях памяти WinAPI-функции файлового ввода/вывода ожидали ближнего указателя. Аналогично, программа, которая хранила данные в блоках глобальной памяти, должна была адресовать их с помощью дальних указателей и, как следствие, файловый ввод/вывод в эти блоки был затруднен. Возникала необходимость, чтобы Windows дублировала вызовы всех функций файлового ввода/вывода, написанных для MS DOS.
    Промежуточные решения

    Версия Windows 3.0 получила широкое распространение, у Microsoft появилась возможность поддерживать защищенный режим (protected mode) процессора Intel 286 (вместо реального режима), причем без существенных проблем для уже существовавших программ. В защищенном режиме сегментный адрес называется селектором (selector). Он также имеет ширину 16 бит, но внутри 286 процессора он ссылается на 24-разрядный базовый адрес (base address), который складывается затем с 16-разрядным смещением, и таким образом, формируется 24-разрядный физический адрес, с помощью которого можно адресовать до 224 = 16.777.216 байт = 16 Мб памяти:
    91.png
    01.png
    trans-lin.png
    Чтобы обеспечить переход от более ранних версий Windows, описатель, возвращаемый функцией выделения глобальной памяти, был просто селектором. Такое использование защищенного режима отчасти облегчало управление памятью, но истинная цель еще не была достигнута.
    32/64-разрядные Windows

    32-разрядные Windows используют 32-разрядную адресацию памяти и могут реализовать доступ к 232 = 4.294.967.296 байтам (или 4 Гб) физической памяти.
    64-разрядные Windows могут реализовать доступ к 264 = 18.446.744.073.709.551.616 байтам или 16 экзабайтам
    Несмотря на то, что стало возможным на аппаратном уровне использовать сегментную адресацию памяти, Windows сохраняет неизменными сегментные регистры и использует 32-разрядную плоскую (model flat) адресацию. Это означает, что адреса в приложении Windows хранятся как простые 32-разрядные величины, обеспечивая доступ к 4 Гб памяти.
    Используемые прикладными программами Windows 32-разрядные адреса для доступа к коду и данным, не являются 32-разрядными физическими адресами, которые микропроцессор использует для адресации физической памяти. Адрес, который используется приложением, называется виртуальным адресом (virtual address). Он преобразуется в физический адрес посредством таблицы страниц (page table). Этот процесс обычно прозрачен для прикладных программ. Программе кажется, что она расположена в 32-разрядном адресном пространстве, и для доступа к ней не требуется никаких особых усилий. Однако, в технической документации по Windows существуют ссылки на виртуальные адреса и таблицы страниц.
    Физическая память делится на страницы (pages) размером 4096 байт (4 Кб). Каждая страница начинается с адреса, в котором младшие 12 бит нулевые. 8 Мб памяти, содержат 2048 страниц. Операционная система Windows хранит набор таблиц страниц (каждая таблица сама представляет собой страницу) для преобразования виртуального адреса в физический.
    Каждый процесс, выполняемый в Windows, имеет свою собственную страницу каталога (directory page) таблиц страниц, которая содержит до 1024 32-разрядных дескриптора таблиц страниц. Физический адрес страницы каталога таблиц страниц хранится в регистре CR3. Содержимое этого регистра изменяется при переключении Windows между процессами. Старшие 10 бит виртуального адреса определяют один из 1024 возможных дескрипторов в каталоге таблиц страниц. В свою очередь, старшие 20 бит дескриптора таблицы страниц определяют физический адрес таблицы страниц (младшие 12 бит физического адреса равны нулю). Каждая таблица страниц содержит, в свою очередь, до 1024 32-разрядных дескриптора страниц. Выбор одного из этих дескрипторов определяется содержимым средних 10 битов исходного виртуального адреса. Старшие 20 бит дескриптора страницы определяют физический адрес начала страницы, а младшие 12 бит виртуального адреса определяют физическое смещение в пределах этой страницы.
    32-разрядный виртуальный адрес с которым оперирует программа представлен в виде 10-разрядного индекса в таблице каталога таблиц страниц (Directory), 10-разрядного индекса в таблице страниц (Table), 12-разрядного смещения (Offset):
    LT4k.png
    Для каждого процесса в регистре CR3 хранятся (r) старшие 20 бит физического адреса таблицы каталога таблиц страниц:rrrr-rrrr-rrrr-rrrr-rrrr
    Начальный физический адрес каталога таблиц страниц определяется так:rrrr-rrrr-rrrr-rrrr-rrrr-0000-0000-0000
    каждая страница имеет размер 4 Кб и начинается с адреса, у которого 12 младших бит нулевые.
    Сначала микропроцессор получает физический адрес:
    rrrr-rrrr-rrrr-rrrr-rrrr-dddd-dddd-dd00
    По этому адресу содержится другое 20-разрядное значение (t-table):tttt-tttt-tttt-tttt-tttt
    соответствующее начальному физическому адресу таблицы страниц:tttt-tttt-tttt-tttt-tttt-0000-0000-0000
    Затем, микропроцессор осуществляет доступ по физическому адресу:tttt-tttt-tttt-tttt-tttt-pppp-pppp-pp00
    Здесь хранится 20-битная величина, являющаяся основой для физического адреса начала страницы памяти (f-page frame):ffff-ffff-ffff-ffff-ffff
    Результирующий 32-разрядный физический адрес получается в результате комбинирования основы физического адреса страницы и 12-разрядного смещения виртуального адреса:ffff-ffff-ffff-ffff-ffff-oooo-oooo-oooo
    Это и есть результирующий физический адрес.
    Микропроцессоры имеют внутреннюю кэш-память, в которой могут храниться таблицы страниц. Фактически, преобразование адреса осуществляется очень быстро без каких-либо существенных потерь производительности. Такое двухступенчатое разделение памяти на страницы дает каждому приложению теоретическое ограничение по памяти в 1 миллион страниц по четыре килобайта каждая. Преимущества разделения памяти на страницы.
    1. приложения изолированы друг от друга. Никакой процесс не может случайно или преднамеренно использовать адресное пространство другого процесса, так как он не имеет возможности его адресовать без указания соответствующего значения регистра CR3 этого процесса, которое устанавливается только внутри ядра Windows.
    2. такой механизм разделения на страницы решает одну из основных проблем в многозадачной среде ― объединение свободной памяти. При более простых схемах адресации в то время, как множество программ выполняются и завершаются, память может стать фрагментированной. В случае, если память сильно фрагментирована, программы не могут выполняться из-за недостатка непрерывной памяти, даже если общего количества свободной памяти вполне достаточно. При использовании разделения на страницы нет необходимости объединять свободную физическую память, поскольку страницы необязательно должны быть расположены последовательно. Все управление памятью производится с помощью манипуляций с таблицами страниц. Потери связаны с самими таблицами страниц и с их 4 Кб размером.
    3. в 32-битных дескрипторах страниц существует еще 12 бит, кроме тех, которые используются для адреса страницы.
    PTE.png

    1. "Бит доступа" (accessed bit) показывает возможность доступа к конкретной странице;
    2. "Бит мусора" (dirty bit) показывает, была ли произведена запись в эту страницу.
      Windows может использовать эти биты для того чтобы определить, можно ли сохранить эту страницу в файле подкачки для освобождения памяти.
    3. "Бит присутствия" (present bit) показывает, была ли страница сброшена на диск и должна ли быть подкачена обратно в память.
    4. "Бит чтения/записи" показывает, разрешена ли запись в данную страницу памяти. Этот бит обеспечивает защиту кода от "блуждающих" указателей. Например, если включить следующий оператор в программу для Windows:
    Код (C):
    1. *(int*) WinMain = 0;
    то на экран будет выведено следующее окно сообщения:
    This program has performed an illegal operation and will be shutdown.
    ("программа выполнила недопустимую операцию и будет завершена").
    Этот бит не препятствует компилированной и загруженной в память программе быть запущенной на выполнение.
    • Управление памятью в 32-разрядных Windows
      • Виртуальные адреса имеют разрядность 32 бита.
      • Для выявления нулевых указателей 0 - 0FFFFh
      • Программа и данные имеют адреса в диапазоне от 0 до 7FFFFFFFh.
      • Сама Windows использует адреса от 80000000h до 0FFFFFFFFh. В этой области располагаются точки входа в динамически подключаемые библиотеки Windows.
    • Управление памятью в 64-разрядных Windows
      • Для выявления нулевых указателей 0 - 0FFFFh
      • Для кода и данных пользовательского режима 10000h- 3FFFFFEFFFFh
      • Закрытый раздел размером 64 Кб 3FFFFFF0000h - 3FFFFFFFFFFh
      • Для кода и данных режима ядра 40000000000h-0FFFFFFFFFFFFFFFFh
    Общее количество свободной памяти, доступной программе, определяется как количество свободной физической памяти плюс количество свободного места на жестком диске, доступного для свопинга страниц. Как правило, при управлении виртуальной памятью Windows использует алгоритм LRU (least recently used) для определения того, какие страницы будут сброшены на диск. Бит доступа и бит мусора помогают осуществить эту операцию. Страницы кода не должны сбрасываться на диск: поскольку запись в его страницы запрещена, они могут быть просто загружены из файла с расширением .EXE или из динамически подключаемой библиотеки. Иногда вы можете заметить, что происходит обращение к диску во время перемещения мыши из рабочей области одной программы в рабочую область другой программы. Почему это происходит? Windows должна посылать сообщения о передвижении мыши второму приложению. Если программа, выполняющая обработку этого сообщения, не находится в данный момент в памяти, то Windows загружает ее с диска. Если запущено несколько больших приложений одновременно, а в компьютере немного памяти, то вы можете стать свидетелем чрезмерного количества обращений к диску в моменты перехода от одной программы к другой, так как Windows вновь загружает с диска ранее удаленные страницы. Время от времени отдельные программы будут замедляться (или приостанавливаться на какое-то время), пока Windows осуществляет свопинг.
    Страницы кода могут разделяться между приложениями. Это особенно полезно для динамически подключаемых библиотек. Несколько программ, выполняемых одновременно, могут использовать одни и те же функции Windows, не требуя, чтобы один и тот же код загружался в память несколько раз. Достаточно одной копии. При динамическом выделении памяти каждый выделяемый блок необязательно получает свою собственную страницу. Последовательное выделение небольших объемов памяти производится в одной и той же физической странице с ближайшего 4-разрядного стартового адреса (то есть для выделения одного байта используется 16 бит). Если какой-либо блок расширяется, то он может быть физически перемещен в памяти, если следующий за ним блок памяти занят.
    Кроме разделения памяти на страницы по 4 Кб физическая память не может стать безнадежно фрагментированной, поскольку дефрагментация заключается только в манипуляциях с таблицами страниц. Однако виртуальная память конкретного приложения может стать фрагментированной, если приложение осуществляет выделение, освобождение, повторное выделение и освобождение слишком большого числа блоков памяти. Ограничения в 2 ГБ обычно достаточно для приложения и его данных. Но возможно, что программа столкнется с нехваткой физической памяти до того, как будет достигнут предел виртуальной памяти. Если вы считаете, что это может случиться с вашей программой, то вам стоит подумать об использовании перемещаемой (moveable) памяти.
    Выделение памяти

    WinAPI-функции
    E4PtHtGXMAYv1w5.png
    Вы можете определить в программе указатель (например, на массив целых чисел) следующим образом:
    Код (ASM):
    1. pMem dq ?
    Указатель pMem ― 64-разрядное неинициализированое число. Вы можете выделить блок памяти, на который будет указывать pMem, следующим образом:
    Код (ASM):
    1. invoke    malloc,1024
    2.     mov    pMem,rax
    При этом выделяется блок памяти размером 1024 байта, который может хранить 256 32-разрядных целых. Указатель, равный NULL, показывает, что выделение памяти не было успешным. Можно также выделить такой блок памяти, используя следующий вызов:
    Код (ASM):
    1. invoke    calloc,256, sizeof DWORD
    2.     mov    pMem,rax
    Два параметра функции calloc перемножаются и в результате получается 1024 байта. Кроме того, функция calloc производит обнуление блока памяти.
    Если вам необходимо увеличить размер блока памяти (например, удвоить его), то вы можете вызвать функцию:
    Код (ASM):
    1. invoke    realloc,pMem, 2048
    2.     mov    pMem,rax
    Указатель является параметром функции, и указатель (возможно, отличающийся по значению от первого, особенно, если блок увеличивается) является возвращаемым значением функции. Этот пример показывает, что Windows может перемещать блок в рамках виртуальной памяти. Например, если вы выделили блок размером 1024 байта, то его виртуальный адрес может быть равен 750100h. Вы можете выделить второй блок памяти и получить виртуальный адрес 750504h. Расширив первый блок памяти до 2048 байт, использовать тот же виртуальный адрес невозможно. В этом случае Windows должна переместить блок в физической памяти на новую страницу.
    При окончании работы с памятью, вызовите функцию:
    Код (ASM):
    1. invoke    free,pMem
    Фундаментальное выделение памяти в Windows

    Всё, что вы можете делать с помощью WinAPI-функций, вы можете делать самостоятельно, или используя вызовы функций ядра Windows. Функция Windows для выделения блока памяти для указателя на целые:
    Код (ASM):
    1. invoke GlobalAlloc,uiFlags, dwSize
    2. mov pMem,rax
    Функция имеет два параметра:
    • набор флагов
    • размер выделяемого блока в байтах
    Функция возвращает виртуальный адрес, который может использоваться в программе для доступа к выделенной памяти. Значение NULL говорит о том, что имеющейся в распоряжении памяти для выделения недостаточно.
    Для каждой функции, начинающейся со слова Global, существует функция, начинающаяся со слова Local. Два набора функций в Windows идентичны. Два различных слова сохранены для совместимости с предыдущими версиями Windows, где функции Global возвращали дальние указатели, а функции Local ― ближние.
    Хотя определения параметров немного отличаются, они оба являются 64-разрядными беззнаковыми целыми. Если первый параметр задать нулевым, то это эквивалентно использованию флага GMEM_FIXED (=0).
    Такой вызов функции GlobalAlloc эквивалентен вызову функции malloc. В ранних версиях Windows присутствие флага GMEM_FIXED приводило к проблемам управления памятью, поскольку Windows не могла перемещать такие блоки в физической памяти. Сейчас флаг GMEM_FIXED вполне допустим, поскольку функция возвращает виртуальный адрес, и операционная система может перемещать блок в физической памяти, внося изменения в таблицу страниц.
    Можно использовать флаг GMEM_ZEROINIT для обнуления всех байтов выделяемого блока памяти. Флаг GPTR включает в себя флаги GMEM_FIXED и GMEM_ZEROINIT:
    Код (ASM):
    1. GPTR equ GMEM_FIXED or GMEM_ZEROINIT
    Функция изменения размера блока памяти:
    Код (ASM):
    1. invoke GlobalReAlloc,pMem, dwSize, uiFlags
    2. mov pMem,rax
    Можно использовать флаг GMEM_ZEROINIT для обнуления добавляющихся в блок памяти байтов, если блок расширяется.
    Функция, возвращающая размер блока памяти:
    Код (ASM):
    1. invoke GlobalSize,pMem
    2. mov dwSize,rax
    Функция освобождения памяти:
    Код (ASM):
    1. invoke GlobalFree,pMem
    Перемещаемая память

    В предыдущих версиях Windows наличие флага GMEM_FIXED приводило к проблемам при управлении памятью, поскольку Windows должна была сохранять блок памяти в фиксированном месте физической памяти. Сейчас блок памяти может быть перемещен в физической памяти при сохранении виртуального адреса неизменным. Функция GlobalAlloc, тем не менее, поддерживает флаг GMEM_MOVEABLE
    и комбинированный флаг для дополнительного обнуления блока памяти:
    Код (ASM):
    1. GHND equ GMEM_MOVEABLE or GMEM_ZEROINIT
    Флаг GMEM_MOVEABLE позволяет перемещать блок памяти в виртуальной памяти. Это не означает, что блок памяти будет перемещен в физической памяти, но адрес, которым пользуется программа для чтения и записи, может измениться.
    Если ваша программа выделяет, расширяет, освобождает память, то виртуальная память может сделаться фрагментированной. Может ли ваша программа дойти до предела в 2 ГБ виртуальной памяти до того, как будет достигнут предел 4, 8 или 16 Мб физической памяти? Проблема встает острее при непрерывном использовании компьютера. Программы, выполнение которых происходит в течение нескольких дней, в конце концов могут столкнуться с большей фрагментацией памяти, чем программы, разработанные для выполнения в течение одного-двух часов. Вы можете захотеть использовать перемещаемую память. Как это делается?
    1. определим указатель и переменную типа GLOBALHANDLE:
      Код (ASM):
      1. pMem dq ?
      2. hGlobal GLOBALHANDLE ?
    2. выделим память:
      Код (ASM):
      1. invoke GlobalAlloc,GHND, 1024
      2. mov hGlobal,rax
    3. Когда вам необходимо обратиться к памяти, для фиксации блока используйте вызов:
      Код (ASM):
      1. invoke GlobalLock,hGlobal
      2. mov pMem,rax
      Эта функция преобразует описатель памяти в указатель. Пока блок зафиксирован, Windows не изменяет его виртуальный адрес.
    4. Когда вы заканчиваете работу с блоком, для снятия фиксации вызовите функцию:
      Код (ASM):
      1. invoke GlobalUnlock,hGlobal
      Этот вызов дает Windows свободу перемещать блок в виртуальной памяти. Для того чтобы правильно осуществлять этот процесс, вы должны фиксировать и снимать фиксацию блока памяти в ходе обработки одного сообщения.
    5. Когда вы хотите освободить память, вызовите функцию GlobalFree с параметром-описателем, а не указателем. Если в данный момент вы не имеете доступа к описателю, то вам необходимо использовать функцию:
      Код (ASM):
      1. invoke GlobalHandle,pMem
      2. mov hGlobal,rax
      Вы можете фиксировать блок памяти несколько раз до того, как снять с него фиксацию. Windows запоминает количество фиксаций, и каждое фиксирование требует снятия для того чтобы дать возможность блоку перемещаться. Перемещение блока в виртуальной памяти не есть перемещение байтов с одного места в другое ― производятся только манипуляции с таблицами страниц. Единственной причиной для выделения перемещаемой памяти служит предотвращение фрагментации виртуальной памяти.
    Удаляемая память

    Если вы используете опцию GMEM_MOVEABLE, то попробуйте использовать опцию GMEM_DISCARDABLE. Эта опция может быть использована только совместно с GMEM_MOVEABLE. Блок памяти, выделенный с этим флагом, может быть удален из физической памяти ядром Windows, когда необходима свободная память. Блоки памяти, содержащие код, являются удаляемыми. Они защищены от записи. Следовательно, быстрее загрузить код из исходного EXE-файла, чем записывать его на диск, а затем вновь загружать с диска. Если вы выделяете память для неизменяемых данных, которые могут быть легко регенерированы (обычно загрузкой из файла), то можно сделать этот блок удаляемым. О том, что данные были сброшены, вы узнаете, когда вызовите функцию GlobalLock и получите в ответ NULL. Теперь, вы восстанавливаете данные.
    Блок памяти не может быть удален до тех пор, пока счетчик фиксаций больше нуля. Для преднамеренного удаления блока памяти, вызовите:
    Код (ASM):
    1. invoke GlobalDiscard,hGlobal
    Другие функции и флаги

    Другим доступным для использования в функции GlobalAlloc является флаг GMEM_SHARE или GMEM_DDESHARE. Этот флаг предназначен для динамического обмена данными.
    Функции GlobalAlloc и GlobalReAlloc могут включать флаги GMEM_NODISCARD и GMEM_NOCOMPACT. Эти флаги указывают Windows не удалять и не перемещать блоки памяти для удовлетворения запросов памяти. Только излишне альтруистичные программисты используют эти флаги.
    Функция GlobalReAlloc может изменять флаги (например, преобразовывать фиксированный блок памяти в перемещаемый, и наоборот), если новый размер блока задан равным нулю, и указан флаг GMEM_MODIFY.
    Функция GlobalFlags возвращает комбинацию флагов GMEM_DISCARDABLE, GMEM_DISCARDED и GMEM_SHARE.
    Функция GlobalMemoryStatus с указателем на структуру типа MEMORYSTATUS для определения количества физической и виртуальной памяти, доступной приложению.
    Windows поддерживает функции:
    • FreeMemory заполнение конкретным байтом,
    • ZeroMemory обнуление памяти,
    • CopyMemory и MoveMemory ― обе копируют данные из одной области памяти в другую. Если эти области перекрываются, то функция CopyMemory может работать некорректно. Вместо нее используйте функцию MoveMemory.
    Перед тем как осуществить доступ к памяти, вам придется проверить, возможен доступ или нет. Если указатель является недействительным, включается общая защита программы. Предварительная проверка указателя гарантирует, что этого не произойдет. Эту проверку выполняют функции IsBadCodePtr, IsBadReadPtr, IsBadWritePtr,IsBadStringPtr.
    • IsBadCodePtr принимает указатель в качестве параметра и возвращает ненулевое значение (TRUE), если указатель действителен.
    • IsBadReadPtr, IsBadWritePtr, IsBadStringPtr получают указатель в качестве первого параметра и длину блока памяти в качестве второго параметра.
    • Функция IsBadStringPtr осуществляет проверку до тех пор, пока не встретит нулевой ограничитель строки.
     

    Вложения:

    • help1.zip
      Размер файла:
      55,9 КБ
      Просмотров:
      739
    • help2.zip
      Размер файла:
      57,4 КБ
      Просмотров:
      723
    • help3.zip
      Размер файла:
      58,6 КБ
      Просмотров:
      763
    • 00.png
      00.png
      Размер файла:
      2,9 КБ
      Просмотров:
      656
    kero и Aiks нравится это.
  7. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.709
    Функции управления виртуальной памятью

    Windows поддерживает ряд функций, начинающихся с Virtual. Эти функции предоставляют значительно больше возможностей управления памятью. Однако, только очень необычные приложения требуют использования эти функции.
    Например, ваша программа читает исходный код и компилирует его, а результат компиляции заносится в память. Затем, вы хотите пометить этот блок памяти как "только для выполнения", то есть так, чтобы было невозможно случайно или преднамеренно прочитать (или того хуже, записать) в него что-либо из программы, которая была только что скомпилирована и готова к выполнению. Это одно из действий, которое должна осуществлять ваша программа для обработки ошибок при работе с указателями в пользовательской программе. Вы можете также пометить часть блоков памяти "только для чтения". Оба указанных действия выполняются только с помощью функций управления виртуальной памятью.
    Более часто возникает необходимость зарезервировать большой блок виртуальной памяти для данных, который может быть сильно увеличен в процессе выполнения программы. Действуя обычным путем ― то есть используя функции realloc или функцию GlobalReAlloc для динамического изменения размера выделенного блока памяти ― можно снизить производительность программы. Функции управления виртуальной памятью могут помочь избежать этого.
    В Windows любой блок виртуальной памяти может находиться в одном из трех состояний:
    • "committed" (блок спроецирован в физическую память),
    • "free" (свободен, доступен для будущего выделения),
    • "reserved" (зарезервирован). Зарезервированный блок виртуальной памяти не отображается в физическую память. Адреса в пределах этого блока будут недоступны до тех пор, пока всему блоку или его какой-либо части не будет передан блок физической памяти. Таким образом, вы можете зарезервировать достаточно большой блок виртуальной памяти, не передавая ему физической памяти. Когда будет необходимо обратиться по какому-либо виртуальному адресу в пределах этого блока, вы передаете по этому адресу ровно столько физической памяти, сколько необходимо, то есть в зарезервированном блоке виртуальной памяти могут быть участки, как связанные, так и несвязанные с блоками физической памяти. Спроецировав физическую память на нужный участок зарезервированной области виртуальной памяти, программа может обращаться к нему, не вызывая при этом исключения нарушения доступа.
    Для того чтобы использовать функции работы с виртуальной памятью, вашей программе необходимо знать размер страницы памяти. Размер страницы всегда равен 4096 байт. Используйте функцию GetSystemInfo для получения размера страницы. Функция имеет один параметр ― указатель на структуру SYSTEM_INFO.
    Код (C):
    1. typedef struct _SYSTEM_INFO
    2. {
    3.   union
    4.   {
    5.      DWORD  dwOemId;
    6.      struct
    7.     {
    8.         WORD wProcessorArchitecture;
    9.         WORD wReserved;
    10.      };
    11.    };
    12.   DWORD  dwPageSize;
    13.   LPVOID  lpMinimumApplicationAddress;
    14.   LPVOID  lpMaximumApplicationAddress;
    15.   DWORD_PTR dwActiveProcessorMask;
    16.   DWORD  dwNumberOfProcessors;
    17.   DWORD  dwProcessorType;
    18.   DWORD  dwAllocationGranularity;
    19.   WORD  wProcessorLevel;
    20.   WORD  wProcessorRevision;
    21. } SYSTEM_INFO;
    Поле dwPageSize этой структуры содержит размер страницы. Поля lpMinimumApplicationAddress и lpMaximumApplicationAddress содержат минимальный и максимальный адреса, имеющиеся в распоряжении приложения. Для Windows эти значения равны соответственно 400000h и 7FFFFFFFh.
    Функция VirtualAlloc выглядит следующим образом:
    Код (ASM):
    1. invoke VirtualAlloc,pAddr, dwSize, iAllocType, iProtect
    2. mov pMem,rax
    Первый параметр ― желаемый стартовый базовый адрес виртуальной памяти, его можно установить в NULL при первом вызове этой функции. Второй параметр ― размер. Третий параметр может быть MEM_RESERVE (для резервирования блока виртуальной памяти) или MEM_COMMIT (для резервирования и передачи физической памяти). Четвертый параметр ― константа, начинающаяся с префикса PAGE_ (PAGE_READONLY или PAGE_EXECUTE) для задания защиты блока памяти. Последовательные вызовы функции VirtualAlloc могут передавать или резервировать секции этого блока. Функция VirtualFree используется для освобождения виртуальной памяти.
    Функции работы с "кучей"

    Функции, имена которых начинаются со слова Heap (куча). Эти функции создают и поддерживают непрерывный блок виртуальной памяти, из которого можно выделять память более мелкими блоками. Работа начинается с вызова функции HeapCreate. Затем, используются функции HeapAllocate, HeapReAllocate и HeapFree для выделения и освобождения блоков памяти в рамках "кучи". "Куча" может быть уплотнена для объединения свободного пространства.
    Файловый ввод/вывод

    для файлового ввода/вывода используются WinAPI-функции fopen, fseek, fread, fwrite и fclose.
    Отличия Windows

    Можно читать и записывать файл большими блоками информации за один прием, используя однократный вызов функций fread и fwrite (или их эквивалентами). Отпадает необходимость в использовании циклов при работе с файлами большого размера.
    Windows поддерживает длинные имена файлов. Можно использовать данные, возвращаемые функцией GetVolumeInformation, для динамического выделения буферов для хранения имен файлов. Рекомендуется использовать константы MAX_PATH = 260 и MAX_FNAME = 256 для статического выделения памяти.
    Функции файлового ввода/вывода, поддерживаемые Windows

    Функция CreateFile
    Код (ASM):
    1. invoke CreateFile,szName, dwAccess, dwShare, NULL, dwCreate, dwFlags, 0
    2. mov hFile,rax
    Функция используется для открытия существующего файла, для открытия каналов, используемых при обмене между процессами, а также коммуникационных устройств.
    первый параметр является именем файла.
    Второй имеет значение либо GENERIC_READ, либо GENERIC_WRITE, либо GENERIC_READ | GENERIC_WRITE. Использование нулевого значения позволяет получить информацию о файле без доступа к его содержимому.
    Параметр dwShare открывает файл с общими атрибутами, позволяя другим процессам читать из него (FILE_SHARE_READ), или записывать в него (FILE_SHARE_WRITE), или и то и другое вместе.
    Флаг dwCreate ― константа, показывающая, каким образом файл должен быть открыт.
    • Флаг CREATE_NEW вызывает ошибку, если файл уже существует
    • флаг CREATE_ALWAYS приводит к удалению содержимого существующего файла,
    • флаг OPEN_EXISTING вызывает ошибку, если файл не существует,
    • флаг OPEN_ALWAYS создает файл, если он не существует.
    • Флаг TRUNCATE_EXISTING приводит к ошибке, если файл не существует, и удаляет все содержимое, если файл существует.
    Параметр dwFlags может быть комбинацией констант, начинающихся со слов FILE_ATTRIBUTE и FILE_FLAG, для установки атрибутов файла и других особенностей.
    Функция CreateFile возвращает переменную типа HANDLE. При завершении работы с файлом его необходимо закрыть, используя функцию CloseHandle с описателем файла в качестве параметра. Функции ReadFile и WriteFile похожи:
    Код (ASM):
    1. invoke ReadFile,hFile, pBuffer, dwToRead, &dwHaveRead, NULL
    2. invoke WriteFile,hFile, pBuffer, dwToWrite, &dwHaveWritten, NULL
    • первый параметр ― описатель файла
    • Второй параметр ― указатель на буфер, содержащий данные;
    • третий параметр ― количество байтов для чтения или записи;
    • четвертый параметр ― указатель на переменную, в которую при возврате из функции будет занесено количество байтов, которые были реально считаны или записаны. (Последний параметр используется только для файла, открываемого с флагом FILE_FLAG_OVERLAPPED
    Ввод/вывод с использованием файлов, проецируемых в память

    При работе в Windows существует возможность читать и записывать данные в файл так, как будто это блок памяти. Этот прием рекомендуется использовать также при разделении памяти между двумя и более процессами.
    Вот простейший подход к вводу/выводу с использованием файлов, проецируемых в память (memory mapped files):
    Сначала создается обычный файл с использованием функции CreateFile.
    Затем вызывается функция:
    Код (ASM):
    1. invoke CreateFileMapping,hFile, NULL, dwProtect, 0, 0, szName
    2. mov hMap,rax
    Параметр dwProtect принимает одно из следующих значений, и должен быть совместим с режимом разделения файла: PAGE_READONLY, PAGE_WRITECOPY, PAGE_READWRITE. Последний параметр функции ― необязательное имя, обычно используемое для разделения данных между процессами. В этом случае, функцияOpenFileMapping открывает тот же файл с указанным именем. Обе функции возвращают значение типа HANDLE. Если вам необходимо осуществить доступ к части файла, вызовите функцию MapViewOfFile:
    Код (ASM):
    1. invoke MapViewOfFile,hMap, dwAccess, dwHigh, dwLow, dwNumber
    2. mov pMem,rax
    Весь файл или его часть могут быть спроецированы в память, начиная с заданного 64-разрядного смещения, которое задается параметрами dwHigh и dwLow. (dwHigh = 0, если файл менее 4 ГБ.) Параметр dwNumber задает количество байтов, которое вы хотите спроецировать в память. Параметр dwAccess может быть равен FILE_MAP_WRITE (данные можно записывать и считывать) или FILE_MAP_READ (данные можно только считывать), и должен соответствовать параметру dwProtect функции CreateFileMapping.
    После этого вы можете использовать указатель, возвращаемый функцией, для доступа или модификации данных в файле. Функция FlushViewOfFile записывает на диск все измененные страницы файла, спроецированного в память. Функция UnmapViewOfFile делает недействительным указатель, возвращаемый функцией MapViewOfFile. Затем необходимо закрыть файл, используя функцию CloseHandle.


    Комментарий leo к 12 уроку Iczelion'а "Память и файлы"

    Забудьте раз и навсегда о GlobalAlloc с флагом GMEM_MOVEABLE!!! То, что было "традиционно" во времена перехода с Win16 на Win32, в наше время стало просто глупым и абсурдным. Никакого перемещения блоков памяти внутри кучи Win32 реально не поддерживают, так как им это не нужно ― все "перемещения" осуществляются на уровне подкачки и трансляции страниц. Но использовать флаг GMEM_MOVEABLE не только бессмысленно, но и накладно с точки зрения расхода памяти и быстродействия.
    Поясняю. Основными функциями для работы с кучей в Win32 являются kernel32.HeapAlloc\HeapFree, которые в NT+ просто мапятся в соответствующие функции ntdll.RtlAllocateHeap\RtlFreeHeap. Некоторым "неудобством" этих функций является то, что им нужно передавать хэндл кучи. Для основной кучи процесса этот хэндл возвращается функцией GetProcessHeap. Разумеется при многократных вызовах HeapAlloc имеет смысл один раз получить этот хэндл и сохранить его в переменной hHeap. Но если кому и один раз "в лом" вызвать GetProcessHeap, то можно использовать GlobalAlloc с флагом GMEM_FIXED. GlobalAlloc первым делом устанавливает SEH-обработчик и проверяет флаги. Если флаг GMEM_MOVEABLE не установлен, то просто берется хэндл основной кучи, вызывается HeapAlloc и затем удаляется SEH. Разумеется имеем дополнительные затраты времени на лишние call'ы, jmp'ы и mov'ы, но чего не сделаешь ради "простоты" :)
    С бестолковым флагом GMEM_MOVEABLE дела обстоят гораздо хуже. В итоге память точно также выделяется HeapAlloc, но дополнительно создается дескриптор HGLOBAL, хранящий ссылку на выделенный блок памяти. В Win 9x и NT дескрипторы создаются и хранятся по разному. В Win 9х память под дескриптор выделяется в той же основной куче процесса, то есть вместо одного HeapAlloc имеем два, плюс различные навороты типа блокировки кучи HeapLock\Unlock и т.п. В Win NT под дескрипторы HGLOBAL вообще выделяется отдельный регион памяти, который отъедает у процесса 512К(!) виртуальных адресов и как минимум 4К физической памяти у системы. Выделение памяти под дескрипторы производится при первом вызове GlobalAlloc с флагом GMEM_MOVEABLE и естественно сопровождается огромными потерями времени на обработку отказа страницы ― не менее 4-5 тысяч тактов процессора. Вот и спрашивается: насколько нужно любить и уважать "традиции", чтобы
    1. использовать совершенно бессмысленный флаг GMEM_MOVEABLE, зная, что в реальной ситуации блоки памяти в куче никуда не перемещаются
    2. бессмысленно вызывать GlobalLock\GlobalUnlock, которые только и делают, что увеличивают или уменьшают счетчик ссылок в HGLOBAL, а блок памяти как сидел на своем месте в куче так и сидит
    3. занимать 512К виртуальных адресов и 4К дополнительной физической памяти и напрягать процессор и систему, заставляя их выделять новую страницу только для того, что нам пришло в голову обращаться к выделенному блоку кучи не напрямую, а через через одно хорошо известное место :)
    PS: Еще пара замечаний до кучи:
    1. В GlobalUnlock положено передавать хэндл hMemory, а не указатель на блок pMemory. Хотя с pMemory тоже работает благодаря внутренним взаимным ссылкам hMemory ― pMemory
    2. задавать флаги GMEM_ZEROINIT или HEAP_ZERO_MEMORY во многих случаях не имеет смысла, как в рассматриваемом примере с ReadFile\WriteFile. При SendMessage+WriteFile вообще незачем занулять блок памяти, а при чтении файла достаточно занулить последний байт считанной строки и не тратить впустую время на обнуление всего блока размером MEMSIZE = 64K


    В чём разница между LocalAlloc и GlobalAlloc?


    Перевод фрагмента статьи "What was the difference between LocalAlloc and GlobalAlloc?" Реймонда Ченя.
    Когда-то во времена 16-ти битных Windows разница была огромной.
    В ранних версиях Windows доступ к памяти получали через значения, называемые селекторами (selectors), каждый из которых позволял адресовать память до 64 Кб. Существовал селектор по-умолчанию, который назывался селектором данных (data selector); операции с так называемыми ближними указателями (near pointers) осуществлялись относительно селектора данных. Например, если у вас был ближний указатель p со значением 1234h и ваш селектор данных был 012Fh, то тогда, когда вы писали p^, вы получали доступ к памяти по адресу 012F:1234 (когда вы объявляли указатель, он по-умолчанию считался ближним. Вам нужно было явно приписывать far, чтобы указать, что вам нужен дальний указатель).
    Важный момент: ближние указатели всегда относительны к селектору, обычно: к селектору данных.
    Функция GlobalAlloc выделяет селектор, который может быть использован для доступа к запрошенному вами количеству памяти (а если вы попросите выделить вам больше 64 Кб памяти, то произойдёт нечто волнующее, что, впрочем, сейчас не важно). Вы можете получить доступ к памяти по этому селектору через дальний указатель (far pointer). Дальний указатель ― это селектор, соединённый с ближним указателем (не забывайте: ближний указатель относителен к селектору; когда вы соединяете ближний указатель с соответствующим ему селектором, вы получаете дальний указатель).
    Каждый экземпляр (instance) программы и DLL имеет свой собственный селектор данных, известный как HINSTANCE. Селектор данных по-умолчанию для кода в программе был HINSTANCE этого экземпляра программы; селектор данных по-умолчанию для DLL был HINSTANCE этой DLL. Поэтому, если у вас был ближний указатель p, то разыменовывая его как p^ из кода программы, вы получали доступ к памяти относительно HINSTANCE экземпляра программы. Если вы разыменовывали его в DLL, то вы получали память, относительно HINSTANCE вашей DLL.
    Память, на которую ссылается селектор по-умолчанию, может быть превращена в локальную кучу (local heap) вызовом функции LocalInit. Инициализация локальной кучи обычно была одной из первых вещей, которые делала программа или DLL при запуске (для DLL это было обычно единственной вещью, которую она делала при загрузке!). Когда у вас есть локальная куча, вы можете вызывать LocalAlloc для выделения из неё памяти. Функция LocalAlloc возвращала ближний указатель, относительный к селектору по-умолчанию, так что если вы вызывали её из программного модуля, она выделяла память для HINSTANCE программы; если вы вызывали её из DLL, она выделяла память из HINSTANCE DLL.
    Если вы были сообразительны, вы могли понять, что вы можете использовать LocalAlloc для выделения памяти из других блоков, не только из HINSTANCE. Всё, что вам нужно было для этого сделать, так это изменить ваш селектор по-умолчанию на селектор для памяти, выделенной через GlobalAlloc, вызвать функцию LocalAlloc, а затем восстановить селектор по-умолчанию. Это давало вам ближний указатель, относительный к чему-то, отличному от селектора по-умолчанию, что было очень страшной вещью. Но если вы были умны и аккуратно всё делали, то вы могли избежать неприятностей.
    Заметьте, что в 16-ти битных Windows, функции LocalAlloc и GlobalAlloc были совершенно различными! LocalAlloc возвращала ближний указатель, в то время как GlobalAlloc вообще возвращала селектор.
    Указатели, которые вы хотели передавать между модулями, должны были иметь вид "дальних указателей", потому что у каждого модуля был свой селектор по-умолчанию. Если вы хотели передать владение памятью в другой модуль, вам нужно было использовать GlobalAlloc, потому что это позволяло вызывающему использовать потом вызов GlobalFree для его освобождения (вызывающий не мог использовать LocalFree, потому что LocalFree работает в локальной куче, которая будет кучей вызывающего ― это не то же самое, что ваша куча).
    Эта историческая разница между локальной и глобальной памятью до сих пор остаётся в Win32. Если у вас есть функция, которая пришла из 16-ти битных Windows, и она передаёт право на память, то она будет работать со значениями типа HGLOBAL. Классическим примером таких функций являются функции буфера обмена (clipboard). Если вы размещаете блок памяти в буфере обмена, он должен быть выделен через HGLOBAL, потому что вы передаёте память буферу обмена, и он вызовет GlobalFree, когда эта память станет ему не нужна. Память, передаваемая через STGMEDIUM, принимает форму HGLOBAL по той же причине.
    Даже в Win32, вам нужно быть осторожными и не перепутать локальную кучу и глобальную. Память, выделенная в одной, не может быть освобождена в другой. Хотя функциональные различия в основном исчезли; и семантика к этому моменту практически идентична. Все странности по ближним и дальним указателям тоже исчезли при переходе к Win32. Но функции локальной и глобальной куч, тем не менее, остаются двумя различными и не связанными интерфейсами куч.
     
    Последнее редактирование: 30 янв 2020
    kero, Коцит и Aiks нравится это.
  8. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.709
    Глава пятидесятая. Братец Кролик подключает к MessageBox кнопку Help

    Для добавления кнопки "Help" в стиль MessageBox достаточно установить в единицу 14-ый бит
    Код (ASM):
    1. MB_HELP        equ 4000h
    Кнопка "Help" добавится к MessageBox с любым сочетанием клавиш, но на этом дело и остановится. Если вы нажимаете на любую клавишу кроме клавиши "Help" MessageBox всегда закрывается и программа переходит к обработке той клавиши которая только-что была нажата, но к кнопке "Help" это не относится.
    Вариант первый
    Проще всего обработку нажатия "Help" можно добавить в MessageBoxIndirect. Эта функция получает в качестве единственного параметра ссылку на структуру MSGBOXPARAMS где в поле lpfnMsgBoxCallback содержится адрес функции MsgBoxCallback.
    Код (ASM):
    1. MSGBOXPARAMS   struc
    2.   cbSize                           dd ?,?;UINT
    3.   hwndOwner                dq ?  ;HWND
    4.   hInstance                    dq ?  ;HINSTANCE
    5.   lpszText                       dq ?  ;LPCTSTR
    6.   lpszCaption                dq ?  ;LPCTSTR
    7.   dwStyle                       dd ?,?;DWORD
    8.   lpszIcon                      dq ?  ;LPCTSTR
    9.   dwContextHelpId     dd ?,?;DWORD_PTR
    10.   lpfnMsgBoxCallback dq ?  ;MSGBOXCALLBACK
    11.   dwLanguageId            dd ?,?;DWORD
    12. MSGBOXPARAMS ends
    Для вывода на экран справки используется функция WinHelp или ShellExecute которая обработает расширение .hlp, .chm программой "по-умолчанию"
    tut_01.asm вывод справочной информации из MessageBoxIndirect
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. .code
    4. capt        db "Hello!",0
    5. msg         db "Customized message box",0
    6. ButtonText  db "Click here",0
    7. hlpfile     db "tut_01.hlp",0
    8.  
    9. WinMain proc
    10. local mbp:MSGBOXPARAMS
    11.  
    12.         mov mbp.cbSize,sizeof MSGBOXPARAMS
    13.         and mbp.hwndOwner,0;
    14.         mov mbp.hInstance,IMAGE_BASE
    15.         movr mbp.lpszText,msg
    16.         movr mbp.lpszCaption,capt
    17.         mov mbp.dwStyle,MB_HELP or MB_USERICON
    18.         mov mbp.lpszIcon,1000
    19.         mov mbp.dwContextHelpId,1    ;help topic ID
    20.         mov eax,offset MsgBoxCallback
    21.          mov mbp.lpfnMsgBoxCallback,rax;
    22.          and mbp.dwLanguageId,0
    23.          invoke MessageBoxIndirect,&mbp
    24.          invoke RtlExitUserProcess,NULL
    25. WinMain endp
    26. MsgBoxCallback proc x:qword
    27.  
    28.     invoke ShellExecute,0,0,&hlpfile,0,0,1
    29.     leave
    30.     retn
    31. MsgBoxCallback endp
    32. end
    tut_01.rc
    Код (C):
    1. 1000 ICON DISCARDABLE "br_Bear4.ico"
    Здесь asm/rc/exe-файлы, файл с иконкой и hlp-файл
    Вариант второй
    tut_02.asm через создание нового потока
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. .code
    4. capt             db "Hello!",0
    5. msg              db "Customized message box",0
    6. ButtonText  db "OK",0
    7. bclass           db "Button",0
    8. hlpfile          db "imagedit.hlp",0
    9. pOldProc     dq ?
    10. HelpBtnID   dq ?
    11. message        dq ?
    12. caption         dq ?
    13. button           dq ?
    14. WinMain proc
    15. LOCAL ThreadID:QWORD
    16. LOCAL hWnd:QWORD
    17. LOCAL hThread:QWORD
    18. LOCAL hClick:QWORD
    19.  
    20.         movr message,msg
    21.         movr caption,capt
    22.         movr button,ButtonText
    23.         invoke CreateThread,0,\      ;атрибуты безопасности по умолчанию
    24.                             0,\      ;размер стека используется по умолчанию
    25.                             &ThreadProc1,\;функция потока
    26.                             &caption,\    ;аргумент функции потока
    27.                             0,\           ;флажки создания используются по умолчанию
    28.                             &ThreadID     ;возвращает идентификатор потока
    29.         mov hThread,rax
    30.         invoke GetCurrentProcess
    31.         invoke WaitForInputIdle,rax,INFINITE
    32.         invoke EnumWindows,&EnumWndProc,&ThreadID
    33.         invoke FindWindowEx,hWnd,0,&bclass,0
    34.         mov hClick,rax
    35.         invoke FindWindowEx,hWnd,eax,&bclass,0
    36.         invoke GetDlgCtrlID,eax
    37.         mov HelpBtnID,rax
    38.         invoke SetWindowText,hClick,&ButtonText
    39.         invoke SetWindowLongPtr,hWnd,GWL_WNDPROC,&MsgboxProc
    40.         mov pOldProc,rax
    41.         invoke WaitForSingleObject,hThread,INFINITE
    42.         invoke CloseHandle,hThread
    43.          invoke RtlExitUserProcess,NULL
    44. WinMain endp
    45. ThreadProc1 PROC pParams:QWORD
    46.  
    47.         mov eax,ecx;ecx=pParams
    48.         invoke MessageBox,QWORD PTR [rax-16],QWORD PTR [rax-8],QWORD PTR [rax],MB_HELP
    49.          leave
    50.         retn
    51. ThreadProc1 ENDP
    52. EnumWndProc PROC hWnd:QWORD,lParam:QWORD
    53. LOCAL pid:QWORD
    54.       mov hWnd,rcx
    55.       mov lParam,rdx
    56.  
    57.         invoke GetWindowThreadProcessId,,&pid
    58.         mov rdx,lParam
    59.         cmp eax,[rdx]
    60.         mov eax,TRUE
    61.         jne @f
    62.         mov rax,hWnd
    63.         mov [rdx-8],rax  ; get the handle of the window
    64.         xor eax,eax      ; displaying the message box
    65. @@:     leave
    66.         retn
    67. EnumWndProc ENDP
    68. MsgboxProc PROC hWnd:HWND,uMsg:QWORD,wParam:WPARAM,lParam:LPARAM
    69. mov hWnd,rcx
    70. mov uMsg,rdx
    71. mov wParam,r8
    72. mov lParam,r9
    73.  
    74.         cmp edx,WM_COMMAND
    75.         jne @f
    76.         mov rax,r8;wParam
    77.         mov edx,eax
    78.         shr edx,16         ;cmp dx,BN_CLICKED=0
    79.         jne @f
    80.         mov rcx,HelpBtnID
    81.         cmp ax,cx
    82.          jne @f
    83.          invoke ShellExecute,0,0,&hlpfile,0,0,1
    84. @@: invoke CallWindowProc,pOldProc,hWnd,uMsg,wParam,lParam
    85.          leave
    86.           retn
    87. MsgboxProc    ENDP
    88. end
    Здесь asm/exe-файлы и hlp-файл
    Вариант третий
    tut_03.asm создаем окошко и обрабатываем сообщение WM_HELP
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. HELPINFO struct
    4.     cbSize dq ?      ;размер структуры в байтах
    5.     iContextType dq ?;тип справки
    6.     iCtrlId dq ?     ;идентификатор окна либо меню
    7.     hItemHandle dq ? ;идентификатор дочернего окна либо связанного меню
    8.     dwContextId dq ? ;контекстный идентификатор либо окна либо элемента управления
    9.     MousePos POINT <>
    10. HELPINFO ends
    11. .code
    12. WinMain proc
    13. local msg:MSG
    14.  
    15.     xor ebx,ebx
    16.     mov esi,IMAGE_BASE
    17.     mov edi,offset ClassName
    18.     mov ecx,offset FileName
    19.     invoke LoadCursorFromFile
    20.     push rax    ;hIconSm
    21.     push rdi    ;lpszClassName
    22.     push rbx    ;lpszMenuName
    23.     push COLOR_WINDOW+1;hbrBackground
    24.     push 10003h    ;hCursor
    25.     push rax        ;hIcon
    26.     push rsi    ;hInstance
    27.     push rbx        ;cbClsExtra & cbWndExtra
    28.     pushaddr WndProc;lpfnWndProc
    29.     push sizeof WNDCLASSEX;cbSize & style
    30.     invoke RegisterClassEx,esp    ;addr WNDCLASSEX
    31.     push rbx
    32.     push rsi    ;rsi=400000h
    33.     shl esi,9    ;rsi=CW_USEDEFAULT
    34.     push rbx
    35.      push rbx
    36.     push rsi
    37.     push rsi
    38.     push rsi
    39.     push rsi
    40.     sub esp,20h
    41.     mov r9d,WS_OVERLAPPEDWINDOW or WS_VISIBLE
    42.         invoke CreateWindowEx,0,edi,edi
    43.     mov hwnd,rax
    44.     lea edi,msg
    45. @@:    invoke GetMessage,edi,NULL,0,0
    46.         invoke TranslateMessage,edi
    47.     invoke DispatchMessage,edi
    48.     jmp @b
    49. WinMain endp
    50. WndProc proc hWnd:QWORD,uMsg:QWORD,wParam:QWORD,lParam:QWORD
    51. local ps:PAINTSTRUCT
    52. local expRect:RECT
    53.  
    54.     mov hWnd,rcx
    55.     mov wParam,r8
    56.     mov lParam,r9
    57.  
    58.       cmp edx,WM_DESTROY
    59.       je wmDESTROY
    60.         cmp edx,WM_PAINT
    61.         je wmPAINT
    62.         cmp edx,WM_HELP
    63.         je wmHELP
    64.         cmp edx,WM_KEYDOWN
    65.         je wmF1
    66.         leave
    67.          jmp NtdllDefWindowProc_
    68.  
    69. wmDESTROY: invoke RtlExitUserProcess,NULL
    70. wmPAINT:invoke BeginPaint,,addr ps
    71.         invoke GetClientRect,hWnd,addr expRect
    72.         invoke DrawText,ps.hdc,&message,-1,addr expRect,DT_SINGLELINE or DT_CENTER or DT_VCENTER
    73.         invoke EndPaint,hWnd,addr ps
    74.        jmp wmBYE
    75. wmHELP:    mov rax,[r9+HELPINFO.iCtrlId]
    76.        cmp rax,hwnd
    77.        je wmBYE
    78.         invoke ShellExecute,0,0,&hlpfile,0,0,1
    79.         jmp wmBYE
    80. wmF1:    cmp r8,VK_F1
    81.         jne wmBYE
    82.        invoke MessageBox,hwnd,&message2,&ClassName,MB_HELP
    83. wmBYE:  leave
    84.         ret
    85. WndProc endp
    86. ;-----------------------------------
    87. ClassName db "Uncle Remus tales:#3 Simple window",0
    88. FileName db "..\Images\br_Rabbit3.cur",0
    89. message db "Press on F1 button",0
    90. message2 db "Press on 'Help'",0
    91. hlpfile db "tut_01.hlp",0
    92. hwnd dq ?
    93. end
    Здесь asm/exe-файлы и hlp-файл
    Вариант четвертый
    tut_04.asm обработка нажатия "Help" в SoftModalMessageBox.
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. MSGBOXDATA struct
    4.      params              MSGBOXPARAMS <>
    5.      pwndOwner           QWORD ?
    6.      wLanguageId         DWORD ?,?
    7.      pidButton           QWORD ?         ; // Array of button IDs
    8.      ppszButtonText      QWORD ?         ; // Array of button text strings
    9.      cButtons            DWORD ?
    10.      DefButton           DWORD ?
    11.      CancelId            DWORD ?
    12.      Timeout             DWORD ?
    13. MSGBOXDATA ends
    14. .code
    15. hlpfile     db 'ImagEdit.hlp',0
    16. MsgBoxText1:    du <Win64 Assembly is Great>
    17. MsgCaption8: du <SoftModalMessageBox>
    18. sBTN1: du <OK>
    19. sBTN2: du <Help>
    20. dwBtnIds  dd 1,9
    21. dwTxtTbl  dq sBTN1,sBTN2
    22. align 16
    23. WinMain proc
    24. local mb:MSGBOXPARAMS
    25. local mbxData:MSGBOXDATA
    26.  
    27.      mov mbxData.params.cbSize,sizeof MSGBOXPARAMS
    28.      and mbxData.params.hwndOwner,0
    29.      mov mbxData.params.hInstance,IMAGE_BASE
    30.      movr mbxData.params.lpszText,MsgBoxText1;адрес текста в окне сообщений      8
    31.      movr mbxData.params.lpszCaption,MsgCaption8;адрес заголовка в окне сообщений   8
    32.      mov mbxData.params.dwStyle,MB_OK or MB_USERICON or MB_HELP;MB_YESNOCANCEL OR MB_ICONWARNING or MB_USERICON
    33.      movr mbxData.params.lpszIcon,1000
    34.      mov mbxData.params.dwContextHelpId,1
    35.      mov eax,offset MsgBoxCallback
    36.      mov mbxData.params.lpfnMsgBoxCallback,rax
    37.       mov mbxData.params.dwLanguageId,0
    38.       and mbxData.pwndOwner,0
    39.       and mbxData.wLanguageId,0
    40.       movr mbxData.pidButton,dwBtnIds
    41.       movr mbxData.ppszButtonText,dwTxtTbl
    42.       mov mbxData.cButtons,2;16
    43.       and mbxData.DefButton,0
    44.        mov mbxData.CancelId,1
    45.        or mbxData.Timeout,-1
    46.       invoke SoftModalMessageBox,&mbxData
    47.       invoke RtlExitUserProcess,NULL
    48. WinMain endp
    49. align 16
    50. MsgBoxCallback proc lpHelpInfo:qword;(LPHELPINFO lpHelpInfo)
    51.  
    52.      invoke ShellExecute,0,0,&hlpfile,0,0,1
    53.      leave
    54.      retn
    55. MsgBoxCallback endp
    56. end
    tut_04.rc
    Код (C):
    1. 1000 ICON DISCARDABLE "br_Bear4.ico"
    Здесь asm/rc/exe-файлы, иконка и hlp-файл


    © Mikl___ 2021
     

    Вложения:

    • 05.jpg
      05.jpg
      Размер файла:
      36 КБ
      Просмотров:
      2.261
    • help0.zip
      Размер файла:
      58,2 КБ
      Просмотров:
      755
    kero, q2e74 и Aiks нравится это.
  9. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.709
    Глава пятьдесят вторая. Братец Кролик и просмотр видео-файлов

    Пишем плеер на основе Animate-класса


    Один из простейших проигрывателей. Создаем окно, в это окно загружаем дочернее окно с классом Animate с указанием файла, который хотим воспроизвести. Создаем дочернее окно с помощью функции CreateWindowEx. Нам не нужно регистрировать класс окна, поскольку он уже зарегистрирован Windows. При создании экрана указываем «SysAnimate32» в качестве имени класса CreateWindowsEx. Другие параметры, которые нужно указать, — это дескриптор родительского окна и идентификатор элемента управления. Идентификатор элемента управления должен быть уникальным, если мы использовали несколько элементов управления, чтобы отличить этот элемент управления от других. Установим ID = 104. Нам также необходимо указать размеры экрана и координаты его верхнего левого угла. Обычно дочернее окно создается во время обработки сообщения WM_CREATE главного окна. Мы создадим дочернее окно перед обработкой цикла сообщений. После создания инструмента управления анимацией мы отправляем сообщение ACM_OPEN через функцию SendDlgItemMessage, чтобы открыть AVI-файл и загрузить его в память. В сообщении указываем путь к AVI-файлу.
    Принцип действия органа управления Animation заключается в проигрывании несжатого AVI -файла. Для сжатия можно использовать алгоритм RLE, причем AVI-файл не должен содержать звуковой информации.
    Код (ASM):
    1. ; GUI #
    2. OPTION DOTNAME
    3. include win64a.inc
    4. ACM_OPEN = WM_USER + 100
    5. ACS_AUTOPLAY = 4
    6. ID_ANIMATE = 101
    7. .code
    8. WinMain proc
    9. local msg:MSG
    10. local hwnd:QWORD
    11.      xor ebx,ebx
    12.      mov esi,IMAGE_BASE
    13.      invoke LoadCursorFromFile,&FileNameCur
    14.      mov edi,offset ClassName
    15.      push rax ;hIconSm
    16.      push rdi ;lpszClassName
    17.      push rbx ;lpszMenuName
    18.      push COLOR_WINDOW;hbrBackground
    19.      push rax ;hCursor
    20.      push rax        ;hIcon
    21.      push rsi ;hInstance
    22.      push rbx        ;cbClsExtra & cbWndExtra
    23.      pushaddr WndProc      ;lpfnWndProc
    24.      push sizeof WNDCLASSEX;cbSize & style
    25.       invoke RegisterClassEx,esp ;addr WNDCLASSEX
    26.       push rbx
    27.      push rsi ;rsi=400000h
    28.      push rbx
    29.      push rbx
    30.      push 440
    31.      push 510
    32.      push 10
    33.      push 10
    34.      sub esp,20h
    35.      invoke CreateWindowEx,0,edi,edi,WS_CAPTION or WS_SYSMENU or WS_VISIBLE
    36.      mov hwnd,rax
    37.      push rbx
    38.      push rsi;IMAGE_BASE
    39.      push ID_ANIMATE
    40.      push rax;hwnd
    41.      push rbx;ширина и высота кадра настроятся автоматически
    42.      push rbx
    43.      push 20
    44.      push 20
    45.      sub esp,20h
    46.      invoke CreateWindowEx, WS_EX_STATICEDGE or WS_EX_CLIENTEDGE,&Animate32,&NoText, \            WS_CHILD or WS_VISIBLE or WS_TABSTOP or ACS_AUTOPLAY
    47.      movr qword ptr [rsp+20h],AviFile
    48.     invoke SendDlgItemMessage,hwnd,ID_ANIMATE,ACM_OPEN,IMAGE_BASE
    49.     lea edi,msg
    50. @@:     invoke GetMessage,edi,0,0,0
    51.         invoke DispatchMessage,edi
    52.         jmp @b
    53. WinMain endp
    54. WndProc: cmp edx,WM_DESTROY
    55.         je wmDESTROY
    56.         jmp NtdllDefWindowProc_
    57. wmDESTROY:invoke RtlExitUserProcess,NULL
    58. ;---------------------------------------
    59. .data
    60. ClassName db 'Uncle Remus tales:#37a Animation',0
    61. FileNameCur db "..\Images\br_Rabbit3.cur",0
    62. AviFile db 'movie0.avi',0
    63. Animate32 db "SysAnimate32"
    64. NoText db 0
    65. end
    SendDlgItemMessageA(
    _In_ HWND hwnd, ;Дескриптор окна, оконная процедура которого получит сообщение
    _In_ int ID_ANIMATE, ;Идентификатор элемента Animate32
    _In_ UINT ACM_OPEN, ;Сообщение, которое нужно отправить
    _In_ WPARAM IMAGE_BASE, ;Дескриптор экземпляра модуля
    _In_ LPARAM lpszName ;путь к AVI-файлу
    avi-файл для пробы movie0.avi
    Для Animation можно отправлять сообщения
    ЗначениесообщенияОписание
    hexbin
    46410001100100ACM_OPENAоткрывает AVI-клип и показывает на экране в аниматоре его первый кадр
    46510001100101ACM_PLAYпроигрывает AVI-клип
    46610001100110ACM_STOPостанавливает воспроизведениеAVI-клипа в аниматоре
    46710001100111ACM_OPENW
    ЗначениеСтильОписание
    hexbin
    1001ACS_CENTERВидеоизображение центрировано в окне органа управления
    2010ACS_TRANSPARENTВидеоизображение транслируется в прозрачном режиме
    4100ACS_AUTOPLAYПроигрывание видеоизображения начинается автоматически сразу после открытия соответствующего AVI-файла
    Извещения от органа управления Animation

    ЗначениеСообщениеОписание
    hexbin
    1001ACN_STARTпроцесс проигрывания видеоролика начался
    2010ACN_STOPпроцесс завершился
    Animation посылает в родительское окно извещения вместе с сообщением WM_COMMAND. Это извещения ACN_START и ACN_STOP.
     

    Вложения:

    • 00.jpg
      00.jpg
      Размер файла:
      64,4 КБ
      Просмотров:
      242
    Research, mantissa и Marylin нравится это.
  10. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.709

    Видео-плеер на основе интерфейса управляющих сообщений MCI

    Устройство открывается командой MCI_OPEN с использованием структуры MCI_OPEN_PARMS Поле lpstrDeviceType в этой структуре должно содержать указатель на строку имени устройства, или константный идентификатор устройства.
    hexКомандаНазначение
    804MCI_CLOSE эта команда закрывает устройство. Ее необходимо выдавать после завершения работы с устройством
    806MCI_PLAYКоманда предназначена для проигрывания
    809MCI_PAUSEКоманда приостанавливает выполнение операции проигрывания
    808MCI_STOPКоманда останавливает выполнение операции проигрывания
    807MCI_SEEKКоманда позволяет выполнять позиционирование в пределах файла
    811MCI_BREAKС помощью команды указывается виртуальный код клавиши, с помощью которой можно прервать выполнение операции
    80BMCI_GETDEVCAPSС помощью команды можно определить возможности устройства.
    80AMCI_INFOС помощью команды можно получить информацию об устройстве в виде текстовой строки, такую как описание аппаратуры, имя файла, связанного с устройством.
    810MCI_SYSINFOС помощью команды можно получить системную информацию об устройстве в виде текстовой строки
    814MCI_STATUSКоманда используется для определения текущего состояния устройства
    80DMCI_SETКоманда предназначена для установки режима работы устройства
    852MCI_COPYКоманда предназначена для копирования данных в универсальный буфер обмена Clipboard. Для нее используется блок параметров в формате структуры MCI_GENERIC_PARMS, флаги MCI_NOTIFY и MCI_WAIT
    853MCI_PASTEКоманда вставляет данные из Clipboard в текущий буфер устройства. Для нее, как и для команды MCI_COPY, используется блок параметров в формате структуры MCI_GENERIC_PARMS, флаги MCI_NOTIFY и MCI_WAIT
    851MCI_CUTКоманда удаляет данные из текущего буфера устройства и копирует их в универсальный буфер обмена Clipboard. Для нее используется блок параметров в формате структуры MCI_GENERIC_PARMS, флаги MCI_NOTIFY и MCI_WAIT
    856MCI_DELETEКоманда удаляет данные из текущего буфера устройства без копирования их в Clipboard
    850MCI_LOADКоманда предназначена для загрузки файла
    Немного стараний и можно получить видио-плеер и редактор видео-файлов в одном флаконе.
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. MCI_ANIM_OPEN_PARMS STRUCT
    4.   dwCallback        QWORD      ?
    5.   wDeviceID         DWORD      ?
    6.   lpstrDeviceType   QWORD      ?
    7.   lpstrElementName  QWORD      ?
    8.   lpstrAlias        QWORD      ?
    9.   dwStyle           DWORD      ?
    10.   hWndParent        QWORD      ?
    11. MCI_ANIM_OPEN_PARMS ENDS
    12. MCI_ANIM_PLAY_PARMS STRUCT
    13.   dwCallback    QWORD      ?
    14.   dwFrom        DWORD      ?
    15.   dwTo          DWORD      ?
    16.   dwSpeed       DWORD      ?
    17. MCI_ANIM_PLAY_PARMS ENDS
    18. MCI_GENERIC_PARMS STRUCT
    19.   dwCallback  QWORD      ?
    20. MCI_GENERIC_PARMS ENDS
    21. .code
    22. WinMain proc
    23. local msg:MSG
    24. local buffer[200h]:byte
    25. local hFile:qword
    26. local wid:qword
    27. local hei:qword
    28. local szReadWrite:QWORD
    29. xor ebx,ebx
    30. mov esi,IMAGE_BASE
    31. invoke LoadCursorFromFileA,&FileNameCur
    32. mov edi,offset ClassName
    33. push rax ;hIconSm
    34. push rdi ;lpszClassName
    35. push rbx ;lpszMenuName
    36. push COLOR_WINDOW;hbrBackground
    37. push rax ;hCursor
    38. push rax        ;hIcon
    39. push rsi ;hInstance
    40. push rbx        ;cbClsExtra & cbWndExtra
    41. pushaddr WndProc      ;lpfnWndProc
    42. push sizeof WNDCLASSEX;cbSize & style
    43.     invoke RegisterClassExA,esp ;addr WNDCLASSEX
    44.         mov [rsp+30h],rbx          ;hTemplateFile
    45. mov qword ptr [rsp+28h],FILE_ATTRIBUTE_ARCHIVE ;dwFlagsAndAttributes
    46. mov qword ptr [rsp+20h],OPEN_EXISTING ;dwCreationDisposition
    47. invoke CreateFile,&ElementName,GENERIC_READ,\    ;dwDesiredAccess
    48. FILE_SHARE_READ or FILE_SHARE_WRITE,0  ;lpSecurityAttributes
    49. mov hFile,rax;handle to file
    50.         mov [rsp+20h],rbx
    51. invoke ReadFile,rax,&buffer,200h,&szReadWrite
    52.         invoke CloseHandle,hFile
    53.         mov eax,dword ptr buffer[102h]
    54. add eax,20
    55. mov wid,rax
    56.         mov eax,dword ptr buffer[106h]
    57. add eax,40
    58. mov hei,rax
    59. mov rax,qword ptr buffer[66h]
    60. mov edx,429497
    61. mul edx
    62. mov dur,rdx
    63. push rbx
    64. push rsi ;rsi=400000h
    65. shl esi,9
    66. push rbx
    67. push rbx
    68. push hei
    69. push wid
    70. push rsi
    71. push rsi
    72. sub esp,20h
    73.     invoke CreateWindowExA,0,edi,edi,WS_CAPTION or WS_SYSMENU or WS_MINIMIZEBOX or WS_VISIBLE
    74.     lea edi,msg
    75. @@:     invoke GetMessageA,edi,0,0,0
    76.         invoke DispatchMessageA,edi
    77.         jmp @b
    78. WinMain endp
    79. WndProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
    80. local buff[96]:BYTE
    81. mov hWnd,rcx
    82. cmp edx,WM_DESTROY
    83. je wmDESTROY
    84. cmp edx,WM_CREATE
    85. je wmCREATE
    86. cmp edx,MM_MCINOTIFY
    87. je mmMCINOTIFY
    88. leave
    89.         jmp NtdllDefWindowProc_
    90. wmDESTROY:mov ecx,mciOP.wDeviceID
    91. invoke mciSendCommand,,MCI_CLOSE,0,&mciCP
    92.         invoke RtlExitUserProcess,NULL
    93. wmCREATE:mov mciOP.hWndParent,rcx
    94. invoke mciSendCommand,0,MCI_OPEN,MCI_WAIT or MCI_OPEN_ELEMENT or \
    95. MCI_ANIM_OPEN_WS or MCI_ANIM_OPEN_PARENT,&mciOP
    96. or eax,eax
    97. je @f
    98. invoke MCIError
    99. ;--------------------------------------------------------------------- EOF AVI
    100. mmMCINOTIFY:;invoke DestroyWindow,hWnd
    101. jmp wmBYE
    102. ;-------------------------------------------------------------------- Play AVI
    103. @@: mov rax,hWnd
    104. mov mciPP.dwCallback,rax
    105. mov ecx,mciOP.wDeviceID
    106. invoke mciSendCommand,,MCI_PLAY,MCI_NOTIFY,&mciPP
    107. or eax,eax
    108. je wmBYE
    109. MCIError:sub esp,28h
    110. invoke mciGetErrorString,eax,&buff,96
    111. invoke MessageBoxA,hWnd,&buff,&aMCIError,MB_OK or MB_ICONSTOP
    112. wmBYE: leave
    113. ret
    114. WndProc endp
    115. .data
    116. ClassName db 'Uncle Remus tales:#37b Animation',0
    117. FileNameCur db "..\Images\br_Rabbit3.cur",0
    118. mciOP  MCI_ANIM_OPEN_PARMS <0,0,DeviceType,ElementName,0,WS_CHILD,0>
    119. mciPP  MCI_ANIM_PLAY_PARMS <0>
    120. mciCP  MCI_GENERIC_PARMS   <1>
    121. aMCIError db "MCI Error",0
    122. DeviceType DB 'AVIVideo',0
    123. ElementName DB 'movie2.wmv',0
    124. dur dq ?
    125. end
     

    Вложения:

    • movie2.wmv
      Размер файла:
      5,3 МБ
      Просмотров:
      80
    • 00.jpg
      00.jpg
      Размер файла:
      39,3 КБ
      Просмотров:
      233
    Marylin и mantissa нравится это.
  11. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.709
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. .code
    4. WinMain proc
    5.        sub esp,7*8
    6.        mov qword ptr [rsp+28h],SW_SHOWNORMAL
    7.        and qword ptr [rsp+20h],0
    8.        invoke ShellExecute,0,&szNoTxt,&szFilm,0
    9.         invoke RtlExitUserProcess,NULL
    10. WinMain endp
    11. .data
    12. szFilm db 'movie3.wmv'
    13. szNoTxt db 0
    14. end
     

    Вложения:

    • 00.jpg
      00.jpg
      Размер файла:
      52,7 КБ
      Просмотров:
      239
    • movie3.wmv
      Размер файла:
      4 МБ
      Просмотров:
      82
    Последнее редактирование: 9 дек 2023
    mantissa нравится это.
  12. Intro

    Intro Active Member

    Публикаций:
    0
    Регистрация:
    29 авг 2009
    Сообщения:
    562
    У меня не получилось откомпилировать файл, нет масм64. Но я переделал под вин32 и UASM
    Код (ASM):
    1. ; Демка проигрывания avi файла на форме.
    2. .386
    3. .model flat,stdcall
    4. option casemap:none
    5. include \masm32\include\windows.inc
    6. include \masm32\include\user32.inc
    7. include \masm32\include\kernel32.inc
    8. includelib \masm32\lib\user32.lib
    9. includelib \masm32\lib\kernel32.lib
    10. include msvcrt.inc
    11. include macros.asm
    12. ACM_OPEN        = WM_USER + 100
    13. ACS_AUTOPLAY    = 4
    14. MAIN_FORM_ID    = 0
    15. ID_ANIMATE      = 101
    16. WS_MAIN_FORM    = WS_CAPTION or WS_SYSMENU or WS_VISIBLE
    17. WS_AVI_FORM     = WS_CHILD or WS_VISIBLE or WS_TABSTOP or ACS_AUTOPLAY
    18. .const
    19. ClassName       db "Uncle Remus tales:#37a Animation",0
    20. .code
    21. WinMain proc hInst:HINSTANCE, hPrevInst:HINSTANCE, CmdLine:LPSTR, CmdShow:DWORD
    22. local wc:WNDCLASSEX, msg:MSG
    23. ;edi -  hWnd:HWND
    24.     lea     esi, wc
    25.     xor     ebx, ebx
    26.     ASSUME  esi:ptr WNDCLASSEX, edi:ptr MSG
    27.     mov     [esi].cbSize, sizeof WNDCLASSEX
    28.     mov     [esi].style, CS_BYTEALIGNCLIENT
    29.     mov     [esi].lpfnWndProc, offset WndProc
    30.     mov     [esi].cbClsExtra, ebx   ;=NULL
    31.     mov     [esi].cbWndExtra, ebx   ;=NULL
    32.     mrm     [esi].hInstance, hInst
    33.     mov     [esi].hbrBackground, COLOR_WINDOW
    34.     mov     [esi].lpszClassName, offset ClassName
    35.     mov     [esi].hIcon, LoadIcon(ebx, IDI_APPLICATION)
    36.     mov     [esi].hIconSm, eax
    37.     mov     [esi].hCursor, LoadCursor(ebx, IDC_ARROW)
    38.     RegisterClassEx(esi)
    39.     mov     edi, CreateWindowEx(ebx,&ClassName,&ClassName,WS_MAIN_FORM,200,50,510,440,ebx,MAIN_FORM_ID,hInst,ebx)
    40.     CreateWindowEx(WS_EX_STATICEDGE + WS_EX_CLIENTEDGE, CSTR("SysAnimate32"), ebx, WS_AVI_FORM, 20,20,99,99, edi, ID_ANIMATE, hInst, ebx)
    41.     SendDlgItemMessage(edi, ID_ANIMATE, ACM_OPEN, hInst, CSTR("output.avi"))
    42. ;   ShowWindow(edi, SW_SHOWNORMAL)
    43. ;   UpdateWindow(edi)
    44.     lea     edi, msg
    45.     .while (true)
    46.         GetMessage(edi, ebx, ebx, ebx)
    47.         .break .if (!eax)
    48.         TranslateMessage(edi)
    49.         DispatchMessage(edi)
    50.     .endw
    51.     mov     eax, [edi].wParam
    52.     ASSUME  esi:nothing, edi:nothing
    53.     ret
    54. WinMain endp
    55. align_proc
    56. WndProc proc uses esi edi ebx hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
    57.     .if (uMsg == WM_DESTROY)
    58.         PostQuitMessage(NULL);
    59. ;   .elseif (uMsg == WM_CREATE)
    60.     .else
    61.         DefWindowProc(hWnd, uMsg, wParam, lParam)
    62.         ;//перемещаем форму за любую часть!
    63.         .if (uMsg == WM_NCHITTEST && eax == HTCLIENT)
    64.             mov     eax, HTCAPTION
    65.         .endif
    66.         jmp     EXIT
    67.     .endif
    68.     xor     eax, eax
    69. EXIT:
    70.     ret
    71. WndProc endp
    72. main_startup_Win32_END
    Для моих библиотечных файлов. Работает!
     
    Последнее редактирование: 8 дек 2023
    Mikl___ нравится это.
  13. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.329
    Современные сеньоры девелоперы не могут длину строки посчитать без подсказок от чата жпт, а вы им видеоплееры на ассемблере предлагаете :)
     
    Mikl___ нравится это.
  14. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.709
    Структура SHELLEXECUTEINFO
    полетипописание
    cbSizedwordразмер структуры
    fMaskdwordКомбинация флагов, определяющих используемую часть структуры
    hwndqwordДескриптор окна, вызывающего функцию ShellExecuteEx
    lpVerbqwordСтрока, определяющее действие с файлом lpFile
    lpFileqwordИмя файла для открытия, печати, запуска и других операций lpVerb
    lpParametersqwordДополнительные параметры. Обычно используется как опции командной строки
    lpDirectoryqwordПуть используемой папки. Если параметр не определен, то используется текущая папка
    nShowdword, dwordПоказать открытое окно и активировать его
    hInstAppqwordЕсли ShellExecuteEx отработала успешно, то параметр получает дескриптор экземпляра приложения
    lpIDListqwordУказатель на структуру ITEMIDLIST (PIDL), определяющую файл для запуска. Данный параметр используется, если fMask содержит SEE_MASK_IDLIST или SEE_MASK_INVOKEIDLIST
    lpClassqwordИмя класса файла или глобальный идентификатор (GUID). Данный параметр используется, если fMask содержит SEE_MASK_CLASSNAME
    hkeyClassqwordДескриптор ключа реестра. Данный параметр используется, если fMask содержит SEE_MASK_CLASSKEY
    dwHotKeyqword Горячая клавиша, ассоциированная с приложением. Младшее слово является виртуальным кодом клавиши, а старшее слово - комбинация флагов Данный параметр используется, если fMask содержит SEE_MASK_HOTKEY
    hIconqwordДескриптор значка, используемого для класса файла. Данный параметр используется, если fMask содержит SEE_MASK_ICON
    hProcessqwordДескриптор процесса. Данный параметр используется, если fMask содержит SEE_MASK_NOCLOSEPROCESS
    hexfMask
    1​
    SEE_MASK_CLASSNAME Используется lpClass
    3​
    SEE_MASK_CLASSKEYИспользуется hkeyClass
    4​
    SEE_MASK_IDLISTИспользуется lpIDList
    C​
    SEE_MASK_INVOKEIDLISTИспользуется lpIDList
    10​
    SEE_MASK_ICONИспользуется hIcon
    20​
    SEE_MASK_HOTKEYИспользуется dwHotKey
    40​
    SEE_MASK_NOCLOSEPROCESSИспользуется hProcess
    80​
    SEE_MASK_CONNECTNETDRVПроверка на расшаренность файла и связь с диском. lpFile является универсальным именем (UNC) файла в сети
    100​
    SEE_MASK_FLAG_DDEWAIT,
    SEE_MASK_NOASYNC
    If ShellExecuteEx starts a DDE conversation, wait for that conversation to finish before the function returns.
    200​
    SEE_MASK_DOENVSUBSTРасширяет среду переменных окружения в lpDirectory или lpFile
    400​
    SEE_MASK_FLAG_NO_UIНе показывать диалоговое окно ошибки в случае ее возникновения
    4000​
    SEE_MASK_UNICODE
    8000​
    SEE_MASK_NO_CONSOLE
    10000​
    SEE_MASK_ASYNCOK
    20000​
    SEE_MASK_HMONITOR
    800000​
    SEE_MASK_NOZONECHECKS
    1000000​
    SEE_MASK_NOQUERYCLASSSTORE
    2000000​
    SEE_MASK_WAITFORINPUTIDLE
    4000000​
    SEE_MASK_FLAG_LOG_USAGE
    lpVerb
    "explore"Если lpFile имя файла, то открывает его в Проводнике
    "open"Открывает lpFile с помощью связанной с этим типом файла программой. Открытие исполняемых файлов запускает файл
    "print"Печать lpFile с использованием связанной с печатью программой
    bindecnShow
    0000
    0​
    SW_HIDEСкрыть окно
    0001
    1​
    SW_SHOWNORMALПоказать открытое окно и активировать его (как обычно)
    0010
    2​
    SW_SHOWMINIMIZEDПоказать открытое окно свернутым
    0011
    3​
    SW_MAXIMIZE,
    SW_SHOWMAXIMIZED
    Показать открытое окно развернутым
    0100
    4​
    SW_SHOWNOACTIVATEПоказать открытое окно в текущих размерах и позиции, но не активировать его
    0101
    5​
    SW_SHOWПоказать окно
    0110
    6​
    SW_MINIMIZEСвернуть окно
    0111
    7​
    SW_SHOWMINNOACTIVEПоказать открытое окно свернутым, но не активировать его
    1000
    8​
    SW_SHOWNAПоказать открытое окно в текущем состоянии, но не активировать его
    1001
    9​
    SW_RESTOREВосстановить окно
    В случае ошибки получает один из следующих флагов, определяющих тип ошибки:
    bindechInstApp
    000001
    2​
    SE_ERR_FNFФайл не найден
    000011
    3​
    SE_ERR_PNFПуть не найден
    000101
    5​
    SE_ERR_ACCESSDENIEDВ доступе отказано
    001000
    8​
    SE_ERR_OOMНедостаточно памяти
    011010
    26​
    SE_ERR_SHAREРасшаренный файл не открывается
    011011
    27​
    SE_ERR_ASSOCINCOMPLETEНет информации об ассоциации файла
    011100
    28​
    SE_ERR_DDETIMEOUTThe DDE operation timed out
    011101
    29​
    SE_ERR_DDEFAILОперация DDE не прошла
    011110
    30​
    SE_ERR_DDEBUSYОперация DDE занята
    011111
    31​
    SE_ERR_NOASSOCНет ассоциированной программы для требуемого действия
    100000
    32​
    SE_ERR_DLLNOTFOUNDТребуемый DLL не найден
    Горячая клавиша, ассоциированная с приложением. Младшее слово является виртуальным кодом клавиши, а старшее слово - комбинация следующих флагов:
    bindecdwHotKey
    0001
    1​
    HOTKEYF_SHIFTКлавиша Shift как модификатор
    0010
    2​
    HOTKEYF_CONTROLКлавиша Ctrl как модификатор
    0100
    4​
    HOTKEYF_ALTКлавиша Alt как модификатор
    1000
    8​
    HOTKEYF_EXTДополнительная клавиша как модификатор
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. SHELLEXECUTEINFO struct
    4.    cbSize dd ?
    5.    fMask  dd ?
    6.    hwnd   dq ?
    7.     lpVerb dq ?
    8.     lpFile dq ?
    9.     lpParameters dq ?
    10.    lpDirectory dq ?
    11.     nShow dd ?,?
    12.     hInstApp dq ?
    13.    lpIDList dq ?
    14.    lpClass dq ?
    15.    hkeyClass dq ?
    16.    dwHotKey dq ?
    17.    hIcon dq ?
    18.    hProcess dq ?
    19. SHELLEXECUTEINFO ends
    20. .code
    21. WinMain proc
    22.        sub esp,7*8
    23.        invoke ShellExecuteEx,&sei
    24.        invoke RtlExitUserProcess,NULL
    25. WinMain endp
    26. .data
    27. sei label   SHELLEXECUTEINFO
    28.        dd sizeof SHELLEXECUTEINFO ;cbSize
    29.        dd 1500h ;fMask
    30.        dq 0     ;hwnd
    31.        dq szNoTxt;lpVerb
    32.        dq szFilm ;lpFile
    33.        dq 0      ;lpParameters
    34.        dq 0 ;lpDirectory
    35.        dd SW_SHOWNORMAL,0;nShow
    36.        dq 0    ;hInstApp
    37.        dq 0    ;lpIDList
    38.        dq 0 ;lpClass
    39.        dq 0 ;hkeyClass
    40.        dq 0    ;dwHotKey
    41.        dq 0 ;hIcon
    42.        dq 0    ;hProcess
    43. szFilm db 'movie4.wmv'
    44. szNoTxt db 0
    45. end
     

    Вложения:

    • movie4.wmv
      Размер файла:
      2,9 МБ
      Просмотров:
      77
    • 00.jpg
      00.jpg
      Размер файла:
      65,4 КБ
      Просмотров:
      220
    Win32Api нравится это.
  15. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.709
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. .code
    4. SHELLEXECUTEINFO struct
    5.        cbSize dd ?
    6.        fMask dd ?
    7.        hwnd dq ?
    8.        lpVerb dq ?
    9.        lpFile dq ?
    10.        lpParameters dq ?
    11.        lpDirectory dq ?
    12.        nShow dd ?,?
    13.        hInstApp dq ?
    14.        lpIDList dq ?
    15.        lpClass dq ?
    16.        hkeyClass dq ?
    17.        dwHotKey dq ?
    18.        hIcon dq ?
    19.        hProcess dq ?
    20. SHELLEXECUTEINFO ends
    21. WinMain proc
    22.         sub esp,8       ;<--16bit align
    23.        xor ebx,ebx
    24.        push rbx ; hProcess
    25.        push rbx ;      hMonitor
    26.        push rbx ;      hIcon
    27.        push rbx ;      dwHotKey
    28.        push rbx ;      hkeyClass
    29.        push rbx ;      lpClass
    30.        push rbx ;      lpIDList
    31.        push SW_SHOWNORMAL; nShow   +   hInstapp
    32.        push rbx ;      lpDirectory
    33.        push rbx ;      lpParameters
    34.        pushaddr szFilm ;      lpFile
    35.        pushaddr szOpen ;      lpVerb
    36.        push rbx ;      hWnd
    37.        mov rax,((1500h shl 32) + (sizeof SHELLEXECUTEINFO)) ;cbSize=sizeof SHELLEXECUTEINFO  fMask=1500h
    38.        push rax ; cbSize   fMask
    39.        invoke ShellExecuteEx,esp
    40.        invoke RtlExitUserProcess,NULL
    41. WinMain endp
    42. .data
    43. szFilm db 'movie6.mp4',0
    44. szOpen db 'open'
    45. end
     

    Вложения:

    • 00.jpg
      00.jpg
      Размер файла:
      50,9 КБ
      Просмотров:
      218
    • movie6.mp4
      Размер файла:
      1 МБ
      Просмотров:
      73
    Marylin и Win32Api нравится это.
  16. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.709

    Видео-плеер на основе MCI-окна

    Создаем MCI-окно, вызывая для этого функцию MCIWndCreate со следующими параметрами
    параметрназначение
    hwndParentидентификатор родительского окна
    hInstanceидентификатор приложения
    dwStyleстиль окна
    szFileимя устройства или путь к файлу

    Более подробно о параметрах функции

    hwndParent
    Через этот параметр приложение передает функции идентификатор окна, создавшего MCI-окно. Если родительского окна нет, в качестве параметра указывают NULL.
    dwStyle
    Стиль создаваемого окна. Можно указывать стили, стандартные для функции CreateWindow, а также дополнительные, список которых приведен в таблице ниже. Если стандартные стили не указаны, то если есть родительское окно, используются стили WS_CHILD, WS_BORDER и WS_VISIBLE. Если параметр hwndParent указан как NULL, используются стили WS_OVERLAPPEDWINDOW и WS_VISIBLE. Для создания невидимого окна используют один из стандартных стилей, например, WS_CHILD
    szFile

    Указатель на текстовую строку, содержащую имя устройства или путь к файлу

    Функция MCIWndCreate позволяет определить обычные стили окна (WS_OVERLAPPEDWINDOW и WS_VISIBLE), а также специфические для окна MCI ― MCIWNDF_SHOWNAME и MCIWNDF_SHOWMODE.
    список дополнительных стилей, которые можно использовать при создании MCI-окна.
    dwStyleОписание
    MCIWNDF_NOAUTOSIZEWINDOWРазмер окна не изменяется при изменении размера изображения
    MCIWNDF_NOAUTOSIZEMOVIEПри изменении размеров окна не следует выполнять масштабирование изображения для полного заполнения внутренней области окна
    MCIWNDF_NOPLAYBARЕсли задан этот стиль, не отображается полоса просмотра
    MCIWNDF_NOMENUНе отображается кнопка для доступа к меню
    MCIWNDF_RECORDОтображается кнопка записи, в меню добавляется строка "New"
    MCIWNDF_NOERRORDLGПри возникновении ошибки на экран не выводится диалоговая панель с описанием этой ошибки. Приложение может получить описание самой последней возникшей ошибки при помощи функции MCIWndGetError
    MCIWNDF_NOTIFYMODEПри изменении режима родительское окно получит извещающее сообщение MCIWNDM_NOTIFYMODE
    MCIWNDF_NOTIFYPOSПри изменении текущей позиции приложение получит извещающее сообщение MCIWNDM_NOTIFYPOS
    MCIWNDF_NOTIFYMEDIAПри замене носителя данных (например, звукового компакт-диска) приложение получит извещающее сообщение MCIWNDM_NOTIFYMEDIA
    MCIWNDF_NOTIFYSIZEРодительское окно получит извещающее сообщение MCIWNDM_NOTIFYSIZE при изменении размераMCI-окна
    MCIWNDF_NOTIFYERRORПри возникновении ошибки родительское окно получит сообщение MCIWNDM_NOTIFYERROR
    MCIWNDF_NOTIFYALL MCI-окно будет извещать родительское окно в случае возникновения любых событий
    MCIWNDF_SHOWNAMEВ заголовке окна будет отображаться имя устройства или путь к файлу
    MCIWNDF_SHOWPOSВ заголовке окна будет отображаться текущая позиция
    MCIWNDF_SHOWMODEВ заголовке окна будет отображаться текущий режим работы
    MCIWNDF_SHOWALLБудут использованы все возможности MCI-окна (все органы управления, отображение информации в заголовке и так далее)
    Другой способ создания MCI-окна ― регистрация класса окна MCIWND_WINDOW_CLASS функцией MCIWndRegisterClass, не имеющей параметров, и создании на базе этого класса окна функцией CreateWindow.
    После создания окна запускается цикл обработки сообщений.
    asm-файл
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. include msvfw32.inc
    4. includelib msvfw32.lib
    5. MENU_ABOUT           equ 5
    6. MCIWNDF_NOPLAYBAR           equ 2
    7. MCIWNDF_NOMENU              equ 8
    8. MCIWNDM_CHANGESTYLES        equ WM_USER+135
    9. MCIWNDM_SENDSTRINGA         equ WM_USER+101
    10. MCIWNDM_SETZOOM             equ WM_USER+108
    11. MCIWNDM_OPENA               equ WM_USER+153
    12. IDC_ICON1      equ 500
    13. MSGBOXPARAMS struct
    14.   cbSize dd ?,?
    15.   hwndOwner dq ?
    16.   hInstance dq ?
    17.   lpszText dq ?
    18.   lpszCaption dq ?
    19.   dwStyle dd ?,?
    20.   lpszIcon dq ?
    21.   dwContextHelpId dd ?,?
    22.   lpfnMsgBoxCallback dq ?
    23.   dwLanguageId dd ?,?
    24. MSGBOXPARAMS ends
    25. .code
    26. WinMain proc
    27. local buffer[128]:BYTE
    28. local msg:MSG
    29.        xor ebx,ebx
    30.        lea eax,buffer
    31.        mov pBuffer,rax
    32.        invoke MCIWndCreate,0,IMAGE_BASE,WS_VISIBLE or WS_OVERLAPPEDWINDOW or MCIWNDF_NOMENU,&MediaFileName;имя устройства или путь к файлу
    33.         mov mcihWnd,rax
    34.         invoke DragAcceptFiles,eax,TRUE
    35. ;-----------------------------------------------
    36.         invoke GetSystemMenu,mcihWnd,FALSE
    37.         mov hMenu,rax
    38. @@: mov rax,handler_menu[rbx*8]
    39.        mov [rsp+20h],rax
    40.         invoke InsertMenuA,hMenu,ebx,MF_BYPOSITION,ebx
    41.        inc ebx
    42.        cmp ebx,6
    43.        jb @b
    44.         invoke SetWindowLongPtrA,mcihWnd,GWL_WNDPROC,&WndProc
    45.         mov prevWindow,rax
    46.        invoke LoadCursorFromFileA,&FileNameCur
    47.         invoke SetClassLongPtrA,mcihWnd,GCL_HICON,rax
    48.            lea edi,msg
    49. @@: invoke GetMessageA,edi,0,0,0
    50.         invoke DispatchMessageA,edi
    51.         jmp @b
    52. handler_menu dq szFile,szCD,szVideoDisk,szVideoPlayer,szFullScreen,szAbout
    53. WinMain endp
    54. WndProc proc hWnd:QWORD,uMsg:QWORD,wParam:QWORD,lParam:QWORD
    55.         mov hWnd,rcx
    56.        mov uMsg,rdx
    57.        mov wParam,r8
    58.         mov lParam,r9
    59.        xor ebx,ebx
    60.  
    61.         cmp edx,WM_CLOSE
    62.         je wmCLOSE
    63.         cmp edx,WM_SYSCOMMAND
    64.         je wmSYSCOMMAND
    65.         cmp edx,WM_DROPFILES
    66.         je wmDROPFILES
    67.         cmp edx,MM_MCINOTIFY
    68.         je mmMCINOTIFY
    69.         cmp edx,WM_CLOSE
    70.         je wmCLOSE
    71.         cmp edx,WM_DESTROY
    72.         jne default
    73. wmDESTROY:invoke RtlExitUserProcess,NULL
    74. mmMCINOTIFY:invoke ShowWindow,hWnd,SW_MINIMIZE or SW_SHOWNORMAL
    75.         invoke SendMessageA,hWnd, MCIWNDM_CHANGESTYLES,MCIWNDF_NOMENU,FALSE
    76.         invoke SendMessageA,hWnd,MCIWNDM_SENDSTRINGA,0,&szStop
    77.        jmp default
    78. wmDROPFILES:invoke DragQueryFile,wParam,0,pBuffer,128
    79.         invoke DragFinish,wParam
    80.        jmp a1
    81. wmSYSCOMMAND:cmp r8d,MENU_ABOUT
    82.        ja default
    83.        jmp [handle+r8*8]
    84. wmCLOSE:invoke SendMessageA,hWnd,MCIWNDM_SENDSTRINGA,0,&szStop
    85.         invoke SendMessageA,hWnd,MCIWNDM_SENDSTRINGA,0,&szClose
    86.        invoke DestroyWindow,hWnd
    87.        jmp default
    88. mnuFILE:mov rdx,pBuffer
    89.        and [rdx],rbx; ноль в начало буфера для названия файла
    90. ;заполняю OPENFILENAME
    91.        push rbx ;<--- align 16 bytes
    92.        push rbx;lpTemplateName
    93.        push rbx;lpfnHook
    94.        push rbx;lCustData
    95.        push rbx;lpstrDefExt
    96.        push OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or OFN_LONGNAMES \
    97. or OFN_EXPLORER or OFN_HIDEREADONLY;Flags & nFileOffset & nFileExtension
    98.        push rbx;lpstrTitle
    99.        push rbx;lpstrInitialDir
    100.        push rbx;nMaxFileTitle
    101.        push rbx;lpstrFileTitle
    102.        push 124;nMaxFile
    103.        push rdx;lpstrFile
    104.        push rbx;nMaxCustFilter & nFilterIndex
    105.        push rbx;lpstrCustomFilter
    106.         pushaddr LoadFileFilter;lpstrFilter
    107.        push IMAGE_BASE;hInstance
    108.        push hWnd;hwndOwner
    109.        push sizeof OPENFILENAME;lStructSize
    110. ;----------------------------------------------------
    111.        mov edi,esp;адрес OPENFILENAME
    112.         invoke GetOpenFileName,edi
    113.        test eax,eax
    114. jz wmCLOSE; если не выбран никакой файл
    115.         movzx edx,word ptr [rdi+OPENFILENAME.nFileExtension]
    116.         add rdx,[rdi+OPENFILENAME.lpstrFile];offset LoadFileBuffer
    117. ;add esp,4Ch; удаляю OPENFILENAME
    118.         mov eax,[rdx];в регистре еах расширение файла
    119.         or eax,202020h;приводим к нижнему регистру
    120.         cmp eax,"adc"
    121.        jnz a1
    122. mnuCD:  mov r8d,offset cdaudioDev
    123.        jmp @f
    124. mnuVIDEODISK: mov r8d,offset videodiscDev
    125.        jmp @f;wmBYE
    126. mnuVIDEOPLAYER:mov r8d,offset szVideoPlayer
    127. @@: invoke lstrcpy,pBuffer
    128. a1: invoke SendMessageA,hWnd,MCIWNDM_SENDSTRINGA,0,&szStop
    129.         invoke SendMessageA,hWnd,MCIWNDM_OPENA,0,pBuffer
    130.         test eax,eax
    131.        jnz NoMedia;        .if eax = 0
    132.         invoke SendMessageA,hWnd,MCIWNDM_SENDSTRINGA,0,&szPlay
    133.         test eax,eax
    134.        jnz NoMedia;            .if eax = 0
    135.         invoke ShowWindow,hWnd,SW_SHOWNORMAL
    136.         invoke SendMessageA,hWnd,MCIWNDM_CHANGESTYLES,MCIWNDF_NOPLAYBAR,0
    137.         invoke SendMessageA,hWnd,MCIWNDM_SETZOOM,0,100
    138.        mov flag_fullscreen,TRUE
    139.         jmp @f
    140. NoMedia:mov flag_fullscreen,rbx;FALSE
    141.         invoke SendMessageA,hWnd,MCIWNDM_SENDSTRINGA,0,&szClose
    142. invoke SendMessageA,hWnd, MCIWNDM_CHANGESTYLES, MCIWNDF_NOPLAYBAR, MCIWNDF_NOPLAYBAR
    143. @@:     invoke DragAcceptFiles,mcihWnd,TRUE
    144.        jmp default
    145. mnuFULLSCREEN:invoke ShowWindow,hWnd,SW_SHOWNORMAL
    146.         invoke SendMessageA,hWnd,MCIWNDM_SENDSTRINGA,0,&szPlayfullscreen
    147.         test eax,eax;.if eax=0
    148.        jnz default
    149. invoke SendMessageA,hWnd,MCIWNDM_CHANGESTYLES, MCIWNDF_NOPLAYBAR, MCIWNDF_NOPLAYBAR
    150.         jmp default
    151. mnuABOUT:invoke MessageBoxIndirectA,&mb
    152. default:mov rax,lParam
    153.        mov [rsp+20h],rax
    154.        invoke CallWindowProcA,prevWindow,hWnd,uMsg,wParam
    155.        leave
    156.        retn
    157. handle dq mnuFILE,mnuCD, mnuVIDEODISK, mnuVIDEOPLAYER, mnuFULLSCREEN, mnuABOUT
    158. WndProc endp
    159. ;---------------------------------------
    160. .data
    161. FileNameCur db "br_Rabbit3.cur",0
    162. mcihWnd                 dq ?
    163. prevWindow            dq ?
    164. pBuffer                      dq ?
    165. hMenu                       dq ?
    166. flag_fullscreen dq FALSE
    167. szFile                         db "File",0
    168. szCD                          db "Audio CD",0
    169. szVideoDisk             db "Video CD",0
    170. szVideoPlayer          db "vcr",0
    171. szFullScreen            db "Full screen",0
    172. LoadFileFilter          db "All files",0,"*",0,0;
    173. szAbout                      db "About program...",0
    174. szPlay                          db "PLAY",0
    175. szStop                         db "STOP",0
    176. szClose                        db "CLOSE",0
    177. szPlayfullscreen        db "PLAY FULLSCREEN NOTIFY",0
    178. szAboutText               db "Mini-media player",0Dh,0Ah,\
    179.                            "Based on JTG coding",0
    180. cdaudioDev              db "cdaudio",0
    181. vcrExt                        db "UNKNOWN",0
    182. videodiscDev           db "videodisk",0
    183. mb label   MSGBOXPARAMS
    184.   dd sizeof MSGBOXPARAMS,?;cbSize
    185.   dq 0  ;hwndOwner
    186.   dq IMAGE_BASE  ;hInstance
    187.   dq szAboutText ;lpszText
    188.   dq szAbout  ;lpszCaption
    189.   dd MB_OK or MB_USERICON,?;dwStyle
    190.   dq IDC_ICON1  ;lpszIcon
    191.   dd 0,?;dwContextHelpId
    192.   dq 0  ;lpfnMsgBoxCallback
    193.   dd 0,?;dwLanguageId
    194. MediaFileName           db "movie7.wmv"
    195. end
    rc-файл
    Код (C++):
    1. #define IDC_ICON1 500
    2. IDC_ICON1 ICON "br_Fox1.ico"
     

    Вложения:

    • 00.jpg
      00.jpg
      Размер файла:
      40 КБ
      Просмотров:
      217
    • movie7.wmv
      Размер файла:
      496,9 КБ
      Просмотров:
      64
    Win32Api нравится это.
  17. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.709
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. include msvfw32.inc
    4. includelib msvfw32.lib
    5. MCIWNDF_NOMENU              equ 8
    6. MCIWNDM_GETLENGTH           equ WM_USER+104
    7. MCIWNDM_SENDSTRINGA         equ WM_USER+101
    8. .code
    9. WinMain proc
    10. local msg:MSG
    11.      
    12.        invoke MCIWndCreate,0,IMAGE_BASE,WS_VISIBLE or WS_OVERLAPPEDWINDOW or \
    13. MCIWNDF_NOMENU,&MediaFileName;имя устройства или путь к файлу
    14.         mov mcihWnd,rax
    15.         invoke SetWindowLongPtrA,mcihWnd,GWL_WNDPROC,&WndProc
    16.         mov prevWindow,rax
    17.        invoke LoadCursorFromFileA,&FileNameCur
    18.         invoke SetClassLongPtrA,mcihWnd,GCL_HICON,rax
    19.         lea edi,msg
    20. @@:     invoke GetMessageA,edi,0,0,0
    21.         invoke DispatchMessageA,edi
    22.         jmp @b
    23. WinMain endp
    24. WndProc proc hWnd:QWORD,uMsg:QWORD,wParam:QWORD,lParam:QWORD
    25.         mov hWnd,rcx
    26.         mov uMsg,rdx
    27.         mov wParam,r8
    28.         mov lParam,r9
    29.         cmp  edx,WM_CLOSE
    30.         je   wmCLOSE
    31.         cmp  edx,WM_DESTROY
    32.         jne  default
    33. wmDESTROY:invoke RtlExitUserProcess,NULL
    34. wmCLOSE:invoke SendMessageA,hWnd,MCIWNDM_SENDSTRINGA,0,&szStop
    35.         invoke SendMessageA,hWnd,MCIWNDM_SENDSTRINGA,0,&szClose
    36.         invoke DestroyWindow,hWnd
    37. default:mov rax,lParam
    38.         mov [rsp+20h],rax
    39.         invoke CallWindowProcA,prevWindow,hWnd,uMsg,wParam
    40.         leave
    41.         retn
    42. WndProc endp
    43. ;---------------------------------------
    44. .data
    45. FileNameCur db "br_Rabbit3.cur",0
    46. mcihWnd         dq ?
    47. prevWindow      dq ?
    48. szStop          db "STOP",0
    49. szClose         db "CLOSE",0
    50. MediaFileName   db "movie9.wmv"
    51. end
     

    Вложения:

    • 00.jpg
      00.jpg
      Размер файла:
      46,5 КБ
      Просмотров:
      216
    • movie9.wmv
      Размер файла:
      8,5 МБ
      Просмотров:
      150
    Win32Api нравится это.
  18. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.709
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. include winmm.inc
    4. includelib winmm.lib
    5. .code
    6. WinMain proc
    7. local msg:MSG
    8.        xor ebx,ebx
    9.         mov esi,IMAGE_BASE
    10.        mov edi,offset ClassName
    11.        invoke LoadCursorFromFileA,&FileNameCur
    12.         push rax ;hIconSm
    13.        push rdi ;lpszClassName
    14.        push rbx ;lpszMenuName
    15.        push COLOR_WINDOWTEXT;hbrBackground
    16.        push rax ;hCursor
    17.        push rax    ;hIcon
    18.        push rsi ;hInstance
    19.        push rbx    ;cbClsExtra & cbWndExtra
    20.        pushaddr WndProc  ;lpfnWndProc
    21.        push sizeof WNDCLASSEX;cbSize & style
    22.        invoke RegisterClassExA,esp ;addr WNDCLASSEX
    23.        push rbx
    24.        push rsi ;rsi=400000h
    25.        shl esi,9 ;rsi=CW_USEDEFAULT
    26.        push rbx
    27.        push rbx
    28.        push 360
    29.        push 450
    30.        push rsi
    31.        push rsi
    32.        sub esp,20h
    33.        invoke CreateWindowExA,0,edi,edi,WS_OVERLAPPEDWINDOW or WS_VISIBLE
    34.        lea edi,msg
    35. @@:     invoke GetMessageA,edi,0,0,0
    36.         invoke DispatchMessageA,edi
    37.         jmp @b
    38. WinMain endp
    39. WndProc proc hWnd:QWORD,uMsg:QWORD,wParam:QWORD,lParam:QWORD
    40.        mov hWnd,rcx
    41.        mov uMsg,rdx
    42.        mov wParam,r8
    43.         mov lParam,r9
    44.         cmp edx,WM_CREATE
    45.         je wmCREATE
    46.         cmp edx,WM_DESTROY
    47.         je wmDESTROY
    48.        cmp edx,MM_MCINOTIFY
    49.        je mmMCINOTIFY
    50.        leave
    51.        jmp NtdllDefWindowProc_
    52. ;-------------- Close AVI
    53. wmDESTROY:mov ecx,mciOP.wDeviceID
    54.        invoke mciSendCommand,,MCI_CLOSE,0,&mciCP
    55.        invoke RtlExitUserProcess,NULL
    56. wmCREATE:mov mciOP.hWndParent,rcx;hWnd
    57.        invoke mciSendCommand,0,MCI_OPEN,MCI_WAIT or MCI_OPEN_ELEMENT or \
    58. MCI_ANIM_OPEN_WS or MCI_ANIM_OPEN_PARENT,&mciOP
    59.        or eax,eax
    60.        je @f
    61.        invoke MCIError
    62. ;------------------------ EOF AVI
    63. mmMCINOTIFY:invoke DestroyWindow
    64.        jmp wmBYE
    65. ;------------------------ Play AVI
    66. @@:     mov rax,hWnd
    67.        mov mciPP.dwCallback,rax
    68.        mov ecx,mciOP.wDeviceID
    69.        invoke mciSendCommand,,MCI_PLAY,MCI_NOTIFY,&mciPP
    70.        or eax,eax
    71.        jz wmBYE
    72.        CALL MCIError
    73. wmBYE:  leave
    74.         retn
    75. WndProc endp
    76. ;--------------------------------------
    77. MCIError proc
    78. local buffer[100]:BYTE;временный буфер для сообщения об ошибках
    79.        invoke mciGetErrorString,rax,&buffer,100
    80.        invoke MessageBoxA,0,&buffer,&aMcierror,MB_OK or MB_ICONSTOP
    81.        leave
    82.        retn
    83. MCIError endp
    84. ;---------------------------------------
    85. .data
    86. FileNameCur db "br_Rabbit3.cur",0
    87. ;align 8
    88. mciOP  MCI_ANIM_OPEN_PARMS <0,0,DeviceType,ElementName,0,WS_CHILD,0>
    89. mciPP  MCI_ANIM_PLAY_PARMS <0>
    90. mciCP  MCI_GENERIC_PARMS   <1>
    91. aMcierror db "MCI Error",0
    92. DeviceType DB 'AVIVideo',0
    93. ElementName db "movie10.wmv",0
    94. ClassName db 'Uncle Remus tales:#37e-2 Animation',0
    95. end
     

    Вложения:

    • 00.jpg
      00.jpg
      Размер файла:
      48,9 КБ
      Просмотров:
      217
    • movie10.wmv
      Размер файла:
      378,7 КБ
      Просмотров:
      77
    Последнее редактирование: 9 дек 2023
    Win32Api нравится это.
  19. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.709

    Используем GDI+ для просмотра анимированного gif-файла


    ФункцияОписание
    GdiplusStartup инициализирует Windows GDI+
    GdipLoadImageFromFileСоздает объект изображения на основе файла
    GdipDisposeImageОсвобождает ресурсы, используемые объектом
    GdipImageGetFrameDimensionsCountВозвращает количество размеров кадра в этом объекте Image
    GdipAllocвыделяет память для одного объекта Windows GDI+
    GdipImageGetFrameDimensionsListВозвращает идентификаторы размеров кадра этого объекта Image
    GdipImageGetFrameCountвозвращает количество кадров выбранной размерности
    GdipGetPropertyItemSizeВозвращает размер (в байтах) указанного элемента свойства этого объекта Image
    GdipGetPropertyItemВозвращает указанный элемент свойства (часть метаданных) из этого объекта Image
    GdipFreeОсвобождает память для одного объекта Windows GDI+
    GdipGetImageWidthВозвращает ширину этого изображения (в пикселях)
    GdipGetImageHeightВозвращает высоту изображения (в пикселях) этого изображения.
    GdiplusShutdownочищает ресурсы, используемые Windows GDI+
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. include gdiplus.inc
    4. includelib gdiplus.lib
    5. PropertyTagFrameDelay  equ 5100h
    6. cdXPos          equ 127
    7. cdYPos          equ 127
    8. cdXSize         equ 200
    9. cdYSize         equ 100
    10. cdVBarTipo      equ 0
    11. cdMainIcon      equ 100
    12. cdIdTimer       equ 1
    13. .code
    14. WinMain proc
    15. local msg:MSG
    16. local ptDiff:POINT
    17. local rctWnd:RECT
    18. local rctClient:RECT
    19. local nSize:qword
    20. local pDimensionIDs:qword
    21. local count:qword
    22. ;инициализация библиотеки GDIPLUS
    23.        invoke GdiplusStartup,&gdiplusToken,&gsi,0
    24.        xor ebx,ebx
    25.        mov edi,offset ClassName
    26.        invoke LoadCursorFromFile,&FileName
    27.        push rax ;hIconSm
    28.        push rdi ;lpszClassName
    29.        push rbx ;lpszMenuName
    30.        push COLOR_WINDOWTEXT ;hbrBackground
    31.        push rax ;hCursor
    32.        push rax ;hIcon
    33.        push IMAGE_BASE ;hInstance
    34.        push rbx ;cbClsExtra & cbWndExtra
    35.        pushaddr WndProc  ;lpfnWndProc
    36.        push sizeof WNDCLASSEX;cbSize & style
    37.        invoke RegisterClassExA,esp ;addr WNDCLASSEX
    38.        invoke GdipLoadImageFromFile,&szfilename,&g_image
    39. ;TestForAnimatedGIF-------------------------------
    40.        lea edx,count
    41.        mov [rdx],ebx;count=0
    42.        mov ecx,g_image
    43.        invoke GdipImageGetFrameDimensionsCount
    44.        mov ecx,dword ptr count
    45.        test ecx,ecx
    46.        jz @f
    47.        shl ecx,4
    48.        invoke GdipAlloc
    49.        mov dword ptr pDimensionIDs,eax
    50.        mov ecx,g_image
    51.        invoke GdipImageGetFrameDimensionsList,,eax,count
    52.        or eax,eax
    53.        jnz @f
    54.        mov ecx,g_image
    55.        invoke GdipImageGetFrameCount,,pDimensionIDs,&nFrameCount
    56.        or eax,eax
    57.        jnz @f
    58.        mov ecx,g_image
    59.        invoke GdipGetPropertyItemSize,,PropertyTagFrameDelay,&nSize
    60.        or eax,eax
    61.        jnz @f
    62.        mov ecx,dword ptr nSize
    63.        shl ecx,2
    64.        invoke GdipAlloc
    65.        mov pPropertyItem,eax
    66.        mov ecx,g_image
    67.        invoke GdipGetPropertyItem,,PropertyTagFrameDelay,nSize,eax
    68.        or eax,eax
    69.        jnz @f
    70.        mov ecx,dword ptr pDimensionIDs
    71.         invoke GdipFree
    72. @@:;------------------------------------
    73.        mov edx,offset nWidth
    74.        mov ecx,g_image
    75.        call GdipGetImageWidth
    76.        mov edx,offset nHeight
    77.        mov ecx,g_image
    78.        call GdipGetImageHeight
    79.        push rbx
    80.        push IMAGE_BASE
    81.        push rbx
    82.        push rbx
    83.        push cdYSize ; nHeight
    84.        push cdXSize ; nWidth
    85.        push cdYPos ; Y
    86.        push cdXPos ; X
    87.        sub esp,20h
    88.        invoke CreateWindowExA,0,edi,edi,WS_OVERLAPPEDWINDOW or WS_VISIBLE
    89.         mov hMainWnd,eax
    90.        invoke GetClientRect,eax,&rctClient ;lpRect
    91.        mov ecx,hMainWnd
    92.        invoke GetWindowRect,,&rctWnd ;lpRect
    93.        mov eax,rctWnd.right
    94.        sub eax,rctWnd.left
    95.        sub eax,rctClient.right
    96.        mov ptDiff.x,eax
    97.        mov eax,rctWnd.bottom
    98.        sub eax,rctWnd.top
    99.        sub eax,rctClient.bottom
    100.        mov ptDiff.y,eax
    101.        mov qword ptr [rsp+28h],TRUE ; bRepaint
    102.         mov ecx,nHeight
    103.        add ecx,ptDiff.y
    104.        mov [rsp+20h],rcx ;nHeight
    105.        mov eax,nWidth
    106.        add eax,ptDiff.x
    107.        mov ecx,hMainWnd
    108.        invoke MoveWindow,,cdXPos,cdYPos,rax
    109.        lea edi,msg
    110. @@: invoke GetMessageA,edi,NULL,0,0
    111.        cmp msg.wParam,VK_ESCAPE;user press 'Esc'?
    112.        je wmDESTROY
    113.        invoke DispatchMessageA,edi
    114.        jmp @b
    115. WinMain endp
    116. WndProc proc hWnd:qword,umsg:qword,wParam:qword,lParam:qword
    117. local ps:PAINTSTRUCT
    118. local graphics:qword
    119.        mov hWnd,rcx
    120.        mov wParam,r8
    121.        mov lParam,r9
    122.        cmp edx,WM_DESTROY
    123.        je wmDESTROY
    124.        cmp edx,WM_CREATE
    125.        je wmCREATE
    126.        cmp edx,WM_SIZE
    127.        je wmSIZE
    128.        cmp edx,WM_PAINT
    129.        je wmPAINT
    130.        cmp edx,WM_TIMER
    131.        je wmTIMER
    132.        leave
    133.         jmp NtdllDefWindowProc_
    134. wmDESTROY::invoke KillTimer,,cdIdTimer
    135.        cmp g_image,0
    136.        jz @f
    137.        mov ecx,g_image
    138.        invoke GdipDisposeImage
    139. @@: cmp pPropertyItem,0
    140.        jz @f
    141.        mov ecx,pPropertyItem
    142.        invoke GdipFree
    143. @@:invoke GdiplusShutdown,gdiplusToken
    144.       invoke RtlExitUserProcess,NULL
    145. wmPAINT:invoke BeginPaint,hWnd,&ps
    146. ;DrawFrameGIF---------------------
    147.        mov ecx,g_image
    148.        invoke GdipGetImageWidth,,&nWidth
    149.        or eax,eax
    150.        jnz @f
    151.        mov ecx,g_image
    152.        invoke GdipGetImageHeight,,&nHeight
    153.        or eax,eax
    154.        jnz @f
    155.        invoke GdipCreateFromHDC,ps.hdc,&graphics
    156.        mov eax,dword ptr vdyClient
    157.        mov [rsp+28h],rax
    158.        mov eax,dword ptr vdxClient
    159.        mov [rsp+20h],rax
    160.        mov edx,g_image
    161.        invoke GdipDrawImageRectI,graphics,,0,0
    162.        invoke GdipDeleteGraphics,graphics
    163.        mov r8d,nFramePosition
    164.        inc nFramePosition
    165.        mov ecx,g_image
    166.        invoke GdipImageSelectActiveFrame,,&pageGuid
    167.        mov eax,nFramePosition
    168.        sub eax,nFrameCount
    169.        jnz @f
    170.        mov nFramePosition,eax
    171. ;-------------------------------
    172. @@: invoke EndPaint,hWnd,&ps
    173.        jmp wmBYE
    174. wmTIMER:invoke InvalidateRect,hWnd,0,0
    175.        jmp wmBYE
    176. wmCREATE:invoke SetTimer,hWnd,cdIdTimer,100,0
    177.        jmp wmBYE
    178. wmSIZE: mov rax,r9;lParam
    179.        mov vdxClient,ax
    180.        shr eax,10h
    181.        mov vdyClient,ax
    182.        jmp wmBYE
    183. wmBYE: leave
    184.        retn
    185. WndProc endp
    186. ;-----------------------------------
    187. ClassName db "Uncle Remus tales:#37i gif animation",0
    188. FileName db "br_Rabbit3.cur",0
    189. gsi GdiplusStartupInput <1,0,0,0,0>
    190. pageGuid GUID <6AEDBD6Dh,3FB5h,418Ah,<83h,0A6h,7Fh,45h,22h,9Dh,0C8h,72h>>
    191. szfilename: du <movie.gif>
    192. gdiplusToken dq ?
    193. nWidth dd ?
    194. nHeight dd ?
    195. vdxClient dw 0,0
    196. vdyClient dw 0,0
    197. nFrameCount dd ?
    198. nFramePosition dd 0
    199. pPropertyItem dd ?
    200. g_image dd ?
    201. hMainWnd dd ?
    202. end
     

    Вложения:

    • 00.jpg
      00.jpg
      Размер файла:
      65,6 КБ
      Просмотров:
      210
    • movie.gif
      movie.gif
      Размер файла:
      1,7 МБ
      Просмотров:
      68
    Win32Api нравится это.
  20. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.709

    Используем GDI+ для создания анимации из jpg-файла

    Чтобы получить этот проигрыватель пришлось поиграть в Уолта Диснея. Из фильма "The song of south" был вырезан 8 секундный клип, из этого клипа вырезались фрагменты помеченные красным
    01.jpg
    после склейки этих фрагментов был создан файл all3.jpg
    Перед тем как использовать GDI+, необходимо инициализировать Windows GDI+. Для этого используется функция GdiplusStartup. Функция имеет три параметра. Первый параметр — адрес учетверенного слова gdiplusToken, куда будет помещен маркер, который будет использован при закрытии библиотеки. Второй параметр — указатель на структуру gsi типа GdiplusStartupInput. Первый элемент структуры содержит версию библиотеки =1. Во втором элементе помещают указатель на процедуру, которая получит управление в случае возникновения ошибки, в третьем элементе — логическое значение, указывающее, следует ли подавлять фоновый поток, и в четвертом элементе — логическое значение, указывающее, следует ли подавлять внешние кодеки изображений. В простейшем случае (как у нас) эти поля заполняют нулям. В конце работы программы закрываем Windows GDI+ при помощи функции GdiplusShutdown. Единственный параметр этой функции — значение маркера gdiplusToken, который получаем после вызова функции GdiplusStartup.
    Отображение рисунка, хранящегося в файле, осуществляется по схеме: загрузить изображение из файла в память с помощью GdipCreateBitmapFromFile создать изображение с помощью GdipCreateHBITMAPFromBitmap освободить память с помощью GdipDisposeImage. Имя файла all3.jpg указано в формате Unicode. При загрузке изображения в память получают дескриптор pImage, который затем используется для вывода изображения в окно. Из одного изображения с помощью ImageList_Add создаем список изображений и далее, с помощью ImageList_Draw, рисуем элемент из списка изображений в указанный контекст устройства (на экран).
    02.jpg
    всего 210 кадров, каждый кадр остается на экране 1/25 секунды (40 мСек), затем переходим к следующему кадру. По достижению 210 кадра счетчик обнуляется и все повторяется сначала :) Оцените!
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. include gdiplus.inc
    4. includelib gdiplus.lib
    5. ILD_NORMAL equ 0
    6. .code
    7. WinMain proc
    8. local msg:MSG
    9. local hwnd:qword
    10. ;inizialisation GDIPLUS
    11.        invoke GdiplusStartup,&gdiplusToken,&gsi,0
    12.        xor ebx,ebx
    13.        mov esi,IMAGE_BASE
    14.        mov edi,offset ClassName
    15.        invoke LoadCursorFromFileA,&FileName
    16.        push rax ;hIconSm
    17.        push rdi ;lpszClassName
    18.        push rbx ;lpszMenuName
    19.        push rbx ;COLOR_WINDOWTEXT;hbrBackground
    20.        push rax ;hCursor
    21.        push rax    ;hIcon
    22.        push rsi ;hInstance
    23.        push rbx    ;cbClsExtra & cbWndExtra
    24.        pushaddr WndProc  ;lpfnWndProc
    25.        push sizeof WNDCLASSEX;cbSize & style
    26.        invoke RegisterClassExA,esp ;addr WNDCLASSEX
    27.        push rbx
    28.        push rsi ;rsi=400000h
    29.        shl esi,9 ;rsi=CW_USEDEFAULT
    30.        push rbx
    31.        push rbx
    32.        push 180
    33.        push 170
    34.        push rsi
    35.        push rsi
    36.        sub esp,20h
    37.     invoke CreateWindowExA,0,edi,edi,WS_CAPTION or WS_SYSMENU or WS_VISIBLE
    38.     mov hwnd,rax
    39.         and  qword ptr [rsp+20h],0
    40.        invoke ImageList_Create,153,147,ILC_COLOR24,1
    41.        mov hList,rax
    42.        invoke GdipCreateBitmapFromFile,&FilenameW,&pImage
    43.        invoke  GdipCreateHBITMAPFromBitmap,pImage,&hBmp,0
    44.        invoke  GdipDisposeImage,pImage
    45.        invoke ImageList_Add,hList,hBmp,0
    46.        invoke DeleteObject,hBmp
    47.         invoke GetDC,hwnd
    48.         mov hDC,rax
    49.         invoke SetTimer,hwnd,1,40,&Draw
    50.        lea edi,msg
    51. @@: invoke GetMessageA,edi,NULL,0,0
    52.        invoke DispatchMessageA,edi
    53.        jmp @b
    54. WinMain endp
    55. WndProc: cmp edx,WM_DESTROY
    56.        je wmDESTROY
    57.        jmp NtdllDefWindowProc_
    58. wmDESTROY:invoke GdiplusShutdown,gdiplusToken
    59.       invoke RtlExitUserProcess,NULL
    60. ;-------------------------------------
    61. Draw proc
    62.         enter 30h,0
    63.        and qword ptr [rbp-8],ILD_NORMAL; drawing style
    64.        and qword ptr [rbp-10h],0;y-coordinate to draw at
    65.        invoke ImageList_Draw,hList,count,hDC,0
    66.        inc count
    67.        cmp count,210
    68.        jb @f
    69.        and count,0
    70. @@: leave
    71.        ret
    72. Draw endp
    73. ;-----------------------------------
    74. .data
    75. align 2
    76. FilenameW: du <all3.jpg>
    77. ClassName db "Uncle Remus tales:#37j Simple animation",0
    78. gsi GdiplusStartupInput <1,0,0,0,0>
    79. FileName db "br_Rabbit3.cur",0
    80. gdiplusToken dq ?
    81. hBmp dq ?
    82. count dq ?
    83. hList dq ?
    84. hDC dq ?
    85. pImage dq ?
    86. end
     

    Вложения:

    • all3.jpg
      all3.jpg
      Размер файла:
      1,6 МБ
      Просмотров:
      70
    • 00.jpg
      00.jpg
      Размер файла:
      13,1 КБ
      Просмотров:
      210
    mantissa и Win32Api нравится это.