MFC: общение с помощью View from Dialog - PullRequest
2 голосов
/ 01 октября 2019

Я хочу, чтобы мой Диалог связывался с моим существующим представлением вне ответа OK (таким образом, используя заявку или подобное). Я предполагаю, что сообщения - лучший способ сделать это.

Я уверен, что в наши дни не так много вопросов о MFC, поэтому я надеюсь, что кто-то сможет помочь.

Создание новогоПроект через мастера, я добавляю диалог (скажем, CPropertySheet), который создается в представлении.

MyPropertiesSheet ps(_T("MyPropertiesSheet"));

if (ps.DoModal() == IDOK) {
    // I don't care about this section
}

Сначала я предполагал, что когда я нажму «применить», я смогу отправить сообщение в представление и заставить его что-то сделать (как оно было создано в представлении);однако я не могу передавать сообщения непосредственно в представление.

Из диалогового окна, которое я использую:

GetParent()->SendMessage(WM_BUTTON1, 0, 0);

Я могу перехватить сообщение в моем MainFrm (CmainFrame), который запустит указанную Button1(), но я не могу поймать сообщение в представлении, используя тот же код (ниже).

BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWndEx)
    ...
    ON_MESSAGE(WM_BUTTON1, Button1)
END_MESSAGE_MAP()

Это имеет смысл, так как я предполагаю, что View является дочерним элементом MainFrm, а Dialog принадлежит кMainFrm, а не View.

My Программирование Windows с помощью MFC (2nd ed), автор Jeff Prosise, использует пользовательский OnCreate для получения ссылки на View, создав его вручную, но яна самом деле не хочу этого делать, так как это кажется довольно сложным. Я уверен, что таким образом я создам много проблем. По умолчанию OnCreate, похоже, не имеет очевидной ссылки на мое представление (включенное, например, но не стесняйтесь пропускать это).

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CMDIFrameWndEx::OnCreate(lpCreateStruct) == -1)
        return -1;

    BOOL bNameValid;

    CMDITabInfo mdiTabParams;
    mdiTabParams.m_style = CMFCTabCtrl::STYLE_3D_ONENOTE; // other styles available...
    mdiTabParams.m_bActiveTabCloseButton = TRUE;      // set to FALSE to place close button at right of tab area
    mdiTabParams.m_bTabIcons = FALSE;    // set to TRUE to enable document icons on MDI taba
    mdiTabParams.m_bAutoColor = TRUE;    // set to FALSE to disable auto-coloring of MDI tabs
    mdiTabParams.m_bDocumentMenu = TRUE; // enable the document menu at the right edge of the tab area
    EnableMDITabbedGroups(TRUE, mdiTabParams);

    if (!m_wndMenuBar.Create(this))
    {
        TRACE0("Failed to create menubar\n");
        return -1;      // fail to create
    }

    m_wndMenuBar.SetPaneStyle(m_wndMenuBar.GetPaneStyle() | CBRS_SIZE_DYNAMIC | CBRS_TOOLTIPS | CBRS_FLYBY);

    // prevent the menu bar from taking the focus on activation
    CMFCPopupMenu::SetForceMenuFocus(FALSE);

    if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
        !m_wndToolBar.LoadToolBar(theApp.m_bHiColorIcons ? IDR_MAINFRAME_256 : IDR_MAINFRAME))
    {
        TRACE0("Failed to create toolbar\n");
        return -1;      // fail to create
    }

    CString strToolBarName;
    bNameValid = strToolBarName.LoadString(IDS_TOOLBAR_STANDARD);
    ASSERT(bNameValid);
    m_wndToolBar.SetWindowText(strToolBarName);

    CString strCustomize;
    bNameValid = strCustomize.LoadString(IDS_TOOLBAR_CUSTOMIZE);
    ASSERT(bNameValid);
    m_wndToolBar.EnableCustomizeButton(TRUE, ID_VIEW_CUSTOMIZE, strCustomize);

    // Allow user-defined toolbars operations:
    InitUserToolbars(nullptr, uiFirstUserToolBarId, uiLastUserToolBarId);

    if (!m_wndStatusBar.Create(this))
    {
        TRACE0("Failed to create status bar\n");
        return -1;      // fail to create
    }
    m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT));

    // TODO: Delete these five lines if you don't want the toolbar and menubar to be dockable
    m_wndMenuBar.EnableDocking(CBRS_ALIGN_ANY);
    m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
    EnableDocking(CBRS_ALIGN_ANY);
    DockPane(&m_wndMenuBar);
    DockPane(&m_wndToolBar);


    // enable Visual Studio 2005 style docking window behavior
    CDockingManager::SetDockingMode(DT_SMART);
    // enable Visual Studio 2005 style docking window auto-hide behavior
    EnableAutoHidePanes(CBRS_ALIGN_ANY);

    // Load menu item image (not placed on any standard toolbars):
    CMFCToolBar::AddToolBarForImageCollection(IDR_MENU_IMAGES, theApp.m_bHiColorIcons ? IDB_MENU_IMAGES_24 : 0);

    // create docking windows
    if (!CreateDockingWindows())
    {
        TRACE0("Failed to create docking windows\n");
        return -1;
    }

    m_wndFileView.EnableDocking(CBRS_ALIGN_ANY);
    m_wndClassView.EnableDocking(CBRS_ALIGN_ANY);
    DockPane(&m_wndFileView);
    CDockablePane* pTabbedBar = nullptr;
    m_wndClassView.AttachToTabWnd(&m_wndFileView, DM_SHOW, TRUE, &pTabbedBar);
    m_wndOutput.EnableDocking(CBRS_ALIGN_ANY);
    DockPane(&m_wndOutput);
    m_wndProperties.EnableDocking(CBRS_ALIGN_ANY);
    DockPane(&m_wndProperties);

    // set the visual manager and style based on persisted value
    OnApplicationLook(theApp.m_nAppLook);

    // Enable enhanced windows management dialog
    EnableWindowsDialog(ID_WINDOW_MANAGER, ID_WINDOW_MANAGER, TRUE);

    // Enable toolbar and docking window menu replacement
    EnablePaneMenu(TRUE, ID_VIEW_CUSTOMIZE, strCustomize, ID_VIEW_TOOLBAR);

    // enable quick (Alt+drag) toolbar customization
    CMFCToolBar::EnableQuickCustomization();

    if (CMFCToolBar::GetUserImages() == nullptr)
    {
        // load user-defined toolbar images
        if (m_UserImages.Load(_T(".\\UserImages.bmp")))
        {
            CMFCToolBar::SetUserImages(&m_UserImages);
        }
    }

    // enable menu personalization (most-recently used commands)
    // TODO: define your own basic commands, ensuring that each pulldown menu has at least one basic command.
    CList<UINT, UINT> lstBasicCommands;

    lstBasicCommands.AddTail(ID_FILE_NEW);
    lstBasicCommands.AddTail(ID_FILE_OPEN);
    lstBasicCommands.AddTail(ID_FILE_SAVE);
    lstBasicCommands.AddTail(ID_FILE_PRINT);
    lstBasicCommands.AddTail(ID_APP_EXIT);
    lstBasicCommands.AddTail(ID_EDIT_CUT);
    lstBasicCommands.AddTail(ID_EDIT_PASTE);
    lstBasicCommands.AddTail(ID_EDIT_UNDO);
    lstBasicCommands.AddTail(ID_APP_ABOUT);
    lstBasicCommands.AddTail(ID_VIEW_STATUS_BAR);
    lstBasicCommands.AddTail(ID_VIEW_TOOLBAR);
    lstBasicCommands.AddTail(ID_VIEW_APPLOOK_OFF_2003);
    lstBasicCommands.AddTail(ID_VIEW_APPLOOK_VS_2005);
    lstBasicCommands.AddTail(ID_VIEW_APPLOOK_OFF_2007_BLUE);
    lstBasicCommands.AddTail(ID_VIEW_APPLOOK_OFF_2007_SILVER);
    lstBasicCommands.AddTail(ID_VIEW_APPLOOK_OFF_2007_BLACK);
    lstBasicCommands.AddTail(ID_VIEW_APPLOOK_OFF_2007_AQUA);
    lstBasicCommands.AddTail(ID_VIEW_APPLOOK_WINDOWS_7);
    lstBasicCommands.AddTail(ID_SORTING_SORTALPHABETIC);
    lstBasicCommands.AddTail(ID_SORTING_SORTBYTYPE);
    lstBasicCommands.AddTail(ID_SORTING_SORTBYACCESS);
    lstBasicCommands.AddTail(ID_SORTING_GROUPBYTYPE);

    CMFCToolBar::SetBasicCommands(lstBasicCommands);

    // Switch the order of document name and application name on the window title bar. This
    // improves the usability of the taskbar because the document name is visible with the thumbnail.
    ModifyStyle(0, FWS_PREFIXTITLE);

    return 0;
}

Я предполагаю, что должен быть способ получить дескриптор моего представления из MainFrm.

Я пробовал:

auto pView = GetActiveView();
if (pView == NULL) {
    std::string error = "Unable to get Active View\n";
    TRACE(error.c_str());
}
else {
    pView->SendMessage(WM_BUTTON1, 0, 0);
}

, но возвращается NULL (поэтому я не могу использовать это для отправки сообщения).

Я даже не уверен, что мне это нужно, но меня интересует, почему это не работает и почему я не могу получить указатель на свой вид из MainFrm.

Ответы [ 2 ]

1 голос
/ 07 октября 2019

Для простого решения я бы опубликовал вашу команду WM_BUTTON1 с WM_COMMAND . Затем команда направляется по пути MFC MSDN (MDI: основной кадр, активный дочерний кадр, активный просмотр, активный документ, приложение).
Нет необходимости обрабатывать и пересылать его в CMainframe. Это происходит автоматически для вас.

В вашем CDialog:

AfxGetMainWnd()->PostMessage(WM_COMMAND, WM_BUTTON1, 0);

Добавьте ваш обработчик в CView

ON_COMMAND(WM_BUTTON1, &CMyView::OnButton)
0 голосов
/ 02 октября 2019

Нет гарантий ... в основном из памяти. Я не использовал CMDIFrameWndEx, только CMDIFrameWnd, но я предполагаю, что он должен работать для производного варианта Ex ... казалось, это был ваш основной класс кадров.

// псевдокод

CMDIFrameWndEx* pFrame = DYNAMIC_DOWNCAST(CMDIFrameWndEx, AfxGetMainWnd()); // doesn't always work for OLE servers
if (pFrame)
{
   CMDIChileWnd* pMDIChild = pFrame->MDIGetActive();
   if (pMDIChild)
   {
      CYourView* pYourView = DYNAMIC_DOWNCAST(CYourView, pMDIChild->GetActiveView());
      if (pYourView)
      {
         // do something
      }
   }
}
...