summaryrefslogtreecommitdiff
path: root/Editor/GUI/ContainerWindow.cpp
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2021-10-20 13:50:50 +0800
committerchai <chaifix@163.com>2021-10-20 13:50:50 +0800
commitafdcbfa9c4259fb003fd072ae011836230e7e39b (patch)
tree28687805fa6cd08ea998adffeac7b241af42cfe8 /Editor/GUI/ContainerWindow.cpp
parentc795fb754bfd5c84c1bfd7dc793c6519f01109ea (diff)
+containers
Diffstat (limited to 'Editor/GUI/ContainerWindow.cpp')
-rw-r--r--Editor/GUI/ContainerWindow.cpp437
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)
+{
+
+}