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 :
PS : every pages is a CDialog for now.
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);
}
}