X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/f8d7977b360e4756d0aa045a7396756973c1568c..41d3adbbfed77605e4a397ce199c5751c35bf94b:/window.c diff --git a/window.c b/window.c index 15f23870..4bcc2697 100644 --- a/window.c +++ b/window.c @@ -11,6 +11,13 @@ #endif #endif +#ifndef NO_MULTIMON +#if WINVER < 0x0500 +#define COMPILE_MULTIMON_STUBS +#include +#endif +#endif + #include #include #include @@ -55,15 +62,19 @@ #define IDM_SAVED_MAX 0x2000 #define WM_IGNORE_CLIP (WM_XUSER + 2) +#define WM_FULLSCR_ON_MAX (WM_XUSER + 3) /* Needed for Chinese support and apparently not always defined. */ #ifndef VK_PROCESSKEY #define VK_PROCESSKEY 0xE5 #endif -/* Needed for mouse wheel support and not defined in earlier SDKs. */ +/* Mouse wheel support. */ #ifndef WM_MOUSEWHEEL -#define WM_MOUSEWHEEL 0x020A +#define WM_MOUSEWHEEL 0x020A /* not defined in earlier SDKs */ +#endif +#ifndef WHEEL_DELTA +#define WHEEL_DELTA 120 #endif static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); @@ -75,10 +86,15 @@ static void init_fonts(int, int); static void another_font(int); static void deinit_fonts(void); static void set_input_locale(HKL); +static int do_mouse_wheel_msg(UINT message, WPARAM wParam, LPARAM lParam); + +static int is_full_screen(void); +static void make_full_screen(void); +static void clear_full_screen(void); +static void flip_full_screen(void); /* Window layout information */ static void reset_window(int); -static int full_screen = 0; static int extra_width, extra_height; static int font_width, font_height, font_dualwidth; static int offset_width, offset_height; @@ -90,10 +106,12 @@ static WPARAM pend_netevent_wParam = 0; static LPARAM pend_netevent_lParam = 0; static void enact_pending_netevent(void); static void flash_window(int mode); -static void flip_full_screen(void); +static void sys_cursor_update(void); static time_t last_movement = 0; +static int caret_x = -1, caret_y = -1; + #define FONT_NORMAL 0 #define FONT_BOLD 1 #define FONT_UNDERLINE 2 @@ -143,6 +161,8 @@ static int compose_state = 0; static OSVERSIONINFO osVersion; +static UINT wm_mousewheel = WM_MOUSEWHEEL; + /* Dummy routine, only required in plink. */ void ldisc_update(int echo, int edit) { @@ -192,6 +212,16 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) } /* + * If we're running a version of Windows that doesn't support + * WM_MOUSEWHEEL, find out what message number we should be + * using instead. + */ + if (osVersion.dwMajorVersion < 4 || + (osVersion.dwMajorVersion == 4 && + osVersion.dwPlatformId != VER_PLATFORM_WIN32_NT)) + wm_mousewheel = RegisterWindowMessage("MSWHEEL_ROLLMSG"); + + /* * See if we can find our Help file. */ { @@ -624,15 +654,15 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) set_input_locale(GetKeyboardLayout(0)); /* - * Finally show the window! + * Open the initial log file if there is one. */ - ShowWindow(hwnd, show); - SetForegroundWindow(hwnd); + logfopen(); /* - * Open the initial log file if there is one. + * Finally show the window! */ - logfopen(); + ShowWindow(hwnd, show); + SetForegroundWindow(hwnd); /* * Set the palette up. @@ -695,7 +725,8 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) timer_id = 0; } HideCaret(hwnd); - term_out(); + if (GetCapture() != hwnd) + term_out(); term_update(); ShowCaret(hwnd); @@ -1483,12 +1514,14 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, HDC hdc; static int ignore_clip = FALSE; static int need_backend_resize = FALSE; + static int fullscr_on_max = FALSE; switch (message) { case WM_TIMER: if (pending_netevent) enact_pending_netevent(); - term_out(); + if (GetCapture() != hwnd) + term_out(); noise_regular(); HideCaret(hwnd); term_update(); @@ -1613,9 +1646,9 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, (cfg.resize_action == RESIZE_DISABLED) ? MF_GRAYED : MF_ENABLED); /* Gracefully unzoom if necessary */ - if (full_screen && + if (IsZoomed(hwnd) && (cfg.resize_action == RESIZE_DISABLED)) { - flip_full_screen(); + ShowWindow(hwnd, SW_RESTORE); } } @@ -1643,6 +1676,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, cfg.width != prev_cfg.width || cfg.savelines != prev_cfg.savelines || cfg.resize_action == RESIZE_FONT || + (cfg.resize_action == RESIZE_EITHER && IsZoomed(hwnd)) || cfg.resize_action == RESIZE_DISABLED) term_size(cfg.height, cfg.width, cfg.savelines); @@ -1670,15 +1704,22 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, nexflag &= ~(WS_EX_CLIENTEDGE); nflg = flag; - if (full_screen ? + if (is_full_screen() ? cfg.scrollbar_in_fullscreen : cfg.scrollbar) nflg |= WS_VSCROLL; else nflg &= ~WS_VSCROLL; + + if (cfg.resize_action == RESIZE_DISABLED || + is_full_screen()) + nflg &= ~WS_THICKFRAME; + else + nflg |= WS_THICKFRAME; + if (cfg.resize_action == RESIZE_DISABLED) - nflg &= ~(WS_THICKFRAME | WS_MAXIMIZEBOX); + nflg &= ~WS_MAXIMIZEBOX; else - nflg |= (WS_THICKFRAME | WS_MAXIMIZEBOX); + nflg |= WS_MAXIMIZEBOX; if (nflg != flag || nexflag != exflag) { if (nflg != flag) @@ -1814,8 +1855,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, PostMessage(hwnd, WM_CHAR, ' ', 0); break; case IDM_FULLSCREEN: - flip_full_screen(); - break; + flip_full_screen(); + break; default: if (wParam >= IDM_SAVED_MIN && wParam <= IDM_SAVED_MAX) { SendMessage(hwnd, WM_SYSCOMMAND, IDM_SAVEDSESS, wParam); @@ -1828,45 +1869,6 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, #define TO_CHR_X(x) ((((x)<0 ? (x)-font_width+1 : (x))-offset_width) / font_width) #define TO_CHR_Y(y) ((((y)<0 ? (y)-font_height+1: (y))-offset_height) / font_height) -#define WHEEL_DELTA 120 - case WM_MOUSEWHEEL: - { - wheel_accumulator += (short) HIWORD(wParam); - wParam = LOWORD(wParam); - - /* process events when the threshold is reached */ - while (abs(wheel_accumulator) >= WHEEL_DELTA) { - int b; - - /* reduce amount for next time */ - if (wheel_accumulator > 0) { - b = MBT_WHEEL_UP; - wheel_accumulator -= WHEEL_DELTA; - } else if (wheel_accumulator < 0) { - b = MBT_WHEEL_DOWN; - wheel_accumulator += WHEEL_DELTA; - } else - break; - - if (send_raw_mouse) { - /* send a mouse-down followed by a mouse up */ - - term_mouse(b, - MA_CLICK, - TO_CHR_X(X_POS(lParam)), - TO_CHR_Y(Y_POS(lParam)), wParam & MK_SHIFT, - wParam & MK_CONTROL, is_alt_pressed()); - term_mouse(b, MA_RELEASE, TO_CHR_X(X_POS(lParam)), - TO_CHR_Y(Y_POS(lParam)), wParam & MK_SHIFT, - wParam & MK_CONTROL, is_alt_pressed()); - } else { - /* trigger a scroll */ - term_scroll(0, - b == MBT_WHEEL_UP ? -rows / 2 : rows / 2); - } - } - return 0; - } case WM_LBUTTONDOWN: case WM_MBUTTONDOWN: case WM_RBUTTONDOWN: @@ -1911,7 +1913,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, * window, we put up the System menu instead of doing * selection. */ - if (full_screen && press && button == MBT_LEFT && + if (is_full_screen() && press && button == MBT_LEFT && X_POS(lParam) == 0 && Y_POS(lParam) == 0) { SendMessage(hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, 0); return 0; @@ -1939,7 +1941,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, */ noise_ultralight(lParam); - if (wParam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) { + if (wParam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON) && + GetCapture() == hwnd) { Mouse_Button b; if (wParam & MK_LBUTTON) b = MBT_LEFT; @@ -2041,10 +2044,10 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, term_update(); break; case WM_KILLFOCUS: - if (full_screen) flip_full_screen(); show_mouseptr(1); has_focus = FALSE; DestroyCaret(); + caret_x = caret_y = -1; /* ensure caret is replaced next time */ term_out(); term_update(); break; @@ -2158,6 +2161,12 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, return rv; } /* break; (never reached) */ + case WM_FULLSCR_ON_MAX: + fullscr_on_max = TRUE; + break; + case WM_MOVE: + sys_cursor_update(); + break; case WM_SIZE: #ifdef RDB_DEBUG_PATCH debug((27, "WM_SIZE %s (%d,%d)", @@ -2173,6 +2182,12 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, cfg.win_name_always ? window_name : icon_name); if (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED) SetWindowText(hwnd, window_name); + if (wParam == SIZE_RESTORED) + clear_full_screen(); + if (wParam == SIZE_MAXIMIZED && fullscr_on_max) { + make_full_screen(); + fullscr_on_max = FALSE; + } if (cfg.resize_action == RESIZE_DISABLED) { /* A resize, well it better be a minimize. */ @@ -2235,6 +2250,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, reset_window(0); } } + sys_cursor_update(); return 0; case WM_VSCROLL: switch (LOWORD(wParam)) { @@ -2344,6 +2360,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, /* wParam == Font number */ /* lParam == Locale */ set_input_locale((HKL)lParam); + sys_cursor_update(); break; case WM_IME_NOTIFY: if(wParam == IMN_SETOPENSTATUS) { @@ -2358,7 +2375,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, HIMC hIMC; int n; char *buff; - + if(osVersion.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS || osVersion.dwPlatformId == VER_PLATFORM_WIN32s) break; /* no Unicode */ @@ -2369,9 +2386,17 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, n = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, NULL, 0); if (n > 0) { + int i; buff = (char*) smalloc(n); ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, buff, n); - luni_send((unsigned short *)buff, n / 2, 1); + /* + * Jaeyoun Chung reports that Korean character + * input doesn't work correctly if we do a single + * luni_send() covering the whole of buff. So + * instead we luni_send the characters one by one. + */ + for (i = 0; i < n; i += 2) + luni_send((unsigned short *)(buff+i), 1, 1); free(buff); } ImmReleaseContext(hwnd, hIMC); @@ -2408,6 +2433,56 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, SetCursor(LoadCursor(NULL, IDC_ARROW)); return TRUE; } + default: + if (message == wm_mousewheel || message == WM_MOUSEWHEEL) { + int shift_pressed=0, control_pressed=0, alt_pressed=0; + + if (message == WM_MOUSEWHEEL) { + wheel_accumulator += (short)HIWORD(wParam); + shift_pressed=LOWORD(wParam) & MK_SHIFT; + control_pressed=LOWORD(wParam) & MK_CONTROL; + } else { + BYTE keys[256]; + wheel_accumulator += (int)wParam; + if (GetKeyboardState(keys)!=0) { + shift_pressed=keys[VK_SHIFT]&0x80; + control_pressed=keys[VK_CONTROL]&0x80; + } + } + + /* process events when the threshold is reached */ + while (abs(wheel_accumulator) >= WHEEL_DELTA) { + int b; + + /* reduce amount for next time */ + if (wheel_accumulator > 0) { + b = MBT_WHEEL_UP; + wheel_accumulator -= WHEEL_DELTA; + } else if (wheel_accumulator < 0) { + b = MBT_WHEEL_DOWN; + wheel_accumulator += WHEEL_DELTA; + } else + break; + + if (send_raw_mouse && + !(cfg.mouse_override && shift_pressed)) { + /* send a mouse-down followed by a mouse up */ + term_mouse(b, + MA_CLICK, + TO_CHR_X(X_POS(lParam)), + TO_CHR_Y(Y_POS(lParam)), shift_pressed, + control_pressed, is_alt_pressed()); + term_mouse(b, MA_RELEASE, TO_CHR_X(X_POS(lParam)), + TO_CHR_Y(Y_POS(lParam)), shift_pressed, + control_pressed, is_alt_pressed()); + } else { + /* trigger a scroll */ + term_scroll(0, + b == MBT_WHEEL_UP ? -rows / 2 : rows / 2); + } + } + return 0; + } } return DefWindowProc(hwnd, message, wParam, lParam); @@ -2421,13 +2496,35 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, */ void sys_cursor(int x, int y) { + int cx, cy; + + if (!has_focus) return; + + /* + * Avoid gratuitously re-updating the cursor position and IMM + * window if there's no actual change required. + */ + cx = x * font_width + offset_width; + cy = y * font_height + offset_height; + if (cx == caret_x && cy == caret_y) + return; + caret_x = cx; + caret_y = cy; + + sys_cursor_update(); +} + +static void sys_cursor_update(void) +{ COMPOSITIONFORM cf; HIMC hIMC; if (!has_focus) return; - - SetCaretPos(x * font_width + offset_width, - y * font_height + offset_height); + + if (caret_x < 0 || caret_y < 0) + return; + + SetCaretPos(caret_x, caret_y); /* IMM calls on Win98 and beyond only */ if(osVersion.dwPlatformId == VER_PLATFORM_WIN32s) return; /* 3.11 */ @@ -2438,8 +2535,8 @@ void sys_cursor(int x, int y) /* we should have the IMM functions */ hIMC = ImmGetContext(hwnd); cf.dwStyle = CFS_POINT; - cf.ptCurrentPos.x = x * font_width + offset_width; - cf.ptCurrentPos.y = y * font_height + offset_height; + cf.ptCurrentPos.x = caret_x; + cf.ptCurrentPos.y = caret_y; ImmSetCompositionWindow(hIMC, &cf); ImmReleaseContext(hwnd, hIMC); @@ -3470,11 +3567,24 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, p += sprintf((char *) p, "\x1B%c", xkey); else { int app_flg = (app_cursor_keys && !cfg.no_applic_c); - /* VT100 & VT102 manuals both state the app cursor keys - * only work if the app keypad is on. +#if 0 + /* + * RDB: VT100 & VT102 manuals both state the + * app cursor keys only work if the app keypad + * is on. + * + * SGT: That may well be true, but xterm + * disagrees and so does at least one + * application, so I've #if'ed this out and the + * behaviour is back to PuTTY's original: app + * cursor and app keypad are independently + * switchable modes. If anyone complains about + * _this_ I'll have to put in a configurable + * option. */ if (!app_keypad_keys) app_flg = 0; +#endif /* Useful mapping of Ctrl-arrows */ if (shift_state == 2) app_flg = !app_flg; @@ -3654,8 +3764,7 @@ void set_sbar(int total, int start, int page) { SCROLLINFO si; - if ((full_screen && !cfg.scrollbar_in_fullscreen) || - (!full_screen && !cfg.scrollbar)) + if (is_full_screen() ? !cfg.scrollbar_in_fullscreen : !cfg.scrollbar) return; si.cbSize = sizeof(si); @@ -3788,13 +3897,11 @@ void write_clip(wchar_t * data, int len, int must_deselect) len * sizeof(wchar_t)); clipdata2 = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, len2); - if (!clipdata || !clipdata2 || !clipdata3) { + if (!clipdata || !clipdata2) { if (clipdata) GlobalFree(clipdata); if (clipdata2) GlobalFree(clipdata2); - if (clipdata3) - GlobalFree(clipdata3); return; } if (!(lock = GlobalLock(clipdata))) @@ -4096,68 +4203,6 @@ void beep(int mode) } /* - * Toggle full screen mode. Thanks to cwis@nerim.fr for the - * implementation. - * Revised by - */ -static void flip_full_screen(void) -{ - WINDOWPLACEMENT wp; - LONG style; - - wp.length = sizeof(wp); - GetWindowPlacement(hwnd, &wp); - - full_screen = !full_screen; - - if (full_screen) { - if (wp.showCmd == SW_SHOWMAXIMIZED) { - /* Ooops it was already 'zoomed' we have to unzoom it before - * everything will work right. - */ - wp.showCmd = SW_SHOWNORMAL; - SetWindowPlacement(hwnd, &wp); - } - - style = GetWindowLong(hwnd, GWL_STYLE) & ~(WS_CAPTION|WS_THICKFRAME); - style &= ~WS_VSCROLL; - if (cfg.scrollbar_in_fullscreen) - style |= WS_VSCROLL; - SetWindowLong(hwnd, GWL_STYLE, style); - - /* Some versions of explorer get confused and don't take - * notice of us going fullscreen, so go topmost too. - */ - SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, - SWP_NOACTIVATE | SWP_NOCOPYBITS | - SWP_NOMOVE | SWP_NOSIZE | - SWP_FRAMECHANGED); - - wp.showCmd = SW_SHOWMAXIMIZED; - SetWindowPlacement(hwnd, &wp); - } else { - style = GetWindowLong(hwnd, GWL_STYLE) | WS_CAPTION; - if (cfg.resize_action != RESIZE_DISABLED) - style |= WS_THICKFRAME; - style &= ~WS_VSCROLL; - if (cfg.scrollbar) - style |= WS_VSCROLL; - SetWindowLong(hwnd, GWL_STYLE, style); - - SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, - SWP_NOACTIVATE | SWP_NOCOPYBITS | - SWP_NOMOVE | SWP_NOSIZE | - SWP_FRAMECHANGED); - - wp.showCmd = SW_SHOWNORMAL; - SetWindowPlacement(hwnd, &wp); - } - - CheckMenuItem(GetSystemMenu(hwnd, FALSE), IDM_FULLSCREEN, - MF_BYCOMMAND| full_screen ? MF_CHECKED : MF_UNCHECKED); -} - -/* * Minimise or restore the window in response to a server-side * request. */ @@ -4177,6 +4222,11 @@ void set_iconic(int iconic) */ void move_window(int x, int y) { + if (cfg.resize_action == RESIZE_DISABLED || + cfg.resize_action == RESIZE_FONT || + IsZoomed(hwnd)) + return; + SetWindowPos(hwnd, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER); } @@ -4186,7 +4236,7 @@ void move_window(int x, int y) */ void set_zorder(int top) { - if (cfg.alwaysontop || full_screen) + if (cfg.alwaysontop) return; /* ignore */ SetWindowPos(hwnd, top ? HWND_TOP : HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); @@ -4206,13 +4256,9 @@ void refresh_window(void) */ void set_zoomed(int zoomed) { - if (IsZoomed(hwnd) || full_screen) { - if (!zoomed) { - if (full_screen) - flip_full_screen(); - else - ShowWindow(hwnd, SW_RESTORE); - } + if (IsZoomed(hwnd)) { + if (!zoomed) + ShowWindow(hwnd, SW_RESTORE); } else { if (zoomed) ShowWindow(hwnd, SW_MAXIMIZE); @@ -4256,3 +4302,105 @@ char *get_window_title(int icon) { return icon ? icon_name : window_name; } + +/* + * See if we're in full-screen mode. + */ +int is_full_screen() +{ + if (!IsZoomed(hwnd)) + return FALSE; + if (GetWindowLong(hwnd, GWL_STYLE) & WS_CAPTION) + return FALSE; + return TRUE; +} + +/* + * Go full-screen. This should only be called when we are already + * maximised. + */ +void make_full_screen() +{ + DWORD style; + int x, y, w, h; + + assert(IsZoomed(hwnd)); + + /* Remove the window furniture. */ + style = GetWindowLong(hwnd, GWL_STYLE); + style &= ~(WS_CAPTION | WS_BORDER | WS_THICKFRAME); + if (cfg.scrollbar_in_fullscreen) + style |= WS_VSCROLL; + else + style &= ~WS_VSCROLL; + SetWindowLong(hwnd, GWL_STYLE, style); + + /* Resize ourselves to exactly cover the nearest monitor. */ +#ifdef MONITOR_DEFAULTTONEAREST + { + HMONITOR mon; + MONITORINFO mi; + mon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); + mi.cbSize = sizeof(mi); + GetMonitorInfo(mon, &mi); + x = mi.rcMonitor.left; + y = mi.rcMonitor.top; + w = mi.rcMonitor.right; + h = mi.rcMonitor.bottom; + } +#else + x = y = 0; + w = GetSystemMetrics(SM_CXSCREEN); + h = GetSystemMetrics(SM_CYSCREEN); +#endif + SetWindowPos(hwnd, HWND_TOP, x, y, w, h, SWP_FRAMECHANGED); + + /* Tick the menu item in the System menu. */ + CheckMenuItem(GetSystemMenu(hwnd, FALSE), IDM_FULLSCREEN, + MF_CHECKED); +} + +/* + * Clear the full-screen attributes. + */ +void clear_full_screen() +{ + DWORD oldstyle, style; + + /* Reinstate the window furniture. */ + style = oldstyle = GetWindowLong(hwnd, GWL_STYLE); + style |= WS_CAPTION | WS_BORDER; + if (cfg.resize_action == RESIZE_DISABLED) + style &= ~WS_THICKFRAME; + else + style |= WS_THICKFRAME; + if (cfg.scrollbar) + style |= WS_VSCROLL; + else + style &= ~WS_VSCROLL; + if (style != oldstyle) { + SetWindowLong(hwnd, GWL_STYLE, style); + SetWindowPos(hwnd, NULL, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | + SWP_FRAMECHANGED); + } + + /* Untick the menu item in the System menu. */ + CheckMenuItem(GetSystemMenu(hwnd, FALSE), IDM_FULLSCREEN, + MF_UNCHECKED); +} + +/* + * Toggle full-screen mode. + */ +void flip_full_screen() +{ + if (is_full_screen()) { + ShowWindow(hwnd, SW_RESTORE); + } else if (IsZoomed(hwnd)) { + make_full_screen(); + } else { + SendMessage(hwnd, WM_FULLSCR_ON_MAX, 0, 0); + ShowWindow(hwnd, SW_MAXIMIZE); + } +}