Commit d814bb65 authored by Pascal Lessard's avatar Pascal Lessard Committed by Alexandre Julliard

Implemented the system button behavior and associated it to the system

menu in win95. Also permit the SC_CLOSE item to be disabled.
parent 1c08ac60
......@@ -75,6 +75,7 @@ typedef struct {
HBRUSH hbrBack; /* brush for menu background */
DWORD dwContextHelpID;
DWORD dwMenuData; /* application defined value */
HMENU hSysMenuOwner; /* Handle to the dummy sys menu holder */
} POPUPMENU, *LPPOPUPMENU;
/* internal flags for menu tracking */
......@@ -460,7 +461,10 @@ static void MENU_InitSysMenuPopup( HMENU hmenu, DWORD style, DWORD clsStyle )
gray = !(style & (WS_MAXIMIZE | WS_MINIMIZE));
EnableMenuItem( hmenu, SC_RESTORE, (gray ? MF_GRAYED : MF_ENABLED) );
gray = (clsStyle & CS_NOCLOSE) != 0;
EnableMenuItem( hmenu, SC_CLOSE, (gray ? MF_GRAYED : MF_ENABLED) );
/* The menu item must keep its state if it's disabled */
if(gray)
EnableMenuItem( hmenu, SC_CLOSE, MF_GRAYED);
}
......@@ -3191,15 +3195,39 @@ UINT WINAPI EnableMenuItem( HMENU hMenu, UINT wItemID, UINT wFlags )
{
UINT oldflags;
MENUITEM *item;
POPUPMENU *menu;
TRACE("(%04x, %04X, %04X) !\n",
hMenu, wItemID, wFlags);
/* Get the Popupmenu to access the owner menu */
if (!(menu = (POPUPMENU *) USER_HEAP_LIN_ADDR(hMenu)))
return (UINT)-1;
if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags )))
return (UINT)-1;
oldflags = item->fState & (MF_GRAYED | MF_DISABLED);
item->fState ^= (oldflags ^ wFlags) & (MF_GRAYED | MF_DISABLED);
/* In win95 if the close item in the system menu change update the close button */
if (TWEAK_WineLook == WIN95_LOOK)
if((item->wID == SC_CLOSE) && (oldflags != wFlags))
{
if (menu->hSysMenuOwner != 0)
{
POPUPMENU* parentMenu;
/* Get the parent menu to access*/
if (!(parentMenu = (POPUPMENU *) USER_HEAP_LIN_ADDR(menu->hSysMenuOwner)))
return (UINT)-1;
/* Refresh the frame to reflect the change*/
SetWindowPos(parentMenu->hWnd, 0, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
}
}
return oldflags;
}
......@@ -3777,6 +3805,12 @@ HMENU WINAPI GetSystemMenu( HWND hWnd, BOOL bRevert )
if( wndPtr->hSysMenu )
{
HMENU retvalue = GetSubMenu16(wndPtr->hSysMenu, 0);
/* Store the dummy sysmenu handle to facilitate the refresh */
/* of the close button if the SC_CLOSE item change */
POPUPMENU *menu = (POPUPMENU*) USER_HEAP_LIN_ADDR(retvalue);
menu->hSysMenuOwner = wndPtr->hSysMenu;
WIN_ReleaseWndPtr(wndPtr);
return retvalue;
}
......
......@@ -26,10 +26,13 @@
#include "options.h"
#include "shellapi.h"
#include "cache.h"
#include "bitmap.h"
DECLARE_DEBUG_CHANNEL(nonclient)
DECLARE_DEBUG_CHANNEL(shell)
BOOL NC_DrawGrayButton(HDC hdc, int x, int y);
static HBITMAP16 hbitmapClose = 0;
static HBITMAP16 hbitmapCloseD = 0;
static HBITMAP16 hbitmapMinimize = 0;
......@@ -39,6 +42,17 @@ static HBITMAP16 hbitmapMaximizeD = 0;
static HBITMAP16 hbitmapRestore = 0;
static HBITMAP16 hbitmapRestoreD = 0;
BYTE lpGrayMask[] = { 0xAA, 0xA0,
0x55, 0x50,
0xAA, 0xA0,
0x55, 0x50,
0xAA, 0xA0,
0x55, 0x50,
0xAA, 0xA0,
0x55, 0x50,
0xAA, 0xA0,
0x55, 0x50};
#define SC_ABOUTWINE (SC_SCREENSAVE+1)
#define SC_PUTMARK (SC_SCREENSAVE+2)
......@@ -711,9 +725,11 @@ static LONG NC_DoNCHitTest (WND *wndPtr, POINT16 pt )
if (wndPtr->dwStyle & WS_SYSMENU)
rect.left += GetSystemMetrics(SM_CXSIZE);
if (pt.x <= rect.left) return HTSYSMENU;
/* Check maximize box */
if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
if (pt.x >= rect.right) return HTMAXBUTTON;
/* Check minimize box */
if (wndPtr->dwStyle & WS_MINIMIZEBOX)
......@@ -857,13 +873,16 @@ NC_DoNCHitTest95 (WND *wndPtr, POINT16 pt )
if (pt.x > rect.right) return HTCLOSE;
/* Check maximize box */
if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
/* In win95 there is automatically a Maximize button when there is a minimize one*/
if ((wndPtr->dwStyle & WS_MAXIMIZEBOX)|| (wndPtr->dwStyle & WS_MINIMIZEBOX))
rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
if (pt.x > rect.right) return HTMAXBUTTON;
/* Check minimize box */
if (wndPtr->dwStyle & WS_MINIMIZEBOX)
/* In win95 there is automatically a Maximize button when there is a Maximize one*/
if ((wndPtr->dwStyle & WS_MINIMIZEBOX)||(wndPtr->dwStyle & WS_MAXIMIZEBOX))
rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
if (pt.x > rect.right) return HTMINBUTTON;
return HTCAPTION;
}
......@@ -1061,17 +1080,20 @@ NC_DrawSysButton95 (HWND hwnd, HDC hdc, BOOL down)
* void NC_DrawCloseButton95(
* HWND32 hwnd,
* HDC32 hdc,
* BOOL32 down )
* BOOL32 down,
* BOOL bGrayed )
*
* Draws the Win95 close button.
*
* If bGrayed is true, then draw a disabled Close button
*
* Revision history
* 11-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
* Original implementation from NC_DrawSysButton95 source.
*
*****************************************************************************/
static void NC_DrawCloseButton95 (HWND hwnd, HDC hdc, BOOL down)
static void NC_DrawCloseButton95 (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
{
RECT rect;
HDC hdcMem;
......@@ -1088,10 +1110,15 @@ static void NC_DrawCloseButton95 (HWND hwnd, HDC hdc, BOOL down)
hBmp = down ? hbitmapCloseD : hbitmapClose;
hOldBmp = SelectObject (hdcMem, hBmp);
GetObjectA (hBmp, sizeof(BITMAP), &bmp);
BitBlt (hdc, rect.right - (GetSystemMetrics(SM_CYCAPTION) + 1 + bmp.bmWidth) / 2,
rect.top + (GetSystemMetrics(SM_CYCAPTION) - 1 - bmp.bmHeight) / 2,
bmp.bmWidth, bmp.bmHeight, hdcMem, 0, 0, SRCCOPY);
if(bGrayed)
NC_DrawGrayButton(hdc,rect.right - (GetSystemMetrics(SM_CYCAPTION) + 1 + bmp.bmWidth) / 2 + 2,
rect.top + (GetSystemMetrics(SM_CYCAPTION) - 1 - bmp.bmHeight) / 2 + 2);
SelectObject (hdcMem, hOldBmp);
DeleteDC (hdcMem);
}
......@@ -1103,10 +1130,13 @@ static void NC_DrawCloseButton95 (HWND hwnd, HDC hdc, BOOL down)
* NC_DrawMaxButton95(
* HWND32 hwnd,
* HDC16 hdc,
* BOOL32 down )
* BOOL32 down
* BOOL bGrayed )
*
* Draws the maximize button for Win95 style windows.
*
* If bGrayed is true, then draw a disabled Maximize button
*
* Bugs
* Many. Spacing might still be incorrect. Need to fit a close
* button between the max button and the edge.
......@@ -1118,7 +1148,7 @@ static void NC_DrawCloseButton95 (HWND hwnd, HDC hdc, BOOL down)
*
*****************************************************************************/
static void NC_DrawMaxButton95(HWND hwnd,HDC16 hdc,BOOL down )
static void NC_DrawMaxButton95(HWND hwnd,HDC16 hdc,BOOL down, BOOL bGrayed)
{
RECT rect;
HDC hdcMem;
......@@ -1131,18 +1161,24 @@ static void NC_DrawMaxButton95(HWND hwnd,HDC16 hdc,BOOL down )
NC_GetInsideRect95( hwnd, &rect );
hdcMem = CreateCompatibleDC( hdc );
hBmp = IsZoomed(hwnd) ?
(down ? hbitmapRestoreD : hbitmapRestore ) :
(down ? hbitmapMaximizeD: hbitmapMaximize);
hBmp = IsZoomed(hwnd) ?
(down ? hbitmapRestoreD : hbitmapRestore ) :
(down ? hbitmapMaximizeD: hbitmapMaximize);
hOldBmp=SelectObject( hdcMem, hBmp );
GetObjectA (hBmp, sizeof(BITMAP), &bmp);
if (wndPtr->dwStyle & WS_SYSMENU)
rect.right -= GetSystemMetrics(SM_CYCAPTION) + 1;
BitBlt( hdc, rect.right - (GetSystemMetrics(SM_CXSIZE) + bmp.bmWidth) / 2,
rect.top + (GetSystemMetrics(SM_CYCAPTION) - 1 - bmp.bmHeight) / 2,
bmp.bmWidth, bmp.bmHeight, hdcMem, 0, 0, SRCCOPY );
if(bGrayed)
NC_DrawGrayButton(hdc, rect.right - (GetSystemMetrics(SM_CXSIZE) + bmp.bmWidth) / 2 + 2,
rect.top + (GetSystemMetrics(SM_CYCAPTION) - 1 - bmp.bmHeight) / 2 + 2);
SelectObject (hdcMem, hOldBmp);
DeleteDC( hdcMem );
}
......@@ -1154,10 +1190,13 @@ static void NC_DrawMaxButton95(HWND hwnd,HDC16 hdc,BOOL down )
* NC_DrawMinButton95(
* HWND32 hwnd,
* HDC16 hdc,
* BOOL32 down )
* BOOL32 down,
* BOOL bGrayed )
*
* Draws the minimize button for Win95 style windows.
*
* If bGrayed is true, then draw a disabled Minimize button
*
* Bugs
* Many. Spacing is still incorrect. Should scale the image with the
* title bar. And more...
......@@ -1168,7 +1207,7 @@ static void NC_DrawMaxButton95(HWND hwnd,HDC16 hdc,BOOL down )
*
*****************************************************************************/
static void NC_DrawMinButton95(HWND hwnd,HDC16 hdc,BOOL down )
static void NC_DrawMinButton95(HWND hwnd,HDC16 hdc,BOOL down, BOOL bGrayed)
{
RECT rect;
HDC hdcMem;
......@@ -1190,15 +1229,21 @@ static void NC_DrawMinButton95(HWND hwnd,HDC16 hdc,BOOL down )
if (wndPtr->dwStyle & WS_SYSMENU)
rect.right -= GetSystemMetrics(SM_CYCAPTION) + 1;
if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
/* In win 95 there is always a Maximize box when there is a Minimize one */
if ((wndPtr->dwStyle & WS_MAXIMIZEBOX) || (wndPtr->dwStyle & WS_MINIMIZEBOX))
rect.right += -1 - (GetSystemMetrics(SM_CXSIZE) + bmp.bmWidth) / 2;
BitBlt( hdc, rect.right - (GetSystemMetrics(SM_CXSIZE) + bmp.bmWidth) / 2,
rect.top + (GetSystemMetrics(SM_CYCAPTION) - 1 - bmp.bmHeight) / 2,
bmp.bmWidth, bmp.bmHeight, hdcMem, 0, 0, SRCCOPY );
if(bGrayed)
NC_DrawGrayButton(hdc, rect.right - (GetSystemMetrics(SM_CXSIZE) + bmp.bmWidth) / 2 + 2,
rect.top + (GetSystemMetrics(SM_CYCAPTION) - 1 - bmp.bmHeight) / 2 + 2);
SelectObject (hdcMem, hOldBmp);
DeleteDC( hdcMem );
DeleteDC( hdcMem );
}
WIN_ReleaseWndPtr(wndPtr);
}
......@@ -1486,6 +1531,7 @@ static void NC_DrawCaption95(
WND *wndPtr = WIN_FindWndPtr( hwnd );
char buffer[256];
HPEN hPrevPen;
HMENU hSysMenu;
if (wndPtr->flags & WIN_MANAGED)
{
......@@ -1514,22 +1560,36 @@ static void NC_DrawCaption95(
hbitmapRestore = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_RESTORE) );
hbitmapRestoreD = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_RESTORED) );
}
if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
if (NC_DrawSysButton95 (hwnd, hdc, FALSE))
r.left += GetSystemMetrics(SM_CYCAPTION) - 1;
}
if (style & WS_SYSMENU) {
NC_DrawCloseButton95 (hwnd, hdc, FALSE);
if (style & WS_SYSMENU)
{
UINT state;
/* Go get the sysmenu */
hSysMenu = GetSystemMenu(hwnd, FALSE);
state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
/* Draw a grayed close button if disabled and a normal one if SC_CLOSE is not there */
NC_DrawCloseButton95 (hwnd, hdc, FALSE,
((((state & MF_DISABLED) || (state & MF_GRAYED))) && (state != 0xFFFFFFFF)));
r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
}
if (style & WS_MAXIMIZEBOX) {
NC_DrawMaxButton95( hwnd, hdc, FALSE );
r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
}
if (style & WS_MINIMIZEBOX) {
NC_DrawMinButton95( hwnd, hdc, FALSE );
r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
{
/* In win95 the two buttons are always there */
/* But if the menu item is not in the menu they're disabled*/
NC_DrawMaxButton95( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
NC_DrawMinButton95( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
}
}
if (GetWindowTextA( hwnd, buffer, sizeof(buffer) )) {
......@@ -2281,6 +2341,83 @@ END:
/***********************************************************************
* NC_TrackMinMaxBox95
*
* Track a mouse button press on the minimize or maximize box.
*
* The big difference between 3.1 and 95 is the disabled button state.
* In win95 the system button can be disabled, so it can ignore the mouse
* event.
*
*/
static void NC_TrackMinMaxBox95( HWND hwnd, WORD wParam )
{
MSG msg;
POINT16 pt16;
HDC hdc = GetWindowDC( hwnd );
BOOL pressed = TRUE;
UINT state;
DWORD wndStyle = GetWindowLongA( hwnd, GWL_STYLE);
HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
void (*paintButton)(HWND, HDC16, BOOL, BOOL);
if (wParam == HTMINBUTTON)
{
/* If the style is not present, do nothing */
if (!(wndStyle & WS_MINIMIZEBOX))
return;
/* Check if the sysmenu item for minimize is there */
state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
paintButton = &NC_DrawMinButton95;
}
else
{
/* If the style is not present, do nothing */
if (!(wndStyle & WS_MAXIMIZEBOX))
return;
/* Check if the sysmenu item for maximize is there */
state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
paintButton = &NC_DrawMaxButton95;
}
SetCapture( hwnd );
(*paintButton)( hwnd, hdc, TRUE, FALSE);
do
{
BOOL oldstate = pressed;
MSG_InternalGetMessage( &msg, 0, 0, 0, PM_REMOVE, FALSE );
CONV_POINT32TO16( &msg.pt, &pt16 );
pressed = (NC_HandleNCHitTest( hwnd, pt16 ) == wParam);
if (pressed != oldstate)
(*paintButton)( hwnd, hdc, pressed, FALSE);
} while (msg.message != WM_LBUTTONUP);
(*paintButton)( hwnd, hdc, FALSE, FALSE);
ReleaseCapture();
ReleaseDC( hwnd, hdc );
/* If the item minimize or maximize of the sysmenu are not there */
/* or if the style is not present, do nothing */
if ((!pressed) || (state == 0xFFFFFFFF))
return;
if (wParam == HTMINBUTTON)
SendMessage16( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, *(LONG*)&pt16 );
else
SendMessage16( hwnd, WM_SYSCOMMAND,
IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, *(LONG*)&pt16 );
}
/***********************************************************************
* NC_TrackMinMaxBox
*
* Track a mouse button press on the minimize or maximize box.
......@@ -2294,14 +2431,13 @@ static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
void (*paintButton)(HWND, HDC16, BOOL);
SetCapture( hwnd );
if (wParam == HTMINBUTTON)
paintButton =
(TWEAK_WineLook == WIN31_LOOK) ? &NC_DrawMinButton : &NC_DrawMinButton95;
paintButton = &NC_DrawMinButton;
else
paintButton =
(TWEAK_WineLook == WIN31_LOOK) ? &NC_DrawMaxButton : &NC_DrawMaxButton95;
paintButton = &NC_DrawMaxButton;
(*paintButton)( hwnd, hdc, TRUE );
(*paintButton)( hwnd, hdc, TRUE);
do
{
......@@ -2311,13 +2447,14 @@ static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
pressed = (NC_HandleNCHitTest( hwnd, pt16 ) == wParam);
if (pressed != oldstate)
(*paintButton)( hwnd, hdc, pressed );
(*paintButton)( hwnd, hdc, pressed);
} while (msg.message != WM_LBUTTONUP);
(*paintButton)( hwnd, hdc, FALSE );
(*paintButton)( hwnd, hdc, FALSE);
ReleaseCapture();
ReleaseDC( hwnd, hdc );
if (!pressed) return;
if (wParam == HTMINBUTTON)
......@@ -2338,12 +2475,25 @@ NC_TrackCloseButton95 (HWND hwnd, WORD wParam)
{
MSG msg;
POINT16 pt16;
HDC hdc = GetWindowDC( hwnd );
HDC hdc;
BOOL pressed = TRUE;
HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
UINT state;
if(hSysMenu == 0)
return;
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) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
return;
hdc = GetWindowDC( hwnd );
SetCapture( hwnd );
NC_DrawCloseButton95 (hwnd, hdc, TRUE);
NC_DrawCloseButton95 (hwnd, hdc, TRUE, FALSE);
do
{
......@@ -2353,10 +2503,10 @@ NC_TrackCloseButton95 (HWND hwnd, WORD wParam)
pressed = (NC_HandleNCHitTest( hwnd, pt16 ) == wParam);
if (pressed != oldstate)
NC_DrawCloseButton95 (hwnd, hdc, pressed);
NC_DrawCloseButton95 (hwnd, hdc, pressed, FALSE);
} while (msg.message != WM_LBUTTONUP);
NC_DrawCloseButton95 (hwnd, hdc, FALSE);
NC_DrawCloseButton95 (hwnd, hdc, FALSE, FALSE);
ReleaseCapture();
ReleaseDC( hwnd, hdc );
......@@ -2472,14 +2622,17 @@ LONG NC_HandleNCLButtonDown( WND* pWnd, WPARAM16 wParam, LPARAM lParam )
case HTMINBUTTON:
case HTMAXBUTTON:
NC_TrackMinMaxBox( hwnd, wParam );
if (TWEAK_WineLook == WIN31_LOOK)
NC_TrackMinMaxBox( hwnd, wParam );
else
NC_TrackMinMaxBox95( hwnd, wParam );
break;
case HTCLOSE:
if (TWEAK_WineLook >= WIN95_LOOK)
NC_TrackCloseButton95 (hwnd, wParam);
break;
case HTLEFT:
case HTRIGHT:
case HTTOP:
......@@ -2622,3 +2775,36 @@ LONG NC_HandleSysCommand( HWND hwnd, WPARAM16 wParam, POINT16 pt )
WIN_ReleaseWndPtr(wndPtr);
return 0;
}
/*************************************************************
* NC_DrawGrayButton
*
* Stub for the grayed button of the caption
*
*************************************************************/
BOOL NC_DrawGrayButton(HDC hdc, int x, int y)
{
HBITMAP hMaskBmp;
HDC hdcMask = CreateCompatibleDC (0);
HBRUSH hOldBrush;
hMaskBmp = CreateBitmap (12, 10, 1, 1, lpGrayMask);
if(hMaskBmp == 0)
return FALSE;
SelectObject (hdcMask, hMaskBmp);
/* Draw the grayed bitmap using the mask */
hOldBrush = SelectObject (hdc, RGB(128, 128, 128));
BitBlt (hdc, x, y, 12, 10,
hdcMask, 0, 0, 0xB8074A);
/* Clean up */
SelectObject (hdc, hOldBrush);
DeleteObject(hMaskBmp);
DeleteDC (hdcMask);
return TRUE;
}
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