0

クラスがあります

クラスCCfgUserPage:public CPropertyPage

チェックボックスからテキスト領域まで、さまざまなコントロールも所有しています。各コントロールにツールチップを追加したいのですが、問題があるようです。

CCfgUserPageで、これをメッセージマップに追加しました

ON_NOTIFY_EX(TTN_NEEDTEXT、0、OnToolTipText)

このオブジェクトがそのメッセージをキャッチすると、次のような関数OnToolTipTextを呼び出します。

BOOL CCfgUserPage::OnToolTipText( UINT id, NMHDR * pNMHDR, LRESULT * pResult )
{
    TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;
    UINT nID = pNMHDR->idFrom;
    CString ttStr;

    int partOrient = GetDlgItem(IDC_PARTORIENT_CHECK)->GetDlgCtrlID();

    if (pTTT->uFlags & TTF_IDISHWND)
    {
        // idFrom is actually the HWND of the tool
        nID = ::GetDlgCtrlID((HWND)nID);
        if( nID == partOrient ) // Only Display TT for The buttons with these ID's
        {
            if( nID == partOrient )
                ttStr = "Part Orient";
            pTTT->lpszText = (LPTSTR)(LPCTSTR)ttStr;
            pTTT->hinst = AfxGetResourceHandle();
            return TRUE;
        }
    }
    return FALSE;
}

でツールのヒントも有効にしました

CCfgUserPage :: OnInitDialog

OnToolTipTextがTRUEを返すたびに、アプリケーションがクラッシュし、通知します

アクセス違反の読み取り場所

私はスタックフレームを通過しようとしていますが、何が問題になっているのかを理解するには、MFCに深く入り込んでいます。これが起こる原因となる何が欠けている可能性がありますか?

4

2 に答える 2

2

MSDNにあるヒントをご覧ください。

TTN_NEEDTEXT通知メッセージを処理するときは、次のいずれかの方法で表示する文字列を指定します。

  • szTextメンバーによって指定されたバッファーにテキストをコピーします。
  • テキストを含むバッファーのアドレスをlpszTextメンバーにコピーします。
  • 文字列リソースの識別子をlpszTextメンバーにコピーし、リソースを含むインスタンスのハンドルをhinstメンバーにコピーします。

したがって、実行する代わりに:

        CString ttStr;
        // ...
        if( nID == partOrient )
            ttStr = "Part Orient";
        // Below is the unsafe part: you initialize lpszText with something
        //       expected to be valid after you return from the handler
        //       effectively, this is internal buffer of local ttStr valriable
        //       which is to be freed and lpszText would keep point to undefined
        //       memory
        pTTT->lpszText = (LPTSTR)(LPCTSTR)ttStr;
        pTTT->hinst = AfxGetResourceHandle();

あなたはむしろ:

        if(nID == partOrient)
        {
            // NOTE: Here instead you don't create any dynamic instances (strings)
            //       and the value resides directly in the notification structure
            _tcsncpy_s(pTTT->szText, _T("Part Orient"), _TRUNCATE);
            pTTT->lpszText = pTTT->szText; // Just a safety, it's already pointing there
        }
于 2013-03-25T15:48:08.747 に答える
0

問題は、関数の最後でttStrがスコープ外になり、そのポインターへのポインターを返すことです。ポインターが無効になり、ポインターを参照しようとするとアプリがクラッシュします。

ツールチップが常に小さい(80文字未満)場合は、提供されているバッファーを使用するか、メンバー変数を使用してツールチップのテキストを格納します。

于 2015-03-21T16:32:15.200 に答える