[PR]子育てママさんへ:3年毎に15万円うけとれる医療保険?
Wintabを学ぶ(MDIの実験編)
はぅー,久しぶり〜(プログラミングするのが)
イカンいかん!こんなことじゃいつまでたっても成長しねぇー! (TдT)
えへへ.バーチャルボーイ買っちゃったー♪ヽ(´ー`)ノ
ソフト付きで2000円でしたw
(>ω<) 目がチカチカするよぅ!
さて,今回は,MDIアプリケーションでタブレットの情報を得る実験.
いや,実験するってほどのことでもないんですがね,いままでSDIでしかやったことなかったから,MDIでも使えるかな〜と思って.
ふぅーむ.まずは,タブレットのコンテキストハンドルをどうするかが問題.
とりあえず,以下の2つの案が候補になりました.
A.コンテキストハンドルは1つだけ作る.
B.タブレットの情報を得たい領域ごとに,コンテキストハンドルを作る.
ん〜,なんだかB案は処理自体は簡単かもしれないけど,なんとなく嫌だなぁー.
仕様書にも「通常はコンテキストは1つで十分です」みたいなことが書いてあるし…
というわけで,今回はA案でやってみました.
さて,タブレットの位置情報を親フレーム内に表示するプログラムを作成してみようかな.
↓完成予想図はこちら!

動作要件としては,マウスでカーソルを動かしたときに,その座標を親ウィンドウに表示してくれる.
また,タブレットでカーソルを動かしたとき,親ウィンドウ内であれば,モチロンその座標を表示してくれて,
子ウィンドウ内のパネル内にあるときも座標を表示して欲しい…って感じ.
さて,早速実装.
MDIアプリケーションの骨組みはDelphiに作ってもらおうー.らくちんー♪
前回タブレットの部分とメインフレームを一緒にしていたので,今回はタブレットに使用する
部分はクラス(TWintab)として独立させました.
タブレットのクラス:TWintab(Wintab.pas)
そして,このWintabクラスのインスタンスを親フレームに持たせます.
親フレームの側では,他の子ウィンドウからでもこのクラスにアクセスできるように,プロパティとして公開することにしました.
MAIN.PAS(の一部)
type
TMainForm = class(TForm)
private
{ Private 宣言 }
FTablet : TWintab ; // タブレットクラス本体
public
{ Public 宣言 }
procedure DisplayTabletPos( packet_num, x, y : Integer );
property Tablet : TWintab read FTablet ; // 子ウィンドウに公開
end;
var
MainForm: TMainForm;
そして,実際にタブレットから情報を取り出すタイミングは,マウスが移動したときなので,OnMouseMoveハンドラを記述します.
MAIN.PAS(の一部)
{
[イベントハンドラ]
マウスが移動した.
}
procedure TMainForm.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var
packet_num : Integer ;
packets : array[0..PACKETNUM-1] of TPacket ;
begin
// パケットを取り出す
packet_num := FTablet.GetPackets( packets );
// 表示させる
if ( packet_num > 0 ) then begin
DisplayTabletPos( packet_num, packets[0].pkX, packets[0].pkY );
end else begin
LabelMousePos.Caption := Format('(%d,%d)',[X,Y]);
end;
Repaint;
end;
さて,この状態で起動!
親ウィンドウ内でマウスが動いてる間はマウス座標が,タブレットが動いている間はタブレットの座標(といってもマウスと位置的には同じ)が表示されました.
でも…というか当然というか,子ウィンドウを「新規作成」してそのなかにカーソルが入ると,タブレットの座標が更新されませんでした.
まぁ,子ウィンドウに何も仕掛けをしなかったので,当然ですがね・・・
そこで,子ウィンドウのパネルにもOnMouseMoveのイベントハンドラを記述してみました.
CHILDWIN.PAS(の一部)
{
[イベントハンドラ]
マウスが移動したとき
}
procedure TMDIChild.FImgFrontMouseMove(Sender: TObject; Shift: TShiftState;
X, Y: Integer);
var
packet_num : Integer ;
packets : array[0..PACKETNUM-1] of TPacket ;
begin
// 親フレームに持たせてあるタブレットのクラスを使用する.
packet_num := MainForm.Tablet.GetPackets( packets ) ;
if ( packet_num > 0 ) then MainForm.DisplayTabletPos( packet_num, packets[0].pkX, packets[0].pkY );
end;
なんとなく,イベントを受け取れないんじゃないかなー? あるいは,ウィンドウが違うからパケットが空なんじゃない
かなー? とか思ってダメ元で起動してみましたが,ちゃんと動きます.
ありり? なんでだろ?
理由はわかりませんがちゃんと期待通りの座標を返しているようです.
んー.仕組みが分からん… ( ̄∀ ̄;)
誰か,その辺の事情をご存知の方,教えてください.お願いします.
ふむぅー.こうなるとB案を試す必要がなくなったにゃー.
A案の方が,タブレットを使いたいコンポーネントは,マウスイベントの時にポーリングするだけでいいから使うのが
ラクチンだしなぁ.
B案のメリットってあるのかなー?
さて,今後検討しないといけない問題点もまだまだあるからなぁ.
・DLLのダイナミックローディングへの対応.(まだやってなかったんかい!)
・TWintabクラスは1つでいいことが分かったので,TWintabクラスにシングルトンパターンを適用して,親フレームにも持たせなくて利用できるようにする.
んー,ひょっとして今回は,「動いた!」と勘違いしてるだけかなー?
何か,落とし穴がありそうな気がするけど・・・
まぁ,この辺も様子見ながら,次回は上の2つの問題点を解決だッ!
今回作成したサンプル.
Delphi6 Personal (タダのやつ)で作りました.
WintabMDI02.zip(274KB)
今回も,DLLを静的にリンクしているので,タブレットの無い環境の実行は保証できませんがね.
ψ(`∀´)ψ けっけっけ
<< Back to Diary...