2

ON_UPDATE_COMMAND_UIVisual Studio では、アイドル状態中に送信される MFC CToolBar ボタンが更新されます。ON_UPDATE_COMMAND_UIハンドラーでボタンの有効/無効状態を変更すると、このメカニズムにバグがあると思います。

具体的には:

ボタンが有効な状態になったとします。ある時点で、コードはボタンを無効にすることを「望んでいます」(もちろん、ユーザーがクリックするべきではありません)が、次の図に示すように、ボタンは次のアイドル期間で実際に無効になります。

ここに画像の説明を入力

図の赤い部分は、私の意見ではコードの状態が不安定であり、開発者はボタンの状態を手動で確認して、この不安定な状態を処理する必要があります。何かを見逃したのか、このメカニズムを誤解しているのかわかりませんか?

PS: メニューの手順はOKです。常にハンドラーを呼び出しON_UPDATE_COMMAND_UI、ハンドラーの前にボタンの状態を確認しますON_COMMAND

私の質問は、メニューと同じようにハンドラーのON_UPDATE_COMMAND_UI前にハンドラーを呼び出す方法です。ON_COMMAND

4

2 に答える 2

0

デバッグとトレースの後、最終的に可能な解決策を見つけました。キーコードは、同じ問題を抱えている他の人を助けるためにここにリストされています. 次のように OnCommand をオーバーライドします。

BOOL CMainDlg::OnCommand(WPARAM wParam, LPARAM lParam)
{
    // Disable WM_COMMAND reflection for ToolBar control
    // makes the ON_UPDATE_COMMAND_UI handler be called 
    // right before ON_COMMAND handler.

    if ((HWND)lParam == m_wndToolBar.GetSafeHwnd())
        lParam = NULL;

    return CDialog::OnCommand(wParam, lParam);
}

副作用WM_COMMANDとして、ツールバーのリフレクションが無効になりますが、ほとんどの場合は問題ありません。

于 2016-05-25T08:35:13.110 に答える
0

これに遭遇したので、ソリューションを追加すると思いました。レコードをデータベースに貼り付けるボタンがあるので、クライアントにとっては明らかです。クリップボードに有効なデータがある場合にのみボタンを有効にしたかったのです。これは次のようになります。

ここに画像の説明を入力

レコードが選択された、背面の My App と前面の notepad++。Notepad++ のテキストを「ctrl C」すると、アプリがアイドル状態であっても、ツールバーの「I」がアクティブになります。私のアプリはクリップボード チェーンの一部であり、通知を受け取ります。これは WM_DRAWCLIPBOARD ハンドラです。

LRESULT CMainFrame::OnDrawClipboard(  WPARAM wparam, LPARAM lparam  )
{
    if( hWndClipboardChain )
        ::SendMessage( hWndClipboardChain, WM_DRAWCLIPBOARD, wparam, lparam );

    if( wparam )
        PostMessage( ID_CLIPBOARD_HASCHANGED, 0, 0 );

    return TRUE;
}

そこから、WM_DRAWCLIPBOARD メッセージの邪魔にならないようにアプリに投稿します。

LRESULT CMainFrame::OnCheckClipboard(  WPARAM wparam, LPARAM lparam  )
{
    std::string data( GetClipboardStr( ) );
    std::string::size_type end_cnt= data.find( "\r\n" );
    if( end_cnt == std::string::npos )
        bClipboardHasValidRecords= false;
    else
    {
        auto header_end= data.begin( ) + end_cnt;
        csv_vect_t header;
        split( header, str_it_range_t( data.begin( ), header_end ), boost::is_any_of("\t") );

        bClipboardHasValidRecords= header.size( ) == RARECORD_SIZE;
    }
    return TRUE;
}

私のアプリのメインスレッドはメッセージによって起動され、「私」はアプリをアクティブウィンドウにせずにオンとオフを切り替えます。そして、それは追加のコードなしで起こります。

于 2016-06-18T21:02:04.813 に答える