love5an: (Default)
[personal profile] love5an
Почему "модные"?
Ну потому, что look-and-feel в стиле Windows 2000 в 2011 году не моден.


Начну издалека.

Стандартные win32-контролы(так называемые Common Controls)(обертками над которыми являются классы MFC, Windows.Forms, или других подобных GUI-тулкитов), начиная с кнопок и заканчивая всякими там TreeView, в винде реализованы в библиотеке comctl32.dll. И с этой библиотекой связан один очень неприятный момент.

Дело в том, что давным-давно, а именно с появлением Windows XP, Microsoft выпустила 6ю версию этой библиотеки, в которую добавила кучу свистелок и перделок("темы" и т.п.), связанных главным образом с отрисовкой(благодаря этому, новые версии винды выглядят не так уныло, как раньше, т.е. во времена Win95-2000). Но, к несчастью, 6я comctl32 стала немножко обратно-несовместимой с предыдущими версиями, и по этой причине, если мы линкуемся с этой библиотекой, или же подружаем ее динамически(через LoadLibrary etc.), винда по дефолту подгружает 5ю версию, и все стандартные виджеты в нашем приложении выглядят так же, как они должны были выглядеть 11 лет назад.

Заставить систему подключать нам как минимум 6ю comctl32 можно через так называемые "контексты активации". К несчастью для динамичного лиспового видения программ, единственный способ задать стандартный контекст активации, или создать новый довольно статичен по своей сути - это так называемые "манифесты". Манифест представляет собой xml-документ, в котором описываются какие-либо свойства приложения/библиотеки(assembly), считываемые Windows при ее загрузке.

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

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

Я предпочитаю использовать первый способ и собирать рантаймы лиспов с уже включенным в них манифестом.

Как это делается? Ну для примера возьмем SBCL.
Предположим, манифест имеет такой вид:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity type="Win32" name="MyProgram"
                    processorArchitecture="x86" version="1.0.0.0" />
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="asInvoker" uiAccess="false"/>
      </requestedPrivileges>
    </security>
  </trustInfo>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="Win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0"
                        processorArchitecture="x86" publicKeyToken="6595b64144ccf1df" language="*"/>
    </dependentAssembly>
  </dependency>
</assembly>      


Запишем его в файл с именем, ну, пусть "program.manifest".
После этого создаем файл описания ресурсов(пусть будет "program.rc"),

#include <winuser.h>
1 ICON program.ico // application icon
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST program.manifest


и берем утилиту windres из тулчейна MinGW, с помощью которого мы компилируем этот файл:
windres -i program.rc -o resources.res -O coff

Далее мы складываем полученный файл в директорию путь_к_сорцам_sbcl/src/runtime/ и немного изменяем файл GNUMakefile, находящийся там же; в частности, строчку
OBJS = $(C_SRC:.c=.o) $(ASSEM_SRC:.S=.o) ${OS_OBJS}

меняем на
OBJS = $(C_SRC:.c=.o) $(ASSEM_SRC:.S=.o) resources.res ${OS_OBJS}

Ну и после этого собираем SBCL как обычно(кстати, вот если кому надо, бинарник(x86-32) из HEAD форка [livejournal.com profile] akovalenko, собранный таким образом, с иконкой от lisperati.com: http://rghost.ru/18554241).

Ну и напоследок, вот пример одной и той же программы(http://paste.lisp.org/display/124128) на Windows 7 со включенными Visual Styles(т.е. comctl32 >= 6.0.0.0)(справа) и без них(слева):

This account has disabled anonymous posting.
If you don't have an account you can create one now.
HTML doesn't work in the subject.
More info about formatting

Profile

love5an: (Default)
Dmitry Ignatiev

June 2020

S M T W T F S
 123456
78910 111213
14151617181920
21222324252627
282930    

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jul. 19th, 2025 10:27 pm
Powered by Dreamwidth Studios