314 lines
8.7 KiB
C
314 lines
8.7 KiB
C
#include "ctlspriv.h"
|
|
|
|
#define MAININSYS
|
|
|
|
#ifndef WIN32
|
|
/* This returns the index of a submenu in a parent menu. The return is
|
|
* < 0 if the submenu does not exist in the parent menu
|
|
*/
|
|
int GetMenuIndex(HMENU hMenu, HMENU hSubMenu)
|
|
{
|
|
int i;
|
|
|
|
if (!hMenu || !hSubMenu)
|
|
return(-1);
|
|
|
|
for (i=GetMenuItemCount(hMenu)-1; i>=0; --i)
|
|
{
|
|
if (hSubMenu == GetSubMenu(hMenu, i))
|
|
break;
|
|
}
|
|
|
|
return(i);
|
|
}
|
|
#endif // WIN32
|
|
|
|
|
|
BOOL IsMaxedMDI(HMENU hMenu)
|
|
{
|
|
return(GetMenuItemID(hMenu, GetMenuItemCount(hMenu)-1) == SC_RESTORE);
|
|
}
|
|
|
|
|
|
/* Note that if iMessage is WM_COMMAND, it is assumed to have come from
|
|
* a header bar or toolbar; do not pass in WM_COMMAND messages from any
|
|
* other controls.
|
|
*/
|
|
|
|
#define MS_ID GET_WM_MENUSELECT_CMD
|
|
#define MS_FLAGS GET_WM_MENUSELECT_FLAGS
|
|
#define MS_MENU GET_WM_MENUSELECT_HMENU
|
|
|
|
#define CMD_NOTIFY GET_WM_COMMAND_CMD
|
|
#define CMD_ID GET_WM_COMMAND_ID
|
|
#define CMD_CTRL GET_WM_COMMAND_HWND
|
|
|
|
|
|
void WINAPI MenuHelp(UINT iMessage, WPARAM wParam, LPARAM lParam,
|
|
HMENU hMainMenu, HINSTANCE hAppInst, HWND hwndStatus, UINT *lpwIDs)
|
|
{
|
|
UINT wID;
|
|
UINT *lpwPopups;
|
|
int i;
|
|
TCHAR szString[256];
|
|
BOOL bUpdateNow = TRUE;
|
|
#if defined(WINDOWS_ME)
|
|
MENUITEMINFO mii;
|
|
#endif
|
|
|
|
switch (iMessage)
|
|
{
|
|
case WM_MENUSELECT:
|
|
if ((WORD)MS_FLAGS(wParam, lParam)==(WORD)-1 && MS_MENU(wParam, lParam)==0)
|
|
{
|
|
#ifndef WIN32
|
|
EndMenuHelp:
|
|
#endif
|
|
SendMessage(hwndStatus, SB_SIMPLE, 0, 0L);
|
|
break;
|
|
}
|
|
|
|
szString[0] = TEXT('\0');
|
|
#if defined(WINDOWS_ME)
|
|
i = MS_ID(wParam, lParam);
|
|
|
|
memset(&mii, 0, SIZEOF(MENUITEMINFO ));
|
|
mii.cbSize = sizeof(mii);
|
|
mii.fMask = MIIM_TYPE;
|
|
mii.cch = 0; //If we ask for MIIM_TYPE, this must be set to zero!
|
|
//Otherwise, win95 attempts to copy the string too!
|
|
if (GetMenuItemInfo((HMENU)MS_MENU(wParam, lParam), i, TRUE, &mii))
|
|
mii.fState = mii.fType & MFT_RIGHTORDER ?SBT_RTLREADING :0;
|
|
#endif
|
|
if (!(MS_FLAGS(wParam, lParam)&MF_SEPARATOR))
|
|
{
|
|
if (MS_FLAGS(wParam, lParam)&MF_POPUP)
|
|
{
|
|
/* We don't want to update immediately in case the menu is
|
|
* about to pop down, with an item selected. This gets rid
|
|
* of some flashing text.
|
|
*/
|
|
bUpdateNow = FALSE;
|
|
|
|
/* First check if this popup is in our list of popup menus
|
|
*/
|
|
for (lpwPopups=lpwIDs+2; *lpwPopups; lpwPopups+=2)
|
|
{
|
|
/* lpwPopups is a list of string ID/menu handle pairs
|
|
* and MS_ID(wParam, lParam) is the menu handle of the selected popup
|
|
*/
|
|
if (*(lpwPopups+1) == (UINT)MS_ID(wParam, lParam))
|
|
{
|
|
wID = *lpwPopups;
|
|
goto LoadTheString;
|
|
}
|
|
}
|
|
|
|
/* Check if the specified popup is in the main menu;
|
|
* note that if the "main" menu is in the system menu,
|
|
* we will be OK as long as the menu is passed in correctly.
|
|
* In fact, an app could handle all popups by just passing in
|
|
* the proper hMainMenu.
|
|
*/
|
|
if ((HMENU)MS_MENU(wParam, lParam) == hMainMenu)
|
|
{
|
|
#ifdef WIN32
|
|
i = MS_ID(wParam, lParam);
|
|
#else // WIN32
|
|
i = GetMenuIndex((HMENU)MS_MENU(wParam, lParam), (HMENU)MS_ID(wParam, lParam));
|
|
if (i >= 0)
|
|
#endif // WIN32
|
|
{
|
|
if (IsMaxedMDI(hMainMenu))
|
|
{
|
|
if (!i)
|
|
{
|
|
wID = IDS_SYSMENU;
|
|
hAppInst = HINST_THISDLL;
|
|
goto LoadTheString;
|
|
}
|
|
else
|
|
--i;
|
|
}
|
|
wID = (UINT)(i + lpwIDs[1]);
|
|
goto LoadTheString;
|
|
}
|
|
}
|
|
|
|
/* This assumes all app defined popups in the system menu
|
|
* have been listed above
|
|
*/
|
|
if ((MS_FLAGS(wParam, lParam)&MF_SYSMENU))
|
|
{
|
|
wID = IDS_SYSMENU;
|
|
hAppInst = HINST_THISDLL;
|
|
goto LoadTheString;
|
|
}
|
|
|
|
goto NoString;
|
|
}
|
|
else if (MS_ID(wParam, lParam) >= MINSYSCOMMAND)
|
|
{
|
|
wID = (UINT)(MS_ID(wParam, lParam) + MH_SYSMENU);
|
|
hAppInst = HINST_THISDLL;
|
|
}
|
|
else
|
|
{
|
|
wID = (UINT)(MS_ID(wParam, lParam) + lpwIDs[0]);
|
|
}
|
|
|
|
LoadTheString:
|
|
if (hAppInst == HINST_THISDLL)
|
|
LocalizedLoadString(wID, szString, ARRAYSIZE(szString));
|
|
else
|
|
LoadString(hAppInst, wID, szString, ARRAYSIZE(szString));
|
|
}
|
|
|
|
NoString:
|
|
#if defined(WINDOWS_ME)
|
|
SendMessage(hwndStatus, SB_SETTEXT, mii.fState|SBT_NOBORDERS|255,
|
|
(LPARAM)(LPSTR)szString);
|
|
#else
|
|
SendMessage(hwndStatus, SB_SETTEXT, SBT_NOBORDERS|255,
|
|
(LPARAM)(LPTSTR)szString);
|
|
#endif
|
|
SendMessage(hwndStatus, SB_SIMPLE, 1, 0L);
|
|
|
|
if (bUpdateNow)
|
|
UpdateWindow(hwndStatus);
|
|
break;
|
|
|
|
#ifndef WIN32
|
|
|
|
case WM_COMMAND:
|
|
switch (CMD_NOTIFY(wParam, lParam))
|
|
{
|
|
#ifdef WANT_SUCKY_HEADER
|
|
case HBN_BEGINDRAG:
|
|
bUpdateNow = FALSE;
|
|
wID = IDS_HEADER;
|
|
goto BeginSomething;
|
|
|
|
case HBN_BEGINADJUST:
|
|
wID = IDS_HEADERADJ;
|
|
goto BeginSomething;
|
|
#endif
|
|
case TBN_BEGINADJUST:
|
|
/* We don't want to update immediately in case the operation is
|
|
* aborted immediately.
|
|
*/
|
|
bUpdateNow = FALSE;
|
|
wID = IDS_TOOLBARADJ;
|
|
goto BeginSomething;
|
|
|
|
BeginSomething:
|
|
SendMessage(hwndStatus, SB_SIMPLE, 1, 0L);
|
|
hAppInst = HINST_THISDLL;
|
|
goto LoadTheString;
|
|
|
|
case TBN_BEGINDRAG:
|
|
MenuHelp(WM_MENUSELECT, (WPARAM)CMD_CTRL(wParam, lParam), 0L,
|
|
hMainMenu, hAppInst, hwndStatus, lpwIDs);
|
|
break;
|
|
#ifdef WANT_SUCKY_HEADER
|
|
case HBN_ENDDRAG:
|
|
case HBN_ENDADJUST:
|
|
#endif
|
|
case TBN_ENDDRAG:
|
|
case TBN_ENDADJUST:
|
|
goto EndMenuHelp;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
#endif // !WIN32
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
BOOL WINAPI ShowHideMenuCtl(HWND hWnd, WPARAM wParam, LPINT lpInfo)
|
|
{
|
|
HWND hCtl;
|
|
UINT uTool, uShow = MF_UNCHECKED | MF_BYCOMMAND;
|
|
HMENU hMainMenu;
|
|
BOOL bRet = FALSE;
|
|
|
|
hMainMenu = IntToPtr_(HMENU, lpInfo[1]);
|
|
|
|
for (uTool=0; ; ++uTool, lpInfo+=2)
|
|
{
|
|
if ((WPARAM)lpInfo[0] == wParam)
|
|
break;
|
|
if (!lpInfo[0])
|
|
goto DoTheCheck;
|
|
}
|
|
|
|
if (!(GetMenuState(hMainMenu, (UINT) wParam, MF_BYCOMMAND)&MF_CHECKED))
|
|
uShow = MF_CHECKED | MF_BYCOMMAND;
|
|
|
|
switch (uTool)
|
|
{
|
|
case 0:
|
|
bRet = SetMenu(hWnd, (HMENU)((uShow&MF_CHECKED) ? hMainMenu : 0));
|
|
break;
|
|
|
|
default:
|
|
hCtl = GetDlgItem(hWnd, lpInfo[1]);
|
|
if (hCtl)
|
|
{
|
|
ShowWindow(hCtl, (uShow&MF_CHECKED) ? SW_SHOW : SW_HIDE);
|
|
bRet = TRUE;
|
|
}
|
|
else
|
|
uShow = MF_UNCHECKED | MF_BYCOMMAND;
|
|
break;
|
|
}
|
|
|
|
DoTheCheck:
|
|
CheckMenuItem(hMainMenu, (UINT) wParam, uShow);
|
|
|
|
#ifdef MAININSYS
|
|
hMainMenu = GetSubMenu(GetSystemMenu(hWnd, FALSE), 0);
|
|
if (hMainMenu)
|
|
CheckMenuItem(hMainMenu, (UINT) wParam, uShow);
|
|
#endif
|
|
|
|
return(bRet);
|
|
}
|
|
|
|
|
|
void WINAPI GetEffectiveClientRect(HWND hWnd, LPRECT lprc, LPINT lpInfo)
|
|
{
|
|
RECT rc;
|
|
HWND hCtl;
|
|
|
|
GetClientRect(hWnd, lprc);
|
|
|
|
/* Get past the menu
|
|
*/
|
|
for (lpInfo+=2; lpInfo[0]; lpInfo+=2)
|
|
{
|
|
hCtl = GetDlgItem(hWnd, lpInfo[1]);
|
|
/* We check the style bit because the parent window may not be visible
|
|
* yet (still in the create message)
|
|
*/
|
|
if (!hCtl || !(GetWindowStyle(hCtl) & WS_VISIBLE))
|
|
continue;
|
|
|
|
GetWindowRect(hCtl, &rc);
|
|
|
|
//
|
|
// This will do the ScrrenToClient functionality, plus
|
|
// it will return a good rect (left < right) when the
|
|
// hWnd parent is RTL mirrored. [samera]
|
|
//
|
|
MapWindowPoints(HWND_DESKTOP, hWnd, (PPOINT)&rc, 2);
|
|
|
|
SubtractRect(lprc, lprc, &rc);
|
|
}
|
|
}
|