вторник, 31 марта 2009 г.

True-color иконки в тулбарах

Для любого GUI-приложения не последнее значение имеет внешний вид – дизайн интерфейса.  Мысль не новая. Но далеко не каждое приложение имеет не то, что достойный, а хотя бы минимально приемлемый дизайн. И полагаю, причина тут кроется не только в том, что разработчики не самые замечательные дизайнеры [пользовательских интерфейсов]… Но иногда дизайн-то может быть и есть, но вот интегрировать его в приложение не так-то просто.
- “У вас дизайн еззь?
- Езззь!
- За?ебизззь!” (© )
Но на этом собственно всё: дизайн, конечно, “езь”! Но интегрировать его в приложение никто не спешит.

Почти в каждом приложении есть тулбар (toolbar). И причем занимает он весьма значительное место на экране, и поэтому во многом именно он и определяет внешний вид приложения. Так что, уж если редизайнить, то начиная с тулбаров.

Первым делом, при таком раскладе хочется сменить иконки в тулбарах на truecolor. Вот об этом и пойдет речь. Недавно Begemot выдал мега-полезный пост “Где брать бесплатные иконки”, и это только сподвигнуло к давно откладываемому редизайну иконок в Aml Pages.

Но тут же нарисовалось маленькое, но весьма существенное препятствие. Тулбары в Aml Pages набиты кнопками под завязку, просто в силу того, что и возможностей в Aml Pages немало. А посему перетасовываются кнопки тулбаров у меня чуть-ли не каждую версию – регулярный такой  в общем редизайн GUI.

В Visual Studio я постоянно пользуюсь встроенным редактором тулбаров . И отказываться от этой привычки нет ни малейшего желания – несмотря на всю ограниченность этого редактора, создавать в нем кнопки, перемещать их, редактировать подписи ну и так далее достаточно просто, быстро и удобно. Но есть одно “но”. Даже в не самой старой VS 2005, и уж тем более в моей любимой VS6 сам редактор иконок поддерживает всего 16 (шестнадцать!!!) цветов. Это означает, что редактировать сами изображения нельзя, в противном случае при первом же сохранении измененного изображения вместо кульной true-color иконки получите “кастрированный” вариант в “шашнадцать” цветов.

Ну лиха беда начало – айда в Google в поисках более продвинутого редактора тулбаров. Гуглящий да обрящет! В первых же строках  нашелся искомый редактор для 7-ой студии. Но и он был не лишен недостатков: частенько привирал с фоновыми цветами, не всегда корректно импортировал тулбары из RC-файла, да и нацелен он был все-таки на то, что каждый тулбар переделывается полностью.

А при моем числе кнопок переделывать весь тулбар - работа немалая. А при том, что мои тулбары частенько и меняются, работа эта еще и будет регулярная. И еще важный для меня аспект: все-таки подавляющее большинство уже сделанных кнопок, меня устраивают более чем, и хотелось бы лишь некоторые изменить “на лету”.

Собственно было найдено следующее решение. Редактор изображений в Visual Studio из-за своей намертво-прошитой 16-цветности отпадает как класс . Но тем не менее, сам компилятор ресурсов абсолютно корректно собирает в конечный exe-шник иконки из ico-файлов, не изменяя при этом сами изображения.

ОК! То, что нужно.

  1. Глубину цвета “модных” иконок не нарушаем. Т.к. иконки расположены в отдельных ico-файлах.
  2. Можем на лету заменить только некоторые кнопки тулбаров, ручками загрузив изображение из ресурсов (через LoadImage).
  3. Ничто не заставляет редактировать весь тулбар, да причем еще “ах раз, да еще раз, еще много, много раз” в каждой новой версии.

Дизайнеры, вероятно возмутятся, читая про эти “художества”. Что ж – вы правы! Но я не дизайнер. У меня несколько иная задача: заменить только некоторые иконки в кнопках на лету, причем чтобы не приходилось править код и иконки при малейшем изменении исходников, ресурсов, расположения кнопок и.т.д. Чтоб мухи отдельно, котлеты отдельно.

Сам алгоритм решения прост до неприличия: после загрузки стандартного ресурса тулбара, наш код создает новый ImageList с более “глубокими” цветами. После чего копируют все иконки из старого ImageList`а в новый, заменяя нужные более симпатишными из включенных в ресурсы ico-файлов. И наконец, этот новый ImageList просто-напросто назначается тулбару. Упс! Всё готово! Этот код примерно выглядит так:

tb_icons_code

Пожалуй стоит сказать и о недостатках такой схемы.  Несколько неприглядно выглядят иконки “дизейбленных” кнопок.

tb_badgray

Но это уже на вкус и на цвет. Google легко выдает несколько примеров преобразования иконки в градации серого – как этот или этот. Но  эксперименты показали, что при использовании этих примеров в реальном коде, получается все равно далеко не идеально. Код примеров еще дотачивать и дотачивать до идеала напильником . Но,  хозяева-барины: можно сяк, а можно эдак, в конце концов можно вообще создать отдельный Disabled ImageList из модных иконок… Вовсе не обязательно переделывать весь тулбар снова и снова, как только понадобится улучшить всего лишь пару иконок на кнопках.

суббота, 14 марта 2009 г.

Как таблицы в текст пихались

В ОС Windows в RichEdit-контроле - который отвечает за форматированный текст RTF - поддержка таблиц реализована… да никак она, собственно, и не реализована. И девелоперском кругу бытует мнение, “что великий чешский писатель Карел Чапек был карелом”… тьфу ты… что поделать с таким “отсутствием” таблиц ничего нельзя. Однако на самом деле, чем старше версия RichEdit, тем больше возможностей работы с таблицами. Правда, иногда до них не так-то просто добраться, но все же они есть. Ты видишь суслика? Нет… Но суслик есть!” © – как именно добраться – разговор отдельный.

А за прошедшие зимние месяцы распространился было слушок, что новейшая версия RichEdit 6.0 (RE) не только умеет создавать и показывать таблицы – экая невидаль, это давным-давно “взятая высота”! Но и изменять размеры ячеек. Ну, а такой функционал меняет дело. Одно дело генерировать таблицы да любоваться на них, совсем другое предоставить пользователю возможность и самому порезвиться. А раз есть разница для пользователя, то скорее всего должна быть разница и для нашего кармана.

Оказывается эта версия RE есть в составе Microsoft Office 2007 (и не только). Не долго размышляя, скачал 2007-ой офис, поставил, с тоской посмотрел на него… и незамедлительно выпил © снёс.

Офис то снесен, но вот файлы системные от него остались. А вот именно они-то мне и нужны. Иду в папку %COMMON_FILES%\Microsoft Shared\OFFICE12 и с любопытством копаюсь в ее содержимом. Все привычно, серая скука и до боли знакомые файлы. Но посредь папки гордо красуется файл RichEd20.DLL, который вообще говоря, есть почти в любой даже Win98\2K, не то что в XP. Ага, думаю, очередная заглушка для совместимости… Но нафига же новейшему офису совместимость с древним RE 2.x-3.x – уж эти “заглушечные” DLL есть вообще практически в любой XP. Да и офис немаленький, на кой ему таскать заглушки, если он сам ими и вовсе не пользуется…

В общем, есть над чем призадуматься. Сигаретку, еще кофейчинского (ну какой девелопер без кофейчиского!?!) и начинаем, неспеша, эдакой “археологической метелкой” сметать пыль с нижних пластов “офисных” недр – ковыряться в подробностях.

Смотрите, экая штука! А размер-то RichEd20.DLL – аж почти цельный метр мегабайт – многова-а-ато - это уже вообще на заглушку никак не тянет.  И… о-п-п-па, смотрим в детали и вот оно: описание – “Microsoft RichEdit 6.0”, да и номер версии файла аж 12.xxx. Вообще в RichEd20.DLL содержится реализация RichEdit версии 3.0. Но размер самой DLL в версии 3.0 значительно меньше – что-то около 400 килобайт. И уж точно major-номер версии ну никак не 12 (имеется ввиду версия файла, если RichEdit 6.0 это версия продукта вообще, то версия файла несколько иное. Вы можете всё это увидеть в свойствах файла).

Ну, точно судя по всему это и есть новая версия. Долго сказки блоги сказываются, да быстро код пишется. Фтоппку все эти дот.нет`ы. Стартую старинную подружку 6-ую студию, генерю визардом простейшее MFC-приложение на основе СRichEditView и начинаю колдовать над “визардовым” кодом.

Элементарно, Ватсон! Ручками загружаем в адресное простраство необходимую DLL. На этапе создания вида CRichEditView подменяем имя класса окна… Компилируемся, с предыханием запускаем… И у-у-упс! Все сработало!  Рихтеровским Spy`ем проверяем класс окна. Отлично! Это RichEdit60W – приложение создало именно то, что просили. Затаив дыхание, открываем любой rtf-файл c таблицей… Подтаскиваем мыша к границе таблицы… Курсор меняется на стрелку! Нажали левую кнопку и перетаскиваем границы ячеек. Вуаля!

Получили приложение с поддержкой таблиц в тексте ака в не самой старой Висте. Но созданное аж в древнем Visual C++ 6, причем безо всяких там VS2008, WPF, SilverLight и иже с ними. Не так страшен черт, как его малюют, если только чуть-чуть спуститься с заоблачных высот абстракций к старому доброму WinAPI. Ну не люблю я, хоть режьте меня, все эти похотливые до вычислительных ресурсов модные новинки: постоянно пытающиеся подкачать очередной Дот.Нет в десяток метров, требущие пары гигов памяти, очередных service pack`ов…  А если можно несколькими простыми штрихами создать приложение, весящее первые сотни килобайт,  то зачем, пожалуйста скажите мне, за-а-ачем платить больше?

четверг, 5 марта 2009 г.

Aml Pages, тайм-менеджмент и формализм

На днях меня в очередной и наверное в уже какой-нибудь юбилейный раз попросили добавить в Aml Pages функции планирования,  тайм-менеджмента и все в подобном же духе.  Стоит заметить, что эта просьба озвучивается с завидной регулярностью. И с такой же завидной регулярностью, по меньшей мере до сих пор, не выполняется. Однако в этот раз все обстояло несколько иначе: просил старинный, любимый и уважаемый мною пользователь, отличающийся редким сочетанием качеств: непрограммист (следует читать, “человек, не считающий что он единственный знает, как лучше и что именно сделать”), но между прочим вполне “варящий головой”. Да и у самого у меня уже возникали не столь четко выраженные, но все же похожие потребности. Резон призадуматься был на лицо.

Тут просто грех не сослаться на шикарнейшую мысль Валерия Расторгуева о тайм-менеджменте. Настоятельно рекомендую прочесть – это вам не модные басни! Это разумные, аргументированные и взвешенные мысли.

Посмотрите, какая отличная формулировка: “…он (тайм-менеджмент в Outlook) хорош как раз для «людей-роботов»…”!?!

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

Вы всегда точно знаете, что и когда вы планируете, да еще и с точностью до минут? Вы всегда и безаппеляционно уверены в приоритетах и типах задач еще на этапе планирования? Почему авторы такого софта не допускают даже и мысли, что все эти подобные детали мы хотели бы оставить на потом? Вы никогда, разговаривая по телефону, не набрасывали на обрывке бумаги “Перезвонить Иван Иванычу до пятницы”… Без приоритета Иван Иваныча, без даты начала Иваныча, и уж тем более без типизации этой с позволения сказать “задачи”?

Конечно, бумага всё стерпит! Но разве такой софт не может стерпеть подобные непунктуальности хотя бы до поры до времени? Но софт не бумага – хотя он и soft, но терпеть не желает. Почему-то… Отчего-то…

Кстати, во все времена  в Aml Pages никогда и ни при каких обстоятельствах не делался упор на формализм. Собственно говоря, с этого всё и началось. Навязчивый формализм подобного “тайм-менеджмента” в какой-то момент просто мешал “записать Иваныча”. От всего этого было уже не столько пользы, сколько вреда (“черт с ней с датой конца Иваныча, куда я его телефон подевал!?!”). Так и появилась Aml Pages – с желанием записывать что и как угодно, никаких ежесекундных требований, все можно изменить потом. И уж точно никакого формализма.

Формализм вообще homo sapiens`у не присущ и вовсе. Знаете чем отличается поиск от запроса в контексте терминологии use-case? Поиск – это анализ множества на предмет соответствия (с некоторой точностью) образцу, искомому. Например, найти все вхождения строки. А запрос – это выборка из множества по ряду признаков. Вот когда я разыскивал ссылку на мысль Валерия – поиск в Aml Pages мне выдал весьма немало страниц со словом “робот”, а в найденном частенько попадались и слова “тайм-менеджмент”. А почему? Да потому, что я не знал что именно нужно искать, какие образцы использовать для поиска!?! Ну да, ну да… Вроде что-то там было про планирование, и про роботов. Но этот признак слишком формален, поэтому я и получал такие выборки не многим меньше, чем у самого Google. А тем не менее, я совершенно точно помнил как мне попалась эта статья - нашел я ее месяца полтора или два назад, нашел в сети, и вроде бы скидывал о ней заметку в Aml Pages. Всё оказалось крайне просто: первое - запрос по датам, потом - запрос по типам данных, потом запрос к найденному на предмет содержания ссылок. Вместо шести десятков страниц со словами “планирование” и “робот” я получил всего полтора десятка, быстренько пролистав которые, я тут же нашел ссылку на нужную статью. Вуаля! Причем потратив на это всего одну минуту! И заметьте, потратил на решение своей задачи. А не задачки для этого “чертова большого калькулятора”, как бы блин ему “сформулить”, чтобы он нашел то, что нужно мне, а не все то, что формально совпадает…

Знаете, мне никогда не катила фраза “Яндекс – найдется всё”.  Не надо всё! Совсем не надо… Просто найди то, что нужно! Вполне достаточно!

Человеку значительно проще двигаться шагами, сужая область поиска, постепенно приближаясь или отдаляясь от нужного результата. Нам, в отличие от компьютера, куда как проще выстраивать алгоритм пошагово, постепенно, приноравливаясь, и оценивая верность или неверность сделанного шага. А сколько бы я промучился с формальным поиском? Долой формальность – да здрям неформальность!

Между прочим,  все запросы в Aml Pages изначально и специально сделано абсолютно антиформальными – здесь вам не выборки SQL. После выполнения запроса, когда все разделы не попавшие в запрос просто временно скрыты, перейдите в непопавший раздел – он будет автоматически добавлен в запрос. Не подпадает под условия запроса? О да! Это не верно с формальной точки зрения? О да! В Aml Pages нет места формализму! Раз пользователь решил перейти к разделу, значит он ему нужен. И нужен здесь и сейчас. Нет никакой необходимости заставлять его отменять запрос – куда как проще, если раздел окажется в запросе автоматически. Если же пользователю нужна четкая формальная выборка – то повторить ее займет всего пару секунд. Кстати заметить, иногда этот прием вызывал некоторое удивление у новых пользователей с последующим вопросом в саппорт или форум. Удивление? Да! Еще бы – где это сделано еще? Но никогда неприятие – после разъяснений абсолютно все соглашались, что такой подход действительно удобен и именно то, что нужно (именно это и называется use-case анализ).

Не держите пользователя за идиота, он все равно лучше знает чего хочет, хотя и не всегда способен это выразить формально. Но ему нет ни малейшей необходимости формально свои желания и выражать. Формальность – удел кода.

Вернемся же к нашим баранам тайм-менеджменту, планированию, напоминаниям и в том же духе. Я далеко ни один день выпытывал у моего старинного (а главное, вменяемо отвечающего и мыслящего) пользователя, так что же он на самом деле все-таки хочет от эдакого тайм-менеджмента? Суть да дело, после продолжительных дискуссий, переубеждений друг друга и прочего флейма удалось сузить функционал до определенного разумного минимума. В конце концов, я поинтересовался, а нельзя ли прикрутить функционал к какой-нибудь уже существующей “капле” из моря тайм-менеджментного софта? И причина оказалось до смеха простой – прикрутить-то можно, но работать с этими софтинками оказывается неудобно (“со всеми” – это его слова, а перепробовал он их немало)!?! И опять все тот же формализм? Ну почему даже могучий, и вызывающий искреннее уважение LeaderTask не способен на банальное inplace-редактирование? Почему обязательно нужен очередной модальный диалог, чтобы вписать пару слов, и опять же нажимать ОК или Отмена? Зачем модальность? Где тут режим? Неужели так сложно по какому-либо банальному дабл-клику развернуть окно редактирования и закрывать его с сохранением после Enter, или без после Отмены (потери фокуса)? Почему в набившем оскомину Проводнике Windows, никто не заставляет вас вызывать модальный диалог для редактирования имени файла… Неужели сложно сделать также? Думается, что нет.  И это между прочим флагман подобного софта! Что же с остальными!?!

И вот из-за такой мелочи огромному числу пользователей втрое тяжелее работать. А всего то нужно – удобное редактирование… И неспроста интеграционный софт занимает такую долю рынка… И возможность в той или иной степени сослаться на некую внешнюю сущность: файл, адрес URL, почтовый адрес – что это как ни интеграция!?! Немного бы мы “шарились” по социальным сетям, если бы они также “любили” модальные диалоги! (ну да, ну да, я в курсе насколько с ними проще нашему братцу-программисту… в курсе :)

Вот такой вот в Aml Pages вышел замечательный “симбиоз” между ее параноидальной неформальностью и планированием, как в общем-то, сущностью такой вполне себе формальной. Глядя на это “мать-иво” единство противоположностей о-о-о-о-чень мно-о-о-ого думал. А возможно ли в принципе такие вещи совместить!?! Ох, не знаю, не знаю! Но задачка любопытная. Как формальную сущность сделать неформально удобной, но соблюдя ее формальную природу!?! Use-case жизнь покажет…