前回の続きです。
マルチタッチ対応アプリケーションをつくるためのテストをしています。
ためしにフォームでマウスジェスチャイベントをとって、ピンチ・イン/アウトでメインウィンドウを拡大・縮小する動きを実装してみます。
基本的にはigZoom(=259)があったときに、基準点をグローバル変数に保存し、イベント終了後に、その移動値分だけ、ウィンドウを拡大縮小するという流れになります。
[cpp]
//—————————————————————————
// #include "Unit1.h"
private: // ユーザー宣言
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_LBUTTONDOWN,TWMLButtonDown,WMLButtonDown)
END_MESSAGE_MAP(TForm)
TPoint StartPos;
int FormWidth;
int FormHeight;
//—————————————————————————
// Unit1.cpp
void __fastcall TForm1::FormGesture(TObject *Sender, const TGestureEventInfo &EventInfo,
bool &Handled)
{
int PosX, PosY;
switch(EventInfo.GestureID){
//———————————–
//igZoom
case 259:
Handled = true;
if(EventInfo.Flags.Contains(gfBegin) == true){ //ズーム開始
Form1->Caption = "igZoom[gfBegin]";
//基準座標を保存
StartPos.x = (int)EventInfo.Location.x;
StartPos.y = (int)EventInfo.Location.y;
FormWidth = Form1->Width;
FormHeight = Form1->Height;
}
else if (EventInfo.Flags.Contains(gfInertia) == true ){ //イナーシャ中
//Formには発生しない?
Form1->Caption = "igZoom[gfInertia]";
}
else if ( EventInfo.Flags.Contains(gfEnd) == true ){ //ズーム終了
Form1->Caption = "igZoom[gfEnd]";
/*
PosX = StartPos.x – (int)EventInfo.Location.x;
PosY = StartPos.y – (int)EventInfo.Location.y;
//フォームをそれに伴って拡大縮小する
Form1->Width = Form1->Width – PosX;
Form1->Height = Form1->Height – PosY;
*/
StartPos = TPoint(0,0);
FormWidth = Form1->Width;
FormHeight = Form1->Height;
}
else{
PosX = StartPos.x – (int)EventInfo.Location.x;
PosY = StartPos.y – (int)EventInfo.Location.y;
//フォームをそれに伴って拡大縮小する
Form1->Width = FormWidth – PosX*2;
Form1->Height = FormHeight – PosY*2;
}
break;
//———————————–
//igPan
case 260:
Form1->Caption = "igPan";
break;
//———————————–
//igRotate
case 261:
Form1->Caption = "igRotate";
break;
//———————————–
//igTwoFingerTap
case 262:
Form1->Caption = "igTwoFingerTap";
break;
//———————————–
default:
Form1->Caption = "None";
break;
}//switch;
}
//—————————————————————————
[/cpp]
いろいろ試してみたのですが、Form自体に gfInertia(イナーシャ)が起きることはないようです。これが分かるまで、だいぶ時間を浪費しました。。。
てっきり、ウィンドウがデスクトップ上を、ツツッーと滑るような動きが実装できるものと勘違いしていたのですが、それは無理なようです。
前述の開発者会議において、そのサンプルは、Visual Studioで実装されていたのですが、おそらくそうした動きをC++Builderでやるには、VCL上からではなく、Win32 API(または.NET Framework)を使うしかないのでしょう。
ただ、フォーム内に、スクロールイベントが起きるような ScrollBoxや、Memoコンポーネントなどを配置すれば、そこにイナーシャが発生するのは確認しました。イナーシャが発生するか否かは、各VCLコンポーネントによるのでしょう。
なお、C++Builder2010のそれらVCLコンポーネントでは、イナーシャの値を変更する場所がありませんでした。既定値のみです。たとえば、ツルツルのところを勢いよく滑るような動きや、ごわついた布地をピタッと停まる動きなどの再現は無理です(APIを直接使えば、イナーシャの値は指定できます)。
あと、これはデバイスの差異なのか、感知の仕様によるものなのか、微妙に、igZoomとigRotateイベントを区別して取るのが難しい感じがします。ここはもう一工夫と、いくつかのデバイスを参考にしながらの調整が必要になってくると思います。
とりあえずこのテスト結果を元に、次版のアタッシェケースに実装してみようかと思います。
このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください。
日々の開発作業で気づいたこと共有を。同じところで躓いている人が、 検索で辿り着けたら良いな、というスタンスで記事を書くので不定期更新になります。
コメントする