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

December 24th, 2008 Begemot Posted in Программирование

Со временем я пришел к выводу что иконки лучше хранить в 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 или мы можем доставлять вам новые посты прямо в ваш почтовый ящик.

Related:

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

  1. # wxString text = wxString::FromUTF8(buf.get(), sz);

    а если у меня UNICODE сборка, все равно так же использовать?

  2. да, я сам использую только Юникодную сборку. В данном случае FromUTF8 отражает тот факт что текст в зипе лежит в utf8 и при считывании мы его конвертим в юникод.

  3. Тут нюанс в том что вроде ж PNG и так являются файлами паканными zlib’ом.
    А вот можно ж еще более красиво сделать: PNG в архив, а архив с помощью Bin2C в код, а из кода в файловую систему в памяти. Хотя, можно для этих целей и XRC поюзать. Эффект тот же.
    А потом бинарий UPX’ом запакать.

  4. А потом зарарить, записать на компакт диск, и спрятать в сейф?:)

    Хранение в отдельном зипе дает пару преимуществ – легче корректировать, пользователь сам может поменять иконки если сильно хочет, и главное можно использовата LGPL иконки.