長押しの実現

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
kazuoni

長押しの実現

#1

投稿記事 by kazuoni » 16年前

お邪魔します。
題名の通り、ボタン長押しの実現をどうするのが一番よいかというのが質問です。

例としては携帯電話のメールの文削除の時を思い浮かべてもらうのがわかりやすいです。
あるキーを押すと関数Aを実行するのですが(携帯のメールでいう一文字削除)
そのキーを押し続けると関数Bを実行する(携帯のメールでいう全文削除)

というのを実装したいのですが、
以下の二つが思いつきました。

1、while内でカウンターが作動し続ける
while(ボタン押し続けられている間)
{
  if(i>=ある整数)
  {
	B();
	break;
    }
  ++i;
}
A();
2、timeを取り、減算
time1=time(NULL);
while(1)
  if(ボタンが離されたら)
  break;
time2=time(NULL);
if(difftime(time2,time1)>=ある時間)
  B();
else
  A();
1で実行したところ、iがものすごい大きい数になりました。
長押しをしたつもりでなくてもiは大きかったです。
これはちょっと危険な感じがしたので2を作りました。
(1では関数Bの後に関数A()に入っていますが、気にしないでください。)

2はうまく実行できているのですが
あまりtime自体使ったことがないので
2が効率がいいのかどうなのかよくわかりません。
もっと良い書き方はあるのでしょうか?
timeを使わないとか・・・。(かつ安全)

初歩的な質問で申し訳ありません。
よろしくお願いします。

tk-xleader

Re:長押しの実現

#2

投稿記事 by tk-xleader » 16年前

2が問題あるとは思いません。標準の関数で組むのならば、それでいいと思います。
もしくはclock()関数を使うとか…

kazuoni

Re:長押しの実現

#3

投稿記事 by kazuoni » 16年前

申し訳ありません。
DXライブラリを使用を前提としていました。。
1、でiが大きいということですが、
例えば2秒押し続けたら関数Bを実行するとなると
i>=6000000
ぐらいでした。

・・・これって思いっきり処理系依存ですよね^^;
・・・1はなかったことにしてください^^;

kazuoni

Re:長押しの実現

#4

投稿記事 by kazuoni » 16年前

tkさんご回答ありがとうございます。

問題なさそうなら2を使用していきます^^

Justy

Re:長押しの実現

#5

投稿記事 by Justy » 16年前


>もっと良い書き方はあるのでしょうか?

 どういう環境で何を押していて、どういうプログラムの中でそれをしようとしているのかなど
状況がよくわからないので、どちらがいいということは言えません。
 ひょっとしたら別の第3、第4の方がいいこともあります。

 押した長さがX秒とかX分とかで判定する必要があるなら、2です。

 でもそうでなくある程度長く押されていたら、というなら1になります。
 
 ただ仰るように1の場合はこのままでは凄い勢いで iが
カウントされていくていくので適当に1秒間に15~60回くらい間隔で
ボタンの押下状況をチェックするように調整する必要がありますし、
2の方はボタンを離さないと Aや Bが実行されないので、携帯電話とは挙動が
異なります。

 ただどちらにしても、1も2も今のような構造ですと、ボタンの押下チェック以外の
処理がしづらいような気がしますが・・・。


 私が書くなら、以下のような関数を作って、それを定期的に(適度な回数)呼びます。
 
[color=#d0d0ff" face="monospace]
void XXXXXXXXXXXXXXXXXXX(Work *work)
{
    // まだ押されていなくて、
    if(!work->keyOnA)
    {
        // Aボタンが押された瞬間(前回は押されていない)ならフラグを立てる
        if(PressKey(BUTTON_A))
        {
            work->keyOnA = true;
            work->keyOnACount = 0;
        }
    }
    else
    {
        // Aボタンが離された瞬間(前回は押されていた)ならフラグを解除
        if(!ReleaseKey(BUTTON_A))
            work->keyOnA = false;
        
        // カウントが小さい状態でキーが離されたのならAを実行
        // 一定時間押しっぱなしにしていたら Bを実行
        if(work->keyOnACount < LIMIT_COUNT)  // 短
        {
            if(!work->keyOnA)
            {
                A();
                work->keyOnA = false;
            }
        }
        else                                 // 長
        {
            B();
            work->keyOnA = false;
        }
    ]
}[/color]
 work->keyOnACountは普通に ++しているだけなので、kazuoniさんのいう「1」ですが
秒やミリ秒単位で見る必要があれば、「2」の方の timeだったり
ハードウェアが持つ高精度タイマーの値にします。

kazuoni

Re:長押しの実現

#6

投稿記事 by kazuoni » 16年前

Justyさんご回答ありがとうございます。
詳細を記入せず、分かりづらい質問で大変申し訳ありませんでした。
せっかく作っていただいたのですが
C言語+DXライブラリ
のみの知識しかないので注釈中心に参考にさせていただきました。

実際は時間は全く関係なく、「ある程度長く押されたら」です。
今回の長押しはサブルーチン化はしておらず、mainに直接書いています。
キー監査はGetHitKeyStateAll_2で行っています。
( 参考:http://l.huu.cc/g/#40 )

Justyさんの作られた関数XXXXXXXXXXXXXXXXXXXは
管理人さんの作られた関数GetHitKeyStateAll_2
に似ていると解釈しました。(違っていたら申し訳ありません。。)

なので以下のようにしてみました。
if(Key[ボタン番号]==1 || flag==1)
{

   flag=1;
   if(Key[ボタン番号]>=100)
   {
	B();
	flag=0;
   }
   else if(Key[ボタン番号]==0)
   {
	A();
	flag=0;
   }
}
初期条件でflag=0です。
こうすると携帯電話のメールの文字削除ようなことはできました。
直線的な書き方しかできなくてこれが限界でした。。

閉鎖

“C言語何でも質問掲示板” へ戻る