none
ダイアログ上にバルーンを出す方法 RRS feed

  • 質問

  • ダイアログ上のコントロールの位置にバルーンを表示させるための機能を調査していて、
    ネット上の例などを元に、以下のルーチンを試作しています。
    VS2017のMFCのダイアログベースで試作していますが、Win32APIレベルのものです。

    これでボタンを押すと、その下にバルーンが表示されました。
    バルーンが出た後の動作はまだ考慮していません。

    void CTestDlg::OnBnClickedButton1()
    {
    DWORD dwStyle = WS_POPUP | WS_VISIBLE | TTS_ALWAYSTIP | TTS_NOPREFIX | TTS_CLOSE | TTS_NOFADE | TTS_NOANIMATE | TTS_BALLOON;
    HWND hWndBalloon = CreateWindowEx(0, TOOLTIPS_CLASS, 0, dwStyle, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, m_hWnd, 0, 0, 0);

    TOOLINFO ti;
    ZeroMemory(&ti, sizeof(ti));
    ti.cbSize = sizeof(ti);
    ti.uFlags = TTF_TRACK | TTF_CENTERTIP;
    ti.hwnd = m_hWnd;
    ti.lpszText = _T("バルーンテスト");

    CRect rect;
    GetDlgItem(IDC_BUTTON1)->GetWindowRect(&rect);
    CPoint point = rect.CenterPoint();

    ::SendMessage(hWndBalloon, TTM_SETMAXTIPWIDTH, 0, 32000);
    ::SendMessage(hWndBalloon, TTM_SETDELAYTIME, TTDT_AUTOPOP, MAKELONG(1, 0));
    ::SendMessage(hWndBalloon, TTM_SETDELAYTIME, TTDT_INITIAL, MAKELONG(1, 0));
    ::SendMessage(hWndBalloon, TTM_SETDELAYTIME, TTDT_RESHOW,  MAKELONG(1, 0));
    ::SendMessage(hWndBalloon, TTM_ADDTOOL, 0, (LPARAM)&ti);
    ::SendMessage(hWndBalloon, TTM_SETTITLE, 0, (LPARAM)_T("タイトル"));
    ::SendMessage(hWndBalloon, TTM_TRACKPOSITION, 0, MAKELONG(point.x, point.y));
    ::SendMessage(hWndBalloon, TTM_TRACKACTIVATE, (WPARAM)TRUE, (LPARAM)&ti);
    }

    しかし、ボタンが画面下ギリギリのところになるようにダイアログを移動させ、
    その状態でボタンを押すと、バルーンはダイアログの上部に表示されてしまいます。

    同じ位置のまま、吹き出しだけ上向きになることを期待していたのですが、
    パラメータの設定などが誤っていますでしょうか。

    よろしくお願いいたします。

    2022年8月24日 3:32

回答

  • ではTTF_CETNERTIPを抜いて

    ZeroMemory(&ti, sizeof(ti));
    ti.cbSize = sizeof(ti);
    ti.uFlags = TTF_TRACK;
    ti.hwnd = this->m_hWnd;
    ti.lpszText = _T("バルーンテスト");

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク nobuo_h 2022年8月25日 0:36
    2022年8月24日 4:30
  • TTF_CENTERTIPの挙動について確認しましたが、バルーンの表示位置は対象のコントロールの中央下部を指定します(参考)。コントロールが画面下部にあり、コントロールの中央下部にバルーンを表示する際画面外に出てしまう場合は、指定したコントロールの上部中央(ti.hwndでダイアログを指定した場合はダイアログのクライアント領域の上部中央)にバルーンの表示位置を自動的に移動する仕様のようです。自動的に移動させたくない場合は、ti.uFlagsにTTF_CENTERTIPとあわせてTTF_ABSOLUTEフラグを追加すると自動的に移動されなくなるようです。ただし、このフラグを使用すると表示位置によってバルーンが画面外に隠れてしまう場合があるため、ユーザビリティ的にTTF_CETNERTIPを使わない手法もありだと思います。
    • 編集済み kenjinoteMVP 2022年8月24日 9:55 日本語修正
    • 回答としてマーク nobuo_h 2022年8月25日 0:36
    2022年8月24日 9:40

すべての返信

  • バルーンの対象となるWindowの指定をボタンコントロールにしてみるのは?

    TOOLINFO ti;
    ZeroMemory(&ti, sizeof(ti));
    ti.cbSize = sizeof(ti);
    ti.uFlags = TTF_TRACK | TTF_CENTERTIP;
    ti.hwnd = GetDlgItem(IDC_BUTTON1)->m_hWnd; //ボタンのHWND
    ti.lpszText = _T("バルーンテスト");


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    2022年8月24日 3:54
  • バルーンの対象となるWindowの指定をボタンコントロールにしてみるのは?

    解説ありがとうございます。
    ボタンの上部には表示されましたが、下向きのときのような中央の位置ではないようです。

    ちなみに、TOOLINFOのhwndにダイアログのHWNDを渡したときには、
    こんな変な動きになるのが標準動作なのでしょうか。

    ダイアログ上の任意の位置を指定したいケースもあるので、
    ダイアログのHWNDを渡すようにしておきたいところですが。


    2022年8月24日 4:14
  • ではTTF_CETNERTIPを抜いて

    ZeroMemory(&ti, sizeof(ti));
    ti.cbSize = sizeof(ti);
    ti.uFlags = TTF_TRACK;
    ti.hwnd = this->m_hWnd;
    ti.lpszText = _T("バルーンテスト");

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク nobuo_h 2022年8月25日 0:36
    2022年8月24日 4:30
  • 解説ありがとうございます。
    TTF_CETNERTIPを消してみたところ、吹き出しの角度が微妙に変わりましたが、
    ダイアログのHWNDを使っても、期待した位置に表示されました。

    TTF_CENTERTIPを付けて画面下部に出したときの動作がバグにしか見えないのですが、
    そういうものだと諦めてTTF_CETNERTIPなしを使っていくべきでしょうかね。

    ・画面中央(TTF_CENTERTIPあり)

    画面中央(TTF_CENTERTIPあり)

    ・画面下部(TTF_CENTERTIPあり)

    画面下部(TTF_CENTERTIPあり)

    ・画面中央(TTF_CENTERTIPなし)

    画面中央(TTF_CENTERTIPなし)

    ・画面下部(TTF_CENTERTIPなし)

    画面下部(TTF_CENTERTIPなし)

    2022年8月24日 5:13
  • TTF_CENTERTIPの挙動について確認しましたが、バルーンの表示位置は対象のコントロールの中央下部を指定します(参考)。コントロールが画面下部にあり、コントロールの中央下部にバルーンを表示する際画面外に出てしまう場合は、指定したコントロールの上部中央(ti.hwndでダイアログを指定した場合はダイアログのクライアント領域の上部中央)にバルーンの表示位置を自動的に移動する仕様のようです。自動的に移動させたくない場合は、ti.uFlagsにTTF_CENTERTIPとあわせてTTF_ABSOLUTEフラグを追加すると自動的に移動されなくなるようです。ただし、このフラグを使用すると表示位置によってバルーンが画面外に隠れてしまう場合があるため、ユーザビリティ的にTTF_CETNERTIPを使わない手法もありだと思います。
    • 編集済み kenjinoteMVP 2022年8月24日 9:55 日本語修正
    • 回答としてマーク nobuo_h 2022年8月25日 0:36
    2022年8月24日 9:40
  • 解説ありがとうございます。

    TTF_CENTERTIPを使うときは子ウィンドウの下辺を指定しているはずだ、
    という前提で、勝手にti.hwndの上辺に移動してしまうということなのですね。

    となると、任意の位置にバルーンを出したいときは、
    TTF_CENTERTIPは使ってはいけないということになりそうです。

    TTF_ABSOLUTEを使うと確かに移動しませんでしたが、
    向きは下方向のままで、画面から見えなくなってしまいました。

    2022年8月25日 0:35