From 18075a43d41d5084ac5ae57a75981e27f2041352 Mon Sep 17 00:00:00 2001 From: YuutaW <17158086+Trumeet@users.noreply.github.com> Date: Sat, 29 Jun 2019 15:03:00 -0700 Subject: feat: add the Window mode Note: there are still some buts to be solved. For instance, the cursor displays as "loading" after displaying until moving outside from the painting area. The IDE cannot run the program in Window mode as well and while running the process is successfully created but no windows are displayed at all. Signed-off-by: Trumeet <17158086+Trumeet@users.noreply.github.com> --- src/mingwMain/kotlin/moe/yuuta/aero/Aero.kt | 168 ++++++++++++++++++++++------ 1 file changed, 132 insertions(+), 36 deletions(-) diff --git a/src/mingwMain/kotlin/moe/yuuta/aero/Aero.kt b/src/mingwMain/kotlin/moe/yuuta/aero/Aero.kt index 6f5f5d3..c2f6e3d 100644 --- a/src/mingwMain/kotlin/moe/yuuta/aero/Aero.kt +++ b/src/mingwMain/kotlin/moe/yuuta/aero/Aero.kt @@ -6,52 +6,127 @@ import platform.windows.* fun main() { SetProcessDPIAware() - val dlgImpl = cValue { - style = (WS_OVERLAPPEDWINDOW or - DS_CENTER or - DS_MODALFRAME).convert() - dwExtendedStyle = 0.convert() - cdit = 0.convert() - x = 0 - y = 0 - cx = 400 - cy = 200 + val hInstance = GetModuleHandleA(null) + val nCmdShow = memScoped { + val startUpInfo = nativeHeap.alloc<_STARTUPINFOA>() + GetStartupInfoA(startUpInfo.ptr) + val nCmdShow = startUpInfo.wShowWindow + nativeHeap.free(startUpInfo) + return@memScoped nCmdShow.convert() } + + val className = "Main Window Class" + memScoped { - return@memScoped DialogBoxIndirectParamW(GetModuleHandleA(null), - dlgImpl.ptr, - null, - staticCFunction(::dlgProc) as DLGPROC, - 0) + val wc = cValue { + lpfnWndProc = staticCFunction(::windowProc) + this.hInstance = hInstance + lpszClassName = className.cstr.ptr + } + RegisterClassA(wc.ptr) + return@memScoped wc + } + + val hwnd = CreateWindowExA( + 0.convert(), + className, + "", // Filling texts will get the white background of the label + WS_OVERLAPPEDWINDOW.convert(), + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + null, + null, + hInstance, + null + ) + + val forceDialogEnv = memScoped { + val buffer = nativeHeap.allocArray(MAX_PATH) + GetEnvironmentVariableA("AERO_DEMO_FORCE_DIALOG", + buffer, + MAX_PATH + ) + val env = buffer.toKString() + nativeHeap.free(buffer) + return@memScoped env + } + + if (hwnd == null || (forceDialogEnv == "true")) { + memScoped { + // Fallback + val dlgImpl = cValue { + style = (WS_OVERLAPPEDWINDOW or + DS_CENTER or + DS_MODALFRAME).convert() + dwExtendedStyle = 0.convert() + cdit = 0.convert() + x = 0 + y = 0 + cx = 400 + cy = 200 + } + return@memScoped DialogBoxIndirectParamW(hInstance, + dlgImpl.ptr, + null, + staticCFunction(::dlgProc), + 0) + } + } else { + ShowWindow(hwnd, nCmdShow) + msgLoop() + } +} + +fun msgLoop() { + memScoped { + val msg = nativeHeap.alloc() + while (GetMessageA(msg.ptr, + null, + 0.convert(), + 0.convert()) != 0) { + TranslateMessage(msg.ptr) + DispatchMessageA(msg.ptr) + } + // The queue quits + nativeHeap.free(msg) } } -fun dlgProc(hDlg: HWND, +fun windowProc(hwnd: HWND?, + uMsg: UINT, + wParam: WPARAM, + lParam: LPARAM): LRESULT { + return when (uMsg.convert()) { + WM_CREATE -> { + setAero(hwnd) + 1 + } + WM_DESTROY -> { + PostQuitMessage(0) + 1 + } + WM_PAINT -> { + val ps = nativeHeap.alloc() + val hdc = BeginPaint(hwnd, ps.ptr) + FillRect(hdc, + ps.rcPaint.ptr, + GetStockObject(BLACK_BRUSH) as HBRUSH) + EndPaint(hwnd, ps.ptr) + nativeHeap.free(ps) + 1 + } + else -> { + DefWindowProcA(hwnd, uMsg, wParam, lParam) + } + } +} + +fun dlgProc(hDlg: HWND?, message: UINT, wParam: WPARAM, lParam: LPARAM): INT_PTR { when (message.convert()) { WM_INITDIALOG -> { - val hUser = GetModuleHandleW("user32.dll") - if (hUser != null) { - val setWindowCompositionAttribute = GetProcAddress(hUser, "SetWindowCompositionAttribute") as pfnSetWindowCompositionAttribute? - if (setWindowCompositionAttribute != null) { - val accent = cValue { - AccentState = ACCENT_ENABLE_BLURBEHIND - AccentFlags = 0.convert() - GradientColor = 0.convert() - AnimationId = 0.convert() - } - memScoped { - val data = cValue { - Attrib = WCA_ACCENT_POLICY - pvData = accent.ptr - cbData = accent.size.convert() - } - setWindowCompositionAttribute(hDlg, data.ptr) - } - } - } + setAero(hDlg) return true.toByte().toLong() } WM_COMMAND -> { @@ -65,4 +140,25 @@ fun dlgProc(hDlg: HWND, return false.toByte().toLong() } } +} + +fun setAero(hwnd: HWND?) { + val hUser = GetModuleHandleW("user32.dll") ?: return + val setWindowCompositionAttribute = GetProcAddress(hUser, + "SetWindowCompositionAttribute") + as pfnSetWindowCompositionAttribute? ?: return + val accent = cValue { + AccentState = ACCENT_ENABLE_BLURBEHIND + AccentFlags = 0.convert() + GradientColor = 0.convert() + AnimationId = 0.convert() + } + memScoped { + val data = cValue { + Attrib = WCA_ACCENT_POLICY + pvData = accent.ptr + cbData = accent.size.convert() + } + setWindowCompositionAttribute(hwnd, data.ptr) + } } \ No newline at end of file -- cgit v1.2.3