Используем png для иконок и храним ресурсы в архиве

December 24th, 2008 Begemot

Со временем я пришел к выводу что иконки лучше хранить в PNG, чем в XPM. Несомненый плюс это наличие альфа-канала. К тому же хранение иконок вне exe файла позволяет пользователю заменить используемые иконки на свои, что дает возможность правильно использовать для вашего приложения графику под LGPL лицензией (Где брать бесплатные иконки).

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

Я написал пару врапперов для удобной работы:

// don't forget call wxFileSystem::AddHandler(new wxZipFSHandler); in MyApp::OnInit() 
wxImage BegUtils::GetImageFromZipResource(const wxString & path, long type/*=wxBITMAP_TYPE_ANY*/)
{
	scoped_ptr<wxFileSystem> fs(new wxFileSystem);
	scoped_ptr<wxFSFile> file(fs->OpenFile(path));
	if (!file) return wxNullImage;
    
	wxInputStream* stream = file->GetStream();
	wxImage image(*stream, type);

	return image;
}


// Load a text resource from zip file
// don't forget call wxFileSystem::AddHandler(new wxZipFSHandler); in MyApp::OnInit()
wxString BegUtils::GetUTF8TextFromZipResource(const wxString& path)
{
    scoped_ptr<wxFileSystem> fs(new wxFileSystem);
    scoped_ptr<wxFSFile> file(fs->OpenFile(path));
    if (!file) wxEmptyString;
    
    wxInputStream* stream = file->GetStream();
    size_t sz = stream->GetSize();
    scoped_array<char> buf(new char[sz]);
    stream->Read((void*) buf.get(), sz);

    wxString text = wxString::FromUTF8(buf.get(), sz);
    if (text[0]==0xFEFF) text.erase(0, 1); // BOM
    return text;
}

 

Использование примерно такое

 

wxString resPath=exePath+wxT("resource.bin#zip:");
...
#define MMB(x) BegUtils::GetImageFromZipResource(resPath+wxT("icons\\")+x+wxT(".png"), wxBITMAP_TYPE_PNG)

  AppendMenuItemWithImage(itemMenu, wxID_HELP, _T("Help\tF1"), _T(""), MMB(wxT("help")));
  AppendMenuItemWithImage(itemMenu, wxID_ABOUT, _T("About\tAlt+F1"), _T(""), MMB(wxT("information")));
....
 m_ToolBar->AddTool(wxID_EXIT, _T(""), MMB(wxT("exit")), wxNullBitmap, wxITEM_NORMAL, _T("Terminate Application (Alt+X)"), wxEmptyString);
....
#undef MMB

AppendMenuItemWithImage можно взять в wxMenu с иконками и обход выделенных атемов в wxListCtrl

Пользуйтесь на здоровье.


Если пост полезен для вас вы можете подписаться на RSS или мы можем доставлять вам новые посты прямо в ваш почтовый ящик.


Я очень, очень не доволен меню и тулбаром!

October 30th, 2008 Begemot

Ужасть просто как недоволен 🙂 Про меню я уже писал частично, сейчас будет вторая серия – буду отрыватся по полной, возможна даже нецензурная лексика:)

1. Хреновое выравнивание, посмотрите что происходит с шоткатом F2 в обоих случаях

menu_shortcut

2. Опять же хреновое выравнивае, но уже для чекбоксов. Почему его тянет на лево?

checkbox

3. Стоковые названия\шоткаты для меню – классная задумка. Но посколько, под виндой шоткаты принято обозначать как ctrl+v, а wxWidgets использует ctrlv, то ради унификации интерфейса приходится жертвовать ими и прописывать все название и комбинации жестко.

4. Для тулбара можно указать две иконки, обычную и вторую для задисейбленного состояние. Для меню только одну. Можно указать одну и там и там, полагаясь на автоматическое создание задисейбленного изображения, но алгоритмы получения второй иконки у них разные – в результате фигня.

menu_toolbar_disable

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

toolbar_disable

6. wxMenu автоматически обрабатывает все шоткаты в меню и похоже это нельзя отключить, и это проблема:(

7. А это тулбар под вистой

toolbar_vista

Пока все что удалось вспомнить. И как они его там тестируют… ? Страшно представить, что же там будет под юкнисом то. Хотя может это только у меня дар и другие не замечают, может мне в тестеры пойти ?:)

Зато wxWidgets позволяет использовать png для иконок, а вот для дельфей такого нету, сегодня народ жаловался:)

Следует отметить что я использую wxAUI, и тулбар соответвенно, от его. Может с родным было бы лучше, надо проверить.

Да, вы главное не подумайте что я сильно расстроен wxWidgets, так просто пар спускаю:) А вообще ничего, можно пользоватся, творить. Я вот даже до беты дописался. так что не все так плохо! 🙂


Если пост полезен для вас вы можете подписаться на RSS или мы можем доставлять вам новые посты прямо в ваш почтовый ящик.


Напишите кто-нибудь нормальное меню

October 15th, 2008 Begemot

+С грустью приходится отметить что в нормальное меню  в wx не завозили:(

А хотелось бы иметь нормальное красивое owner-draw меню, и даже не надо кучи наворотов типа стилей офиса 2003, офиса xp и тд. Просто приятный градиентик сбоку, нормальная прорисовка чекбоксов, возможность задать дисейбленный рисунок… и конечно обязательно нормальное поведение, не хуже системного.

Вот для MFC такое есть.

Напишите кто-нибудь, а ?:)


Если пост полезен для вас вы можете подписаться на RSS или мы можем доставлять вам новые посты прямо в ваш почтовый ящик.


Как выборочно отключить шоткаты в меню. Часть вторая – фигвам.

October 1st, 2008 Begemot

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

Подход основывался на изменении tilte для wxMenu – удаления шотката при закрытии меню и добавления при открытии. Я еще тогда пытался изменить код на Enable\Disable – чтобы оставить текст тайтла в одном месте (легче менять если понадобится). Но это не сработало, разбиратся почему я не стал. Теперь знаю.

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

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

Вызывается OnOpenMenu, добавляет сокращения ко всем пунктам, которые мы вручную отключаем, а вот OnCloseMenu, в данном случае не вызывается.

Полностью отказыватся от автоматический обработки, не хочется, хотя и придется если не найду выхода. Других путей решения задачи пока не нашел. У кого-то есть идеи?


Если пост полезен для вас вы можете подписаться на RSS или мы можем доставлять вам новые посты прямо в ваш почтовый ящик.


Как выборочно отключить шоткаты в меню

September 26th, 2008 Begemot

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

Уже во второй программе я сталкиваюсь с тем что мне необходимо, отключить автоматическую обработку для некоторых пунктов меню. Прямого способа нет. Я спрашивал в wx-листе, но там или меня не поняли или тоже не знали ответа.

Решение нашлось на форуме, собственно ответ тут. Добавляем обработчики для открытия\закрытия меню.

 

EVT_MENU_OPEN(MainFrame::OnOpenMenu)
EVT_MENU_CLOSE(MainFrame::OnCloseMenu)

void MainFrame::OnOpenMenu(wxMenuEvent & event)
{
       GetMenuBar()->FindItem(ID_COPYITEMTOCLIPBOARD)->SetItemLabel(_("&Copy to Clipboard\tCtrl+C"));
	event.Skip();
}

void MainFrame::OnCloseMenu(wxMenuEvent & event)
{
	GetMenuBar()->FindItem(ID_COPYITEMTOCLIPBOARD)->SetItemLabel(_("&Copy to Clipboard"));
	GetMenuBar()->FindItem(ID_COPYITEMTOCLIPBOARD)->SetBitmaps(wxBitmap(copy_clipboard_xpm), wxNullBitmap);  
	event.Skip();
}

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


Если пост полезен для вас вы можете подписаться на RSS или мы можем доставлять вам новые посты прямо в ваш почтовый ящик.