2008年11月02日

トップページを改定

 G.Ishiharaのトップページを大幅に改定しました。一応作成してあったすべてのコンテンツを全部掲載し終わったので、更新終了とします。

 トップページはなんとなく散らかっていた感じがしていたのをシンプルにまとめました。C言語関係のコンテンツはあまり充実していないし、もともとこのホームページを作った初期のころに、内容を膨らますために余力で書いたものなので、公開終了します。ただ、どこかからリンクされているものもあると思うので、サーバには残してあります。

 あとは掲示板かな〜。前にPerlで作ったものを正式版にしようと思っています。しばらく、Perlも何もプログラミング自体から離れていたので浦島太郎状態ですが^^;

 あ、ブログは適当に続けますよ〜。


posted by G.Ishihara at 01:03| Comment(0) | TrackBack(0) | 雑記 | このブログの読者になる | 更新情報をチェックする

2008年08月27日

チンチロリンゲーム構想1

1.導入

 今日一日で考えたことを忘れないようにメモ。すごく長文です^^;

 今日は「賭博破戒録カイジ」の単行本を読んだ。いきなりマンガの話から入るのも唐突だが、これが面白い。今日読んだのが、いわゆる「地下チンチロ編」というところだ。借金の返済のために、地下の強制労働所に送られるのだが、そこから這い上がるために博打を打ち大勝負をする。その博打というのが「チンチロリン」というもので、ルールは単純。サイコロを3つ振り、出た目に従って役がつく。その役で勝負するわけだ。親が一人で、子は複数いる。子は親に対して勝負、親は複数の子に対して勝負する。つまり自分が親の時は必然的に大事な勝負になる。親のときに弱い目を引いたりしたら、大負けになることは必至なのだ。

 まあ、知らない人にはさっぱりだと思うが、「チンチロリン」自体はわりとよく知られている遊びのようだ。ルールなんかはいろいろ解説しているサイトもあるので、詳しくはそちらを参照して欲しい。

 それで、これがプログラミングと何の関係があるのかというところだが、実はここでこの話を取り上げたのは、あることを思いついたからだ。それはつまり、この「チンチロリン」というのがちょっとしたネタになるとみた。つまり、オンラインでこの「チンチロリン」のゲームが作れるのではないかと。

 さっそく、調べてみた。もう既にそういうものがあるのであれば、何も新しく作る事もない。…うーん、www.777town.netに似たようなのがあるな。でもこれは基本有料モノかな?他にはWindowsのスタンドアローンアプリなんかはあるようだ。思っていたようなのはなかった。要するに誰でも無料で手軽に参加できて、オンラインで楽しめるようなもの。オンラインゲームといっても大層なものではなくて、このゲームは派手なグラフィックとかは必要ない。必要なのはせいぜいサイコロの絵ぐらいだ。グラフィックばりばりなのは逆に作れないし。CGIだけでできると思っている。今のところ。

 作ってみる価値はあるかな。前から小出しにしてた構想中のものとこれとはまた別なのだけど、こっちのほうが少し難度が低いと思うので先にこっちをやってみるか。正直、作るよりもアイデアのほうがポンポン出るので悩ましい。これ以外にも、後ろに控えているネタがたくさんある。でも今回のは、突発的ではあるけど、ちょっと面白いとは思うので。

2.詳細

 さて、次はズバリ、できるのかってことだ。技術的に。できないものはできないし、できるものはできる。後は、今できなくても、少し新しい知識を取り込んだらできるようになるというケースもある。まあ、たいていこのケースだったりする^^;

 では、詳細な構想を。今回に限っては、ちょっと実験的な意味もあり、構想段階から全部ぶちまけてしまいます。もしこれを読んで先に作ってしまう人が現れたとしたら、それはそれでいいです。というか、そういう展開であれば相当素敵だと思います。

 それで、先ほども書いたように、CGIでなんとかできそうな予感はする。対戦処理はすべてサーバ側で行う。あとはユーザの管理だ。やはり何度も対戦しながら持ち金の増減に一喜一憂するのが、こういう博打の醍醐味だ。だからユーザの概念を導入したい。ユーザ名とパスワードを管理する。そして対戦成績も管理する。すべてサーバ側だ。

 CGIとサーバ側の処理部分はもちろんPerlで。で、これはとりあえずはこのサイト(g-ishihara.com)内においてもいいかなと思う。つまりレンタルサーバで運用する。自宅の方が使えるようになってきたら移動してもいいかなとは思うが、処理的にレンタルサーバで不自由することはなさそうな気がするので。データサイズも異常に大きくなることは無いと思うし、ソケットやmod_perlなんかも必要ないだろうし。

 そして、もう一つのコンセプト。それは、マンガにできるだけ近づけること。チンチロリン自体の特殊ルールなどはもちろん、シチュエーションなども。まるで、自分が地下強制労働所に送られて、そこで生死をかけてギャンブルをしているような、そんな感覚を味わえるようにする。というのは、想定している客層はもちろん、「カイジ」を読んできているはずだ。自分もこのギャンブルで遊んでみたいと思って来ているはず。ならば、マンガそのままの世界に浸れるようにしてみようと思う。

 マンガを読んでいないと少し分かりにくいかもしれないが、ここで使う貨幣は、ペリカという地下世界だけの単位。10ペリカで1円に相当する。地下労働者は、1ヶ月働いて、9万ペリカの給料がもらえる。つまりたかだか9,000円程度ということだ。新規ユーザは、始めにこの1か月分の給料、9万ペリカをもってギャンブルに挑んでもらう。また、この地下世界では、5,000ペリカで缶ビール、7,000ペリカで焼き鳥なども買えたりする。他に楽しむものもない世界では、ついこういう贅沢品などに手がでてしまうというものだ(という設定。マンガでは。)。そして、50万ペリカで1日外出券が買える。

 マンガではこういう設定なので、そのまま、こういう「アイテム購入」の機能も持たせたい。買ったからどうなるということもないが、まあ、持っていたら他の人にうらやましがられるかも知れないし、ちょっとした達成感も出てくるだろう。

3.ランキング

 さて、オンラインならではの機能として、「ランキング」を導入しようと思う。これは全プレーヤーの総資産順のランキングだ。つまり、ユーザ名や資産、対戦成績などは全て公開される。このランキングの上位を目指してギャンブルを行うわけだ。これがプレーヤーの対戦意欲を煽るともくろんでいる。プレーヤーということでもう一つ付け加えると、最初にユーザ登録してくれたお客さんに対戦相手が一人もいないというのは変なので、最初から登録してあるプレーヤーを何人か用意しようと思う。マンガでは地下収容施設に50人ぐらいいたはずだ。それはちょっと多いかもしれないので、20人ぐらいデフォルトで用意しておこう。とりあえず、それらをNPC(Non Player Character)と呼んでおく。でもちゃんとランキングにも登場するようにする。

 ランキングに表示する項目は、ユーザ種別(NPC/登録ユーザ)、ユーザ名、総資産、現金、貸し出し可能金額、借金、債権、対戦成績(○勝/○敗)、勝率、対戦可能フラグ、最低賭け金額、最高賭け金額、アイテム数(それぞれ)

4.借金制度

 負けが込んで、持ち金が0、あるいはマイナスになったらどうするか。マンガでは、給料の1か月分を前借りできることになっている。もちろん貸してくれる人がいればだが。そして借りることのできる金額は6万ペリカ。つまり1か月分の給料9万ペリカを後で支払う代わりに、6万ペリカを今受け取るのだ。差額の3万ペリカはピンハネということになる。さらに、2か月先の給料を前借すると、受け取れる金額は半分の4.5万ペリカだ。つまり半分はぼったくられることになる。こんな取り決めなので、借金は何としてでも避けたいところだ。

 それでも、借金ができてしまった場合は、他のプレーヤーから借りるより仕方がない。ここからはこのゲームだけの設定だが、プレーヤーは手持ちの現金の中から、いくらまで貸し出しできるかを設定できる。例えば、1か月先の給料である、6万ペリカを借りたい場合は、貸し出しできる金額を6万以上に設定しているプレーヤーを選択すればよい。この場合、借りる側は、6万ペリカの現金を受け取る代わりに、9万ペリカの借金を抱える。貸し出す側は、6万ペリカの現金を失う代わりに、9万ペリカの債権が発生する。

 つまり、この貸借が成立した時点で、借りる側は-3万、貸す側は+3万の総資産の変動が起こることになる。そしてそれによって、ランキング順位も変動する。貸す側にとっては、労せずしてランキングが上がるのだから、悪い話ではない。(しかし現金は当然、目減りする。)

 さて、借りたものはいつか返さなければならない。6万借りたとすれば、それを元手にギャンブルを行い、運良く勝てたとして、9万を超えた時点で自動で(強制的に)返済される。これで一件落着。ただし、そううまくいくとも限らない。もし、さらに負けが込んでマイナスになったら、2ヶ月先の給料4.5万ペリカをさらに誰かに借りなければならない。そうするより他にないのだから。この時点で借金は18万ペリカ。

 ちなみに、このゲームでは給料が受け取れるのは最初の9万ペリカのみとしようと思う。つまり、増やすにはギャンブルをするしかない。待っていてもお金は増えない。これがこのゲームの借金システム。お金はプレーヤー間でのみやりとりされる。これはつまり、1プレーヤーあたりの総資産の平均値は9万ペリカで一定であるということだ。この一定金額、有限のお金の取り合いをするわけだ。

5.対戦システム

 次に、対戦システムについて。プレーヤーは対戦しようと思ったら、対戦相手を選択できることにする。対戦相手は複数選択する。このゲームは3人以上で対戦しないと、親子の駆け引きが生きてこない。ただし、対戦可能フラグがついていないプレーヤーは対戦できない。対戦可能フラグはプレーヤーが自由に設定できる。つまり、自分から対戦しに行くとき以外は対戦したくないとき、言い換えると、他プレーヤーからの挑戦を受けたくない場合は、このフラグをはずしておけばよい。

 プレーヤー同士の対戦について、あれこれ考えたのだが、プレーヤーがものすごく多ければリアルタイムでのプレーヤー同士の対戦もできるのだが、プレーヤーが数人しかいなければリアルタイムでの対戦はほぼ絶望的にできないだろう。そんな超人気ゲームになるとも思っていないので、リアルタイム対戦の線は外そうと思う。変わりに考えたのが、この「対戦を受ける」システムだ。自分から対戦しにいく場合は問題ないが、誰かから対戦相手に指名された場合、その場合は自動で戦う。コンピュータが勝手にサイコロを振るわけだ。まあ、言ってしまえば、このゲームはもともと勝つか負けるかは5分5分なのだ。適当にサイコロを振っても何ら問題はない。というか、むしろサイコロは適当に振る以外に方法はない。

 もし、自分の知らないところで自分の資産が変動するのが嫌なのであれば、「対戦可能フラグ」をOFFにしておけばいい。しかし、ONにしておけば、放っておいても勝手に対戦して勝敗数が増えていくことになる。勝敗数の多さを人気のバロメータと考えるならば、ONにしておくのがいいのではないのだろうか。

 しかし、対戦において1つだけプレーヤーの意思に左右される要素がある。それは賭け金額だ。これは通常、子側が対戦ごとに自由に決められる。小さく張って様子を見るか、ここ一番で大勝負に出るか、それは自由だ。そしてプレーヤーは、自動対戦における賭け金額を設定できる。これが「最低賭け金額」、「最高賭け金額」だ。自動対戦の場合は、この範囲内で賭け金額が自動設定される。対戦してもいいけれど、あまり大きく張りたくないのであれば、「最低賭け金額」、「最高賭け金額」ともに小さく設定しておけばいい。

 ただし、この設定は他のプレーヤーからも閲覧できる。プレーヤーはこの賭け金額を参考にして、どのプレーヤーと対戦するかを選択できるというわけだ。もしかして、あまり小さく張ってばかりいそうなヘタレなプレーヤーは、誰からも見向きもされなかったりするかも。

 対戦のルールについては、マンガと同一とする。ただしイカサマはない^^。純粋な勝負のみ。とりあえず詳細は省略。

う”ーまだ半分ぐらいしか書いてないけど、これ書くだけで結構時間かかる。。。とりあえず続きはまた次回。


posted by G.Ishihara at 05:15| Comment(0) | TrackBack(0) | Perl | このブログの読者になる | 更新情報をチェックする

2008年08月18日

SAPPHIRE RADEON HD 3470

 ビデオカードをSAPPHIRE RADEON X1300からSAPPHIRE RADEON HD 3470に交換した。せっかくなので、どのくらい変わったかベンチマークをとってみた。両方とも同じメーカーかつファンレスのローエンド向けビデオカードなので、比較するのには最適だ。おそらくこういうデータはいくつあっても有用だろう。まずはスペックの違いから。

  SAPPHIRE RADEON X1300 SAPPHIRE RADEON HD 3470
ビデオチップ
ATI RADEON X1300
ATI RADEON HD 3470
ビデオチップ冷却
ファンレス
ファンレス
バスタイプ
PCI-Expressx16
PCI-Expressx16/2.0
ビデオメモリタイプ
DDR2
GDDR3
ビデオメモリ容量
256MB
256MB
ビデオメモリバス
128bit
64bit
コアクロック
450MHz
800MHz
ビデオメモリクロック(実効)
500MHz
1400MHz
DirectX
9.0c
10.1

 X1300からHD 3470までは、ビデオチップとしては2世代分進んでいる。HD 3470の方はビデオメモリバスが64bitになっているがそれがどう響くか。ちなみにローエンドとは言ってもHD 3470はHD 3450の高クロック版になっている。X1300は本当のローエンドなので、その分も速くなっていることが期待できる。

 以下が3DMark06の結果。CPUやメモリなど、ビデオカード以外は全て同じ条件で計測している。

3DMark06 v1.0.2 (1280x1024)
  RADEON X1300 RADEON HD 3470
3DMark Score [3DMarks]
990
2341
 SM2.0 Score
339
803
  GT1 - Return To Proxycon [FPS]
2.328
5.988
  GT2 - Firefly Forest [FPS]
3.319
7.402
 HDR/SM3.0 Score
357
924
  HDR1 - Canyon Flight [FPS]
3.257
8.383
  HDR2 - Deep Freeze [FPS]
3.888
10.008
 CPU Score
1833
1794
  CPU1 - Red Valley [FPS]
0.578
0.568
  CPU2 - Red Valley [FPS]
0.929
0.907
Feature Tests
 
 
 Fill Rate - Single-Texturing [MTexels/s]
658.628
1044.242
 Fill Rate - Multi-Texturing [MTexels/s]
1783.744
3183.429
 Pixel Shader [FPS]
29.188
68.972
 Vertex Shader - Simple [MVertices/s]
93.244
88.434
 Vertex Shader - Complex [MVertices/s]
15.817
27.715
 Shader Particles (SM3.0) [FPS]
N/A
22.118
 Perlin Noise (SM3.0) [FPS]
5.803
19.267
Batch Size Tests
 
 
 8 Triangles [MTriangles/s]
11.596
7.423
 32 Triangles [MTriangles/s]
34.864
35.178
 128 Triangles [MTriangles/s]
35.077
92.863
 512 Triangles [MTriangles/s]
34.856
88.996
 2048 Triangles [MTriangles/s]
45.226
106.066
 32768 Triangles [MTriangles/s]
43.708
109.864

 3DMark Scoreで2倍以上に上がっている。他もおおむねRADEON 3470の方が圧倒的に高い数値が出た。やはり2世代分も違うと結構変わるものだ。

 ここからは私事になるが、ビデオカードを交換したのは、最近かなり久しぶりにPCゲームをやり始めたからだ。The Elder Scrolls.IV Oblivionというゲームだが、X1300ではなんとかぎりぎり遊べるくらいのレベルだった。しかしHD 3470に変えてからは、明らかにスムーズに動くようになった。体感でフレームレートが2倍以上になっていると思う。これならしばらく快適に遊べそうだ。ちなみにSAPPHIRE RADEON HD 3470は並行輸入品(正規代理店を通していないやつ)で5,980円で買った。


posted by G.Ishihara at 18:50| Comment(0) | TrackBack(0) | 雑記 | このブログの読者になる | 更新情報をチェックする

2008年08月03日

アクセスカウンタ

 PerlプログラミングTipsにカウンタを付けた。トップページのアクセス数と総ページビューを表示している。ページごとに同一IPからの連続アクセスはカウントしないようにしている。

 これだけ作るのでも結構大変だった。。。総ページビューを計算するので、全ページに集計用のCGIを仕込んでいる。ちゃんと動いているのかちょっとわからないけど、しばらく様子を見てみよう。


posted by G.Ishihara at 07:15| Comment(0) | TrackBack(0) | Perl | このブログの読者になる | 更新情報をチェックする

2008年08月01日

MFC編 - ダイアログにダイアログバーをつける

 今回はダイアログにダイアログバーをつけてみます。ダイアログバーというのはツールバーやステータスバーと同じ「コントロールバー」の一種です。ダイアログリソースを元にしたバーを作成することができます。

 では、普通にダイアログベースでプロジェクトを作成します。メインのダイアログは特に何もない次のようなものにしました。

 次はダイアログバー用のダイアログリソースを新規作成します。今回は次のようにエディットボックスとボタン1つを追加しました。バーになるので上下左右の余白部分の大きさは調整しておきましょう。

 次はプロパティです。ダイアログバーはメインダイアログの子ウィンドウになるので、「Style」を「子」にします。また、このままだと境界がはっきりわからないので、今回は「Client Edge」を「True」にしています。

 ダイアログバーにもコントロールのイベントを追加できます。ボタンに「BN_CLICKED」のハンドラを追加します。追加するクラスは親ウィンドウであるダイアログクラスにするとよいでしょう。

 ダイアログバー用のダイアログは特定のダイアログクラスに結び付けられているわけではないのでDDX変数はこのままでは追加できません。しかし、今回はエディットボックス1つだけなのでこのままでよいでしょう。

 次は、ダイアログクラスにCDialogBarクラスの変数を追加します。

 では、コードの方を実装していきましょう。まずは、OnInitDialog()での初期化処理です。

BOOL CDlgBarDlg::OnInitDialog()
{
    CDialog::OnInitDialog();
    
    SetIcon(m_hIcon, TRUE);         // 大きいアイコンの設定
    SetIcon(m_hIcon, FALSE);        // 小さいアイコンの設定
    
    // TODO: 初期化をここに追加します。
    {
        int        err = 0;

        if (!err) if (!m_dlgBar.Create(this, 
            IDD_DLGBAR, CBRS_TOP, IDD_DLGBAR)) err = 1;
        if (!err) RepositionBars(IDD_DLGBAR, IDD_DLGBAR, 0);
    }
    
    return TRUE;
}

 ここではまず、CDialogBar::Create()関数でダイアログバーを作成します。引数には親ウィンドウ、ダイアログリソースID、ダイアログバーを配置する位置等を指定します。ここではウィンドウの上部にダイアログバーを表示させるようにしています。

virtual BOOL CDialogBar::Create(
CWnd* pParentWnd, UINT nIDTemplate, UINT nStyle, UINT nID);

説明:
ダイアログバーの作成
引数:
pParentWnd:親ウィンドウへのポインタ
nIDTemplate:ダイアログリソースのID
nStyle:ダイアログバーを配置する位置。CBRS_TOP、CBRS_BOTTOM、CBRS_NOALIGN、CBRS_LEFT、CBRS_RIGHTのどれか
nID:ダイアログバーのコントロールID
戻り値:
正常終了した場合は0以外。それ以外の場合は0

 次はCWnd::RepositionBars()関数でコントロールバーの再配置をします。

void CWnd::RepositionBars(
UINT nIDFirst, UINT nIDLast, UINT nIDLeftOver, UINT nFlag = reposDefault,
LPRECT lpRectParam = NULL, LPCRECT lpRectClient = NULL,
BOOL bStretch = TRUE);

説明:
コントロールバーの再配置
引数:
nIDFirst:再配置するコントロールバーの範囲の最初のID
nIDLast:再配置するコントロールバーの範囲の最後のID
nIDLeftOver:クライアント領域の残りの部分となるペインのID
戻り値:
なし

 次は「取得」ボタンのイベントハンドラです。ここではエディットボックスから文字列を取得してメッセージボックスを表示しています。

// "取得"ボタン押下
void CDlgBarDlg::OnBnClickedBtnGet()
{
    CString        dlgTxt;
    int            err = 0;
    
    if (!err) if (!m_dlgBar.GetDlgItemText(IDC_EDIT1, dlgTxt)) err = 1;
    if (!err) MessageBox(dlgTxt);
}

 では、ビルドして実行してみましょう。ダイアログバーが表示されました。取得ボタンを押すとメッセージボックスに文字列が表示されます。

 ちなみに、表示位置を左、下、右と変えてみると次のようになります。

 ダイアログバーはコントロールバーの一種なので、ツールバーやステータスバーをつけるのと同じ方法でダイアログにつけることができるというわけです。


posted by G.Ishihara at 18:09| Comment(0) | TrackBack(0) | MFC | このブログの読者になる | 更新情報をチェックする

2008年07月29日

MFC編 - ダイアログバーの基本

 今回はダイアログバーを作成してみます。ダイアログバーというのは、次のようなダイアログリソースを元にしたバーです。中にボタンやエディットボックスなどのコントロールを配置することができます。ダイアログバーはツールバーやステータスバーと同じ「コントロールバー」の一種です。

 ドキュメント・ビューにおけるコントロールバーの位置づけは、フレームウィンドウの子ウィンドウです。ビューもフレームウィンドウの子ウィンドウなので、コントロールバーとビューは同じ親を持った兄弟の関係になります。この関係をまず理解しておきましょう。これは後のコード作成で必要になってきます。

 今回は「ツリービューの基本」で作成したプロジェクトにダイアログバーを追加し、ダイアログバーで入力したアイテムをツリーに追加する機能をつけてみましょう。

 では、最初にダイアログバー用のダイアログリソースを作成します。今回はエディットボックスとボタン1つを追加しました。

 バーになるので、ダイアログの上下左右の余白は調整しておきましょう。グリップをつける場合は左側の余白を少し多めに取っておきます。

 ダイアログのプロパティは、「Style」を「子」に、「Border」を「なし」にします。

 次はメインフレームクラスにCDialogBarクラスのメンバを追加します。

 次はボタンのイベントハンドラを追加します。ここでハンドラを追加するクラスを選択できますが、どこに追加すればよいのでしょうか?今回はボタンが押されたらツリービューにアイテムを追加しようとしています。ここで先ほどの関係を思い出してみましょう。ダイアログバーとビューには直接のつながりはなく、共通の親であるフレームウィンドウを介してつながっています。ということは、ボタンのイベントはまず親であるフレームウィンドウに通知し、フレームウィンドウからビューへ通知するのが最も自然な流れです。

 というわけで、ここではCMainFrameクラスにハンドラを追加します。なお、場合によってはまずドキュメントを更新し、ドキュメントが更新されたことによってビューが更新されるということもあるでしょう。その場合は、ダイアログバー→フレームウィンドウ→ドキュメント→ビューというように通知が連鎖していきます。今回は特にドキュメントは使用していないので、フレームウィンドウから直接ビューに通知することにします。

 次は、ビュークラスに関数を追加します。この関数でフレームウィンドウからビューにアイテムの追加を通知します。引数でアイテムの文字列を渡すようにします。

 では、コードを実装していきましょう。まずはフレームウィンドウのOnCreate()関数です。ここでダイアログバーを作成します。

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
        return -1;
    
    if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, 
        WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | 
        CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
        !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
    {
        TRACE0("ツール バーの作成に失敗しました。\n");
        return -1;      // 作成できませんでした。
    }

    if (!m_wndStatusBar.Create(this) ||
        !m_wndStatusBar.SetIndicators(indicators,
          sizeof(indicators)/sizeof(UINT)))
    {
        TRACE0("ステータス バーの作成に失敗しました。\n");
        return -1;      // 作成できませんでした。
    }

    // TODO: ツール バーをドッキング可能にしない場合は、
    // これらの 3 行を削除してください。
    m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
    EnableDocking(CBRS_ALIGN_ANY);
    DockControlBar(&m_wndToolBar);

    // ダイアログバーの生成
    {
        int        err = 0;

        if (!err) if (!m_dlgBar.Create(this, IDD_DLGBAR, 
            CBRS_TOP | CBRS_GRIPPER , AFX_IDW_DIALOGBAR)) err = 1;
        if (!err)
        {
            m_dlgBar.EnableDocking(CBRS_ALIGN_ANY);
            DockControlBar(&m_dlgBar);
        }
    }
    return 0;
}

 ダイアログバーはCDialogBar::Create()関数で作成します。引数には親ウィンドウ、ダイアログリソースID、ダイアログバーを配置する位置等を指定します。ここではウィンドウの上部にダイアログバーを表示させるようにしています。また、左端にグリップをつける場合はnStyleにCBRS_GRIPPERを追加します。

virtual BOOL CDialogBar::Create(
CWnd* pParentWnd, UINT nIDTemplate, UINT nStyle, UINT nID);

説明:
ダイアログバーの作成
引数:
pParentWnd:親ウィンドウへのポインタ
nIDTemplate:ダイアログリソースのID
nStyle:ダイアログバーを配置する位置。CBRS_TOP、CBRS_BOTTOM、CBRS_NOALIGN、CBRS_LEFT、CBRS_RIGHTのどれか
nID:ダイアログバーのコントロールID
戻り値:
正常終了した場合は0以外。それ以外の場合は0

 次はダイアログバーをドッキング可能にします(しなくてもいいですが)。ドッキング可能にするとダイアログバーをドラッグして自由に位置を変えることができるようになります。ドッキング可能にしないと、ダイアログバーは最初の位置で固定になります。

 ドッキング可能にする場合、CControlBar::EnableDocking()関数でコントロールバーをドッキング可能にし、CFrameWnd::DockControlBar()関数でコントロールバーをドッキングします。

 では、次は「追加」ボタンのイベントハンドラです。

// "追加"ボタン押下
void CMainFrame::OnBnClickedBtnAdd()
{
    CTVView        *tvviewP = NULL;
    CString        itemStr;
    int            err = 0;
    
    // View取得
    if (!err) if ((tvviewP = 
        static_cast<CTVView *>(GetActiveView())) == NULL) err = 1;
    // ダイアログバーから文字列取得
    if (!err) if (!m_dlgBar.GetDlgItemText(IDC_EDIT_ITEM, itemStr)) err = 1;
    // Viewにアイテム追加
    if (!err) err = tvviewP->AddItem(itemStr);
}

 ここでは、ダイアログバーのエディットボックスから文字列を取得し、ビュークラスに追加した関数を呼んでいます。フレームウィンドウからのビューの取得は、CFrameWnd::GetActiveView()関数でできます。この関数は現在アクティブなビューのポインタを返します。今回はビューが1つなので必ずツリービューのポインタが返りますが、ビューが2つ以上ある場合は、現在のビューがどれであるのかということを気にする必要が出てきます。

 では、次はビュークラスに追加したアイテムの追加関数です。

// アイテム追加
int CTVView::AddItem(CString item)
{
    CTreeCtrl    &treeCtrl = GetTreeCtrl();
    HTREEITEM    hItem = NULL;
    int          err = 0;

    if (item.IsEmpty()) err = 1;
    if (!err)
    {
        hItem = treeCtrl.GetNextItem(TVI_ROOT, TVGN_CARET);
        if (!treeCtrl.InsertItem(item, hItem ? hItem : TVI_ROOT)) err = 1;
    }
    return err;
}

 ツリーコントロールへのアイテムの追加は「ツリーコントロールの基本」でやりました。詳しくはそちらを見てください。

 では、ビルドして実行してみましょう。ダイアログバーに文字列を入力し、「追加」ボタンを押すと、ツリービューにアイテムが追加されます。


posted by G.Ishihara at 20:32| Comment(0) | TrackBack(0) | MFC | このブログの読者になる | 更新情報をチェックする

2008年07月28日

Webサイト内の検索システム

 ここ数日で、Webサイト内の検索システムについて技術的な検討を進めた。今度作るものは検索がメインというわけではないが、検索は重要な要素の一つだ。

 リクエストが来るたびにサイト内を全文検索するのはちょっと現実的ではない。といっても、普通の規模のWebサイトだったら全文検索してもそんなに気にするほど重くなるわけでもないけど。例えばPerlプログラミングTipsの全文検索機能は、文字通りサイト内の記事を逐次検索している。サイトのボリュームがこれくらいであれば、これで十分だ。

 ただ、今度のはボリュームが結構膨らむ可能性がある。要するにデータを溜め込む性質があるので、インデックスを使った検索を導入するのは必須だ。そこで、候補にしてみたのがSennaとNamazuだ。細かい性能は置いておいて、まず使えるかどうかが第一条件だ。レンタルサーバをあきらめて、自宅サーバでいこうと考えたのもこの辺の絡みがある。レンタルサーバだといろいろ導入するのに制限があるので、後で行き詰るよりも最初から何でもできる自宅サーバでやったほうがいいだろうということだ。

 まず、Sennaから検討したが、結論から言うと「見送り」だ。いろいろ言うと悪口になってしまうかもしれないので詳細は控えるが、使えるかどうかという観点からあきらめた。そして、Namazu。これは採用だ。まだ使い込んだところまでは分からないが、いけそうだという感触はつかんだ。

 ついでに、検討する過程でサーバがDELLのINSPIRON 620mからINSPIRON 710mにパワーアップした。スペックはPentiumM 2.0GHz、メモリ1GB、HDD100GBだ。これにfedora9を入れて使っている。もともとサブノートで使っていたものだが、そんなに使わなくなったので第二の人生を送らせることにした。スペック的に使用に耐えられなくなるまでは当面活躍してもらおう。


posted by G.Ishihara at 22:03| Comment(0) | TrackBack(0) | Perl | このブログの読者になる | 更新情報をチェックする

ApacheでCGIが動かないときは

 fedora9マシンのサーバ環境の整備を少し進めておこうと思って、Apacheをいじり始めた。が、CGIが動かない。。。httpd.confをいろいろ見直してみたけどやっぱりうまくいかない。そこで、Apacheのエラーログを見てみると、

(2)No such file or directory: exec of 'var/www/cgi-bin/xxxx.cgi' failed

とのログが出ている。ファイルはあるのにおかしいな〜と思って、試しに存在しないCGIスクリプトにアクセスしてみると、

script not found or unable to stat: /var/www/cgi-bin/xxxx.cgi

とエラーログが出た。メッセージが違うってことは、少なくともスクリプト自体は認識しているみたいなので、問題はスクリプトの中身のようだ。で、ようやく分かったのだが、改行コードが\r\nだと、一行目の

#!/usr/bin/perl

が、

#!/usr/bin/perl\r

と認識されてしまうらしい。それでそんなコマンドはないよ〜ということになるようだ。まあ、言われてみればもっともだけど、普段は改行コードなんかはテキストエディタがうまく扱ってくれるから気がつかなかった。そこで、viエディタで改行コードを変換する方法。

改行コードを\nにする。つまりUNIXの形式
:set fileformat=unix
(もしくは:set ff=unix)

改行コードを\r\nにする。つまりWindowsの形式
:set fileformat=dos
(もしくは:set ff=dos)


posted by G.Ishihara at 21:14| Comment(0) | TrackBack(0) | Perl | このブログの読者になる | 更新情報をチェックする

2008年07月27日

MFC編 - フォームビューの基本

 フォームビューは、SDI/MDIベースのアプリでダイアログリソースを元にして作成するビューです。フォームビューを使うと、ダイアログのようにウィンドウ上にいろいろなコントロールを配置することができます。

 では、実際に作ってみます。今回はSDIで作成します。アプリケーションウィザードで「ドキュメントの種類」に「シングルドキュメント」を選択します。そして、「生成されたクラス」ページでビューの基本クラスに「CFormView」を選択します。これで、初期作成されるビューがCFormViewの派生クラスになります。

 では、クラスビューで確認してみます。作成されたビュークラスがCFormViewの派生クラスになっていることがわかります。

 次はダイアログリソースを編集していきましょう。今回は簡単に次のようにエディットボックスとボタンを1つずつ追加しました。

 フォームビューもダイアログと同じようにDDX変数を追加したり、コントロールのイベントをハンドルすることができます。では、エディットボックスにDDX変数を追加します。

 ボタンにはBN_CLICKEDのイベントハンドラを追加します。

 それではコードのほうを見てみましょう。フォームビューは特定のダイアログリソースと関連付けられています。これはどこで行われているのでしょうか。フォームビューのクラス定義を見ると次のような記述があります。

class CFVView : public CFormView
{
protected: // シリアル化からのみ作成します。
    CFVView();
    DECLARE_DYNCREATE(CFVView)

public:
    enum{ IDD = IDD_FV_FORM };

 IDD_FV_FORMというのはダイアログリソースのリソースIDです。また、コンストラクタを見ると次のようになっています。

CFVView::CFVView()
    : CFormView(CFVView::IDD)
    , m_xvEdit1(_T(""))
{
    // TODO: 構築コードをここに追加します。
}

 CFormViewクラスのコンストラクタにダイアログのリソースIDを渡しているのがわかります。これによって特定のダイアログリソースとフォームビューが関連付けられているわけです。

 それでは、コードを追加していきましょう。ビューの初期化処理はOnInitialUpdate()関数に記述します。

void CFVView::OnInitialUpdate()
{
    CFormView::OnInitialUpdate();
    GetParentFrame()->RecalcLayout();
    ResizeParentToFit();

    m_xvEdit1 = _T("文字列を入力してください。");
    UpdateData(FALSE);
}

 ここでは、エディットボックスの文字列を初期化しました。UpdateData()関数を呼んで表示を更新します。次はボタンのイベントハンドラです。

// "取得"ボタン押下
void CFVView::OnBnClickedBtnGet()
{
    UpdateData();
    MessageBox(m_xvEdit1);
}

 ここでは、エディットボックスの文字列をメッセージボックスに表示するようにしました。ではビルドして実行してみましょう。

 エディットボックスに文字列を入力して「取得」ボタンを押すとメッセージボックスが表示されます。コントロールの操作はダイアログベースアプリとほぼ同じですね。ただしフォームビューはダイアログではなくあくまでビューの一種です。


posted by G.Ishihara at 09:10| Comment(0) | TrackBack(0) | MFC | このブログの読者になる | 更新情報をチェックする

2008年07月25日

MFC編 - ツリービューの基本

 ツリービューは、SDI/MDIベースのアプリでツリーコントロールを元にリスト表示をするビューです。

 まずはツリービューとツリーコントロールの違いを明確にしておきましょう。ツリービューはドキュメント・ビュー・アーキテクチャにおけるビューの一種です。ツリーコントロールはダイアログのコントロールの一種です。ツリービューを使う場合、ツリーの実際の操作はCTreeView::GetTreeCtrl()関数でツリーコントロールを取得し、CTreeCtrlクラスを使って行います。ツリービューは内部にツリーコントロールを保持しているだけと考えればいいでしょう。

 では、実際に作ってみます。今回はSDIで作成します。アプリケーションウィザードで「ドキュメントの種類」に「シングルドキュメント」を選択します。そして、「生成されたクラス」ページでビューの基本クラスに「CTreeView」を選択します。これで、初期作成されるビューがCTreeViewの派生クラスになります。

 では、クラスビューで確認してみます。作成されたビュークラスがCTreeViewの派生クラスになっていることがわかります。

 それでは、コードを追加していきましょう。ビューの初期化処理はOnInitialUpdate()関数に記述します。

void CTVView::OnInitialUpdate()
{
    CTreeView::OnInitialUpdate();
    {
        CTreeCtrl    &treeCtrl = GetTreeCtrl();
        HTREEITEM    hItem = NULL;
        int            err = 0;

        // アイテム挿入
        if (!err) if ((hItem = treeCtrl.InsertItem
            (_T("乗り物"), TVI_ROOT)) == NULL) err = 1;
        if (!err) if (!treeCtrl.InsertItem(_T("バス"), hItem)) err = 1;
        if (!err) if (!treeCtrl.InsertItem(_T("飛行機"), hItem)) err = 1;
        if (!err) if ((hItem = treeCtrl.InsertItem
            (_T("電車"), hItem)) == NULL) err = 1;
        if (!err) if (!treeCtrl.InsertItem(_T("山手線"), hItem)) err = 1;
    }
}

 ツリーの操作はCTreeCtrlクラスを使って行います。CTreeCtrlのオブジェクトはCTreeView::GetTreeCtrl()関数で取得できます。

 ここではアイテムを挿入しています。ツリーコントロールへのアイテムの挿入は「ツリーコントロールの基本」でやりました。この部分は同じなので詳細はそちらを見てください。

 さて、ツリーコントロールは初期状態だとアイテム間の線や+-ボタンは表示されません。これを表示させたい場合はどうすればいいでしょうか。ダイアログの場合はリソースエディタ上のプロパティで設定できましたが、ビューの場合はリソースはないのでプログラム上で設定しないといけません。

 ツリーコントロールにスタイルを設定する場合は、通常はCTreeCtrl::Create()関数の引数でスタイルを設定しますが、ビューの場合はOnInitialUpdate()の段階ではすでにツリーコントロールが作成されているので、後からスタイルを設定するということができません。

 こういう場合は、CWnd::Create()関数をオーバーライドして、スタイルを追加します。ツリービューのプロパティからCreate()関数をオーバーライドします。

BOOL CTVView::Create(LPCTSTR lpszClassName, 
    LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, 
    CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
{
    // TODO: ここに特定なコードを追加するか、もしくは基本クラスを呼び出してください。
    {
        dwStyle |= TVS_HASBUTTONS;
        dwStyle |= TVS_HASLINES;
    }

    return CTreeView::Create(lpszClassName, lpszWindowName, 
        dwStyle, rect, pParentWnd, nID, pContext);
}

 dwStyleにTVS_HASBUTTONS、TVS_HASLINESを追加します。これでツリーコントロールのアイテム間の線と+-ボタンが表示されるようになります。

 ではビルドして実行してみましょう。ツリーコントロールのアイテムがビューに表示されました。


posted by G.Ishihara at 17:45| Comment(0) | TrackBack(0) | MFC | このブログの読者になる | 更新情報をチェックする