Kam-nagi Software

 

 
adoliBeDITORIAL

1999/5/13 「BPopUpMenuを開く」

 じつはこれって、やり方きっちりマニュアルに書いてあるんすけどね…。いやでも木坂さんも同じ場所ではまってたって言うし、勘違いしやすいとこなんじゃないかな。うん。
 まず最初に、ゆんが間違って書いたコードをお見せしましょう。

// menu は有効な BPopUpMenu* 型

void
MyView::MessageReceived(BMessage *msg)
{
  switch (msg->what)
    {
    case B_MOUSE_DOWN:
      .....
      // マウスカーソルの位置をスクリーン座標で取得
      BPoint point;
      point = msg->FindPoint("where");
      this->ConvertToScreen(&point);

      // カーソルからオフセット(-1, -1)の位置を指定
      point.x --;
      point.y --;

      // ポップアプメニューを開く
      menu->Go(point, true, false);
      break;
    }
}


 たしかにこのコードで、メニューは開きっぱなしにはなるのですが、なんだか動作が不審です。メニューを開いた位置からマウスを動かさずにボタンを離すと、メニューの最上段のアイテムが有無を言わさず選択されてしまいます。ポップアップメニューをマウスの位置までずらして表示しているのだから当然と言えば当然ですが、なんとも納得のいかない話です。
 まあ、納得のいかないのも当たり前、関数の解釈がばっちり間違っていたのですから。

BMenuItem *BPopUpMenu::Go(BPoint screenPoint,
                          bool deliversMessage = false,
                          bool openAnyway = false,
                          bool asynchrounous = false);

BMenuItem *BPopUpMenu::Go(BPoint screenPoint,
                          bool deliversMessage = false,
                          bool openAnyway = false,
                          BRect clickToOpenRect,
                          bool asynchrounous = false);


 この関数、デフォルトの動作では、ユーザーがマウスをドラッグしている間だけポップアップメニューを表示し、離すと同時にメニューが消去されるようになっています。 メニューを表示しっぱなしにさせる動作に関連するのはopenAnyway引数とclickToOpenRect引数なのですが、ポイントは、オペレーションによって指定の仕方が異なるという事。ショートカットキーの操作によってメニューをポップアップする場合と、マウスボタンを押す事でメニューをポップアップする場合とで引数の与え方が変わるのです。ゆんはここで混乱していたのでした。

// menu は有効な BPopUpMenu* 型

void
MyView::MessageReceived(BMessage *msg)
{
  switch (msg->what)
    {
    case B_KEY_DOWN:
      .....
      // マウスカーソルの位置をスクリーン座標で取得
      BPoint point;
      uint32 buttons;
      this->GetMouse(&point, &buttons);
      this->ConvertToScreen(&point);

      // ポップアプメニューを開く
      menu->Go(point, true, true);
      break;
    }
}


 キー操作などによってポップアップメニューを開く場合は、openAnywayフラグをtrueに指定します。すると無事、メニューは開きっぱなしになります。これを忘れると、メニューが表示された瞬間また閉じるという間抜けな目に合います。

// menu は有効な BPopUpMenu* 型

void
MyView::MessageReceived(BMessage *msg)
{
  switch (msg->what)
    {
    case B_MOUSE_DOWN:
      .....
      // マウスカーソルの位置をスクリーン座標で取得
      BPoint point;
      point = msg->FindPoint("where");
      this->ConvertToScreen(&point);

      // カーソルの周囲10x10ドットの領域を指定
      BRect rect(point.x - 5, point.y - 5,
                 point.x + 5, point.y + 5);

      // ポップアプメニューを開く
      menu->Go(point, true, false, rect);
      break;
    }
}


 マウスの押下によって開いたポップアップメニューを開きっぱなしにするには、clickToOpenRectを指定します。ポップアップメニューを開いた後、clickToOpenRectの内側でマウスボタンを離すと、それはメニューのオープン動作と解釈されメニューが開きっぱなしになります。
 これでもうポップアップメニューは開き放題、だらしなく開きまくりましょう
 

 

yun@be-in.org