diff options
author | chai <chaifix@163.com> | 2021-10-20 13:50:50 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2021-10-20 13:50:50 +0800 |
commit | afdcbfa9c4259fb003fd072ae011836230e7e39b (patch) | |
tree | 28687805fa6cd08ea998adffeac7b241af42cfe8 /Editor/GUI/ContainerWindow.cpp | |
parent | c795fb754bfd5c84c1bfd7dc793c6519f01109ea (diff) |
+containers
Diffstat (limited to 'Editor/GUI/ContainerWindow.cpp')
-rw-r--r-- | Editor/GUI/ContainerWindow.cpp | 437 |
1 files changed, 437 insertions, 0 deletions
diff --git a/Editor/GUI/ContainerWindow.cpp b/Editor/GUI/ContainerWindow.cpp new file mode 100644 index 0000000..ee42635 --- /dev/null +++ b/Editor/GUI/ContainerWindow.cpp @@ -0,0 +1,437 @@ +#include <string> + +#include "EditorWindows.h" +#include "WinUtils.h" +#include "Editor/Utils/HelperFuncs.h" +#include "MenuManager.h" +#include "Runtime/Utilities/Assert.h" +#include "Editor/Graphics/Graphics.h" + +using namespace std; + +static bool s_IsMainWindowMaximized; + +extern bool ProcessMainWindowMessages(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT& result); + +static PAINTSTRUCT ps; +LRESULT CALLBACK ContainerWindow::ContainerWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + + ContainerWindow *self = (ContainerWindow*)GetWindowLongPtr(hWnd, GWLP_USERDATA); + if (!self) + { + log_warning("Nullptr ContainerWindow"); + return DefWindowProcW(hWnd, message, wParam, lParam); + } + + //log_info("WndProc", "ContainerWindow::ContainerWndProc(), ContainerWindow name is " + self->GetName()); + + switch (message) + { + case WM_MENUSELECT: + { + if (self->m_ShowMode != ShowMode::kShowMainWindow) + return 0; + uint menuId = LOWORD(wParam); + uint flags = HIWORD(wParam); + HMENU menu = (HMENU)lParam; + MenuManager::Instance()->HandleMenuItemEvent(menu, menuId, flags); + return 0; + } + case WM_SETICON: + return WM_SETICON; + case WM_PAINT: + { + log_info("WM_PAINT"); + self->SetAsRenderContext(); + glEnable(GL_BLEND); + float c = 26 / 255.f; + glClearColor(c, c, c, 1); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glFlush(); + BeginPaint(self->m_Window, &ps); + EndPaint(self->m_Window, &ps); + UpdateWindow(self->m_Window); + return 0; + } + case WM_ENTERMENULOOP: // 点击菜单 + + return 0; + case WM_EXITMENULOOP: // 松开菜单 + return 0; + + case WM_KEYDOWN: // key down + case WM_KEYUP: // key up + case WM_SYSKEYDOWN: // 和 WM_KEYDOWN 的区别是可以捕获快捷键或系统命令按键,比如alt键, Ctrl和shift不属于WM_SYSKEYDOWN + case WM_SYSKEYUP: // 和 WM_KEYUP 的区别是可以捕获快捷键或系统命令按键,比如alt键 + if (message == WM_KEYDOWN && wParam == VK_ESCAPE) { + // Escape should close utility container windows + // 如果本窗口是 utility 窗口,关闭它 + if (self->m_ShowMode == ShowMode::kShowUtility) { + self->Close(); + return 0; + } + } + return 0; + + case WM_ERASEBKGND:// WM_ERASEBKGND是在当窗口*背景*必须被擦除时 (例如,窗口的移动,窗口的大小的改变)发送。 + { + // unity的窗口背景色要么是灰色(免费版) ,要么是深黑色(专业版) + // 对于透明窗口 + if (GetWindowLong(hWnd, GWL_EXSTYLE) & WS_EX_LAYERED) { // WS_EX_LAYERED是extendedStyle透明窗口 + // 填充用户区 + RECT rc; + GetClientRect(hWnd, &rc); + FillRect((HDC)wParam, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH)); + } + // do not erase background + // 如果不是透明窗口不要清除背景,跳过DefWindowProc函数 + return 1; + } + + case WM_WINDOWPOSCHANGED: // 窗口大小、位置、z层级改变,即窗口区域改变 + { + if (!self->m_IsClosing && !IsIconic(hWnd)) //IsIconic 窗口是否是最小化(图标化) + { + // OnRectChanged()回调 + self->OnRectChanged(); + } + // WM_WINDOWPOSCHANGED 消息触发后且调用了DefWindowProc会接着发送WM_SIZE和WM_MOVE消息。在WM_WINDOWPOSCHANGED + // 中一起处理大小和位置改变更高效 + /* + By default, the DefWindowProc function sends the WM_SIZE and WM_MOVE messages to the window. + The WM_SIZE and WM_MOVE messages are not sent if an application handles the WM_WINDOWPOSCHANGED + message without calling DefWindowProc. It is more efficient to perform any move or size change + processing during the WM_WINDOWPOSCHANGED message without calling DefWindowProc. + */ + break; + } + + case WM_SIZE: // 窗口大小改变 + if (self->m_ShowMode == ShowMode::kShowMainWindow) + { + if (IsWindowVisible(hWnd)) + { + bool nowMaximized = wParam == SIZE_MAXIMIZED; + if (s_IsMainWindowMaximized != nowMaximized)//更新s_IsMainWindowMaximized变量 + s_IsMainWindowMaximized = nowMaximized; + } + } + break; + + case WM_SETFOCUS: // 窗口获得焦点 + return 0; + + case WM_ACTIVATEAPP: // 编辑器的激活状态改变,所有的窗口都会获得这个消息,和WM_ACTIVATE不同,WM_ACTIVATE只是单个窗口被激活 + // 发送一个 OnActivateApplication 消息 + self->OnActivateApplication(wParam != FALSE); + break; // fall through to main window processing + + + case WM_NCACTIVATE: // non-client active 即非用户区被激活,用这个消息来刷新编辑器 + + break; + + case WM_ACTIVATE: // 单个窗口的激活状态改变 + + return 0; + + case WM_CLOSE: // 窗口关闭消息 + { + bool isMainAndShouldExit = (self->m_ShowMode == kShowMainWindow && !self->m_CloseFromScriptDontShutdown); + if (isMainAndShouldExit) + { + //退出编辑器 + } + else + { + // 关闭此窗口 + ::SetMenu(hWnd, NULL); // 给窗口分配一个菜单,如果是NULL,这个窗口的菜单被删除 + ::DestroyWindow(hWnd); + } + return 0; + } + + case WM_DESTROY: // 窗口被销毁 + + return 0; + + case WM_INITMENUPOPUP: //下拉菜单或子菜单将要被激活的时候 + + return 0; + + case WM_ENTERSIZEMOVE: // 在大小、位置改变前,即当用户点击标题栏、边框 + + return 0; + } + + if (self->m_ShowMode == ShowMode::kShowMainWindow) + { + LRESULT result; + if (ProcessMainWindowMessages(hWnd, message, wParam, lParam, result)) { + return result; + } + } + + long flag = DefWindowProcW(hWnd, message, wParam, lParam); + return flag; +} + +ContainerWindow::ContainerWindow() +{ +} + +ContainerWindow::~ContainerWindow() +{ + +} + +void ContainerWindow::DoPaint() +{ + SetWindowLongPtr(m_Window, GWLP_USERDATA, (LONG_PTR)this); + SendMessage(m_Window, WM_PAINT, 0, 0); +} + +void ContainerWindow::SetAsRenderContext() +{ + Assert(m_DC != NULL); + Assert(m_RC != NULL); + Assert(wglMakeCurrent(m_DC, m_RC)); + RECT rect; + GetWindowRect(m_Window, &rect); + glViewport(0, 0, rect.right - rect.left, rect.bottom - rect.top); +} + +bool ContainerWindow::SetRenderContext() +{ + m_DC = ::GetDC(m_Window); + if (!m_DC) + log_error("Can't create DC"); + + int bits = 32; + + //static PIXELFORMATDESCRIPTOR pfd = // pfd Tells Windows How We Want Things To Be + //{ + // sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor + // 1, // Version Number + // PFD_DRAW_TO_WINDOW | // Format Must Support Window + // PFD_SUPPORT_OPENGL | // Format Must Support OpenGL + // PFD_DOUBLEBUFFER, // Must Support Double Buffering + // PFD_TYPE_RGBA, // Request An RGBA Format + // bits, // Select Our Color Depth + // 0, 0, 0, 0, 0, 0, // Color Bits Ignored + // 0, // No Alpha Buffer + // 0, // Shift Bit Ignored + // 0, // No Accumulation Buffer + // 0, 0, 0, 0, // Accumulation Bits Ignored + // 16, // 16Bit Z-Buffer (Depth Buffer) + // 0, // No Stencil Buffer + // 0, // No Auxiliary Buffer + // PFD_MAIN_PLANE, // Main Drawing Layer + // 0, // Reserved + // 0, 0, 0 // Layer Masks Ignored + //}; + static PIXELFORMATDESCRIPTOR pfd; + pfd.nSize = sizeof(pfd); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.cColorBits = 32; + + GLuint PixelFormat; + + if (!(PixelFormat = ChoosePixelFormat(m_DC, &pfd))) // Did Windows Find A Matching Pixel Format? + { + MessageBox(NULL, "Can't Find A Suitable PixelFormat.", "ERROR", MB_OK | MB_ICONEXCLAMATION); + return FALSE; // Return FALSE + } + + if (!SetPixelFormat(m_DC, PixelFormat, &pfd)) // Are We Able To Set The Pixel Format? + { + MessageBox(NULL, "Can't Set The PixelFormat.", "ERROR", MB_OK | MB_ICONEXCLAMATION); + return FALSE; // Return FALSE + } + + int pf = 0; + DescribePixelFormat(m_DC, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd); + + if (!(m_RC = wglCreateContext(m_DC))) // Are We Able To Get A Rendering Context? + { + MessageBox(NULL, "Can't Create A GL Rendering Context.", "ERROR", MB_OK | MB_ICONEXCLAMATION); + return FALSE; // Return FALSE + } + + if (m_RC && !g_IsGLInitialized) + { + log_info("Initialize OpenGL"); + wglMakeCurrent(m_DC, m_RC);
+ if (!gladLoadGL()) {
+ log_error("初始化GL错误");
+ }
+ g_IsGLInitialized = true; + } +} + +// 初始化,创建窗口 +void ContainerWindow::Init(Rectf pixelRect, int showMode, const Vector2f& minSize, const Vector2f& maxSize, std::string name) +{ + // Aux windows are mac only. on windows they look just like normal utility windows. + if (showMode == kShowAuxWindow) + showMode = kShowUtility; + + m_Name = name; + m_ShowMode = static_cast<ShowMode>(showMode); + m_IsClosing = false; + m_InMenuLoop = false; + m_CloseFromScriptDontShutdown = false; + + bool shouldMaximize = false; + if (showMode == kShowMainWindow) + { + //shouldMaximize = s_IsMainWindowMaximized = EditorPrefs::GetBool(kIsMainWindowMaximized, false); + //GetRestoredMainWindowDimensions(); + } + + RECT rect; + rect.left = pixelRect.x; + rect.right = pixelRect.x + pixelRect.width; + rect.top = pixelRect.y; + rect.bottom = pixelRect.y + pixelRect.height; + m_InternalRect.x = m_InternalRect.y = m_InternalRect.width = m_InternalRect.height = 0.0f; + + DWORD windowStyle = 0; + DWORD extendedStyle = 0; + LPCWSTR windowClass = WindowUtil::kContainerWindowClassName; + + switch (showMode) { + // 容纳GUIPanel的非主窗口 + case kShowNormalWindow: + windowStyle = WS_POPUP | WS_CLIPCHILDREN | WS_THICKFRAME; + extendedStyle = WS_EX_TOOLWINDOW; + break; + // 主窗口,含菜单 + case kShowMainWindow: + windowStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_CLIPCHILDREN | WS_MAXIMIZEBOX | WS_MINIMIZEBOX; + extendedStyle = 0; + break; + case kShowPopupMenu: + windowStyle = WS_POPUP | WS_CLIPCHILDREN; + extendedStyle = WS_EX_TOOLWINDOW; + windowClass = WindowUtil::kPopupWindowClassName; + break; + case kShowNoShadow: + windowStyle = WS_POPUP | WS_CLIPCHILDREN; + extendedStyle = WS_EX_TOOLWINDOW; + break; + case kShowUtility: + windowStyle = WS_POPUP | WS_CAPTION | WS_THICKFRAME | WS_SYSMENU; + extendedStyle = WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW; + break; + default: + // ErrorString("Unknown container show mode"); + break; + } + + HWND parentWindow = NULL; + if (showMode == kShowMainWindow) + { + parentWindow = NULL; + } + else + { + // parentWindow = GetMainEditorWindow(); + } + + bool notSizeable = (minSize == maxSize) && (minSize != Vector2f::zero); + if (notSizeable) + windowStyle &= ~(WS_THICKFRAME); + + AdjustWindowRectEx(&rect, windowStyle, showMode == kShowMainWindow, extendedStyle); + int extraX = rect.right - rect.left - 200; + int extraY = rect.bottom - rect.top - 200; + + m_MinSize.x = minSize.x + extraX; + m_MinSize.y = minSize.y + extraY; + m_MaxSize.x = maxSize.x + extraX; + m_MaxSize.y = maxSize.y + extraY; + + //if (showMode == kShowUtility) + // s_ZUtilityWindows.push_back(m_ContainerListNode); + // Create window + m_Window = CreateWindowExW( + extendedStyle, + windowClass, + L"", + windowStyle, + rect.left, + rect.top, + rect.right - rect.left, + rect.bottom - rect.top, + parentWindow, + NULL, + winutils::GetInstanceHandle(), + NULL + ); + SetWindowLongPtr(m_Window, GWLP_USERDATA, (LONG_PTR)this); + //UpdateMaxMaximizedRect(); + + if (pixelRect.width > 10 || pixelRect.height > 10) + { + //SetRect(pixelRect); + if (shouldMaximize) + SetWindowLong(m_Window, GWL_STYLE, windowStyle | WS_MAXIMIZE); + } + + if (showMode == kShowMainWindow) + { + //SetMainEditorWindow(m_Window); + //HMENU menu = GetMainMenuHandle(); + //if (menu) + // SetMenu(m_Window, menu); + //GetApplication().UpdateMainWindowTitle(); + //GetApplication().UpdateDocumentEdited(); + } + ShowWindow(m_Window, SW_SHOW); + + //s_ContainerWindows.insert(this); + + //ShowInTaskbarIfNoMainWindow(m_Window); + + SetRenderContext(); + +} + +void ContainerWindow::SetTitle(const char* title) +{ + SetWindowTextA(m_Window, title); +} + +void ContainerWindow::SetIcon(LPCSTR iconName) +{ + Assert(m_ShowMode == ShowMode::kShowMainWindow); + + HICON hWindowIcon = (HICON )LoadImage(winutils::GetInstanceHandle(), iconName, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE); + if (hWindowIcon == NULL) + log_error("icon error: " + to_string(GetLastError())); + if (SendMessage(m_Window, WM_SETICON, ICON_BIG, (LPARAM)hWindowIcon) != WM_SETICON) + log_error("icon error: " + to_string(GetLastError())); + if (SendMessage(m_Window, WM_SETICON, ICON_SMALL, (LPARAM)hWindowIcon) != WM_SETICON) + log_error("icon error: " + to_string(GetLastError())); +} + +void ContainerWindow::Close() +{ + log_info("Close window " + m_Name); + + SendMessage(m_Window, WM_CLOSE, 0, 0); +} + +void ContainerWindow::OnRectChanged() +{ + +} + +void ContainerWindow::OnActivateApplication(bool active) +{ + +} |