第4回 ウィンドウに直接描画する


今回は、ウィンドウに直接描画します。
そのために、BViewクラスが初登場します。
このビューという概念は、Windowsプログラムにはなく、BeOS特有のものですが、
BeOSプログラムの中でも重要な概念なので、きっちり理解してください。

ビューを言葉で説明すると、ウィンドウ内の描画全般と
ユーザーとの対話を受け持つ部門であると言えます。
今回のプログラムでは文字を描画していますが、
BViewの描画機能として(カッコ内はメンバ関数名)

が挙げられます。また、ユーザーとの対話機能として、

があります。今回は文字描画のみですが、基本的な使い方はわかると思います。

今回のサンプルソースです。
前回同様、重要な部分は強調してあります。

// sample03.cpp

#include <Application.h> // BApplicationを使うために必要
#include <Window.h>      // BWindowを使うために必要
#include <Rect.h>        // BRectを使うために必要
#include <View.h>        // BViewを使うために必要

// クラスの前方宣言
class MyApp;
class MyWindow;
class MyView;

class MyApp : public BApplication
{
public:
	MyApp();
private:
	MyWindow* m_win;
};

class MyWindow : public BWindow
{
public:
	MyWindow(BRect frame,const char* title,window_type type,uint32 flags);
	virtual bool QuitRequested();	// 終了が要求されたときに呼ばれる関数
private:
	MyView* m_view;
};

class MyView : public BView
{
public:
	MyView(BRect frame,const char *name,uint32 resizingMode,uint32 flags);
	virtual void Draw(BRect updateRect);  // 再描画要求の時に呼ばれる関数
};

MyApp::MyApp()
      :BApplication("application/x-vnd.big56-MyApp")
{
	m_win = new MyWindow(BRect(100,100,300,150),"BViewのテスト",B_DOCUMENT_WINDOW,0);
	m_win->Show();
}

MyWindow::MyWindow(BRect frame,const char* title,window_type type,uint32 flags)
		:BWindow(frame,title,type,flags)
{
	frame.OffsetTo(0,0);  // 与えられたBRectの左上が(0,0)になるようにする

	m_view = new MyView(frame,"theView",B_FOLLOW_NONE,B_WILL_DRAW);
	AddChild(m_view);
}

bool MyWindow::QuitRequested()
{
// アプリケーションを終了する
	be_app->PostMessage(B_QUIT_REQUESTED);
	return true;
}

MyView::MyView(BRect frame,const char* title,uint32 resizingMode,uint32 flags)
	  :BView(frame,title,resizingMode,flags)
{
	SetViewColor(200,200,200);  // ビューの背景色を設定する
	SetFontSize(20);            // フォントサイズを設定する
}

void MyView::Draw(BRect updateRect)
{
	MovePenTo(20,20);
	DrawString("Hello BView!");
}

int main(int argc,char** argv)
{
 	MyApp app;
	app.Run();
	return 0;
}

今回のプログラムの実行結果は次のようになります。
実行結果

MyWindowのコンストラクタから見てみましょう。

MyWindow::MyWindow(BRect frame,const char* title,window_type type,uint32 flags)
		:BWindow(frame,title,type,flags)
{
	frame.OffsetTo(0,0);  // 与えられたBRectの左上が(0,0)になるようにする

	m_view = new MyView(frame,"theView",B_FOLLOW_NONE,B_WILL_DRAW);
	AddChild(m_view);	
}

まず、frame.OffsetTo(0,0);ですが、これは、BRectの矩形の座標を大きさを変えずに左上を(0,0)にスライドしています。
今回は、ウィンドウの座標を(100,100,300,150)に指定していますが、
この操作をすると、(0,0,200,50)という矩形の座標になります。

なぜこのようなことをするかというと、ビューの占める面積をウィンドウ全体にしたいからです。
ビューを作成するときに、デスクトップの座標ではなく、ウィンドウ内の座標で指定する必要があるため
矩形の左上の点を(0,0)にしているのです。

次にビューのインスタンスをnewで作成して、AddChild()関数でビューをウィンドウの子供として登録します。

ウィンドウとビューの関係、またはビューとビューの関係はフォルダ階層に似ています。
ウィンドウはルートディレクトリ(ドライブのいちばん上のこと)、ビューはフォルダと考えてください。
「子供として登録する」とは、フォルダを掘るのに似ています。
ウィンドウが複数のビュー(ルートディレクトリに複数のフォルダがある)を持ったり、
ウィンドウの子供のビューが、さらに子供にビューを持つ(フォルダの下にさらにフォルダを掘る)こともあります。

「ビューを複数持つことに意味があるのか?」と考える人もいると思いますが、
今後紹介する、ウィンドウのボタン(BButtonクラス)とかチェックボックス(BCheckBoxクラス)は
すべてビューの一部です(BViewクラスから派生している)。
ウィンドウが複数のボタンや複数のチェックボックスを持つ必要があるときに
AddChild()メンバ関数を複数呼んで、ウィンドウは子供のビューを複数持つことになります。

さて、BViewのコンストラクタについての説明をします。

MyView::MyView(BRect frame,const char* title,uint32 resizingMode,uint32 flags)
	  :BView(frame,title,resizingMode,flags)
{
	SetViewColor(200,200,200);  // ビューの背景色を設定する
	SetFontSize(20);            // フォントサイズを設定する
}

BViewのもともとのコンストラクタの引数並びは次のようになっています。

BView(BRect frame,const char* name,uint32 resizingMode,uint32 flags);

BViewでは

を指定する必要があります。
frameは想像通り、ビューの大きさをBRectで指定します。
これが親ウィンドウの座標系である必要があることは、ウィンドウのコンストラクタのところで説明しました。

ビューの名前は直接表示されることはありませんが、プログラム的にビューを識別するのに使います。
今回はビューの名前を利用していません。

resizingModeには次の定数を指定することが出来ます。

B_FOLLOW_LEFT左に追従する
B_FOLLOW_RIGHT右に追従する
B_FOLLOW_LEFT_RIGHT水平方向は親に合わせて子供もリサイズする
B_FOLLOW_H_CENTER左と右の中心の位置を保つ
B_FOLLOW_TOP上に追従する
B_FOLLOW_BOTTOM下に追従する
B_FOLLOW_TOP_BOTTOM垂直方向は親に合わせて子供もリサイズする
B_FOLLOW_V_CENTER上と下の中心の位置を保つ
B_FOLLOW_ALL_SIDESB_FOLOW_LEFT_RIGHTとB_FOLLOW_TOP_BOTTOMをあわせたもの
B_FOLLOW_NONEどこにも移動しない
B_FOLLOW_LEFT_RIGHTとB_FOLLOW_TOP_BOTTOM以外では、ビューは勝手にリサイズされることはありません。
ウィンドウ内の位置が変わるだけです。

flagsには次の定数を指定できます。

B_WILL_DRAWビューが再描画要求の通知を受け取れるようにする。
B_PULSE_NEEDEDビューのPulse()メンバ関数を定期的に呼ぶ。
B_FRAME_EVENTSBViewがリサイズされるときに、FrameResized()メンバ関数と
FrameMoved()メンバ関数を呼び出す
B_FULL_UPDATE_ON_RESIZEリサイズの時にビュー全体を更新する必要があることを
表すフラグ
B_NAVIGATABLEキーボード入力のフォーカスビューになりえることを表すフラグ
B_NAVIGATABLE_JUMPCtrl+Tabキーを押すとビューのグループからビューのグループへジャンプできる。
B_SUBPIXEL_PRECISE描画の際にサブピクセル精度を使用するように指示するフラグ。
これを指示しないと、1座標単位に丸められる。

ということらしいです(実は筆者も全部ためしていない)。

その次のSetViewColorメンバ関数でビュー全体の色を設定します。
SetViewColor()関数の宣言は次のようになっています。

void BView::SetViewColor(rgb_color color);
void BView::SetViewColor(uchar red,uchar green,uchar blue,uchar alpha=0);

rgb_color構造体は、パラメータにredとgreenとblueとalphaという変数名を持つ単純な構造体です。
rgb_color構造体を使用しないほうのSetViewColor関数では、
第1引数に赤成分、第2引数に緑成分、第3引数に青成分、第4引数にアルファ成分(透明度)を指定することによって、
ビューの色を指定します。

SetFontSizeでは描画に使用するフォントの大きさを指定します。
ここの引数を変えると「Hello BView!」の大きさも変化します。

さて、再描画要求にはDrawメンバ関数内で応じるわけですが、この部分のコードの解説をしましょう。

void MyView::Draw(BRect updateRect)
{
	MovePenTo(20,20);
	DrawString("Hello BView!");
}

Draw()メンバ関数の引数には、更新すべき領域の矩形が渡されます。
多くの領域を描画するようなアプリケーションなら、この部分の矩形領域を利用して
必要な所だけ描画するようにするべきでしょうが、今回はこの引数を無視してビュー全体を更新しています。

DrawString()メンバ関数で実際に文字を書いていますが、DrawStringの書き始めの位置は「ペン」と呼ばれるものの座標から始まります。
ペンの座標はMovePenTo()で指定します。
MovePenTo()関数は以下のように宣言されています。

void BView::MovePenTo(BPoint point);
void BView::MovePenTo(float x,float y);
BPointクラスは座標を表すクラスですが、今回は簡単にするために、x座標とy座標を指定するタイプの方を使用しています。
MovePenTo()関数の引数を変えれば「Hello BView!」の位置が変わります。

Draw()関数以外の部分でDrawStringをすると、ほかのウィンドウをかぶせた時に
「Hello BView!」の文字が消えてしまいます。
これは、再描画の必要があるのに文字を描画していないからです。
ビューに対して描画するには、Draw()関数内で描画するのが定石です。

今回のソースについての説明は以上ですが、いかがでしたでしょうか?
ビューはBeOSプログラムにおいて非常に重要な概念なので、きっちり押さえるようにしてください。

[<<前へ] [次へ>>] [戻る]

big56 big56@anet.ne.jp
海外旅行保険の加入はコチラ! あなたの悩み解決します そろそろ結婚適齢期???
[PR] | ヒーリング会社案内 作成se 転職川口栃木荻窪池袋中国SEO対策消費者金融車 買取テンプレート沖縄旅行免許合宿二輪引越しプレゼントゴルフ会員権留学レーシックマッサージFXアフィリエイトFXホームページ制作デイトレードハワイ旅行タイバンコクハワイ レンタカーベスト ハワイ ホテル レーツバリ島Hawaii hotelsHawaii Activitiesbhhrハワイホテルテキスト広告
【運営会社「パラダイムシフト」サービス】 ハワイ現地オプショナルツアーリラックマ) - ビジネスクラス航空券 - 格安航空券(1) - 格安航空券(2) - 海外ホテル - 韓国旅行 - タイムシェア - ホテル 予約
無料ホームページ - 携帯ホームページ - 無料ホームページ作成 - レンタルサーバー - ブログ - ヴィラ - ハワイ コンドミニアム - バリ島 ホテル - プーケット ホテル - 旅行 口コミ - 旅行情報 - 国際電話 - ホノルルマラソン - 掲示板監視 - 風評被害 - ホテル比較 - ノースウェスト航空 - ファイナルチェッカー