Implemented the system button behavior and associated it to the system

menu in win95. Also permit the SC_CLOSE item to be disabled.
This commit is contained in:
Pascal Lessard 1999-07-31 13:02:02 +00:00 committed by Alexandre Julliard
parent 1c08ac604e
commit d814bb657a
2 changed files with 261 additions and 41 deletions

View File

@ -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;
}

View File

@ -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) )) {
@ -2280,6 +2340,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
*
@ -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;
else
paintButton =
(TWEAK_WineLook == WIN31_LOOK) ? &NC_DrawMaxButton : &NC_DrawMaxButton95;
(*paintButton)( hwnd, hdc, TRUE );
if (wParam == HTMINBUTTON)
paintButton = &NC_DrawMinButton;
else
paintButton = &NC_DrawMaxButton;
(*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;
}