Commit 96409189 authored by Dmitry Timoshkov's avatar Dmitry Timoshkov Committed by Alexandre Julliard

- Make GetSystemMenu respect CS_NOCLOSE.

- EnableMenuItem should not generate WM_WINDOWPOSCHANGING message. - Make nonclient code check for presence of SC_CLOSE, not CS_NOCLOSE window class style. - Add a test case.
parent 46d2be98
...@@ -380,6 +380,9 @@ HMENU MENU_GetSysMenu( HWND hWnd, HMENU hPopupMenu ) ...@@ -380,6 +380,9 @@ HMENU MENU_GetSysMenu( HWND hWnd, HMENU hPopupMenu )
if (hPopupMenu) if (hPopupMenu)
{ {
if (GetClassLongW(hWnd, GCL_STYLE) & CS_NOCLOSE)
DeleteMenu(hPopupMenu, SC_CLOSE, MF_BYCOMMAND);
InsertMenuW( hMenu, -1, MF_SYSMENU | MF_POPUP | MF_BYPOSITION, InsertMenuW( hMenu, -1, MF_SYSMENU | MF_POPUP | MF_BYPOSITION,
(UINT_PTR)hPopupMenu, NULL ); (UINT_PTR)hPopupMenu, NULL );
...@@ -3248,15 +3251,18 @@ UINT WINAPI EnableMenuItem( HMENU hMenu, UINT wItemID, UINT wFlags ) ...@@ -3248,15 +3251,18 @@ UINT WINAPI EnableMenuItem( HMENU hMenu, UINT wItemID, UINT wFlags )
{ {
if (menu->hSysMenuOwner != 0) if (menu->hSysMenuOwner != 0)
{ {
RECT rc;
POPUPMENU* parentMenu; POPUPMENU* parentMenu;
/* Get the parent menu to access*/ /* Get the parent menu to access*/
if (!(parentMenu = MENU_GetMenu(menu->hSysMenuOwner))) if (!(parentMenu = MENU_GetMenu(menu->hSysMenuOwner)))
return (UINT)-1; return (UINT)-1;
/* Refresh the frame to reflect the change*/ /* Refresh the frame to reflect the change */
SetWindowPos(parentMenu->hWnd, 0, 0, 0, 0, 0, GetWindowRect(parentMenu->hWnd, &rc);
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER); MapWindowPoints(0, parentMenu->hWnd, (POINT *)&rc, 2);
rc.bottom = 0;
RedrawWindow(parentMenu->hWnd, &rc, 0, RDW_FRAME | RDW_INVALIDATE | RDW_NOCHILDREN);
} }
} }
......
...@@ -2849,6 +2849,47 @@ static void test_showwindow(void) ...@@ -2849,6 +2849,47 @@ static void test_showwindow(void)
flush_sequence(); flush_sequence();
} }
static void test_sys_menu(HWND hwnd)
{
HMENU hmenu;
UINT state;
/* test existing window without CS_NOCLOSE style */
hmenu = GetSystemMenu(hwnd, FALSE);
ok(hmenu != 0, "GetSystemMenu error %ld\n", GetLastError());
state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND);
ok(state != 0xffffffff, "wrong SC_CLOSE state %x\n", state);
ok(!(state & (MF_DISABLED | MF_GRAYED)), "wrong SC_CLOSE state %x\n", state);
EnableMenuItem(hmenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);
ok_sequence(WmEmptySeq, "WmEnableMenuItem", FALSE);
state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND);
ok(state != 0xffffffff, "wrong SC_CLOSE state %x\n", state);
ok((state & (MF_DISABLED | MF_GRAYED)) == MF_GRAYED, "wrong SC_CLOSE state %x\n", state);
EnableMenuItem(hmenu, SC_CLOSE, 0);
ok_sequence(WmEmptySeq, "WmEnableMenuItem", FALSE);
state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND);
ok(state != 0xffffffff, "wrong SC_CLOSE state %x\n", state);
ok(!(state & (MF_DISABLED | MF_GRAYED)), "wrong SC_CLOSE state %x\n", state);
/* test new window with CS_NOCLOSE style */
hwnd = CreateWindowExA(0, "NoCloseWindowClass", NULL, WS_OVERLAPPEDWINDOW,
100, 100, 200, 200, 0, 0, 0, NULL);
ok (hwnd != 0, "Failed to create overlapped window\n");
hmenu = GetSystemMenu(hwnd, FALSE);
ok(hmenu != 0, "GetSystemMenu error %ld\n", GetLastError());
state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND);
ok(state == 0xffffffff, "wrong SC_CLOSE state %x\n", state);
DestroyWindow(hwnd);
}
/* test if we receive the right sequence of messages */ /* test if we receive the right sequence of messages */
static void test_messages(void) static void test_messages(void)
{ {
...@@ -2912,6 +2953,9 @@ static void test_messages(void) ...@@ -2912,6 +2953,9 @@ static void test_messages(void)
SetWindowPos( hwnd, 0, 0, 0, 200, 200, SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE ); SetWindowPos( hwnd, 0, 0, 0, 200, 200, SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE );
ok_sequence(WmSWP_ResizePopupSeq, "SetWindowPos:ResizePopup", FALSE ); ok_sequence(WmSWP_ResizePopupSeq, "SetWindowPos:ResizePopup", FALSE );
test_sys_menu(hwnd);
flush_sequence();
DestroyWindow(hwnd); DestroyWindow(hwnd);
ok_sequence(WmDestroyOverlappedSeq, "DestroyWindow:overlapped", FALSE); ok_sequence(WmDestroyOverlappedSeq, "DestroyWindow:overlapped", FALSE);
...@@ -4650,6 +4694,10 @@ static BOOL RegisterWindowClasses(void) ...@@ -4650,6 +4694,10 @@ static BOOL RegisterWindowClasses(void)
cls.lpszClassName = "SimpleWindowClass"; cls.lpszClassName = "SimpleWindowClass";
if(!RegisterClassA(&cls)) return FALSE; if(!RegisterClassA(&cls)) return FALSE;
cls.style = CS_NOCLOSE;
cls.lpszClassName = "NoCloseWindowClass";
if(!RegisterClassA(&cls)) return FALSE;
ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n"); ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n");
cls.style = 0; cls.style = 0;
cls.hInstance = GetModuleHandleA(0); cls.hInstance = GetModuleHandleA(0);
......
...@@ -891,9 +891,9 @@ static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd, DWORD style, ...@@ -891,9 +891,9 @@ static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd, DWORD style,
hSysMenu = GetSystemMenu(hwnd, FALSE); hSysMenu = GetSystemMenu(hwnd, FALSE);
state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND); state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
/* Draw a grayed close button if disabled and a normal one if SC_CLOSE is not there */ /* Draw a grayed close button if disabled or if SC_CLOSE is not there */
NC_DrawCloseButton (hwnd, hdc, FALSE, NC_DrawCloseButton (hwnd, hdc, FALSE,
((((state & MF_DISABLED) || (state & MF_GRAYED))) && (state != 0xFFFFFFFF))); (state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF));
r.right -= GetSystemMetrics(SM_CYCAPTION) - 1; r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX)) if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
...@@ -1451,9 +1451,17 @@ LONG NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam ) ...@@ -1451,9 +1451,17 @@ LONG NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
break; break;
case HTSYSMENU: case HTSYSMENU:
if (!(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE)) {
HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
/* If the item close of the sysmenu is disabled or not there do nothing */
if ((state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF))
break;
SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam ); SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
break; break;
}
case HTHSCROLL: case HTHSCROLL:
SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam ); SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
......
...@@ -1023,7 +1023,7 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom, ...@@ -1023,7 +1023,7 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
wndPtr->userdata = 0; wndPtr->userdata = 0;
wndPtr->hIcon = 0; wndPtr->hIcon = 0;
wndPtr->hIconSmall = 0; wndPtr->hIconSmall = 0;
wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, 0 ) : 0; wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, (HMENU)-1 ) : 0;
/* /*
* Correct the window styles. * Correct the window styles.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment