2006年05月21日

何?

 wxWidgetsを使って、ドキュメント・ビュー・アーキテクチャーのアプリケーションを作ってみたい。
 単一ウインドウのSDIで、最小限のアプリケーションを模索してみる。
 メモ帳のような、簡単なテキストエディタに仕立て上げられればと思う。
 実はこれはすでにいったん出来上がっているので、これから道に迷うことは無い。
 途中でめんどうくさくならなければ、集結するはずである。
posted by ysfactory at 00:24| Comment(0) | TrackBack(0) | wxWidgets:単一ウインドウSDI | このブログの読者になる | 更新情報をチェックする

まずはアプリケーションクラス

 MinGW Developer Studioを使ってプロジェクトを生成するわけだが、(当然のように・・)ソースコードは何ひとつ作られない。
 まずはアプリケーションクラスを作るか・・
 つぎのコードだけで、何も無い空のウインドウが表示されるアプリケーションが出来上がる。

MyApp.h
#ifndef MY_APP_H
#define MY_APP_H

class MyApp : public wxApp
{
public:
bool OnInit();
};

DECLARE_APP(MyApp);

#endif//MY_APP_H


MyApp.cpp
#include <wx/wx.h>
#include "MyApp.h"

IMPLEMENT_APP(MyApp)

bool MyApp::OnInit()
{
wxFrame* frame = new wxFrame(NULL, -1, argv[0]);
frame->Show();
SetTopWindow(frame);
return true;
}
posted by ysfactory at 00:37| Comment(0) | TrackBack(0) | wxWidgets:単一ウインドウSDI | このブログの読者になる | 更新情報をチェックする

空のドキュメントクラス、ビュークラスを作る

 さて、ウインドウは開いたものの、ドキュメント・ビュー・アプリケーションとは言えない。
 早くドキュメント・テンプレートクラスを作成して、ドキュメント・ビュー・アプリケーションにしたいのだが、そのためには先に、空のドキュメントクラスと、ビュークラスを作成しなければならない。

SWSDIDoc.h
#ifndef SWSDI_DOC_H
#define SWSDI_DOC_H
#include <wx/docview.h>

class SWSDIDoc : public wxDocument
{
DECLARE_DYNAMIC_CLASS(SWSDIDoc)
};

#endif//SWSDI_DOC_H


SWSDIDoc.cpp
#include <wx/wx.h>
#include "SWSDIDoc.h"

IMPLEMENT_DYNAMIC_CLASS(SWSDIDoc, wxDocument)


SWSDIView.h
#ifndef SWSDI_VIEW_H
#define SWSDI_VIEW_H
#include <wx/docview.h>

class SWSDIView : public wxView
{
DECLARE_DYNAMIC_CLASS(SWSDIView)
void OnDraw(wxDC* dc){ };
};


SWSDIView.cpp
#include <wx/wx.h>
#include "SWSDIView.h"

IMPLEMENT_DYNAMIC_CLASS(SWSDIView, wxView)
posted by ysfactory at 01:08| Comment(0) | TrackBack(0) | wxWidgets:単一ウインドウSDI | このブログの読者になる | 更新情報をチェックする

ドキュメントテンプレートを作成

 アプリケーションクラスのOnInit( )でドキュメント・マネージャーと、ドキュメント・テンプレートを生成する。

 wxDocManagerクラスのインスタンスを生成する(docManagerとする)。
 wxDocTemplateクラスのインスタンスを生成する(docManagerを渡す)。
 wxFrameの代わりにwxDocParentFrameを生成する(docManagerを渡す)。

MyApp.cpp
bool MyApp::OnInit()
{
wxDocManager* docManager = new wxDocManager();
new wxDocTemplate(
docManager, //wxDocManager* manager
wxT("SWSDI"), //const wxString& descr
wxT("*.txt"), //const wxString& filter
wxT(""), //const wxString& dir
wxT("txt"), //const wxString& ext
wxT("SWSDI document"),//const wxString& docTypeName
wxT("SWSDI view"), //const wxString& viewTypeName
CLASSINFO(SWSDIDoc),//wxClassInfo* docClassInfo
CLASSINFO(SWSDIView)// wxClassInfo* viewClassInfo
//long flags = wxDEFAULT_TEMPLATE_FLAGS
);
wxDocParentFrame *frame =
new wxDocParentFrame(docManager, NULL, -1, argv[0]);
frame->Show(true);
SetTopWindow(frame);
return true;
}
posted by ysfactory at 01:29| Comment(0) | TrackBack(0) | wxWidgets:単一ウインドウSDI | このブログの読者になる | 更新情報をチェックする

メインフレームを作る

 メインフレームを作り、メニューを表示させる。
 MyApp::OnInit( )での生成も、MainFrameに代える。

MainFrame.h
#ifndef MAIN_FRAME_H
#define MAIN_FRAME_H
#include <wx/docview.h>

class MainFrame : public wxDocParentFrame
{
public:
MainFrame(wxDocManager* manager, wxFrame *parent, wxWindowID id,
const wxString& title, const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize, long style = wxDEFAULT_FRAME_STYLE,
const wxString& name = "frame");
};

#endif//MAIN_FRAME_H


MainFrame.cpp
#include <wx/wx.h>
#include "MainFrame.h"

MainFrame::MainFrame(wxDocManager* manager, wxFrame *parent, wxWindowID id,
const wxString& title, const wxPoint& pos,
const wxSize& size, long style, const wxString& name)
: wxDocParentFrame(manager, parent, id, title, pos, size, style, name)
{
wxMenuBar* menubar = new wxMenuBar;
wxASSERT(menubar);
wxMenu* menu = new wxMenu;
wxASSERT(menu);
menubar->Append(menu, _T("&File"));
menu->Append(wxID_NEW, wxT("&New\tCtrl+N"));
menu->Append(wxID_OPEN, wxT("&Open...\tCtrl+O"));
menu->Append(wxID_SAVE, wxT("&Save\tCtrl+S"));
menu->Append(wxID_SAVEAS, wxT("Save &As..."));
menu->AppendSeparator();
menu->Append(wxID_EXIT, wxT("E&xit\tAlt+X"));
this->SetMenuBar(menubar);
}


MyApp.cpp
bool MyApp::OnInit()
{
...
wxFrame* frame = new MainFrame(docManager, NULL, -1, argv[0]);
frame->Show();
SetTopWindow(frame);
...
}
posted by ysfactory at 01:48| Comment(0) | TrackBack(0) | wxWidgets:単一ウインドウSDI | このブログの読者になる | 更新情報をチェックする

テキストファイルを読み込む

SWSDIDoc.h
#ifndef SWSDI_DOC_H
#define SWSDI_DOC_H
#include <wx/docview.h>

class SWSDIDoc : public wxDocument
{
DECLARE_DYNAMIC_CLASS(SWSDIDoc)
public:
const wxString& GetText() const;
protected:
wxString m_text;
private:
wxInputStream& LoadObject(wxInputStream& stream);
};

#endif//SWSDI_DOC_H


SWSDIDoc.cpp

#include <wx/wx.h>
#include "SWSDIDoc.h"
#include <wx/txtstrm.h>

IMPLEMENT_DYNAMIC_CLASS(SWSDIDoc, wxDocument)

const wxString& SWSDIDoc::GetText() const
{
return m_text;
}

wxInputStream& SWSDIDoc::LoadObject(wxInputStream& stream)
{
wxTextInputStream text_stream(stream);
for( ; ; ){
m_text += text_stream.ReadLine();
if( stream.Eof() )break;
m_text += wxT('\n');
}
return stream;
}
posted by ysfactory at 20:07| Comment(0) | TrackBack(0) | wxWidgets:単一ウインドウSDI | このブログの読者になる | 更新情報をチェックする

テキストコントロールはどこに貼る?

 ビューにテキストコントロールを貼り、読み込んだテキストを表示させ・・たいのだが・・。

 テキストコントロールはどこに貼る?ビューはウインドウではない。
 いつものウインドウなら、コンストラクタでthisを渡し、気軽にコントロールを貼り付けられる。
 ビューでは、それをするのはOnCreate( )らしい。

 それでは、親ウインドウには何を渡せばいい?
 単一ウインドウのアプリケーションを作ろうとしているのだから、トップのフレームを渡せば良さそうだが、ビューはそれをどうやって知ればいい?
 ・・アプリケーションクラスから、トップウインドウを教えてもらう方法をとる。

 ビューには、GetFrame( )というのが備わっているから、それが使えるかと思ったが、GetFrame( )は何も教えてくれない。
 仕方ないので、自分でSetFrame( )しておく。
posted by ysfactory at 20:41| Comment(0) | TrackBack(0) | wxWidgets:単一ウインドウSDI | このブログの読者になる | 更新情報をチェックする

ひとつのウインドウを使いまわす

 単一ウインドウのアプリケーションを作ろうとしているのだから、ドキュメントを何度開こうが、新規作成しようが、ウインドウは同じ物が使いまわされる。
 一方ビューはそのたび生成され、破棄される。プログラマーは、この両者のみぞを埋めなければならない。

 OnCreate( )で、フレームが持つ全ての子ウインドウをDestroyしてしまう・・。この方法を採った。一番最初、フレームがまだ何も子ウインドウを持っていないときには、この呼び出しは何も起こらない。2度目からは、前回使ったものを、ここで破棄する。
posted by ysfactory at 22:16| Comment(0) | TrackBack(0) | wxWidgets:単一ウインドウSDI | このブログの読者になる | 更新情報をチェックする

さて、テキストコントロールを貼る

 OnCreate( )ではまだ、ドキュメントクラスはテキストをまだ読み込んでいない。OnUpdate( )で取得して、コントロールに渡す。
 テキストコントロールを貼ったあと、SendSizeEvent( )を呼ばないと、コントロールが、ウインドウいっぱいに広がらない。
 さらに、すぐにカーソルが出て編集できるようにするために、SetFocus( )を呼び出す。

SWSDIView.h
#ifndef SWSDI_VIEW_H
#define SWSDI_VIEW_H
#include <wx/docview.h&rt;
class SWSDIDoc;

class SWSDIView : public wxView
{
DECLARE_DYNAMIC_CLASS(SWSDIView)
void OnDraw(wxDC* dc){ };
protected:
SWSDIDoc& SWSDIView::GetDocument() const;
wxTextCtrl* m_textControl;
private:
bool OnCreate(wxDocument* doc, long flags);
void OnUpdate(wxView* sender, wxObject* hint);
};

#endif//SWSDI_VIEW_H


SWSDIView.cpp
#include 6lt;wx/wx.h>
#include "SWSDIView.h"
#include "SWSDIDoc.h"
#include "MyApp.h"

IMPLEMENT_DYNAMIC_CLASS(SWSDIView, wxView)

SWSDIDoc& SWSDIView::GetDocument() const
{
SWSDIDoc* document =
dynamic_cast<SWSDIDoc*&rt;(wxView::GetDocument());
wxASSERT(document);
return *document;
}

bool SWSDIView::OnCreate(wxDocument* doc, long flags)
{
wxFrame* frame =
dynamic_cast<wxFrame*>(wxGetApp().GetTopWindow());
wxASSERT(frame);
frame->DestroyChildren();
SetFrame(frame);

m_textControl = new wxTextCtrl(
frame, -1, "", wxDefaultPosition, wxDefaultSize,
wxTE_MULTILINE,
wxDefaultValidator, wxTextCtrlNameStr);
wxASSERT(m_textControl);

frame->SendSizeEvent();
m_textControl->SetFocus();

return true;
}

void SWSDIView::OnUpdate(wxView* sender, wxObject* hint)
{
m_textControl->SetValue(GetDocument().GetText());
}

posted by ysfactory at 22:24| Comment(0) | TrackBack(0) | wxWidgets:単一ウインドウSDI | このブログの読者になる | 更新情報をチェックする

2006年05月22日

ドキュメントクラスへの更新のセット

 テキストコントロールからの、テキスト更新イベントを受けて、ドキュメントクラスの更新をセットしにいく。
 テキスト更新イベントは、最初にテキストを渡したときなど、余計なときも飛ぶので、本当にテキストが変更されているかどうかを確かめてからセットしにいく。
 これにより、今まで無効だったファイルセーブメニューが有効になる。

SWSDIView.h
class SWSDIView : public wxView
...
private:
void OnTextUpdated(wxCommandEvent& event);
DECLARE_EVENT_TABLE()
...
};


SWSDIView.cpp
BEGIN_EVENT_TABLE(SWSDIView, wxView)
EVT_TEXT(-1, SWSDIView::OnTextUpdated)
END_EVENT_TABLE()


void SWSDIView::OnTextUpdated(wxCommandEvent& event)
{
GetDocument().Modify(m_textControl->IsModified());
}
posted by ysfactory at 23:08| Comment(0) | TrackBack(0) | wxWidgets:単一ウインドウSDI | このブログの読者になる | 更新情報をチェックする

2006年05月23日

ファイルをセーブする

 編集したテキストの、セーブ部分をつくる。
 テキストコントロールを使っているので残念ながら、ドキュメントクラスは編集データを保持できない。セーブする際にビューからデータを取得する。

 ロードするときは、ドキュメントクラスがデータを保持し、編集中のデータはビューが保持する。ちょっと変則的になる。

SWSDIDoc.h
class SWSDIDoc : public wxDocument
{
protected:
const SWSDIView& GetView() const;
private:
wxOutputStream& SaveObject(wxOutputStream& stream);
};

#endif//SWSDI_DOC_H


SWSDIDoc.cpp
const SWSDIView& SWSDIDoc::GetView() const
{
SWSDIView* view =
dynamic_cast<SWSDIView*>(wxDocument::GetFirstView());
wxASSERT(view);
return *view;
}

wxOutputStream& SWSDIDoc::SaveObject(wxOutputStream& stream)
{
m_text = GetView().GetText();
wxStringTokenizer tokenizer(m_text, wxT("\n"),wxTOKEN_RET_EMPTY_ALL);
wxTextOutputStream text_stream(stream);
for( ; ; ){
text_stream << tokenizer.GetNextToken();
if(!tokenizer.HasMoreTokens())break;
text_stream << endl;
}
return stream;
}
posted by ysfactory at 22:32| Comment(0) | TrackBack(0) | wxWidgets:単一ウインドウSDI | このブログの読者になる | 更新情報をチェックする

広告


この広告は60日以上更新がないブログに表示がされております。

以下のいずれかの方法で非表示にすることが可能です。

・記事の投稿、編集をおこなう
・マイブログの【設定】 > 【広告設定】 より、「60日間更新が無い場合」 の 「広告を表示しない」にチェックを入れて保存する。


×

この広告は1年以上新しい記事の投稿がないブログに表示されております。