Управление окнами и менеджер окон
Необходимо написать приложение ,которое реализует систему управления окнами. В системы должны присутствовать два обязательных класса:
- Базовый класс окна
- Менеджер окон
Требования к данной системе:
- Запуск окна происходит через единственную функцию, при этом менеджер окон запоминает порядок запуска окон и никогда его не меняет.
- Должна быть возможность переопределения порядка отображения окон, пример: окно, которое всегда отображается поверх других окон. Нельзя использовать сырую память.И нужно использовать библиотеку STL Для визуализации можно использовать любою Api.
Набросок кода сделал,но как сделать класс Менеджера ,не понимаю. Помогите пожалуста разобраться
#include <stack>
#include <memory>
#include<Windows.h>
LRESULT CALLBACK _WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
TCHAR CLASS_NAME[] = L"ClassWindow";
class Window
{
public:
Window() = default;
void Create(LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, RECT pos)
{
HINSTANCE hInstence = (HINSTANCE)GetModuleHandle(NULL);
WNDCLASS wc = { };
wc.lpfnWndProc = _WindowProc;
wc.hInstance = hInstence;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
if (m_hWnd == NULL)
{
MessageBox(NULL, L"Не удалось зарегистрировать класс окна!", L"Ошибка регистрации", MB_OK);
}
}
void showWindow()
{
::ShowWindow(m_hWnd, SW_SHOW);
}
private:
LRESULT WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(m_hWnd, uMsg, wParam, lParam);
}
}
friend LRESULT CALLBACK _WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
Window* p;
if (uMsg != WM_CREATE)
p = reinterpret_cast<Window*>(::GetWindowLongPtr(hwnd, GWLP_USERDATA));
else
{
::SetWindowLongPtr(hwnd, GWLP_USERDATA, lParam);
p = reinterpret_cast<Window*>(lParam);
}
return p->WndProc(uMsg, wParam, lParam);
}
HWND m_hWnd = NULL;
};
int WINAPI WinMain(HINSTANCE hInstence, HINSTANCE, LPSTR pCmdLine, int nCmdLine)
{
Window w;
w.Create("Window", "Window", CS_VREDRAW, { 10, 20, 100, 100 });
w.showWindow();
// Run the message loop.
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
class WindowManager
{
public:
std::shared_ptr<Window> CreateWindow(args.....................)
{
return m_windows.emplace_back(std::make_shared<Window>(args.....................));
}
private:
std::list<std::shared_ptr<Window>> m_windows;
};
int main()
{
std::shared_ptr <Windows> ptrWindow(new Windows);
// если нажата кнопка Создать
ptrWindow->createWindow();
ptrWindow->showWindow();
//если нажата кнопка Поверх всех
std::stack <Windows> stackWin;
stackWin.push(ptrWindow);
return 0;
}
Ответы (1 шт):
Автор решения: Кирилл Чебурин
→ Ссылка
Реализация без использования std::stack
global.h
#ifndef GLOBAL_H
#define GLOBAL_H
//-------------------------------------------------------------------------
#include <windows.h>
#include <tchar.h>
#define mainwindowclass "tcontrol"
//-------------------------------------------------------------------------
// delete_null удаляет объект и устанавливает указатель на null
// Не завершайте конец этого макроса ";"
#define delete_null(ptr) { delete ptr; ptr = nullptr; }
//Голбальная переменная приложения.
//Каждое новое приложение должно начинаться со строчки
//application=new tapplication(); если этого не сделать то переменная будет
//указывать на null и приложение сразу некорректно завершится.
class tapplication;
extern tapplication* application;
//-------------------------------------------------------------------------
#endif
tobjectmanager.h
#ifndef TOBJECTMANAGER_H
#define TOBJECTMANAGER_H
class tobjectmanager
{
public:
virtual void free();
virtual tobject* find(tobject* pitem);
virtual void empty();
virtual bool Delete(tobject* pitem, bool bdeleteitem = true);
virtual void add(tobject* pitem, bool baddatbeginningoflist = false);
tobjectmanager();
virtual ~tobjectmanager();
// Возвращаем число элементов в списке или объектов помещенных в список
UINT getcount() { return m_nitemcount; }
// Указатели на первый и последний объект в списке
tobject* m_pfirstitem;
tobject* m_plastitem;
// Число элементов в списке
UINT m_nitemcount;
};
// Это частный tobjectmanager который никогда не удаляет объекты из листа
class twindowlist : public tobjectmanager
{
public:
twindowlist()
{
}
~twindowlist()
{
empty();
}
};
#endif
tobjectmaneger.cpp
#include "tobjectmanager.h"
/*---------------------------------------------------------------------------
Назначение:
Конструктор по умолчанию.Инициализирует внутренние члены
Примечания:
//-------------------------------------------------------------------------*/
tobjectmanager::tobjectmanager()
{
empty();
}
/*---------------------------------------------------------------------------
Назначение:
Виртуальный деструктор. Вызывает free() для удаления объектов содержащихся
в связанном списке
Примечания:
//-------------------------------------------------------------------------*/
tobjectmanager::~tobjectmanager()
{
free();
}
/*---------------------------------------------------------------------------
Назначение:
Добавляет элемент в конец списка если только baddatbeginningoflist
равен true
Примечания:
//-------------------------------------------------------------------------*/
void tobjectmanager::add(tobject* pitem, bool baddatbeginningoflist)
{
if (!pitem)
return;
if (m_pfirstitem)
{
if (baddatbeginningoflist)
{
pitem->m_pnextitem = m_pfirstitem;
m_pfirstitem = pitem;
}
else
{
m_plastitem->m_pnextitem = pitem;
m_plastitem = pitem;
}
}
else
m_pfirstitem = m_plastitem = pitem;
// Увеличиваем счетчик
m_nitemcount++;
}
/*---------------------------------------------------------------------------
Назначение:
Удаляет pitem из связанного списка. Если bdeleteitem =true будет удален и
pitem
//-------------------------------------------------------------------------*/
bool tobjectmanager::Delete(tobject* pitem, bool bdeleteitem)
{
if (!pitem)
return false;
// Ищем предыдущий элемент в списке
tobject* pthisitem = m_pfirstitem;
tobject* ppreviousitem = nullptr;
bool bresult = false;
while (pthisitem)
{
if (pthisitem == pitem)
{
bresult = true;
// Это первый элемент ?
if (pitem == m_pfirstitem)
m_pfirstitem = pitem->m_pnextitem;
// Это последний элемент
if (pitem == m_plastitem)
m_plastitem = ppreviousitem;
// Назначаем предыдущий узел указывать на следующий
if (ppreviousitem)
ppreviousitem->m_pnextitem = pitem->m_pnextitem;
// Уменьшаем счетчик
m_nitemcount--;
//Закончили
break;
}
else
{
// Сохраняем предыдущий элемент и берм следующий элемент для цикла
ppreviousitem = pthisitem;
pthisitem = pthisitem->m_pnextitem;
}
}
// Удаляем pitem ?
if (bdeleteitem)
delete_null(pitem)
return bresult;
}
void tobjectmanager::empty()
{
m_pfirstitem = m_plastitem = nullptr;
m_nitemcount = 0;
}
/*---------------------------------------------------------------------------
Назначение:
Ищем элемент в списке и возвращаем его или возвращаем null если объект не
найден
//-------------------------------------------------------------------------*/
tobject* tobjectmanager::find(tobject* pitem)
{
if (pitem)
{
tobject* pthisitem = m_pfirstitem;
while (pthisitem)
{
if (pthisitem == pitem)
return pthisitem;
pthisitem = pthisitem->m_pnextitem;
}
}
return nullptr;
}
/**
Назначение:
Освобождаем все элементы в списке. Функция также удаляет сами объекты в списке.
Примечания:
Если требуется только сбросить содержимое стоит вызывать empty()
//-------------------------------------------------------------------------*/
void tobjectmanager::free()
{
tobject* pitem = m_pfirstitem;
tobject* pnextitem = nullptr;
while (pitem)
{
pnextitem = pitem->m_pnextitem;
delete_null(pitem)
pitem = pnextitem;
}
empty();
}