◆◇◆ Tips! ◆◇◆

イベント盛りだくさん!

[Japanese Pocket C User's Page]-[Tips!]


GUIアプリケーションを作るときに避けて通れないのが、
イベントの制御です。PCFormを使っていれば、VBのような感覚で利用出来ますが、
やはり、基本的な考え方は押さえておいた方がいいでしょう。

1.イベント制御の流れ

GUIを使ったプログラムでは、ボタンを押したとか、
クリックをしたなどのイベントに基づき処理が実行されます。

この流れをPocketCでプログラムにする場合、
大まかな流れは次の通りです。

1)関数sleepを使い、割り込みを待つ

2)関数eventを使い、発生したイベントを分類

3)さまざまな関数を使い、イベントの詳細を調べる。

4)イベントの内容に基づき、処理を実行する。

PCFormでは、1)〜3)までは作ってくれますが、4)の部分は、
各自がコーディングすることになります。

そのため、PC Fromを使っている人は、それぞれのイベントにおいて、
どのような詳細情報を取れるのかという観点で読んでください。

2.イベントの種類

関数eventにて取得出来るイベントは次の通りです。

ID 名称 説明 詳細調査方法
0 PM_NONE なにも発生しなかった  
1 PM_CHAR 文字が入力されたとき key:入力された文字
2 PM_MOUSEMOVE スタイラスが移動 penx,peny:座標
3 PM_MEMORYSHORT メモリが少なくなったとき  
4 PM_BUTTONDOWN 画面がタップされた penx,peny:座標
5 PM_BUTTONUP スタイラスが画面から離れた penx,peny:座標
6 PM_DBCLICK ダブルクリック  
7 PM_PAINT 画面が再描画されたとき  
8 PM_COMMAND GUI コントロールにて、
イベントが発生
guiid:イベント発生オブジェクト
menu:イベントが発生したメニューID
getnotify:メッセージ
9 PM_KEYDOWN キーが押された  
10 PM_KEYUP キーが放された waitp:キーが話されるのを待つ
getc:キーが放されるまで待ち、キーを返す。
11 PM_TIMER タイマーイベントが発生 settimer:タイマーイベントを設定
timerid:発生したタイマーイベント
killtimer:タイマーイベントを削除
12 PM_COMMEVENT シリアル通信が発生したとき 詳しくは、シリアル関連のヘルプを

・ID・・・関数eventの戻値
・名称・・・pcheader.hでの定義名

3.さまざまな動作が発生したときの動き

イベントが発生する流れをいくつかの簡単な例で説明します。

1)ボタンが押されたとき

順番 ID イベント 説明
1 9 PM_KEYDOWN 「SHIFT」が押された(keyで確認)
2 9 PM_KEYDOWN 「a」が押された(keyで確認)
3 1 PM_CHAR 文字「A」が確定(charで確認)
4 10 PM_KEYUP 「a」が放された(keyで確認)
5 10 PM_KEYUP 「SHIFT」が放された(keyで確認)

実際に入力された文字により、処理を分けるときに、
「A」や[B」といった目にみえて分かる文字ならいいですが、
タブやCTRLなどの場合は、判断に迷います。
こういった場合に対応するためのヘッダーファイルが、
CE Factoryさんのところで紹介されています。

VK_Define.hというファイルがそうです。

この中で定義されているコードを利用すれば、何が押されたかが分かります。

2)スタイラスで移動

順番 ID イベント 説明
1 4 PM_BUTTONDOWN スタイラスで画面を触った
2 2 PM_MOUSEMOVE スタイラスを移動
3 5 PM_BUTTONUP スライスを画面から放した

スタイラスの移動については、関数penx,penyにて座標を確認することができます。

3)タイマーイベント

順番 ID イベント 説明
1     settimerで、タイマーイベントを生成
2 11 PM_TIMER タイマーイベントが発生。
timeridで、発生したタイマーイベントを知る
3     killtimerでタイマーイベントを削除

特定の時間が過ぎたら、処理を実行するタイマーイベントは、
あらかじめ関数settimerで定義を行う必要があります。
killtimerを実行しないと、時間が過ぎるたびに、イベントが発生する。

4.イベントを強制的に起動する

イベントを強制的に発生させる方法がいくつかあります。

関数名 発生するイベント 説明
keyevent PM_KEYDOWN,PM_KEYUP 使い方がよく分かりませんでした
postevent ユーザ定義イベント ユーザが設定したイベントIDを発生させる。
システム保有のIDと同じ物を送らないこと。
settimer PM_TIMER タイマーイベントを設定する。

この中でよく使いそうなのは、settimerですね。

 

5.サンプルプログラム

で、今回もサンプルプログラムです。
このサンプルプログラムでは、発生したイベントの情報が画面に表示します。


(プログラム名 event_chk.pc)

#include "/pocketc/pcheader.h"
#include "/pocketc/VK_Define.h"


#define CTL_EDIT 1001
#define CTL_BUTTON 1002
#define TIMER1	1003
#define TIMER2	1004

int r_count; //表示ルーチンの行カウント
int t_count; //タイマーイベントカウント用

// ===== キーコード表示
string showkey(char ch_in)
{
string ans;
ans=ch_in;

switch(ch_in)
	{
	case VK_TAB:
		{
		ans="[TAB]";
		break;
		}
	case VK_SHIFT:
		{
		ans="[SHIFT]";
		break;
		}
	case VK_SPACE:
		{
		ans="[SPACE]";
		break;
		}
	}
return ans;
}

// ===== 表示ルーチン =====
int writestr(string str_txt)
{
string str_add;

r_count++;
str_add=editget(CTL_EDIT) ;
if (r_count==8)
	{
	str_add="";
	r_count=0;
	}
str_add=str_add+ "@"+ str_txt+"\r\n";
editset(CTL_EDIT,str_add );
}

// ===== TIMER1 =====
int ev_timer1()
{
MessageBox((string)t_count,"Timer1",1,1);
t_count++;
if (t_count==3)
	{
	MessageBox("Kill Timer1","Timer1",1,1);
	killtimer(TIMER1);
	}
}

// ===== TIMER2 =====
int ev_timer2()
{
MessageBox("after 5 minutes.exit","Timer2",1,1);
quit();
}

main()
{
int ev;
int flg_change;
int g_id;
int msg;
int t_event;

// ==== 初期化 =====
r_count=0;
t_count=0;


// ===== Timerイベント =====
settimer(TIMER1,15000);
settimer(TIMER2,300000);


//===== 画面作成
createctrl("EDIT","",WS_VISIBLE | WS_BORDER | ES_MULTILINE ,0,20,60,200,140,CTL_EDIT); // EDIT作成
createctrl("BUTTON","event!",WS_VISIBLE | WS_BORDER,0,20,40,200,20,CTL_BUTTON); // BUTTON作成


while(1)
	{
	sleep(0);
	ev=event(0);
	switch(ev)
		{	
		case PM_CHAR:
			{
			writestr(" char "+showkey(key()));
			break;
			}
		case PM_MOUSEMOVE:
			{
			writestr(" move position :"+penx()+","+peny());
			break;
			}
		case PM_BUTTONDOWN:
			{
			writestr(" down position :"+penx()+","+peny());
			break;
			}
		case PM_BUTTONUP:
			{
			writestr(" up position :"+penx()+","+peny());
			break;
			}
		case PM_DBCLICK:
			{
			writestr(" double click position :"+penx()+","+peny());
			break;
			}
		case PM_PAINT:
			{
			g_id=guiid();
			if (g_id !=0)
				{
				writestr("paint /gui id " + g_id  );
				}
			break;
			}
		case PM_COMMAND:
			{
			g_id=guiid();
			msg=getnotify();
			writestr("command /gui id " + g_id + " / message " + msg );
			break;
			}
		case PM_KEYUP:
			{
			writestr(" key up "+showkey(key()));
			break;
			}
		case PM_KEYDOWN:
			{
			writestr(" key down "+showkey(key()));
			break;
			}
		case PM_TIMER:
			{
			t_event=timerid();
			writestr("Timer Event "+t_event);
			switch (t_event)
				{
				case TIMER1:
					{
					ev_timer1();
					break;
					}
				case TIMER2:
					{
					ev_timer2();
					break;
					}
				}
			break;
			}
		}
	}
}

6.解説

ちょっと長く見えますので、簡単に解説おば。

全体の流れは、

・関数を定義
・画面等の初期化
・whileによるイベントループ内で処理

です。それぞれはそれほど難しくはないと思うので、
関数だけ説明しときます。

1)関数:showkey

VK_Define.hを利用して、TAB,SHIFT,SPACEキーが押された時に表示できるようにする。

2)関数:writestr

発生したイベント表示。

3)関数:timer1,timer2
タイマーイベントにより、呼び出される。

 

7.おさらい

今回は次のことを学びました。

1)eventループについて

2)各イベント発生時の詳細情報の取得方法

3)簡単なイベントの流れの例

ちょっと考え方がむずかしくなってきましたが、
分かるところからしっかりと押さえて行きましょう。


 

[Japanese Pocket C User's Page]-[Tips!]