2 votes

Bug du mécanisme de mise à jour de la CToolBar MFC ?

Dans Visual Studio, les boutons de la barre d'outils MFC sont mis à jour par ON_UPDATE_COMMAND_UI qui est envoyé pendant la période d'inactivité. Je suppose que ce mécanisme est bogué si je change l'état d'activation/désactivation du bouton en ON_UPDATE_COMMAND_UI gestionnaire.

En particulier :

Supposons que le bouton soit maintenant activé. À un certain moment, le code "veut" que le bouton soit désactivé (et ne doit évidemment pas être cliqué par l'utilisateur), mais le bouton sera réellement désactivé à la prochaine période d'inactivité, comme le montre la figure suivante :

enter image description here

Dans la zone rouge de la figure, l'état du code est, à mon avis, instable et le développeur doit gérer cet état instable en vérifiant manuellement l'état du bouton. Je ne sais pas si j'ai manqué quelque chose ou si j'ai mal compris ce mécanisme ?

PS : La procédure pour le menu est correcte. Elle appelle toujours ON_UPDATE_COMMAND_UI et vérifie l'état du bouton avant que ON_COMMAND gestionnaire.

Ma question est de savoir comment faire pour que le ON_UPDATE_COMMAND_UI soit appelé avant que ON_COMMAND comme le font les Menus ?

0voto

guan boshen Points 124

Après avoir débogué et tracé, j'ai finalement trouvé une solution possible. Les codes clés sont listés ici pour aider ceux qui ont le même problème. Remplacez OnCommand comme suit :

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);
}

L'effet secondaire est WM_COMMAND La réflexion est désactivée pour la barre d'outils, mais cela ne pose pas de problème dans la plupart des cas.

0voto

lakeweb Points 900

Comme je viens de rencontrer ce problème, j'ai pensé ajouter ma solution. J'ai un bouton pour coller des enregistrements dans une base de données et pour que ce soit clair pour le client, je voulais seulement que le bouton soit activé s'il y a des données valides sur le presse-papiers. Voici à quoi cela ressemble :

enter image description here

Mon application à l'arrière et notepad++ à l'avant avec les enregistrements sélectionnés. Lorsque je "ctrl C" le texte dans notepad++ le "I" sur ma barre d'outils devient actif même si mon application est inactive. Mon application fait partie de la chaîne du presse-papiers et en est informée. Il s'agit du gestionnaire 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;
}

A partir de là, je postule que mon application ne se met pas en travers du message WM_DRAWCLIPBOARD, et c'est là que ça se passe :

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;
}

Le fil principal de mon application est réveillé par les messages et le "je" s'allume et s'éteint sans que l'application soit une fenêtre active. Et cela se passe sans aucun code supplémentaire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X