Share via


Commands between WPF and MFC

When we created the WPF commanding system, we spent a lot of time looking at MFC.  So it's not surprising that the two models integrate pretty well.  One of the interesting parts of MFC is command routing -- the application as a whole has notions of commands it wants to handle, but so do MDI child frames and views -- for each command, MFC asks each of those in turn whether they would like to handle the command.  WPF takes this one step further -- every element and every control can have commands!  And WPF controls have built-in knowledge of many common commands -- e.g., TextBox understands cut/copy/paste.  So if we put some WPF content inside a larger MFC application (using HwndSource), getting the MFC cut menu and toolbar connected to the WPF TextBox is pretty straightforward:

BEGIN_MESSAGE_MAP(CWpfDetailsView, CView)
    ON_COMMAND(ID_EDIT_CUT, &CWpfDetailsView::OnEditCut)
    ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, &CWpfDetailsView::OnUpdateEditCut)
END_MESSAGE_MAP()

void CWpfDetailsView::OnEditCut() {
    UICommand^ command = ApplicationCommands::Cut;
    UIElement^ target = (UIElement^) Keyboard::FocusedElement;
    if (target != nullptr && command->QueryEnabled(target))
        command->Execute(target, nullptr);
}

void CWpfDetailsView::OnUpdateEditCut(CCmdUI* ui) {
    UICommand^ command = ApplicationCommands::Cut;
    UIElement^ target = (UIElement^) Keyboard::FocusedElement;
    BOOL enabled = (target != nullptr && command->QueryEnabled(target));
    ui->Enable(enabled);
}

Because each WPF elements has a notion of commands, we don't need to point the menu at any specific text box -- we just fire the command on whatever WPF element has focus!  And if the focused element isn't a text box, and doesn't know anything about the cut command, that command is disabled.

The WPF equivalent of MFC's OnUpdateXXX is QueryEnabled.  And like MFC, it can be more than just a boolean (enabled/disabled) -- you can change command text or any other arbitrary command property (including defining your own custom properties to query for).