Quantcast
Channel: CodeGuru Forums - Visual C++ Programming
Viewing all articles
Browse latest Browse all 3046

[RESOLVED] Messages can't get to a CWnd

$
0
0
Hello!

I'm trying to do a page navigator class, derived from CWnd, wich contains a list of CWnd pointers, shows only the current page and makes sure it resizes correctly.

However setting the WS_CHILD style to the child window (the page) prevents every kind of interaction. I can't click on button, edit CEdit controls, etc.

So the solution is simple, don't add WS_CHILD and simply destroy all the pages' window when the navigator is itself destroy, right ?
That's kind of a workaround but why not.

However (again), this breaks the maximize thingy. When I'm minimizing the app while the focus is on a page, I can't maximize the app again by clicking the icon in the taskbar nor with ALT+TAB.

I also tried redirecting messages with a PreTranslateMessage and IsDialogMessage, but the navigator won't get all the messages (I thought) it supposed to have, like clicks and stuff.

Any help appreciated, I really want to know WHY this isn't working.
Anyway, here's the code :

Code:

// Header

#pragma once
#include <unordered_map>

class PageNavigator : public CWnd
{
public:
        PageNavigator();
        virtual ~PageNavigator();

    BOOL Create(CWnd* parent, UINT id, CRect rect = {});

    void AddPage(int id, CWnd* page);
    bool ShowPage(int id);
    CWnd* GetCurrentPage() const;

    void SetRoundedCorners(bool active = true);

protected:
    virtual BOOL PreTranslateMessage(MSG* pMsg);

    afx_msg void OnDestroy();
    afx_msg void OnSize(UINT nType, int cx, int cy);
    DECLARE_MESSAGE_MAP()

private:
    std::unordered_map<int, CWnd*> m_pages;
    CWnd* m_currentPage;

    bool m_isRoundedCorners = false;
};

Code:

// Source

#include "stdafx.h"
#include "PageNavigator.h"
#include <src/Sonometre.h>

PageNavigator::PageNavigator()
{
        m_currentPage = nullptr;
}

PageNavigator::~PageNavigator()
{
        DestroyWindow();
}

BEGIN_MESSAGE_MAP(PageNavigator, CWnd)
    ON_WM_DESTROY()
    ON_WM_SIZE()
END_MESSAGE_MAP()

BOOL PageNavigator::Create(CWnd* parent, UINT id, CRect rect)
{
    CString className = AfxRegisterWndClass(CS_DBLCLKS,
        ::LoadCursor(NULL, IDC_ARROW),
        (HBRUSH)(COLOR_BTNFACE + 1),
        NULL);

        return CWnd::Create(className, _T("NavigatorCtrl"), WS_CHILD | WS_VISIBLE, rect, parent, id);
}

void PageNavigator::AddPage(int id, CWnd* page)
{
    if (!page) return;
        m_pages[id] = page;
        page->SetParent(this);
        page->ShowWindow(SW_HIDE);
    page->ModifyStyle(WS_CAPTION | WS_BORDER | WS_DLGFRAME | WS_THICKFRAME | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, WS_CHILD | DS_CONTROL);
    page->ModifyStyleEx(WS_EX_CLIENTEDGE | WS_EX_WINDOWEDGE | WS_EX_DLGMODALFRAME, 0);
}

bool PageNavigator::ShowPage(int id)
{
    if (!IsWindow(m_hWnd)) return false;

    auto it = m_pages.find(id);
    if (it == m_pages.end())
        return false;

    if (m_currentPage) m_currentPage->ShowWindow(SW_HIDE);

    CRect rect;
    GetClientRect(rect);
    ClientToScreen(rect);

    m_currentPage = it->second;
    m_currentPage->MoveWindow(0, 0, rect.Width(), rect.Height());
    m_currentPage->ShowWindow(SW_SHOW);
    return true;
}

CWnd* PageNavigator::GetCurrentPage() const
{
    return m_currentPage;
}

void PageNavigator::SetRoundedCorners(bool active)
{
    if (m_isRoundedCorners == active) return;
    m_isRoundedCorners = active;
    Invalidate();
}

BOOL PageNavigator::PreTranslateMessage(MSG* pMsg)
{
    if (m_currentPage && IsWindow(m_currentPage->m_hWnd))
    {
        if (m_currentPage->IsDialogMessage(pMsg))
            return TRUE;
    }
    return CWnd::PreTranslateMessage(pMsg);
}

void PageNavigator::OnDestroy()
{
    // Vu qu'assigner le style WS_CHILD aux pages les emp?che de toute interaction, MFC ne va pas les d?truire tout seul.
    for (auto [id, page] : m_pages)
        page->DestroyWindow();
   
    m_pages.clear();
    m_currentPage = nullptr;
}

void PageNavigator::OnSize(UINT nType, int cx, int cy)
{
    CWnd::OnSize(nType, cx, cy);
    if (m_currentPage) m_currentPage->MoveWindow(0, 0, cx, cy);

    if (m_isRoundedCorners)
    {
        HRGN hRgn = CreateRoundRectRgn(0, 0, cx, cy, 20, 20);
        SetWindowRgn(hRgn, TRUE);
    }
}

PS : every pages is a CDialog for now.

Viewing all articles
Browse latest Browse all 3046

Trending Articles