なんとな~くしあわせ?の日記

「そしてそれゆえ、知識そのものが力である」 (Nam et ipsa scientia potestas est.) 〜 フランシス・ベーコン

wxHtmlWindow上での動的な画像のリロードなど

JaneStyle等で実装されているHTML表示ウィンドウにて画像のサムネイルを表示させる方法(wxWidgetsにて)を検討していた。他に同じ事を考えている人が居るかもしれないのでメモしておく。

wxHtmlWindow上では「memory:」というタグが最初から使用することができる。タグの後にファイル名を指定すれば、wxHtmlWindow上にファイルの中身を表示させることができる。「memory:」タグに情報を登録するのはwxMemoryFSHandlerというクラスだ。

公式のドキュメントにコメントを付けてみた
wxMemoryFSHandler

/** Windows以外ではlogo.xpmというファイルを読み込ませている */
#ifndef __WXMSW__
#include "logo.xpm"
#endif

/** メニューからのイベント用メソッドとしてOnAboutを実装する */
void MyFrame::OnAbout(wxCommandEvent&)
{
    wxBusyCursor bcur;
    wxFileSystem::AddHandler(new wxMemoryFSHandler);
    
    /** logo.pcx という名前でlogoを登録する */
    wxMemoryFSHandler::AddFile("logo.pcx", wxBITMAP(logo), wxBITMAP_TYPE_PCX);
    /** about.htm という名前で下のHTMLソースを登録する */
    wxMemoryFSHandler::AddFile("about.htm", 
                               "<html><body>About: "
                               "<img src=\"memory:logo.pcx\"></body></html>");

    /** wxDialogの中にwxHtmlWindowを表示させる */
    wxDialog dlg(this, -1, wxString(_("About")));
    wxBoxSizer *topsizer;
    wxHtmlWindow *html;
    topsizer = new wxBoxSizer(wxVERTICAL);
    html = new wxHtmlWindow(&dlg, -1, wxDefaultPosition, 
                            wxSize(380, 160), wxHW_SCROLLBAR_NEVER);
    html->SetBorders(0);

    /** 注目すべきはここ HTMLソースがabout.htmという名前で呼び出せる
        なおかつabout.htmの中でlogo.pcxが呼ばれているため、ダイアログボックスには
        画像が表示される */
    html->LoadPage("memory:about.htm");
    html->SetSize(html->GetInternalRepresentation()->GetWidth(), 
                  html->GetInternalRepresentation()->GetHeight());
    topsizer->Add(html, 1, wxALL, 10);
    topsizer->Add(new wxStaticLine(&dlg, -1), 0, wxEXPAND | wxLEFT | wxRIGHT, 10);
    topsizer->Add(new wxButton(&dlg, wxID_OK, "Ok"), 
                  0, wxALL | wxALIGN_RIGHT, 15);
    dlg.SetAutoLayout(true);
    dlg.SetSizer(topsizer);
    topsizer->Fit(&dlg);
    dlg.Centre();
    dlg.ShowModal();
    
    /** ダイアログボックスでOKが押されたら、登録したリソースを削除する */
    wxMemoryFSHandler::RemoveFile("logo.pcx");
    wxMemoryFSHandler::RemoveFile("about.htm");
}

上の例だとwx-2.8のUnicodeビルドではコンパイルエラーが出ると思われるので少し書き換えてみる。

/** メニューからのイベント用メソッドとしてOnAboutを実装する */
void MyFrame::OnAbout(wxCommandEvent& event)
{
    wxBusyCursor bcur;
    wxFileSystem::AddHandler(new wxMemoryFSHandler);
    
     wxImage image;
     wxBitmap bitmap;

     /** 念のためフルパスで入力 */
     wxString imagePath = wxGetCwd() + wxT("\\logo.png");
     wxMessageBox(wxT("imagePath:") + imagePath);

     // load wxImage
     if (!image.LoadFile(imagePath)) {
	  wxMessageBox(wxT("画像ファイルの読み出しに失敗しました"),
		       wxT("wxMemoryFSHandler"),
		       wxICON_ERROR);
	  return;
     }
     // wxImage to wxBitmap
     bitmap = wxBitmap(image);

     if (!bitmap.Ok()) {
	  wxMessageBox(wxT("画像ファイルの読み出しに失敗しました"),
		       wxT("wxMemoryFSHandler"),
		       wxICON_ERROR);
	  return;
     }

    /** logo.png という名前でlogoを登録する */
    wxMemoryFSHandler::AddFile(_T("logo.png"), bitmap, wxBITMAP_TYPE_PNG);
    /** about.htm という名前で下のHTMLソースを登録する */
    wxMemoryFSHandler::AddFile(_T("about.htm"), 
                               _T("<html><body>About: "
                                  "<img src=\"memory:logo.png\"></body></html>"));

    /** wxDialogの中にwxHtmlWindowを表示させる */
    wxDialog dlg(this, -1, wxString(_("About")));
    wxBoxSizer *topsizer;
    wxHtmlWindow *html;
    topsizer = new wxBoxSizer(wxVERTICAL);
    html = new wxHtmlWindow(&dlg, -1, wxDefaultPosition, 
                            wxSize(380, 160), wxHW_SCROLLBAR_NEVER);
    html->SetBorders(0);

    html->LoadPage(_T("memory:about.htm"));
    html->SetSize(html->GetInternalRepresentation()->GetWidth(), 
                  html->GetInternalRepresentation()->GetHeight());
    topsizer->Add(html, 1, wxALL, 10);
    topsizer->Add(new wxStaticLine(&dlg, -1), 0, wxEXPAND | wxLEFT | wxRIGHT, 10);
    topsizer->Add(new wxButton(&dlg, wxID_OK, _T("Ok")), 
                  0, wxALL | wxALIGN_RIGHT, 15);
    dlg.SetAutoLayout(true);
    dlg.SetSizer(topsizer);
    topsizer->Fit(&dlg);
    dlg.Centre();
    dlg.ShowModal();
    
    /** ダイアログボックスでOKが押されたら、登録したリソースを削除する */
    wxMemoryFSHandler::RemoveFile(_T("logo.pcx"));
    wxMemoryFSHandler::RemoveFile(_T("about.htm"));
}

うまくいくとこんな感じで表示される
f:id:panzer-jagdironscrap1:20130325005038j:plain

wxStringのマクロ

・wxT, _Tがunicode向け、日本語混じりの文はこれを使う => wxString test = wxT("あああ");