ペンタブ関係のプログラムは、なんとなく敷居が高そうですよね? 関連情報を検索してみても、「気軽に手軽に」というような解説サイトは見当たりません。 でもまぁ、最近 Visual C# 2005 Express Edition を久しぶりに触ってみたというキッカケで、WinTab.NETを試してみました。
しかし、開発環境が「2005」ってのは今さら感すぎますね。 パソコンの買いかえを検討中で、もし買いかえたなら 64bitOS + Visual C# 2010 になりそうだけど、2005でやる意味あるんでしょうか?
と、思ったらWinTab.NETのプロジェクト履歴に「64bit対応」とかって書いてます。 完全に時代遅れなネタでもないらしいです。
ってことで統合環境の使い方を思い出しながらコーディング。 適当にC#のプロジェクトを作って「プロジェクト」メニューから「参照の追加」、参照タブで WinTabDotnet.dll のアセンブリを追加。
...アセンブリの追加方法とか、今の開発環境で変更されてたらこのくだり無駄ですね。
気を取り直して、WinTab.NETのアーカイブに入っていたサンプルコードを見ながらこんなの書きました。 思っていたよりずっと簡単にペンタブ用コードが書けるみたいです。
// Form1.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using WinTabDotnet; namespace WinTabDotnetTest01 { public partial class Form1 : Form { private WinTabMessenger m_wtMessenger; private WinTabContext m_wtContext; private int m_x; private int m_y; private int m_pressure; public Form1() { InitializeComponent(); if(!WinTab.LoadWinTab()) { MessageBox.Show("ペンタブレットが見つかりません(WinTab32.dllが見つかりません)。", "WinTab.NET"); throw new WinTabException("WinTab.NETの初期化に失敗しました。"); } m_wtMessenger = new WinTabMessenger(); m_wtContext = new WinTabContext(); m_wtMessenger.CursorMove += Form1_CursorMove; m_wtMessenger.NPressureChange += Form1_NPressureChange; m_wtContext.Open(this.Handle, true, 0, 0, 65536, 65536, ContextOption.DEFAULT, RelativeField.None); } private void Form1_CursorMove(PacketEventArgs e) { m_x = e.pkts.pkX; m_y = e.pkts.pkY; UpdateTitle(); } private void Form1_NPressureChange(PacketEventArgs e) { m_pressure = e.pkts.pkNormalPressure; UpdateTitle(); } private void Form1_Activated(object sender, EventArgs e) { m_wtContext.Overlap(true); } private void Form1_Deactivate(object sender, EventArgs e) { m_wtContext.Overlap(false); } private void UpdateTitle() { this.Text = "(" + m_x + ", " + m_y + ") " + m_pressure; } protected override void WndProc(ref Message m) { if (!m_wtMessenger.WndProc(ref m) ) { base.WndProc(ref m); } } } }
ほとんどコピペですが、一点だけ重要な部分が追加されています。 重要なのはアプリケーションがアクティブになったときに WinTabContext.Overlap(true) 、他のアプリケーションに移ったときに WinTabContext.Overlap(false) をしている所です。 これについては、WacomのSoftware developer supportのWindows版FAQに記述がありました。
ペンタブレットのカーソル移動、筆圧検出のイベントはアプリケーションがアクティブかどうかに関係なく、1番最後にOpenまたはWinTabContext.Overlap(true)したアプリケーションに発行されるようです。 (ラップ元版だとWTOverlap(hCTX,true)になる。) アプリケーションがアクティブでなくなったときは、WinTabContext.Overlap(false)をして別のアプリケーションにイベントを譲るべきとか。 このへんマウスのイベントと違うので注意。
FAQに書いてあるのは、「Overlapの本来の手続きをしないアプリケーションが多いため、wintabが自動でイベントの発行先を変えるようにしたら不都合が出るアプリケーションもウニャムニャ...」ということなのかな? まぁ、ちゃんとOverlapしとけば大丈夫でしょう、多分。
あと、サンプルコードを見て他に気づいたこととか。
WinTab.NET同梱のサンプルコードはOutInfoとPressureTestの2つがあります。 その2つはWinTabContext.open()に渡す引数の値が違います。 これでかなり挙動が変わるようです。
OutInfoではWinTabContext.open()に引数の少ない、デフォルト値を指定したことになる版を使っています。 ContextOptionの指定が省略されると、ペンタブの動きとマウスカーソルが連動します。 これは直感的に分かりやすい動作ですね。 「int xorg, int yorg, int vx, int vy」の座標関係の引数が省略されています。 座標関係の引数を省略すると、WinTabMessenger.CursorMoveのイベントで渡される座標がマウスと同じく画面上のピクセル単位になるようです。 これは、ペンタブの性能がいい場合はせっかくの精度が削がれることになるのではないでしょうか? (安物のペンタブしか持って無いから分からんけど。) vxとvyに大きめな値を渡して、自前でペンタブ座標→クライアント座標の変換をした方が良さそうな気がしますが、はたして?
PressureTestの方はWinTabContext.open()に全ての引数を指定する版を使っています。 ContextOptionの指定は「ContextOption.OFFMODE | ContextOption.SYSTEM」です。 OFFMODEというのは「ContextOption.DEFAULTから指定したオプションを取り除きますよ」という意味です。 Wintab.NETが独自に追加したパラメータのようですね。 ContextOption.SYSTEMが取り除かれると、ペンタブの動きとマウスカーソルが連動しなくなります。 マウスカーソルと連動しないためペンタブの入力範囲全体を特定のウィンドウやコントロールにマッピングさせることができます。 使い方によっては有用かもしれません。 「x座標とy座標を入れ替えてペンタブを縦置きで使用」とかの機能も実装できますね。
最後に、WacomのSoftware developer supportのWindows版を見てて、Wintab.NETへのリンクがあるのに気づきました。 これはsourceforge.jpのWinTab.NETプロジェクトとは別物です。 プロジェクト名はWintabDNでした。
最初は「オフィシャルか?」と思ったけど微妙です。 個人が作っているのをWacomが紹介しているのか、Wacom自体が作っているのか判然としません。 一応、sourceforge.jpのやつよりドキュメントはあるようですが、まだ書きかけの様子。 そしてWintabDNのデモを起動させてみると .NET Framework 4.0 が必要とかって表示が...
HDDが足りなくて3.5までしかインストールして無いんだよっ!
sourceforge.jpの方は .NET Framework 2.0 でOKです。 もしWintabDNが個人作というなら、同じ個人作のsourceforge.jpに登録されたやつでも十分だと思うけど、どうでしょうねぇ?