12/10/1999 by Shigeyuki Seko
8) メニューによる音の ON/OFF
音が付いたのはいいのですが、常に音が出ているのも不便です。音を消したいと思う場面もあります。
そこで、メニューから自由に音の ON/OFF ができるようにしましょう。これはリソースとCのソースの両方を修正します。
まず、リソースファイル book.rcp を開きます。このリソースの下の方にメニューに関する記述があります。MENU ID 3600
BEGIN
PULLDOWN "Menu"
BEGIN
MENUITEM "About" 3601
END
PULLDOWN "Page"
BEGIN
MENUITEM "Go Start Page" 3602
MENUITEM SEPARATOR
MENUITEM "Back" 3603
MENUITEM "Next" 3604
END
ENDこの MENU ID 3600 から BIGIN そして END までがメニューに関するリソースです。
PULLDOWN に続いて書かれているのがプルダウンメニューのタイトル、その下の BEGIN から END までの間に書かれた MENUITEM がプルダウンメニューです。MENUITEM の横に書かれているラベルが実際に表示されるプルダウンメニュー名でその横の数字が、このプルダウンメニューが選ばれた時にメインプログラムに渡される ID 番号です。
さて、まずは音の ON/OFF のメニューを作らなければいけません。
でも心配する事はありません。新しいプルダウンメニューを追加するのは簡単です。
以下のような新しいプルダウンメニューを作ります。PULLDOWN "Sound"
BEGIN
MENUITEM "Sound ON" 3605
MENUITEM "Sound OFF" 3606
ENDここで MENUITEM の ID 番号、3605,3606 は他と重複しない番号を使用してください。
この作成した新しいプルダウンメニューを実際にメニューのリソースに書き込みます。MENU ID 3600
BEGIN
PULLDOWN "Menu"
BEGIN
MENUITEM "About" 3601
END
PULLDOWN "Page"
BEGIN
MENUITEM "Go Start Page" 3602
MENUITEM SEPARATOR
MENUITEM "Back" 3603
MENUITEM "Next" 3604
END
PULLDOWN "Sound"
BEGIN
MENUITEM "Sound ON" 3605
MENUITEM "Sound OFF" 3606
END
ENDリソースの変更はこれだけです。
次に C のソースプログラムを変更します。
以下に book.c の冒頭の部分を示します。
/******************************
Picture Book program
TAB = 4
Shigeyuki Seko
12/6/1999
******************************/#include <Pilot.h>
#define MaxPage 10Int Page;
static void drawBitmap(Int x, Int y, Int id)
{
VoidHand h;
VoidPtr p;
h = DmGet1Resource('Tbmp', id);
if(h != NULL){
p = MemHandleLock(h);
WinDrawBitmap((BitmapPtr)p, x, y);
MemHandleUnlock(h);
DmReleaseResource(h);
}
}/********************************
Start
********************************/static void StartApplication(void)
{
FormPtr frm;
FieldPtr opPtr;
frm = FrmInitForm(1000);
FrmSetActiveForm(frm);
FrmDrawForm(frm);
drawBitmap(5, 20, 7000);
Page=0;
}
まず、#define MaxPage 10 のすぐ下に
#define ON 1
#define OFF 0を記述します。この #define は便利です。これの意味はプログラム中に ON が出てきたら数字の1に、OFF が出てきたら数字の 0 に置き換えをします。define をうまく使う事で見やすいプログラムを書く事ができます。
次に音を鳴らすか鳴らさないかの情報を持った変数をひとつ定義します。
Int Page; のすぐ下にInt SoundSW;
を記述します。この時に気を付けなければいけないのは define には ; が付きませんが Int SoundSW の最後には ; が付きますので間違えないように注意してください。
つぎに StartApplocation の修正です。この StartApplocation はプログラムがスタートする時に一回だけ実行されます。従って、変数の初期化が必要な場合にはこの関数の中で実行します。
SoundSW も初期化が必要です。最初にプログラムを立ち上げた状態(デフォルト)では、Sound は ON になっているとするとSoundSW=ON;
と記述します。ここで最初に定義した #define が活用されます。状態が一目で理解できます。この SoundSW=ON; は StartApplocation の Page=0; の後ろに入れるといいでしょう。
ここまでの変更をした Cのソースを以下に示します。
/******************************
Picture Book program
TAB = 4
Shigeyuki Seko
12/6/1999
******************************/#include <Pilot.h>
#define MaxPage 10
#define ON 1
#define OFF 0Int Page;
Int SoundSW;static void drawBitmap(Int x, Int y, Int id)
{
VoidHand h;
VoidPtr p;
h = DmGet1Resource('Tbmp', id);
if(h != NULL){
p = MemHandleLock(h);
WinDrawBitmap((BitmapPtr)p, x, y);
MemHandleUnlock(h);
DmReleaseResource(h);
}
}/********************************
Start
********************************/static void StartApplication(void)
{
FormPtr frm;
FieldPtr opPtr;
frm = FrmInitForm(1000);
FrmSetActiveForm(frm);
FrmDrawForm(frm);
drawBitmap(5, 20, 7000);
Page=0;
SoundSW=ON;
}さて、次に実際の SoundSW の状態に応じて音を出したり止めたりする部分を作ります。
前章で作成した SndOutput の関数を変更します。void SndOutput (long freq,int time,int Laud)
{SndCommandType s;
s.cmd = sndCmdFreqDurationAmp;
s.param1 = freq; /* freq (Hz) */
s.param2 = time; /* time (ms) */
s.param3 = Laud; /* Laud */
SndDoCmd(0,&s,true);}
実際に音を出しているのは SndDoCmd(0,&s,true); ですので、SoundSW が ON の場合のみこの関数を実行するように小細工すればいい事が解ります。実際には if 文を使用します。if 文は与えられた条件が正しい場合のみ後に続く関数を実行する命令です。
void SndOutput (long freq,int time,int Laud)
{SndCommandType s;
s.cmd = sndCmdFreqDurationAmp;
s.param1 = freq; /* freq (Hz) */
s.param2 = time; /* time (ms) */
s.param3 = Laud; /* Laud */
if (SoundSW==ON) SndDoCmd(0,&s,true);}
これで OK です。SoundSW が ON の場合のみ SndDoCmd を実行します。
ここで、SoundSW==ON と=が2つ書かれていますが、これは代入の = と比較の = を明確に区別するためのルールです。さて、最後にメニューに関するプログラムです。(もうひと息、がんばって!)
メニューは前章で説明したハードウェアーキーと同じ MainFormHandleEvent で記述されます。
以下に示すリストの太字の部分です。
/********************************
Event Loop
********************************/static Boolean MainFormHandleEvent(EventPtr event)
{
Boolean handled = false;
Err error;
FormPtr frm;if(event->eType == ctlSelectEvent){
if(event->data.ctlEnter.controlID == 5000){ /* Go Start Page */
Page=1;
drawBitmap(14, 25, 7000+Page);
}
else if(event->data.ctlEnter.controlID == 5001){ /* Back */
PageDown();
}
else if(event->data.ctlEnter.controlID == 5002){ /* Next */
PageUp();
}
}
else if(event->eType == keyDownEvent){
if (event->data.keyDown.chr == pageUpChr){ /* Scroll up key presed */
PageUp();
handled = true;
}
else if (event->data.keyDown.chr == pageDownChr){ /* Scroll down key presed */
PageDown();
handled = true;
}
}
else if (event->eType == menuEvent){ /* Menu event */
switch (event->data.menu.itemID){
case 3601: /* about */
frm = FrmInitForm(3000);
FrmDoDialog(frm);
FrmDeleteForm(frm);
break;
case 3602: /* Go Start Page */
Page=1;
drawBitmap(14, 25, 7000+Page);
break;
case 3603: /* Back */
PageDown();
break;
case 3604: /* Next */
PageUp();
break;
}
handled = true;
}
else if(event->eType == nilEvent){
handled = true;
}
return handled;
}ここに、新しい Sound に関するメニューを追加します。
case 3602, case 3603, case 3604 はそれぞれプルダウンメニューのMENUITEM の ID 番号です。
この ID 番号はリソースファイルの中でメニューの項目で定義した ID 番号を使用します。
今回 Sound ON には 3605, Sound OFF には 3606 の ID 番号を設定しましたので以下のようになります。case 3605: /* Sound ON */
SoundSW=ON;
break;
case 3606: /* Sound OFF */
SoundSW=OFF;
break;従って、実際の C プログラムのMainFormHandleEventの部分は以下のようになります。
/********************************
Event Loop
********************************/static Boolean MainFormHandleEvent(EventPtr event)
{
Boolean handled = false;
Err error;
FormPtr frm;if(event->eType == ctlSelectEvent){
if(event->data.ctlEnter.controlID == 5000){ /* Go Start Page */
Page=1;
drawBitmap(14, 25, 7000+Page);
}
else if(event->data.ctlEnter.controlID == 5001){ /* Back */
PageDown();
}
else if(event->data.ctlEnter.controlID == 5002){ /* Next */
PageUp();
}
}
else if(event->eType == keyDownEvent){
if (event->data.keyDown.chr == pageUpChr){ /* Scroll up key presed */
PageUp();
handled = true;
}
else if (event->data.keyDown.chr == pageDownChr){ /* Scroll down key presed */
PageDown();
handled = true;
}
}
else if (event->eType == menuEvent){ /* Menu event */
switch (event->data.menu.itemID){
case 3601: /* about */
frm = FrmInitForm(3000);
FrmDoDialog(frm);
FrmDeleteForm(frm);
break;
case 3602: /* Go Start Page */
Page=1;
drawBitmap(14, 25, 7000+Page);
break;
case 3603: /* Back */
PageDown();
break;
case 3604: /* Next */
PageUp();
break;
case 3605: /* Sound ON */
SoundSW=ON;
break;
case 3606: /* Sound OFF */
SoundSW=OFF;
break;
}
handled = true;
}
else if(event->eType == nilEvent){
handled = true;
}
return handled;
}
さぁ、コンパイルして実行させてみてください。
メニューに以下のように新しいプルダウンメニューが追加され、音を出したり止めたりできるはずです。