mirror of
https://github.com/VincentWei/MiniGUI.git
synced 2026-10-01 12:23:22 +08:00
4275 lines
109 KiB
C
4275 lines
109 KiB
C
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IMPORTANT NOTICE
|
|
//
|
|
// The following open source license statement does not apply to any
|
|
// entity in the Exception List published by FMSoft.
|
|
//
|
|
// For more information, please visit:
|
|
//
|
|
// https://www.fmsoft.cn/exception-list
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/*
|
|
* This file is part of MiniGUI, a mature cross-platform windowing
|
|
* and Graphics User Interface (GUI) support system for embedded systems
|
|
* and smart IoT devices.
|
|
*
|
|
* Copyright (C) 2002~2020, Beijing FMSoft Technologies Co., Ltd.
|
|
* Copyright (C) 1998~2002, WEI Yongming
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Or,
|
|
*
|
|
* As this program is a library, any link to this program must follow
|
|
* GNU General Public License version 3 (GPLv3). If you cannot accept
|
|
* GPLv3, you need to be licensed from FMSoft.
|
|
*
|
|
* If you have got a commercial license of this program, please use it
|
|
* under the terms and conditions of the commercial license.
|
|
*
|
|
* For more information about the commercial license, please refer to
|
|
* <http://www.minigui.com/blog/minigui-licensing-policy/>.
|
|
*/
|
|
/*
|
|
** menu.c: The Menu module.
|
|
**
|
|
** Create date: 1999.04.09
|
|
**
|
|
** Used abbreviations in this file:
|
|
** Menu: mnu
|
|
** Popup: ppp
|
|
** Identifier: id
|
|
** Mnemonic: mnic
|
|
** Normal: nml
|
|
** Item: itm
|
|
** Modify records:
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "common.h"
|
|
|
|
#ifdef _MGHAVE_MENU
|
|
#include "minigui.h"
|
|
#include "gdi.h"
|
|
#include "window.h"
|
|
#include "control.h"
|
|
#include "cliprect.h"
|
|
#include "gal.h"
|
|
#include "internals.h"
|
|
#include "menu.h"
|
|
|
|
#define SHORTEN 0
|
|
|
|
/** constant length of menubar or menuitem */
|
|
#define LFRDR_MENUBAROFFX 8
|
|
#define LFRDR_INTERMENUITEMX 12
|
|
#define LFRDR_INTERMENUITEMY 2
|
|
#define LFRDR_MENUITEMOFFX 18
|
|
#define LFRDR_MENUTOPMARGIN 4
|
|
#define LFRDR_MENUBOTTOMMARGIN 4
|
|
#define LFRDR_MENULEFTMARGIN 4
|
|
#define LFRDR_MENURIGHTMARGIN 4
|
|
#define LFRDR_MENUITEMMINX 64
|
|
#define LFRDR_MENUSEPARATORY 4
|
|
#define LFRDR_MENUSEPARATORX 4
|
|
|
|
#define LFRDR_MENUBARITEMMARGIN 2
|
|
|
|
/** minimum menu pic height */
|
|
#define LFRDR_MENUPIC_MIN 6
|
|
|
|
/************************* MENUBAR allocation ********************************/
|
|
static BLOCKHEAP MBHeap;
|
|
inline static void InitFreeMBList (void)
|
|
{
|
|
InitBlockDataHeap (&MBHeap, sizeof (MENUBAR), SIZE_MB_HEAP);
|
|
}
|
|
|
|
inline static PMENUBAR MenuBarAlloc (void)
|
|
{
|
|
return (PMENUBAR) BlockDataAlloc (&MBHeap);
|
|
}
|
|
|
|
inline static void FreeMenuBar (PMENUBAR pmb)
|
|
{
|
|
pmb->category = TYPE_UNDEFINED;
|
|
BlockDataFree (&MBHeap, pmb);
|
|
}
|
|
|
|
inline static void DestroyFreeMBList (void)
|
|
{
|
|
DestroyBlockDataHeap (&MBHeap);
|
|
}
|
|
|
|
/************************* MENUITEM allocation *******************************/
|
|
static BLOCKHEAP MIHeap;
|
|
inline static void InitFreeMIList (void)
|
|
{
|
|
InitBlockDataHeap (&MIHeap, sizeof (MENUITEM), SIZE_MI_HEAP);
|
|
}
|
|
|
|
inline static PMENUITEM MenuItemAlloc (void)
|
|
{
|
|
return (PMENUITEM) BlockDataAlloc (&MIHeap);
|
|
}
|
|
|
|
inline static void FreeMenuItem (MENUITEM* pmi)
|
|
{
|
|
pmi->category = TYPE_UNDEFINED;
|
|
BlockDataFree (&MIHeap, pmi);
|
|
}
|
|
|
|
inline static void DestroyFreeMIList (void)
|
|
{
|
|
DestroyBlockDataHeap (&MIHeap);
|
|
}
|
|
|
|
/************************* TRACKMENUITEM heap *******************************/
|
|
static BLOCKHEAP TMIHeap;
|
|
inline static void InitFreeTMIList (void)
|
|
{
|
|
InitBlockDataHeap (&TMIHeap, sizeof (TRACKMENUINFO), SIZE_TMI_HEAP);
|
|
}
|
|
|
|
inline static PTRACKMENUINFO TrackMenuInfoAlloc (void)
|
|
{
|
|
return (PTRACKMENUINFO) BlockDataAlloc (&TMIHeap);
|
|
}
|
|
|
|
inline static void FreeTrackMenuInfo (TRACKMENUINFO* ptmi)
|
|
{
|
|
BlockDataFree (&TMIHeap, ptmi);
|
|
}
|
|
|
|
inline static void DestroyFreeTMIList(void)
|
|
{
|
|
DestroyBlockDataHeap (&TMIHeap);
|
|
}
|
|
|
|
/************************* Module initialization *****************************/
|
|
|
|
#if 0 /* unused code */
|
|
static BITMAP bmp_menuitem;
|
|
return InitBitmap (HDC_SCREEN_SYS, 16, 12, 0, NULL, &bmp_menuitem);
|
|
UnloadBitmap (&bmp_menuitem);
|
|
#endif
|
|
|
|
BOOL mg_InitMenu (void)
|
|
{
|
|
InitFreeMBList ();
|
|
InitFreeMIList ();
|
|
InitFreeTMIList ();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/************************* Module termination *******************************/
|
|
void mg_TerminateMenu (void)
|
|
{
|
|
DestroyFreeTMIList ();
|
|
DestroyFreeMBList ();
|
|
DestroyFreeMIList ();
|
|
}
|
|
|
|
/***************************** Menu creation *******************************/
|
|
#if 0
|
|
HMENU GUIAPI LoadMenuFromFile (const char* filename, int id)
|
|
{
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
HMENU GUIAPI CreateMenu (void)
|
|
{
|
|
PMENUBAR pmb;
|
|
|
|
if (!(pmb = MenuBarAlloc ()))
|
|
return 0;
|
|
|
|
pmb->category = TYPE_HMENU;
|
|
pmb->type = TYPE_MENUBAR;
|
|
pmb->head = NULL;
|
|
|
|
return (HMENU)pmb;
|
|
}
|
|
|
|
HMENU GUIAPI CreatePopupMenu (PMENUITEMINFO pmii)
|
|
{
|
|
PMENUITEM pmi;
|
|
|
|
#ifdef SHOW_BUG4491
|
|
if (pmii->type == MFT_BITMAP || pmii->type == MFT_STRING) {
|
|
if (pmii->typedata == 0)
|
|
return 0;
|
|
}
|
|
else if (pmii->type == MFT_BMPSTRING) {
|
|
if (pmii->typedata == 0 || pmii->uncheckedbmp == NULL)
|
|
return 0;
|
|
}
|
|
#else
|
|
switch (pmii->type) {
|
|
case MFT_BITMAP:
|
|
case MFT_STRING:
|
|
case MFT_RADIOCHECK:
|
|
case MFT_MARKCHECK:
|
|
if (pmii->typedata == 0)
|
|
return 0;
|
|
break;
|
|
|
|
case MFT_BMPSTRING:
|
|
if (pmii->typedata == 0 || pmii->uncheckedbmp == NULL)
|
|
return 0;
|
|
break;
|
|
|
|
case MFT_SEPARATOR:
|
|
break;
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
if (!(pmi = MenuItemAlloc ()))
|
|
return 0;
|
|
|
|
pmi->category = TYPE_HMENU;
|
|
pmi->type = TYPE_PPPMENU;
|
|
pmi->next = NULL;
|
|
pmi->submenu = NULL;
|
|
|
|
pmi->mnutype = pmii->type;
|
|
pmi->mnustate = pmii->state;
|
|
pmi->id = pmii->id;
|
|
pmi->uncheckedbmp = pmii->uncheckedbmp;
|
|
pmi->checkedbmp = pmii->checkedbmp;
|
|
pmi->itemdata = pmii->itemdata;
|
|
|
|
/* copy string. */
|
|
#ifdef SHOW_BUG4491
|
|
if (pmii->type == MFT_STRING || pmii->type == MFT_BMPSTRING) {
|
|
int len = strlen ((char*)pmii->typedata);
|
|
pmi->typedata = (DWORD)FixStrAlloc (len);
|
|
if (len > 0)
|
|
strcpy ((char*)pmi->typedata, (char*)pmii->typedata);
|
|
}
|
|
else
|
|
pmi->typedata = pmii->typedata;
|
|
#else
|
|
switch (pmii->type) {
|
|
case MFT_STRING:
|
|
case MFT_RADIOCHECK:
|
|
case MFT_MARKCHECK:
|
|
case MFT_BMPSTRING:
|
|
{
|
|
int len = strlen ((char*)pmii->typedata);
|
|
pmi->typedata = (DWORD)FixStrAlloc (len);
|
|
if (len > 0)
|
|
strcpy ((char*)pmi->typedata, (char*)pmii->typedata);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
pmi->typedata = pmii->typedata;
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
if (pmi->mnutype == MFT_BITMAP) {
|
|
if (pmi->uncheckedbmp == NULL)
|
|
pmi->uncheckedbmp = (BITMAP*)pmi->typedata;
|
|
if (pmi->checkedbmp == NULL)
|
|
pmi->checkedbmp = pmi->uncheckedbmp;
|
|
}
|
|
else if (pmi->mnutype == MFT_BMPSTRING) {
|
|
if (pmi->checkedbmp == NULL)
|
|
pmi->checkedbmp = pmi->uncheckedbmp;
|
|
}
|
|
|
|
return (HMENU)pmi;
|
|
}
|
|
|
|
HMENU GUIAPI CreateSystemMenu (HWND hwnd, DWORD dwStyle)
|
|
{
|
|
HMENU hmnu;
|
|
MENUITEMINFO mii;
|
|
|
|
memset (&mii, 0, sizeof(MENUITEMINFO));
|
|
mii.type = MFT_STRING;
|
|
mii.id = 0;
|
|
mii.typedata = (DWORD)GetSysText(IDS_MGST_OPERATIONS);
|
|
|
|
hmnu = CreatePopupMenu (&mii);
|
|
|
|
memset (&mii, 0, sizeof(MENUITEMINFO));
|
|
|
|
if (dwStyle & WS_MINIMIZEBOX) {
|
|
mii.type = MFT_STRING;
|
|
mii.state = 0;
|
|
mii.id = SC_MINIMIZE;
|
|
mii.typedata = (DWORD)GetSysText(IDS_MGST_MINIMIZE);
|
|
InsertMenuItem(hmnu, 0, MF_BYPOSITION, &mii);
|
|
}
|
|
|
|
if (dwStyle & WS_MAXIMIZEBOX) {
|
|
mii.type = MFT_STRING;
|
|
if (dwStyle & WS_MAXIMIZE)
|
|
mii.state = MFS_DISABLED;
|
|
else
|
|
mii.state = 0;
|
|
mii.id = SC_MAXIMIZE;
|
|
mii.typedata = (DWORD)GetSysText(IDS_MGST_MAXIMIZE);
|
|
InsertMenuItem(hmnu, 1, MF_BYPOSITION, &mii);
|
|
|
|
mii.type = MFT_STRING;
|
|
if (dwStyle & WS_MAXIMIZE)
|
|
mii.state = 0;
|
|
else
|
|
mii.state = MFS_DISABLED;
|
|
mii.id = SC_RESTORE;
|
|
mii.typedata = (DWORD)GetSysText(IDS_MGST_RESTORE);
|
|
InsertMenuItem(hmnu, 2, MF_BYPOSITION, &mii);
|
|
|
|
mii.type = MFT_SEPARATOR;
|
|
mii.state = 0;
|
|
mii.id = 0;
|
|
mii.typedata = 0;
|
|
InsertMenuItem(hmnu, 3, TRUE, &mii);
|
|
}
|
|
|
|
mii.type = MFT_STRING;
|
|
mii.state = 0;
|
|
mii.id = SC_CLOSE;
|
|
mii.typedata = (DWORD)GetSysText(IDS_MGST_CLOSE);
|
|
InsertMenuItem(hmnu, 4, MF_BYPOSITION, &mii);
|
|
|
|
return hmnu;
|
|
}
|
|
|
|
static BOOL mnuInsertMenuItem (PMENUITEM pmi, PMENUITEM pnewmi,
|
|
LINT item, BOOL flag)
|
|
{
|
|
PMENUITEM ptmpmi;
|
|
int index;
|
|
|
|
if (flag) {
|
|
// Insert this new menu item at the start.
|
|
if (item == 0) {
|
|
pnewmi->next = pmi;
|
|
return TRUE;
|
|
}
|
|
|
|
index = 1;
|
|
while (pmi->next) {
|
|
|
|
if (index == item) {
|
|
ptmpmi = pmi->next;
|
|
pmi->next = pnewmi;
|
|
pnewmi->next = ptmpmi;
|
|
return FALSE;
|
|
}
|
|
|
|
index ++;
|
|
pmi = pmi->next;
|
|
}
|
|
}
|
|
else {
|
|
if (item == pmi->id) {
|
|
pnewmi->next = pmi;
|
|
return TRUE;
|
|
}
|
|
|
|
while (pmi->next) {
|
|
|
|
if (pmi->next->id == item) {
|
|
ptmpmi = pmi->next;
|
|
pmi->next = pnewmi;
|
|
pnewmi->next = ptmpmi;
|
|
return FALSE;
|
|
}
|
|
|
|
pmi = pmi->next;
|
|
}
|
|
}
|
|
|
|
// append this new menu item at the end.
|
|
pmi->next = pnewmi;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
int GUIAPI InsertMenuItem (HMENU hmnu, LINT item,
|
|
UINT flag, PMENUITEMINFO pmii)
|
|
{
|
|
PMENUBAR pmb;
|
|
PMENUITEM pnewmi, pmi;
|
|
|
|
#ifdef SHOW_BUG4491
|
|
if (pmii->type == MFT_BITMAP || pmii->type == MFT_STRING) {
|
|
if (pmii->typedata == 0)
|
|
return ERR_INVALID_ARGS;
|
|
}
|
|
else if (pmii->type == MFT_BMPSTRING) {
|
|
if (pmii->typedata == 0 || pmii->uncheckedbmp == NULL)
|
|
return ERR_INVALID_ARGS;
|
|
}
|
|
#else
|
|
switch (pmii->type) {
|
|
case MFT_BITMAP:
|
|
case MFT_STRING:
|
|
case MFT_RADIOCHECK:
|
|
case MFT_MARKCHECK:
|
|
if (pmii->typedata == 0)
|
|
return ERR_INVALID_ARGS;
|
|
break;
|
|
|
|
case MFT_BMPSTRING:
|
|
if (pmii->typedata == 0 || pmii->uncheckedbmp == NULL)
|
|
return ERR_INVALID_ARGS;
|
|
break;
|
|
|
|
case MFT_SEPARATOR:
|
|
break;
|
|
|
|
default:
|
|
return ERR_INVALID_ARGS;
|
|
}
|
|
#endif
|
|
|
|
pmb = (PMENUBAR) hmnu;
|
|
|
|
if (pmb->category != TYPE_HMENU)
|
|
return ERR_INVALID_HANDLE;
|
|
|
|
if (!(pnewmi = MenuItemAlloc ()))
|
|
return ERR_RES_ALLOCATION;
|
|
|
|
pnewmi->category = TYPE_HMENU;
|
|
pnewmi->type = TYPE_NMLMENU;
|
|
pnewmi->mnutype = pmii->type;
|
|
pnewmi->mnustate = pmii->state;
|
|
pnewmi->id = pmii->id;
|
|
pnewmi->uncheckedbmp = pmii->uncheckedbmp;
|
|
pnewmi->checkedbmp = pmii->checkedbmp;
|
|
pnewmi->itemdata = pmii->itemdata;
|
|
pnewmi->next = NULL;
|
|
pnewmi->submenu = (PMENUITEM)(pmii->hsubmenu);
|
|
if (pnewmi->mnutype == MFT_SEPARATOR){
|
|
pnewmi->submenu = NULL;
|
|
}
|
|
|
|
/* copy string. */
|
|
#ifdef SHOW_BUG4491
|
|
if (pmii->type == MFT_STRING || pmii->type == MFT_BMPSTRING) {
|
|
int len = strlen ((char*)pmii->typedata);
|
|
pnewmi->typedata = (DWORD)FixStrAlloc (len);
|
|
if (len > 0)
|
|
strcpy ((char*)pnewmi->typedata, (char*)pmii->typedata);
|
|
}
|
|
else
|
|
pnewmi->typedata = pmii->typedata;
|
|
#else
|
|
switch (pmii->type) {
|
|
case MFT_STRING:
|
|
case MFT_RADIOCHECK:
|
|
case MFT_MARKCHECK:
|
|
case MFT_BMPSTRING:
|
|
{
|
|
int len = strlen ((char*)pmii->typedata);
|
|
pnewmi->typedata = (DWORD)FixStrAlloc (len);
|
|
if (len > 0)
|
|
strcpy ((char*)pnewmi->typedata, (char*)pmii->typedata);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
pnewmi->typedata = pmii->typedata;
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
if (pnewmi->mnutype == MFT_BITMAP) {
|
|
if (pnewmi->uncheckedbmp == NULL)
|
|
pnewmi->uncheckedbmp = (BITMAP*)pnewmi->typedata;
|
|
if (pnewmi->checkedbmp == NULL)
|
|
pnewmi->checkedbmp = pnewmi->uncheckedbmp;
|
|
}
|
|
else if (pnewmi->mnutype == MFT_BMPSTRING) {
|
|
if (pnewmi->checkedbmp == NULL)
|
|
pnewmi->checkedbmp = pnewmi->uncheckedbmp;
|
|
}
|
|
|
|
if (pmb->type == TYPE_MENUBAR) {
|
|
pmi = pmb->head;
|
|
|
|
if (!pmi)
|
|
pmb->head = pnewmi;
|
|
else {
|
|
if (mnuInsertMenuItem (pmb->head, pnewmi, item, flag))
|
|
pmb->head = pnewmi;
|
|
}
|
|
}
|
|
else if (pmb->type == TYPE_PPPMENU) {
|
|
pmi = (PMENUITEM)hmnu;
|
|
|
|
if (!pmi->submenu)
|
|
pmi->submenu = pnewmi;
|
|
else {
|
|
if (mnuInsertMenuItem (pmi->submenu, pnewmi, item, flag))
|
|
pmi->submenu = pnewmi;
|
|
}
|
|
}
|
|
else
|
|
return ERR_INVALID_HMENU;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void mnuDeleteMenuItem (PMENUITEM pmi)
|
|
{
|
|
PMENUITEM ptmpmi;
|
|
PMENUITEM psubmi;
|
|
|
|
if (pmi->submenu) {
|
|
psubmi = pmi->submenu;
|
|
while (psubmi) {
|
|
ptmpmi = psubmi->next;
|
|
mnuDeleteMenuItem (psubmi);
|
|
psubmi = ptmpmi;
|
|
}
|
|
}
|
|
|
|
#ifdef SHOW_BUG4491
|
|
if (pmi->mnutype == MFT_STRING || pmi->mnutype == MFT_BMPSTRING)
|
|
FreeFixStr ((void*)pmi->typedata);
|
|
#else
|
|
switch (pmi->mnutype) {
|
|
case MFT_STRING:
|
|
case MFT_RADIOCHECK:
|
|
case MFT_MARKCHECK:
|
|
case MFT_BMPSTRING:
|
|
FreeFixStr ((void*)pmi->typedata);
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
FreeMenuItem (pmi);
|
|
}
|
|
|
|
static PMENUITEM mnuRemoveMenuItem (PMENUITEM phead, LINT item, BOOL flag)
|
|
{
|
|
int index;
|
|
PMENUITEM pmi, ptmpmi;
|
|
|
|
if (!phead) return NULL;
|
|
|
|
if (flag) {
|
|
|
|
if (item == 0) {
|
|
pmi = phead->next;
|
|
if (!phead->submenu)
|
|
mnuDeleteMenuItem (phead);
|
|
return pmi;
|
|
}
|
|
|
|
pmi = phead;
|
|
index = 1;
|
|
while (pmi->next) {
|
|
|
|
if (index == item) {
|
|
ptmpmi = pmi->next;
|
|
pmi->next = pmi->next->next;
|
|
|
|
if (!ptmpmi->submenu)
|
|
mnuDeleteMenuItem (ptmpmi);
|
|
|
|
return phead;
|
|
}
|
|
|
|
index ++;
|
|
pmi = pmi->next;
|
|
}
|
|
}
|
|
else {
|
|
if (phead->id == item) {
|
|
pmi = phead->next;
|
|
if (!phead->submenu)
|
|
mnuDeleteMenuItem (phead);
|
|
return pmi;
|
|
}
|
|
|
|
pmi = phead;
|
|
while (pmi->next) {
|
|
|
|
if (pmi->next->id == item) {
|
|
ptmpmi = pmi->next;
|
|
pmi->next = pmi->next->next;
|
|
|
|
if (!ptmpmi->submenu)
|
|
mnuDeleteMenuItem (ptmpmi);
|
|
|
|
return phead;
|
|
}
|
|
|
|
pmi = pmi->next;
|
|
}
|
|
}
|
|
|
|
return phead;
|
|
}
|
|
|
|
int GUIAPI RemoveMenu (HMENU hmnu, LINT item, UINT flags)
|
|
{
|
|
PMENUBAR pmb;
|
|
PMENUITEM pmi;
|
|
|
|
pmb = (PMENUBAR) hmnu;
|
|
|
|
if (pmb->category != TYPE_HMENU)
|
|
return ERR_INVALID_HANDLE;
|
|
|
|
if (pmb->type == TYPE_MENUBAR)
|
|
pmb->head = mnuRemoveMenuItem (pmb->head, item,
|
|
flags & MF_BYPOSITION);
|
|
else if (pmb->type == TYPE_PPPMENU) {
|
|
pmi = (PMENUITEM) hmnu;
|
|
pmi->submenu = mnuRemoveMenuItem (pmi->submenu, item,
|
|
flags & MF_BYPOSITION);
|
|
}
|
|
else
|
|
return ERR_INVALID_HMENU; /* this is a normal menu item. */
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PMENUITEM mnuDeleteMenu (PMENUITEM phead, LINT item, BOOL flag)
|
|
{
|
|
int index;
|
|
PMENUITEM pmi, ptmpmi;
|
|
|
|
if (!phead) return NULL;
|
|
|
|
if (flag) {
|
|
|
|
if (item == 0) {
|
|
pmi = phead->next;
|
|
mnuDeleteMenuItem (phead);
|
|
return pmi;
|
|
}
|
|
|
|
pmi = phead;
|
|
index = 1;
|
|
while (pmi->next) {
|
|
|
|
if (index == item) {
|
|
ptmpmi = pmi->next;
|
|
pmi->next = pmi->next->next;
|
|
mnuDeleteMenuItem (ptmpmi);
|
|
return phead;
|
|
}
|
|
|
|
index ++;
|
|
pmi = pmi->next;
|
|
}
|
|
}
|
|
else {
|
|
if (phead->id == item) {
|
|
pmi = phead->next;
|
|
mnuDeleteMenuItem (phead);
|
|
return pmi;
|
|
}
|
|
|
|
pmi = phead;
|
|
while (pmi->next) {
|
|
|
|
if (pmi->next->id == item) {
|
|
ptmpmi = pmi->next;
|
|
pmi->next = pmi->next->next;
|
|
mnuDeleteMenuItem (ptmpmi);
|
|
return phead;
|
|
}
|
|
|
|
pmi = pmi->next;
|
|
}
|
|
}
|
|
|
|
return phead;
|
|
}
|
|
|
|
int GUIAPI DeleteMenu (HMENU hmnu, LINT item, UINT flags)
|
|
{
|
|
PMENUBAR pmb;
|
|
PMENUITEM pmi;
|
|
|
|
pmb = (PMENUBAR) hmnu;
|
|
|
|
if (pmb->category != TYPE_HMENU)
|
|
return ERR_INVALID_HANDLE;
|
|
|
|
if (pmb->type == TYPE_MENUBAR){
|
|
pmb->head = mnuDeleteMenu (pmb->head, item,
|
|
flags & MF_BYPOSITION);
|
|
|
|
SendMessage (HWND_DESKTOP,
|
|
MSG_PAINT, 0, 0);
|
|
}
|
|
else if (pmb->type == TYPE_PPPMENU) {
|
|
pmi = (PMENUITEM) hmnu;
|
|
pmi->submenu = mnuDeleteMenu (pmi->submenu, item,
|
|
flags & MF_BYPOSITION);
|
|
}
|
|
else
|
|
return ERR_INVALID_HMENU; /* this is a normal menu item. */
|
|
|
|
return 0;
|
|
}
|
|
|
|
int GUIAPI DestroyMenu (HMENU hmnu)
|
|
{
|
|
PMENUBAR pmb;
|
|
PMENUITEM pmi, ptmpmi;
|
|
|
|
pmb = (PMENUBAR) hmnu;
|
|
|
|
if (pmb->category != TYPE_HMENU)
|
|
return ERR_INVALID_HANDLE;
|
|
|
|
if (pmb->type == TYPE_MENUBAR) {
|
|
pmi = pmb->head;
|
|
while (pmi) {
|
|
ptmpmi = pmi->next;
|
|
mnuDeleteMenuItem (pmi);
|
|
pmi = ptmpmi;
|
|
}
|
|
|
|
FreeMenuBar (pmb);
|
|
}
|
|
else{
|
|
mnuDeleteMenuItem ((PMENUITEM)hmnu);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int GUIAPI IsMenu (HMENU hmnu)
|
|
{
|
|
PMENUBAR pMenu = (PMENUBAR)hmnu;
|
|
|
|
if (pMenu->category != TYPE_HMENU) return 0;
|
|
|
|
return pMenu->type;
|
|
}
|
|
|
|
/*************************** Menu properties support *************************/
|
|
int GUIAPI GetMenuItemCount (HMENU hmnu)
|
|
{
|
|
PMENUBAR pmb;
|
|
PMENUITEM pmi;
|
|
int count;
|
|
|
|
pmb = (PMENUBAR) hmnu;
|
|
|
|
if (pmb->category != TYPE_HMENU)
|
|
return ERR_INVALID_HANDLE;
|
|
|
|
if (pmb->type == TYPE_MENUBAR)
|
|
pmi = pmb->head;
|
|
else if (pmb->type == TYPE_PPPMENU) {
|
|
pmi = (PMENUITEM) hmnu;
|
|
pmi = pmi->submenu;
|
|
}
|
|
else
|
|
pmi = (PMENUITEM) hmnu;
|
|
|
|
count = 0;
|
|
while (pmi) {
|
|
count ++;
|
|
pmi = pmi->next;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
static PMENUITEM mnuGetMenuItem (HMENU hmnu, LINT item, BOOL flag)
|
|
{
|
|
PMENUBAR pmb;
|
|
PMENUITEM pmi;
|
|
int index;
|
|
|
|
pmb = (PMENUBAR) hmnu;
|
|
|
|
if (pmb->category != TYPE_HMENU)
|
|
return NULL;
|
|
|
|
if (pmb->type == TYPE_MENUBAR)
|
|
pmi = pmb->head;
|
|
else if (pmb->type == TYPE_PPPMENU) {
|
|
pmi = (PMENUITEM) hmnu;
|
|
pmi = pmi->submenu;
|
|
}
|
|
else
|
|
pmi = (PMENUITEM) hmnu;
|
|
|
|
if (flag) {
|
|
index = 0;
|
|
while (pmi) {
|
|
if (index == item)
|
|
return pmi;
|
|
|
|
index ++;
|
|
pmi = pmi->next;
|
|
}
|
|
}
|
|
else {
|
|
while (pmi) {
|
|
if (pmi->id == item)
|
|
return pmi;
|
|
|
|
pmi = pmi->next;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
LINT GUIAPI GetMenuItemID (HMENU hmnu, int pos)
|
|
{
|
|
PMENUBAR pmb;
|
|
PMENUITEM pmi;
|
|
int index;
|
|
|
|
pmb = (PMENUBAR) hmnu;
|
|
|
|
if (pmb->category != TYPE_HMENU)
|
|
return ERR_INVALID_HANDLE;
|
|
|
|
if (pmb->type == TYPE_MENUBAR)
|
|
pmi = pmb->head;
|
|
else if (pmb->type == TYPE_PPPMENU) {
|
|
pmi = (PMENUITEM) hmnu;
|
|
pmi = pmi->submenu;
|
|
}
|
|
else
|
|
pmi = (PMENUITEM) hmnu;
|
|
|
|
index = 0;
|
|
while (pmi) {
|
|
|
|
if (index == pos)
|
|
return pmi->id;
|
|
|
|
index ++;
|
|
pmi = pmi->next;
|
|
}
|
|
|
|
return ERR_INVALID_POS;
|
|
}
|
|
|
|
HMENU GUIAPI GetPopupSubMenu (HMENU hpppmnu)
|
|
{
|
|
PMENUITEM pmi;
|
|
|
|
pmi = (PMENUITEM) hpppmnu;
|
|
|
|
if (pmi->category != TYPE_HMENU)
|
|
return 0;
|
|
|
|
if (pmi->type != TYPE_PPPMENU)
|
|
return 0;
|
|
|
|
return (HMENU)(pmi->submenu);
|
|
}
|
|
|
|
HMENU GUIAPI StripPopupHead (HMENU hpppmnu)
|
|
{
|
|
PMENUITEM pmi;
|
|
HMENU hsubmenu;
|
|
|
|
pmi = (PMENUITEM) hpppmnu;
|
|
|
|
if (pmi->category != TYPE_HMENU)
|
|
return 0;
|
|
|
|
if (pmi->type != TYPE_PPPMENU)
|
|
return 0;
|
|
|
|
hsubmenu = (HMENU)(pmi->submenu);
|
|
|
|
#ifdef SHOW_BUG4491
|
|
if (pmi->mnutype == MFT_STRING || pmi->mnutype == MFT_BMPSTRING)
|
|
FreeFixStr ((void*)pmi->typedata);
|
|
#else
|
|
switch (pmi->mnutype) {
|
|
case MFT_STRING:
|
|
case MFT_RADIOCHECK:
|
|
case MFT_MARKCHECK:
|
|
case MFT_BMPSTRING:
|
|
FreeFixStr ((void*)pmi->typedata);
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
FreeMenuItem (pmi);
|
|
|
|
return hsubmenu;
|
|
}
|
|
|
|
HMENU GUIAPI GetSubMenu (HMENU hmnu, int pos)
|
|
{
|
|
PMENUBAR pmb;
|
|
PMENUITEM pmi;
|
|
int index;
|
|
|
|
pmb = (PMENUBAR) hmnu;
|
|
|
|
if (pmb->category != TYPE_HMENU)
|
|
return 0;
|
|
|
|
if (pmb->type == TYPE_MENUBAR)
|
|
pmi = pmb->head;
|
|
else if (pmb->type == TYPE_PPPMENU) {
|
|
pmi = (PMENUITEM) hmnu;
|
|
pmi = pmi->submenu;
|
|
}
|
|
else
|
|
return 0; // this is a normal menu item.
|
|
|
|
index = 0;
|
|
while (pmi) {
|
|
|
|
if (index == pos)
|
|
return (HMENU)(pmi->submenu);
|
|
|
|
index ++;
|
|
pmi = pmi->next;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int GUIAPI GetMenuItemInfo (HMENU hmnu, LINT item,
|
|
UINT flag, PMENUITEMINFO pmii)
|
|
{
|
|
PMENUITEM pmi;
|
|
|
|
if (!(pmi = mnuGetMenuItem (hmnu, item, flag & MF_BYPOSITION)))
|
|
return ERR_INVALID_HMENU;
|
|
|
|
if (pmii->mask & MIIM_CHECKMARKS) {
|
|
pmii->checkedbmp = pmi->checkedbmp;
|
|
pmii->uncheckedbmp = pmi->uncheckedbmp;
|
|
}
|
|
|
|
if (pmii->mask & MIIM_DATA) {
|
|
pmii->itemdata = pmi->itemdata;
|
|
}
|
|
|
|
if (pmii->mask & MIIM_ID) {
|
|
pmii->id = pmi->id;
|
|
}
|
|
|
|
if (pmii->mask & MIIM_STATE) {
|
|
pmii->state = pmi->mnustate;
|
|
}
|
|
|
|
if (pmii->mask & MIIM_SUBMENU) {
|
|
pmii->hsubmenu = (HMENU)(pmi->submenu);
|
|
}
|
|
|
|
if (pmii->mask & MIIM_TYPE) {
|
|
pmii->type = pmi->mnutype;
|
|
#ifdef SHOW_BUG4491
|
|
if (pmii->type == MFT_STRING)
|
|
strncpy ((char*)(pmii->typedata), (char*)(pmi->typedata),
|
|
pmii->cch);
|
|
else
|
|
pmii->typedata = pmi->typedata;
|
|
#else
|
|
switch (pmii->type) {
|
|
case MFT_STRING:
|
|
case MFT_RADIOCHECK:
|
|
case MFT_MARKCHECK:
|
|
case MFT_BMPSTRING:
|
|
strncpy ((char*)(pmii->typedata), (char*)(pmi->typedata),
|
|
pmii->cch);
|
|
break;
|
|
|
|
default:
|
|
pmii->typedata = pmi->typedata;
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int GUIAPI SetMenuItemInfo (HMENU hmnu, LINT item,
|
|
UINT flag, PMENUITEMINFO pmii)
|
|
{
|
|
PMENUITEM pmi;
|
|
|
|
if (!(pmi = mnuGetMenuItem (hmnu, item, flag & MF_BYPOSITION)))
|
|
return ERR_INVALID_HMENU;
|
|
|
|
if (pmii->mask & MIIM_CHECKMARKS) {
|
|
if (pmi->mnutype == MFT_BMPSTRING && pmii->uncheckedbmp == NULL)
|
|
return ERR_INVALID_ARGS;
|
|
|
|
pmi->uncheckedbmp = pmii->uncheckedbmp;
|
|
pmi->checkedbmp = pmii->checkedbmp;
|
|
}
|
|
|
|
if (pmii->mask & MIIM_DATA) {
|
|
pmi->itemdata = pmii->itemdata;
|
|
}
|
|
|
|
if (pmii->mask & MIIM_ID) {
|
|
pmi->id = pmii->id;
|
|
}
|
|
|
|
if (pmii->mask & MIIM_STATE) {
|
|
pmi->mnustate = pmii->state;
|
|
}
|
|
|
|
if (pmii->mask & MIIM_SUBMENU) {
|
|
pmi->submenu = (PMENUITEM)(pmii->hsubmenu);
|
|
}
|
|
|
|
if (pmii->mask & MIIM_TYPE) {
|
|
|
|
#ifdef SHOW_BUG4491
|
|
if (pmi->mnutype == MFT_STRING || pmi->mnutype == MFT_BMPSTRING)
|
|
FreeFixStr ((char*)pmi->typedata);
|
|
#else
|
|
switch (pmi->mnutype) {
|
|
case MFT_STRING:
|
|
case MFT_RADIOCHECK:
|
|
case MFT_MARKCHECK:
|
|
case MFT_BMPSTRING:
|
|
if (pmi->typedata)
|
|
FreeFixStr ((void*)pmi->typedata);
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
pmi->mnutype = pmii->type;
|
|
|
|
#ifdef SHOW_BUG4491
|
|
if ((pmi->mnutype == MFT_STRING
|
|
|| pmi->mnutype == MFT_BMPSTRING
|
|
|| pmi->mnutype == MFT_BITMAP)
|
|
&& pmii->typedata == 0)
|
|
return ERR_INVALID_ARGS;
|
|
|
|
if (pmi->mnutype == MFT_STRING || pmi->mnutype == MFT_BMPSTRING) {
|
|
int len = strlen ((char*)pmii->typedata);
|
|
pmi->typedata = (DWORD)FixStrAlloc (len);
|
|
if (len > 0)
|
|
strcpy ((char*)pmi->typedata, (char*)pmii->typedata);
|
|
}
|
|
else
|
|
pmi->typedata = pmii->typedata;
|
|
#else
|
|
switch (pmii->type) {
|
|
case MFT_STRING:
|
|
case MFT_RADIOCHECK:
|
|
case MFT_MARKCHECK:
|
|
case MFT_BMPSTRING:
|
|
{
|
|
int len;
|
|
if (pmii->typedata == 0) {
|
|
pmi->typedata = 0;
|
|
return ERR_INVALID_ARGS;
|
|
}
|
|
|
|
len = strlen ((char*)pmii->typedata);
|
|
pmi->typedata = (DWORD)FixStrAlloc (len);
|
|
if (len > 0)
|
|
strcpy ((char*)pmi->typedata, (char*)pmii->typedata);
|
|
break;
|
|
}
|
|
|
|
case MFT_BITMAP:
|
|
if (pmii->typedata == 0)
|
|
return ERR_INVALID_ARGS;
|
|
/* no break */
|
|
|
|
default:
|
|
pmi->typedata = pmii->typedata;
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if (pmi->mnutype == MFT_BITMAP) {
|
|
if (pmi->uncheckedbmp == NULL)
|
|
pmi->uncheckedbmp = (BITMAP*)pmi->typedata;
|
|
if (pmi->checkedbmp == NULL)
|
|
pmi->checkedbmp = pmi->uncheckedbmp;
|
|
}
|
|
else if (pmi->mnutype == MFT_BMPSTRING) {
|
|
if (pmi->checkedbmp == NULL)
|
|
pmi->checkedbmp = pmi->uncheckedbmp;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
UINT GUIAPI EnableMenuItem (HMENU hmnu, LINT item, UINT flags)
|
|
{
|
|
PMENUITEM pmi;
|
|
UINT prevstate = 0xFFFFFFFF;
|
|
|
|
if (!(pmi = mnuGetMenuItem (hmnu, item, flags & MF_BYPOSITION)))
|
|
return prevstate;
|
|
|
|
prevstate = 0x0000000F & pmi->mnustate;
|
|
|
|
pmi->mnustate = (0xFFFFFFF0 & pmi->mnustate) | flags;
|
|
|
|
return prevstate;
|
|
}
|
|
|
|
int GUIAPI CheckMenuRadioItem (HMENU hmnu, LINT first, LINT last,
|
|
LINT checkitem, UINT flags)
|
|
{
|
|
PMENUITEM pmi;
|
|
int index;
|
|
|
|
if (!(pmi = mnuGetMenuItem (hmnu, first, flags & MF_BYPOSITION)))
|
|
return ERR_INVALID_HMENU;
|
|
|
|
index = first;
|
|
if (flags & MF_BYPOSITION) {
|
|
while (pmi) {
|
|
/* fix bug 4491 */
|
|
if (pmi->mnutype == MFT_STRING)
|
|
pmi->mnutype = MFT_RADIOCHECK;
|
|
|
|
if (index == checkitem)
|
|
pmi->mnustate = (0xFFFFFFF0 & pmi->mnustate) | MFS_CHECKED;
|
|
else
|
|
pmi->mnustate = (0xFFFFFFF0 & pmi->mnustate) | MFS_UNCHECKED;
|
|
|
|
if (index == last)
|
|
break;
|
|
|
|
index ++;
|
|
pmi = pmi->next;
|
|
}
|
|
}
|
|
else {
|
|
while (pmi) {
|
|
/* fix bug 4491 */
|
|
if (pmi->mnutype == MFT_STRING)
|
|
pmi->mnutype = MFT_RADIOCHECK;
|
|
|
|
if (pmi->id == checkitem)
|
|
pmi->mnustate = (0xFFFFFFF0 & pmi->mnustate) | MFS_CHECKED;
|
|
else
|
|
pmi->mnustate = (0xFFFFFFF0 & pmi->mnustate) | MFS_UNCHECKED;
|
|
|
|
if (pmi->id == last)
|
|
break;
|
|
|
|
pmi = pmi->next;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int GUIAPI SetMenuItemBitmaps (HMENU hmnu, LINT item, UINT flags,
|
|
PBITMAP hBmpUnchecked, PBITMAP hBmpChecked)
|
|
{
|
|
PMENUITEM pmi;
|
|
|
|
if (!(pmi = mnuGetMenuItem (hmnu, item, flags & MF_BYPOSITION)))
|
|
return ERR_INVALID_HMENU;
|
|
|
|
if (pmi->mnutype == MFT_BMPSTRING && hBmpUnchecked == NULL)
|
|
return ERR_INVALID_ARGS;
|
|
|
|
pmi->checkedbmp = hBmpChecked;
|
|
pmi->uncheckedbmp = hBmpUnchecked;
|
|
|
|
if (pmi->mnutype == MFT_BITMAP) {
|
|
if (pmi->uncheckedbmp == NULL)
|
|
pmi->uncheckedbmp = (BITMAP*)pmi->typedata;
|
|
if (pmi->checkedbmp == NULL)
|
|
pmi->checkedbmp = pmi->uncheckedbmp;
|
|
}
|
|
else if (pmi->mnutype == MFT_BMPSTRING) {
|
|
if (pmi->checkedbmp == NULL)
|
|
pmi->checkedbmp = pmi->uncheckedbmp;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifdef _DEBUG_MENU
|
|
|
|
static void mnuDumpMenuItem (PMENUITEM pmi)
|
|
{
|
|
PMENUITEM ptmpmi;
|
|
|
|
printf ("Menu Item (0x%p) Information:\n", pmi);
|
|
|
|
printf ("\tdata category: %d\n", pmi->category);
|
|
printf ("\tdata type: %d\n", pmi->type);
|
|
printf ("\tmenu type: %#x\n", pmi->mnutype);
|
|
printf ("\tmenu state: %#x\n", pmi->mnustate);
|
|
printf ("\tmenu id: %ld\n", pmi->id);
|
|
printf ("\tchecked bitmap: 0x%p\n", pmi->checkedbmp);
|
|
printf ("\tunchecked bitmap:0x%p\n", pmi->uncheckedbmp);
|
|
printf ("\titem data: %p\n", (PVOID)pmi->itemdata);
|
|
if (pmi->mnutype == MFT_STRING)
|
|
printf ("\tstring: %s\n", (char*)pmi->typedata);
|
|
else
|
|
printf ("\ttype data: %p\n", (PVOID)pmi->typedata);
|
|
printf ("\tnext item: 0x%p\n", pmi->next);
|
|
|
|
if (pmi->submenu) {
|
|
ptmpmi = pmi->submenu;
|
|
while (ptmpmi) {
|
|
mnuDumpMenuItem (ptmpmi);
|
|
ptmpmi = ptmpmi->next;
|
|
}
|
|
}
|
|
|
|
printf ("End of Info of Menu Item: 0x%p\n", pmi);
|
|
}
|
|
|
|
void dbg_DumpMenu (HMENU hmnu)
|
|
{
|
|
PMENUBAR pmb;
|
|
PMENUITEM pmi;
|
|
|
|
pmb = (PMENUBAR) hmnu;
|
|
if (pmb->category != TYPE_HMENU) {
|
|
printf ("hmnu is not a valid menu handle.\n");
|
|
return;
|
|
}
|
|
|
|
if (pmb->type == TYPE_MENUBAR) {
|
|
printf ("hmnu is a menu bar.\n");
|
|
|
|
pmi = pmb->head;
|
|
while (pmi) {
|
|
mnuDumpMenuItem (pmi);
|
|
pmi = pmi->next;
|
|
}
|
|
}
|
|
else if (pmb->type == TYPE_PPPMENU) {
|
|
printf ("hmnu is a popup menu.\n");
|
|
pmi = (PMENUITEM)hmnu;
|
|
mnuDumpMenuItem (pmi);
|
|
}
|
|
else {
|
|
printf ("hmnu is a normal menu item.\n");
|
|
pmi = (PMENUITEM)hmnu;
|
|
mnuDumpMenuItem (pmi);
|
|
}
|
|
}
|
|
#endif // _DEBUG_MENU
|
|
|
|
/***************************** Menu owner ***********************************/
|
|
// Global function defined in Desktop module.
|
|
|
|
HMENU GUIAPI SetMenu (HWND hwnd, HMENU hmnu)
|
|
{
|
|
PMAINWIN pWin;
|
|
HMENU hOld;
|
|
|
|
if (!(pWin = checkAndGetMainWinIfMainWin (hwnd))) return 0;
|
|
|
|
hOld = pWin->hMenu;
|
|
pWin->hMenu = hmnu;
|
|
|
|
if (hmnu == 0) {
|
|
return 0;
|
|
}
|
|
|
|
((PMENUBAR)hmnu)->hwnd = hwnd;
|
|
|
|
DrawMenuBar (hwnd);
|
|
|
|
return hOld;
|
|
}
|
|
|
|
HMENU GUIAPI GetMenu (HWND hwnd)
|
|
{
|
|
PMAINWIN pWin;
|
|
|
|
if (!(pWin = checkAndGetMainWinIfMainWin (hwnd))) return 0;
|
|
|
|
return pWin->hMenu;
|
|
}
|
|
|
|
HMENU GUIAPI GetSystemMenu (HWND hwnd, BOOL flag)
|
|
{
|
|
PMAINWIN pWin;
|
|
|
|
if (!(pWin = checkAndGetMainWinIfMainWin (hwnd))) return 0;
|
|
|
|
return pWin->hSysMenu;
|
|
}
|
|
|
|
/**************************** Menu drawing support ***************************/
|
|
static void mnuGetMenuBarItemSize (HWND hwnd, PMENUITEM pmi, SIZE* size)
|
|
{
|
|
size->cy = ((PLOGFONT)GetWindowElementAttr (hwnd, WE_FONT_MENU))->size;
|
|
|
|
/* fix bug #4491: use == instead of & for mnutype. */
|
|
if (pmi->mnutype == MFT_BITMAP) {
|
|
size->cx = pmi->checkedbmp->bmWidth;
|
|
}
|
|
else if (pmi->mnutype == MFT_SEPARATOR) {
|
|
size->cx = LFRDR_MENUSEPARATORX;
|
|
}
|
|
else if (pmi->mnutype == MFT_OWNERDRAW) {
|
|
}
|
|
else {
|
|
SelectFont (HDC_SCREEN_SYS, (PLOGFONT)GetWindowElementAttr
|
|
(hwnd, WE_FONT_MENU));
|
|
GetTextExtent (HDC_SCREEN_SYS, (char*) pmi->typedata, -1, size);
|
|
if (pmi->mnutype == MFT_BMPSTRING) {
|
|
size->cx += size->cy;
|
|
size->cx += LFRDR_INTERMENUITEMX>>1;
|
|
}
|
|
}
|
|
|
|
pmi->h = size->cx;
|
|
return;
|
|
}
|
|
|
|
static void mnuDrawMenuBarItem (HWND hwnd, HDC hdc, PMENUITEM pmi,
|
|
int x, int y, int w, int h, int rect_y, int rect_h)
|
|
{
|
|
PBITMAP bmp;
|
|
PMAINWIN pWin;
|
|
|
|
/** the menu item rect to be drawn*/
|
|
RECT rect;
|
|
int height;
|
|
int inter;
|
|
int old_mode;
|
|
|
|
DWORD darker_dword;
|
|
DWORD lighter_dword;
|
|
DWORD bgc_dword;
|
|
gal_pixel darker_pixel;
|
|
gal_pixel lighter_pixel;
|
|
|
|
pWin = (PMAINWIN) hwnd;
|
|
if (NULL == pWin)
|
|
return;
|
|
|
|
if (!pWin->we_rdr) {
|
|
_WRN_PRINTF ("LFRDR is NULL for window: %p\n", pWin);
|
|
return;
|
|
}
|
|
|
|
height = ((PLOGFONT)GetWindowElementAttr (hwnd, WE_FONT_MENU))->size;
|
|
|
|
inter = LFRDR_INTERMENUITEMX>>1;
|
|
|
|
/** rect to be drawn */
|
|
rect.left = x - inter;
|
|
rect.top = rect_y + LFRDR_MENUBARITEMMARGIN;
|
|
rect.right = rect.left + w + (inter << 1);
|
|
rect.bottom = rect_y + rect_h - LFRDR_MENUBARITEMMARGIN;
|
|
|
|
/** draw the rect, high priority for disabled item. */
|
|
if (pmi->mnustate & MFS_DISABLED)
|
|
{
|
|
/** render a disabled item */
|
|
SetTextColor(hdc, GetWindowElementPixelEx(hwnd, hdc, WE_FGC_DISABLED_ITEM));
|
|
if (pmi->mnustate & MFS_HILITE)
|
|
pWin->we_rdr->draw_disabled_menu_item (hwnd, hdc, &rect,
|
|
GetWindowElementAttr (hwnd, WE_BGC_DISABLED_ITEM));
|
|
else
|
|
pWin->we_rdr->draw_disabled_menu_item (hwnd, hdc, &rect,
|
|
GetWindowElementAttr (hwnd, WE_BGC_MENU));
|
|
|
|
}
|
|
else if (pmi->mnustate & MFS_HILITE)
|
|
{
|
|
/** render a hilite item */
|
|
SetTextColor (hdc, GetWindowElementPixelEx
|
|
(hwnd, hdc, WE_FGC_HIGHLIGHT_ITEM));
|
|
pWin->we_rdr->draw_hilite_menu_item (hwnd, hdc, &rect,
|
|
GetWindowElementAttr (hwnd, WE_BGC_HIGHLIGHT_ITEM));
|
|
}
|
|
else
|
|
{
|
|
/** render a normal item as unhilite */
|
|
SetTextColor (hdc, GetWindowElementPixelEx
|
|
(hwnd, hdc, WE_FGC_MENU));
|
|
pWin->we_rdr->draw_normal_menu_item (hwnd, hdc, &rect,
|
|
GetWindowElementAttr (hwnd, WE_MAINC_THREED_BODY));
|
|
}
|
|
|
|
/* fix bug #4491: use == instead of & for mnutype. */
|
|
if (pmi->mnutype == MFT_BITMAP) {
|
|
|
|
if (pmi->mnustate & MFS_CHECKED)
|
|
bmp = pmi->checkedbmp;
|
|
else
|
|
bmp = pmi->uncheckedbmp;
|
|
|
|
FillBoxWithBitmap (hdc, x, y, pmi->h, height, bmp);
|
|
}
|
|
else if (pmi->mnutype == MFT_SEPARATOR) {
|
|
|
|
/** two vertical separator */
|
|
|
|
bgc_dword = GetWindowElementAttr (hwnd, WE_BGC_MENU);
|
|
darker_dword = pWin->we_rdr->calc_3dbox_color
|
|
(bgc_dword, LFRDR_3DBOX_COLOR_DARKEST);
|
|
lighter_dword = pWin->we_rdr->calc_3dbox_color
|
|
(bgc_dword, LFRDR_3DBOX_COLOR_LIGHTEST);
|
|
|
|
darker_pixel = DWORD2Pixel (hdc, darker_dword);
|
|
lighter_pixel = DWORD2Pixel (hdc, lighter_dword);
|
|
|
|
if (rect.top < rect.bottom - 2)
|
|
{
|
|
SetPenColor (hdc, darker_pixel);
|
|
MoveTo (hdc,
|
|
x + (pmi->h>>1), rect.top);
|
|
LineTo (hdc,
|
|
x + (pmi->h>>1), rect.bottom - 2);
|
|
|
|
SetPenColor (hdc, lighter_pixel);
|
|
MoveTo (hdc,
|
|
x + (pmi->h>>1) + 1, rect.top);
|
|
LineTo (hdc,
|
|
x + (pmi->h>>1) + 1, rect.bottom - 2);
|
|
}
|
|
}
|
|
else if (pmi->mnutype == MFT_OWNERDRAW) {
|
|
}
|
|
else {
|
|
if (pmi->mnutype == MFT_BMPSTRING) {
|
|
if (pmi->mnustate & MFS_CHECKED)
|
|
bmp = pmi->checkedbmp;
|
|
else
|
|
bmp = pmi->uncheckedbmp;
|
|
|
|
FillBoxWithBitmap (hdc, x, y, height, height, bmp);
|
|
x += bmp->bmWidth + inter;
|
|
}
|
|
|
|
SelectFont (hdc, (PLOGFONT)GetWindowElementAttr
|
|
(hwnd, WE_FONT_MENU));
|
|
|
|
old_mode = SetBkMode (hdc, BM_TRANSPARENT);
|
|
TextOut (hdc, x, y, (char *)pmi->typedata);
|
|
SetBkMode (hdc, old_mode);
|
|
}
|
|
}
|
|
|
|
static int mnuGetNextMenuBarItem (PMENUBAR pmb, int pos)
|
|
{
|
|
PMENUITEM pmi;
|
|
int number;
|
|
|
|
number = 0;
|
|
pmi = pmb->head;
|
|
while (pmi) {
|
|
number ++;
|
|
pmi = pmi->next;
|
|
}
|
|
|
|
number--;
|
|
|
|
if (pos == number)
|
|
return 0;
|
|
else
|
|
return pos + 1;
|
|
}
|
|
|
|
static int mnuGetPrevMenuBarItem (PMENUBAR pmb, int pos)
|
|
{
|
|
PMENUITEM pmi;
|
|
int number;
|
|
|
|
number = 0;
|
|
pmi = pmb->head;
|
|
while (pmi) {
|
|
number ++;
|
|
pmi = pmi->next;
|
|
}
|
|
|
|
number--;
|
|
|
|
if (pos == 0)
|
|
return number;
|
|
else
|
|
return pos - 1;
|
|
}
|
|
|
|
/*
|
|
* GetMenuOffy
|
|
* get offset of font
|
|
*
|
|
* Author : zhounuohua<zhounuohua@minigui.com>
|
|
* Data : 2007-11-23
|
|
*/
|
|
static int GetMenuOffy (HWND hwnd, int menu_size)
|
|
{
|
|
int font_size;
|
|
int menu_size_min;
|
|
int off;
|
|
if (0 == menu_size)
|
|
{
|
|
menu_size = GetWindowElementAttr (hwnd, WE_METRICS_MENU);
|
|
}
|
|
font_size = ((PLOGFONT)GetWindowElementAttr (hwnd, WE_FONT_MENU))->size;
|
|
menu_size_min = font_size + (LFRDR_MENUITEMOFFY_MIN << 1);
|
|
if (menu_size > menu_size_min)
|
|
{
|
|
off = menu_size - font_size;
|
|
return off >> 1;
|
|
}
|
|
return LFRDR_MENUITEMOFFY_MIN;
|
|
}
|
|
|
|
HMENU GUIAPI GetMenuBarItemRect (HWND hwnd, int pos, RECT* prc)
|
|
{
|
|
PMAINWIN pWin;
|
|
PMENUBAR pmb;
|
|
PMENUITEM pmi;
|
|
int x, y, inter, h;
|
|
int count;
|
|
SIZE size;
|
|
|
|
if (!(pWin = checkAndGetMainWinIfMainWin (hwnd))) return 0;
|
|
|
|
if (!pWin->hMenu) return 0;
|
|
|
|
pmb = (PMENUBAR) (pWin->hMenu);
|
|
if (pmb->category != TYPE_HMENU) return 0;
|
|
if (pmb->type != TYPE_MENUBAR) return 0;
|
|
|
|
x = pWin->cl - pWin->left;
|
|
x += LFRDR_MENUBAROFFX;
|
|
y = pWin->ct - pWin->top;
|
|
h = GetWindowElementAttr (hwnd, WE_METRICS_MENU);
|
|
y -= h;
|
|
|
|
inter = LFRDR_INTERMENUITEMX;
|
|
|
|
count = 0;
|
|
pmi = pmb->head;
|
|
while (pmi) {
|
|
|
|
mnuGetMenuBarItemSize (hwnd, pmi, &size);
|
|
|
|
if (count == pos)
|
|
break;
|
|
|
|
x = x + inter + size.cx;
|
|
count ++;
|
|
|
|
pmi = pmi->next;
|
|
}
|
|
|
|
if (pmi == NULL) return 0;
|
|
|
|
prc->left = x;
|
|
prc->top = y;
|
|
prc->bottom = y + h;
|
|
prc->right = x + size.cx;
|
|
|
|
return (HMENU) pmi;
|
|
}
|
|
|
|
static BOOL mnuGetMenuBarRect (HWND hwnd, RECT* prc)
|
|
{
|
|
PMAINWIN pWin;
|
|
int h;
|
|
|
|
if (!(pWin = checkAndGetMainWinIfMainWin (hwnd))) return FALSE;
|
|
|
|
prc->left = pWin->cl - pWin->left;
|
|
|
|
h = GetWindowElementAttr (hwnd, WE_METRICS_MENU);
|
|
prc->top = pWin->ct - pWin->top - h;
|
|
|
|
prc->right = pWin->right - pWin->left - prc->left;
|
|
prc->bottom = pWin->bottom - pWin->top - prc->top;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL GUIAPI HiliteMenuBarItem (HWND hwnd, int pos, UINT flags)
|
|
{
|
|
PMENUITEM pmi;
|
|
RECT rcBar;
|
|
RECT rc;
|
|
HDC hdc;
|
|
PMAINWIN pWin;
|
|
|
|
int font_y; /** top of font */
|
|
int font_h; /** height of font */
|
|
int menu_size; /** size of menu item */
|
|
int menubar_offy; /** offset of font */
|
|
|
|
pWin = (PMAINWIN)hwnd;
|
|
if (NULL == pWin) return FALSE;
|
|
|
|
pmi = (PMENUITEM)GetMenuBarItemRect (hwnd, pos, &rc);
|
|
|
|
if (!pmi) return FALSE;
|
|
|
|
if (pmi->mnutype == MFT_SEPARATOR)
|
|
return TRUE;
|
|
|
|
hdc = GetDC (hwnd);
|
|
|
|
mnuGetMenuBarRect (hwnd, &rcBar);
|
|
ClipRectIntersect (hdc, &rcBar);
|
|
|
|
menu_size = GetWindowElementAttr (hwnd, WE_METRICS_MENU);
|
|
menubar_offy = GetMenuOffy (hwnd, menu_size);
|
|
|
|
font_y = pWin->ct - pWin->top;
|
|
font_y -= menu_size;
|
|
font_y += menubar_offy;
|
|
|
|
font_h = menu_size - (menubar_offy << 1);
|
|
if (font_h < 0)
|
|
font_h = 0;
|
|
|
|
switch (flags)
|
|
{
|
|
/** high priority for disabled item */
|
|
case LFRDR_MENU_STATE_DISABLED:
|
|
pmi->mnustate |= MFS_DISABLED;
|
|
break;
|
|
case LFRDR_MENU_STATE_HILITE:
|
|
pmi->mnustate |= MFS_HILITE;
|
|
break;
|
|
case LFRDR_MENU_STATE_NORMAL:
|
|
default:
|
|
pmi->mnustate |= MFS_DEFAULT;
|
|
break;
|
|
}
|
|
|
|
mnuDrawMenuBarItem (hwnd, hdc, pmi, rc.left, font_y,
|
|
RECTW (rc) , font_h, rc.top, RECTH (rc));
|
|
|
|
/** reset draw state */
|
|
pmi->mnustate &= ~(MFS_HILITE | MFS_DEFAULT);
|
|
ReleaseDC (hdc);
|
|
return TRUE;
|
|
}
|
|
|
|
int MenuBarHitTest (HWND hwnd, int mx, int my)
|
|
{
|
|
PMAINWIN pWin;
|
|
PMENUBAR pmb;
|
|
PMENUITEM pmi;
|
|
int x, y, inter, h;
|
|
RECT rc;
|
|
int count;
|
|
SIZE size;
|
|
|
|
if (!(pWin = checkAndGetMainWinIfMainWin (hwnd))) return -1;
|
|
|
|
if (!pWin->hMenu) return -1;
|
|
|
|
pmb = (PMENUBAR) (pWin->hMenu);
|
|
if (pmb->category != TYPE_HMENU) return -1;
|
|
if (pmb->type != TYPE_MENUBAR) return -1;
|
|
|
|
x = pWin->cl;
|
|
x += LFRDR_MENUBAROFFX;
|
|
|
|
y = pWin->ct;
|
|
h = GetWindowElementAttr (hwnd, WE_METRICS_MENU);
|
|
y -= h;
|
|
|
|
inter = LFRDR_INTERMENUITEMX;
|
|
|
|
rc.top = y;
|
|
rc.bottom = y + h;
|
|
|
|
count = 0;
|
|
pmi = pmb->head;
|
|
while (pmi) {
|
|
|
|
mnuGetMenuBarItemSize (hwnd, pmi, &size);
|
|
#if 0
|
|
rc.left = x;
|
|
rc.right = x + size.cx;
|
|
#else/*fix bug 3298, tangjb*/
|
|
rc.left = x-(inter>>1);
|
|
rc.right = x + size.cx + (inter>>1);
|
|
#endif
|
|
if (PtInRect (&rc, mx, my))
|
|
return count;
|
|
|
|
x = x + inter + size.cx;
|
|
count ++;
|
|
|
|
pmi = pmi->next;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
void DrawMenuBarHelper (const MAINWIN* pWin, HDC hdc, const RECT* pClipRect)
|
|
{
|
|
PMENUBAR pmb;
|
|
PMENUITEM pmi;
|
|
/** startx, starty, width, height of menubar*/
|
|
int x, y, w, h;
|
|
/** offset of font*/
|
|
int menubar_offy;
|
|
/** font size*/
|
|
int menu_size;
|
|
int inter;
|
|
/** rect of menubar */
|
|
RECT rc;
|
|
/** HWND of MAINWIN */
|
|
HWND hwnd;
|
|
SIZE size;
|
|
|
|
if (!pWin->hMenu)
|
|
return;
|
|
|
|
hwnd = (HWND)pWin;
|
|
pmb = (PMENUBAR) (pWin->hMenu);
|
|
if (pmb->category != TYPE_HMENU)
|
|
return;
|
|
|
|
x = pWin->cl - pWin->left;
|
|
w = pWin->right - pWin->cl - (pWin->cl - pWin->left);
|
|
|
|
menu_size = GetWindowElementAttr (hwnd, WE_METRICS_MENU);
|
|
if (menu_size <= 0)
|
|
return;
|
|
|
|
menubar_offy = GetMenuOffy (hwnd, menu_size);
|
|
|
|
h = menu_size;
|
|
y = pWin->ct - pWin->top;
|
|
y -= h;
|
|
rc.left = x;
|
|
rc.top = y;
|
|
rc.right = x + w;
|
|
rc.bottom = y + h;
|
|
SelectClipRect (hdc, &rc);
|
|
|
|
if (pClipRect)
|
|
ClipRectIntersect (hdc, pClipRect);
|
|
|
|
SetBrushColor (hdc, GetWindowElementPixelEx (hwnd, hdc, WE_MAINC_THREED_BODY));
|
|
FillBox (hdc, x, y, w + 3, menu_size);
|
|
|
|
x += LFRDR_MENUBAROFFX;
|
|
y += menubar_offy;
|
|
|
|
h -= menubar_offy << 1;
|
|
if (h < 0)
|
|
h = 0;
|
|
|
|
inter = LFRDR_INTERMENUITEMX;
|
|
pmi = pmb->head;
|
|
while (pmi) {
|
|
mnuGetMenuBarItemSize (hwnd, pmi, &size);
|
|
mnuDrawMenuBarItem (hwnd, hdc, pmi,
|
|
x, y, size.cx, h, rc.top, RECTH (rc));
|
|
|
|
x = x + inter + size.cx;
|
|
pmi = pmi->next;
|
|
}
|
|
}
|
|
|
|
void GUIAPI DrawMenuBar (HWND hwnd)
|
|
{
|
|
PMAINWIN pWin;
|
|
HDC hdc;
|
|
|
|
if (!(pWin = checkAndGetMainWinIfMainWin (hwnd))) return;
|
|
|
|
if (!pWin->hMenu) return;
|
|
|
|
hdc = GetDC (hwnd);
|
|
DrawMenuBarHelper (pWin, hdc, NULL);
|
|
ReleaseDC (hdc);
|
|
}
|
|
|
|
static void mnuGetPopupMenuExtent (PTRACKMENUINFO ptmi)
|
|
{
|
|
PTRACKMENUINFO prevtmi;
|
|
PMENUITEM pmi = ptmi->pmi;
|
|
PMENUITEM psubmi;
|
|
int w = 0, h = 0;
|
|
int menu_size;
|
|
int menu_font_size;
|
|
int inter;
|
|
int mioffx, minx;
|
|
SIZE size;
|
|
BOOL has_sub = FALSE;
|
|
BOOL has_txt = FALSE;
|
|
|
|
menu_font_size = ((PLOGFONT)GetWindowElementAttr
|
|
(ptmi->hwnd, WE_FONT_MENU))->size;
|
|
menu_size = GetWindowElementAttr (ptmi->hwnd, WE_METRICS_MENU);
|
|
inter = GetMenuOffy (ptmi->hwnd, menu_size);
|
|
|
|
mioffx = LFRDR_MENUITEMOFFX;
|
|
minx = LFRDR_MENUITEMMINX;
|
|
|
|
ptmi->rc.right = ptmi->rc.left;
|
|
ptmi->rc.bottom = ptmi->rc.top + LFRDR_MENUTOPMARGIN;
|
|
|
|
/* fix bug #4491: use == instead of & for mnutype. */
|
|
if (pmi->mnutype == MFT_OWNERDRAW) {
|
|
}
|
|
else if (pmi->mnutype == MFT_SEPARATOR) {
|
|
pmi->h = LFRDR_MENUSEPARATORY + (inter<<1);
|
|
if (minx > w)
|
|
w = minx;
|
|
}
|
|
else if (pmi->mnutype == MFT_BITMAP) {
|
|
BITMAP* bmp = (BITMAP*)pmi->typedata;
|
|
pmi->h = bmp->bmHeight;
|
|
if (bmp->bmWidth > w)
|
|
w = bmp->bmWidth;
|
|
}
|
|
else {
|
|
SelectFont (HDC_SCREEN_SYS, (PLOGFONT)GetWindowElementAttr
|
|
(ptmi->hwnd, WE_FONT_MENU));
|
|
GetTabbedTextExtent (HDC_SCREEN_SYS, (char*)pmi->typedata, -1, &size);
|
|
|
|
if (pmi->mnutype == MFT_BMPSTRING) {
|
|
pmi->h = MAX (pmi->uncheckedbmp->bmHeight, menu_font_size) + (inter<<1);
|
|
size.cx += pmi->uncheckedbmp->bmWidth;
|
|
}
|
|
else {
|
|
pmi->h = menu_size;
|
|
}
|
|
|
|
if (size.cx > w) w = size.cx;
|
|
|
|
if (pmi->type == TYPE_PPPMENU)
|
|
pmi->h += inter;
|
|
|
|
has_txt = TRUE;
|
|
}
|
|
ptmi->rc.bottom += pmi->h;
|
|
|
|
if (pmi->type == TYPE_PPPMENU) {
|
|
psubmi = pmi->submenu;
|
|
}
|
|
else
|
|
psubmi = pmi->next;
|
|
|
|
if (pmi->submenu)
|
|
has_sub = TRUE;
|
|
|
|
while (psubmi) {
|
|
|
|
/* fix bug #4491: use == instead of & for mnutype. */
|
|
if (psubmi->mnutype == MFT_OWNERDRAW) {
|
|
}
|
|
else if (psubmi->mnutype == MFT_SEPARATOR) {
|
|
psubmi->h = LFRDR_MENUSEPARATORY + (inter<<1);
|
|
if (minx > w)
|
|
w = minx;
|
|
}
|
|
else if (psubmi->mnutype == MFT_BITMAP) {
|
|
BITMAP* bmp = (BITMAP*)psubmi->typedata;
|
|
psubmi->h = bmp->bmHeight;
|
|
if (bmp->bmWidth > w)
|
|
w = bmp->bmWidth;
|
|
}
|
|
else {
|
|
SelectFont (HDC_SCREEN_SYS, (PLOGFONT)GetWindowElementAttr
|
|
(ptmi->hwnd, WE_FONT_MENU));
|
|
GetTabbedTextExtent (HDC_SCREEN_SYS,
|
|
(char*)psubmi->typedata, -1, &size);
|
|
|
|
if (psubmi->mnutype == MFT_BMPSTRING) {
|
|
psubmi->h = MAX (psubmi->uncheckedbmp->bmHeight, menu_font_size)
|
|
+ (inter<<1);
|
|
|
|
size.cx += psubmi->uncheckedbmp->bmWidth;
|
|
}
|
|
else {
|
|
psubmi->h = menu_size;
|
|
}
|
|
|
|
if (size.cx > w) w = size.cx;
|
|
}
|
|
|
|
if (psubmi->submenu)
|
|
has_sub = TRUE;
|
|
|
|
ptmi->rc.bottom += psubmi->h;
|
|
|
|
psubmi = psubmi->next;
|
|
}
|
|
ptmi->rc.bottom += LFRDR_MENUBOTTOMMARGIN;
|
|
|
|
if (has_txt) w += mioffx;
|
|
if (has_sub) w += mioffx;
|
|
w += LFRDR_MENULEFTMARGIN;
|
|
w += LFRDR_MENURIGHTMARGIN;
|
|
|
|
ptmi->rc.right += w;
|
|
|
|
/* adjust the rect according to the alignment flag */
|
|
if (ptmi->flags & TPM_CENTERALIGN) {
|
|
ptmi->rc.left -= w >> 1;
|
|
ptmi->rc.right -= w >> 1;
|
|
}
|
|
|
|
if (ptmi->flags & TPM_RIGHTALIGN) {
|
|
ptmi->rc.left -= w;
|
|
ptmi->rc.right -= w;
|
|
}
|
|
|
|
h = ptmi->rc.bottom - ptmi->rc.top + 1;
|
|
if (ptmi->flags & TPM_VCENTERALIGN) {
|
|
ptmi->rc.top -= h >> 1;
|
|
ptmi->rc.bottom -= h >> 1;
|
|
}
|
|
|
|
if (ptmi->flags & TPM_BOTTOMALIGN) {
|
|
ptmi->rc.top -= h;
|
|
ptmi->rc.bottom -= h;
|
|
}
|
|
|
|
/* adjust the rect according to the screen */
|
|
if (ptmi->rc.right > g_rcScr.right) {
|
|
|
|
if ((prevtmi = ptmi->prev))
|
|
ptmi->rc.left = prevtmi->rc.left - w;
|
|
else
|
|
ptmi->rc.left = g_rcScr.right - w;
|
|
|
|
ptmi->rc.right = ptmi->rc.left + w;
|
|
|
|
if (ptmi->rc.left < 0) {
|
|
ptmi->rc.left = 0;
|
|
ptmi->rc.right = w;
|
|
}
|
|
}
|
|
|
|
if (ptmi->rc.bottom > g_rcScr.bottom) {
|
|
ptmi->rc.top = g_rcScr.bottom - h;
|
|
ptmi->rc.bottom = ptmi->rc.top + h;
|
|
|
|
if (ptmi->rc.top < 0) {
|
|
ptmi->rc.top = 0;
|
|
ptmi->rc.bottom = h;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/** type of menu picture */
|
|
#define LFRDR_MENU_PIC_RADIO 0x00000001L
|
|
#define LFRDR_MENU_PIC_MARK 0x00000002L
|
|
#define LFRDR_MENU_PIC_SUB 0x00000004L
|
|
#define LFRDR_MENU_PIC_MASK 0x0000000FL
|
|
|
|
/*
|
|
* Draw menu radio, menu checkmark, menu sub.
|
|
*
|
|
* param hwnd : handle of window
|
|
* param hdc : handle of HDC
|
|
* param rect : the rectangle in which to draw
|
|
* param pic_type : type of menu picture
|
|
* param menu_state : state of menu
|
|
*
|
|
* return 0 on success, -1 on failure
|
|
*
|
|
* Author : zhounuohua<zhounuohua@minigui.com>
|
|
* Date : 2007-11-27
|
|
*/
|
|
static int mnuDrawMenuPic (HWND hwnd, HDC hdc, RECT* rect,
|
|
int pic_type, int menu_state)
|
|
{
|
|
DWORD rgb_font;
|
|
PMAINWIN pWin;
|
|
int flag = LFRDR_MARK_HAVESHELL;
|
|
int old_bgc;
|
|
|
|
pWin = (PMAINWIN) hwnd;
|
|
if (NULL == pWin) return -1;
|
|
|
|
if (!pWin->we_rdr) {
|
|
_WRN_PRINTF ("LFRDR is NULL for window: %p\n", pWin);
|
|
return -1;
|
|
}
|
|
|
|
if (menu_state & MFS_CHECKED)
|
|
flag |= LFRDR_MARK_ALL_SELECTED;
|
|
|
|
rgb_font = GetWindowElementAttr (hwnd, WE_FGC_MENU);
|
|
|
|
switch (pic_type & LFRDR_MENU_PIC_MASK)
|
|
{
|
|
case LFRDR_MENU_PIC_RADIO:
|
|
pWin->we_rdr->draw_radio (hdc, rect, rgb_font, flag);
|
|
break;
|
|
|
|
case LFRDR_MENU_PIC_MARK:
|
|
pWin->we_rdr->draw_checkmark (hdc, rect, rgb_font, flag);
|
|
break;
|
|
|
|
case LFRDR_MENU_PIC_SUB:
|
|
old_bgc = GetBkColor (hdc);
|
|
if (menu_state & MFS_DISABLED)
|
|
{
|
|
if (menu_state & MFS_HILITE)
|
|
{
|
|
SetBkColor (hdc, GetWindowElementPixelEx
|
|
(hwnd, hdc, WE_BGC_DISABLED_ITEM));
|
|
pWin->we_rdr->draw_arrow (hwnd, hdc, rect,
|
|
GetWindowElementAttr (hwnd, WE_FGC_DISABLED_ITEM),
|
|
LFRDR_ARROW_RIGHT);
|
|
}
|
|
else
|
|
{
|
|
SetBkColor (hdc, GetWindowElementPixelEx
|
|
(hwnd, hdc, WE_BGC_MENU));
|
|
pWin->we_rdr->draw_arrow (hwnd, hdc, rect,
|
|
GetWindowElementAttr (hwnd, WE_FGC_DISABLED_ITEM),
|
|
LFRDR_ARROW_RIGHT);
|
|
}
|
|
}
|
|
else if (menu_state & MFS_HILITE)
|
|
{
|
|
SetBkColor (hdc, GetWindowElementPixelEx
|
|
(hwnd, hdc, WE_BGC_HIGHLIGHT_ITEM));
|
|
pWin->we_rdr->draw_arrow (hwnd, hdc, rect,
|
|
GetWindowElementAttr (hwnd, WE_FGC_HIGHLIGHT_ITEM),
|
|
LFRDR_ARROW_RIGHT);
|
|
}
|
|
else
|
|
{
|
|
SetBkColor (hdc, GetWindowElementPixelEx
|
|
(hwnd, hdc, WE_BGC_MENU));
|
|
pWin->we_rdr->draw_arrow (hwnd, hdc, rect, rgb_font,
|
|
LFRDR_ARROW_RIGHT);
|
|
}
|
|
SetBkColor (hdc, old_bgc);
|
|
break;
|
|
default:
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Draw menu bitmap, menu radio, menu checkmark or menu sub
|
|
*
|
|
* return : 0 on success, -1 on failure
|
|
*
|
|
* Author : zhounuohua<zhounuohua@minigui.com>
|
|
* Date : 2007-11-27
|
|
*/
|
|
static int DrawMenuPic (HWND hwnd, HDC hdc, int x, int y,
|
|
PMENUITEM pmi, BOOL draw_sub, int * bmp_w)
|
|
{
|
|
RECT mp_rect; /** rect of menu pic*/
|
|
int mp_height = 0; /** height of menu pic */
|
|
int mp_type = 0; /** type of menu pic*/
|
|
int bmp_offy = 0;
|
|
PBITMAP bmp;
|
|
|
|
/* not draw menu sub, check */
|
|
if (!draw_sub) {
|
|
|
|
/* fix bug #4491: use == instead of & for mnutype. */
|
|
if (pmi->mnutype == MFT_BMPSTRING) {
|
|
/* MFT_BMPSTRING */
|
|
if (pmi->mnustate & MFS_CHECKED)
|
|
bmp = pmi->checkedbmp;
|
|
else
|
|
bmp = pmi->uncheckedbmp;
|
|
|
|
if (bmp) {
|
|
bmp_offy = (pmi->h - bmp->bmHeight)>>1;
|
|
FillBoxWithBitmap (hdc, x, y + bmp_offy,
|
|
bmp->bmWidth, pmi->h - (bmp_offy<<1), bmp);
|
|
if (bmp_w) {
|
|
*bmp_w = MAX (bmp->bmWidth, LFRDR_MENUITEMOFFX);
|
|
}
|
|
return 0;
|
|
}
|
|
else
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/** get height of pic */
|
|
if (LFRDR_MENUPIC_MIN > pmi->h) {
|
|
mp_height = LFRDR_MENUPIC_MIN;
|
|
}
|
|
else {
|
|
mp_height = (pmi->h) >> 2;
|
|
mp_height += LFRDR_MENUPIC_MIN;
|
|
}
|
|
|
|
if (mp_height > LFRDR_MENUITEMOFFX) {
|
|
mp_height = LFRDR_MENUITEMOFFX;
|
|
}
|
|
|
|
mp_rect.left = x;
|
|
mp_rect.top = y;
|
|
mp_rect.top += (pmi->h - mp_height) >> 1;
|
|
mp_rect.bottom = mp_rect.top + mp_height;
|
|
mp_rect.right = mp_rect.left + mp_height;
|
|
|
|
if (bmp_w) {
|
|
if (LFRDR_MENUITEMOFFX < mp_height)
|
|
*bmp_w = mp_height;
|
|
}
|
|
|
|
/* get type of menu pic */
|
|
if (draw_sub) {
|
|
/* draw menu sub */
|
|
mp_type = LFRDR_MENU_PIC_SUB;
|
|
}
|
|
else {
|
|
/* draw menu radio or menu check */
|
|
/* fix bug #4491: use == instead of & for mnutype. */
|
|
if (pmi->mnutype == MFT_RADIOCHECK)
|
|
mp_type = LFRDR_MENU_PIC_RADIO;
|
|
else if (pmi->mnutype == MFT_MARKCHECK)
|
|
mp_type = LFRDR_MENU_PIC_MARK;
|
|
}
|
|
|
|
mnuDrawMenuPic (hwnd, hdc, &mp_rect, mp_type, pmi->mnustate);
|
|
return 0;
|
|
}
|
|
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
static int create_memdc_for_menu (TRACKMENUINFO* ptmi)
|
|
{
|
|
GAL_Surface* surf;
|
|
POINT wo;
|
|
|
|
if (IsRectEmpty(&ptmi->rc))
|
|
return -1;
|
|
|
|
surf = GAL_CreateSurfaceForZNode (ST_DEFAULT, RECTW(ptmi->rc),
|
|
RECTH(ptmi->rc));
|
|
if (surf == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
ptmi->dc = __mg_create_memdc_for_surface (surf);
|
|
if (ptmi->dc == HDC_INVALID) {
|
|
GAL_FreeSurface (surf);
|
|
return -1;
|
|
}
|
|
|
|
wo.x = ptmi->rc.left;
|
|
wo.y = ptmi->rc.top;
|
|
|
|
SetMapMode (ptmi->dc, MM_ANISOTROPIC);
|
|
SetWindowOrg (ptmi->dc, &wo);
|
|
return 0;
|
|
}
|
|
|
|
static void delete_memdc_for_menu (TRACKMENUINFO* ptmi)
|
|
{
|
|
if (ptmi->dc != HDC_INVALID) {
|
|
|
|
#if 0 /* deprecated code: we always do refcount++ for any memdc */
|
|
/* we must free the surface here, or it can not be freed actually
|
|
due to the referenced count. */
|
|
GAL_Surface *surf = GetSurfaceFromDC (ptmi->dc);
|
|
GAL_FreeSurface (surf);
|
|
#endif /* deprecated code */
|
|
DeleteMemDC (ptmi->dc);
|
|
ptmi->dc = HDC_INVALID;
|
|
}
|
|
}
|
|
|
|
static inline int save_box_under_menu (TRACKMENUINFO* ptmi) { return 0; }
|
|
static inline void restore_dc_under_menu (TRACKMENUINFO* ptmi) { }
|
|
|
|
#else /* not define _MGSCHEMA_COMPOSITING */
|
|
|
|
static inline int create_memdc_for_menu (TRACKMENUINFO* ptmi) {
|
|
ptmi->dc = HDC_SCREEN_SYS;
|
|
return 0;
|
|
}
|
|
|
|
static inline void delete_memdc_for_menu (TRACKMENUINFO* ptmi) { }
|
|
|
|
#ifdef _MENU_SAVE_BOX
|
|
static int save_box_under_menu (TRACKMENUINFO* ptmi)
|
|
{
|
|
memset (&ptmi->savedbox, 0, sizeof (BITMAP));
|
|
if (!GetBitmapFromDC (HDC_SCREEN_SYS, ptmi->rc.left, ptmi->rc.top,
|
|
RECTW (ptmi->rc), RECTH (ptmi->rc), &ptmi->savedbox)) {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void restore_dc_under_menu (TRACKMENUINFO* ptmi)
|
|
{
|
|
FillBoxWithBitmap (HDC_SCREEN_SYS, ptmi->rc.left, ptmi->rc.top,
|
|
RECTW (ptmi->rc), RECTH (ptmi->rc), &ptmi->savedbox);
|
|
free (ptmi->savedbox.bmBits);
|
|
}
|
|
|
|
#else /* not defined _MENU_SAVE_BOX */
|
|
|
|
static inline int save_box_under_menu(TRACKMENUINFO* ptmi) { return 0; }
|
|
|
|
static int mnuShowPopupMenu (PTRACKMENUINFO ptmi);
|
|
static void mnuHiliteMenuItem (PTRACKMENUINFO ptmi, PMENUITEM pmi, BOOL bHilite);
|
|
|
|
static void restore_dc_under_menu (TRACKMENUINFO* ptmi_hiding)
|
|
{
|
|
TRACKMENUINFO* ptmi;
|
|
if (ptmi_hiding == NULL || ptmi_hiding->prev == NULL)
|
|
return;
|
|
|
|
ptmi = ptmi_hiding;
|
|
SelectClipRect (HDC_SCREEN_SYS, &ptmi->rc);
|
|
|
|
/* redraw parent popup menus here */
|
|
while (ptmi->prev != NULL) {
|
|
ptmi = ptmi->prev;
|
|
}
|
|
|
|
do {
|
|
if (DoesIntersect (&ptmi->rc, &ptmi_hiding->rc)){
|
|
mnuShowPopupMenu (ptmi);
|
|
if (ptmi->philite != NULL)
|
|
mnuHiliteMenuItem (ptmi, ptmi->philite, TRUE);
|
|
}
|
|
ptmi = ptmi->next;
|
|
|
|
} while (ptmi != NULL);
|
|
|
|
SelectClipRect (HDC_SCREEN_SYS, NULL);
|
|
}
|
|
|
|
#endif /* _MENU_SAVE_BOX */
|
|
#endif /* not defined _MGSCHEMA_COMPOSITING */
|
|
|
|
static void draw_down_arrowhead(PTRACKMENUINFO ptmi, HDC hdc)
|
|
{
|
|
int l, t, r, b, cx, cy;
|
|
|
|
l = ptmi->bottom_scroll_rc.left;
|
|
t = ptmi->bottom_scroll_rc.top;
|
|
r = ptmi->bottom_scroll_rc.right;
|
|
b = ptmi->bottom_scroll_rc.bottom;
|
|
|
|
cx = (l + r) / 2;
|
|
cy = (t + b) / 2;
|
|
|
|
SetPenColor(hdc, GetWindowElementPixelEx (ptmi->hwnd, hdc, WE_FGC_MENU));
|
|
|
|
MoveTo(hdc, cx-4, cy-2);
|
|
LineTo(hdc, cx+4, cy-2);
|
|
|
|
MoveTo(hdc, cx-3, cy-1);
|
|
LineTo(hdc, cx+3, cy-1);
|
|
|
|
MoveTo(hdc, cx-2, cy);
|
|
LineTo(hdc, cx+2, cy);
|
|
|
|
MoveTo(hdc, cx-1, cy+1);
|
|
LineTo(hdc, cx+1, cy+1);
|
|
|
|
MoveTo(hdc, cx, cy+2);
|
|
LineTo(hdc, cx, cy+2);
|
|
|
|
}
|
|
|
|
static void draw_bottom_scroll_button(PTRACKMENUINFO ptmi)
|
|
{
|
|
PMAINWIN pWin;
|
|
DWORD bgc;
|
|
|
|
pWin = (PMAINWIN) ptmi->hwnd;
|
|
if (NULL == pWin) return;
|
|
|
|
if (!pWin->we_rdr) {
|
|
_WRN_PRINTF ("LFRDR is NULL for window: %p\n", pWin);
|
|
return;
|
|
}
|
|
|
|
bgc = GetWindowElementAttr (ptmi->hwnd, WE_BGC_MENU);
|
|
|
|
pWin->we_rdr->draw_3dbox (HDC_SCREEN_SYS, &ptmi->bottom_scroll_rc, bgc,
|
|
LFRDR_3DBOX_FILLED | LFRDR_3DBOX_THICKFRAME);
|
|
|
|
draw_down_arrowhead(ptmi, HDC_SCREEN_SYS);
|
|
}
|
|
|
|
static int mnuShowPopupMenu (PTRACKMENUINFO ptmi)
|
|
{
|
|
PMENUITEM pmi = ptmi->pmi;
|
|
PMENUITEM psubmi;
|
|
int x, y, offy;
|
|
|
|
int inter;
|
|
int mioffx;
|
|
int marginlx, marginrx;
|
|
int marginy;
|
|
int font_offy;
|
|
int old_mode;
|
|
|
|
PBITMAP bmp;
|
|
|
|
PMAINWIN pWin;
|
|
DWORD bgc;
|
|
|
|
DWORD darker_dword;
|
|
DWORD lighter_dword;
|
|
DWORD bgc_dword;
|
|
gal_pixel darker_pixel;
|
|
gal_pixel lighter_pixel;
|
|
|
|
pWin = (PMAINWIN) ptmi->hwnd;
|
|
if (NULL == pWin) return -1;
|
|
|
|
if (!pWin->we_rdr) {
|
|
_WRN_PRINTF ("LFRDR is NULL for window: %p\n", pWin);
|
|
return -1;
|
|
}
|
|
|
|
if (save_box_under_menu (ptmi)) {
|
|
_WRN_PRINTF ("Can not get DC to show popup menu: %p\n", pWin);
|
|
return -1;
|
|
}
|
|
|
|
bgc = GetWindowElementAttr (ptmi->hwnd, WE_BGC_MENU);
|
|
|
|
inter = LFRDR_INTERMENUITEMY;
|
|
mioffx = LFRDR_MENUITEMOFFX;
|
|
marginlx = LFRDR_MENULEFTMARGIN;
|
|
marginrx = LFRDR_MENURIGHTMARGIN;
|
|
marginy = LFRDR_MENUTOPMARGIN;
|
|
|
|
/*add*/
|
|
ptmi->pstart_show_mi = ptmi->pmi;
|
|
|
|
ptmi->show_rc.top = ptmi->rc.top;
|
|
ptmi->show_rc.left = ptmi->rc.left;
|
|
ptmi->show_rc.right = ptmi->rc.right;
|
|
ptmi->show_rc.bottom = ptmi->rc.bottom;
|
|
|
|
ptmi->selected_rc.top = ptmi->show_rc.top;
|
|
ptmi->selected_rc.left = ptmi->show_rc.left;
|
|
ptmi->selected_rc.right = ptmi->show_rc.right;
|
|
ptmi->selected_rc.bottom = ptmi->show_rc.top + ptmi->pmi->h;
|
|
|
|
ptmi->top_scroll_rc.top = 0;
|
|
ptmi->top_scroll_rc.left= 0;
|
|
ptmi->top_scroll_rc.right= 0;
|
|
ptmi->top_scroll_rc.bottom= 0;
|
|
|
|
ptmi->bottom_scroll_rc.top = 0;
|
|
ptmi->bottom_scroll_rc.left = 0;
|
|
ptmi->bottom_scroll_rc.right = 0;
|
|
ptmi->bottom_scroll_rc.bottom = 0;
|
|
|
|
ptmi->draw_bottom_flag = FALSE;
|
|
ptmi->draw_top_flag = FALSE;
|
|
ptmi->mouse_leave_flag = FALSE;/* mouse is in pcurtmi */
|
|
|
|
/** get darker and lighter color according to backgroup color */
|
|
bgc_dword = GetWindowElementAttr (ptmi->hwnd, WE_BGC_MENU);
|
|
darker_dword = pWin->we_rdr->calc_3dbox_color
|
|
(bgc_dword, LFRDR_3DBOX_COLOR_DARKEST);
|
|
lighter_dword = pWin->we_rdr->calc_3dbox_color
|
|
(bgc_dword, LFRDR_3DBOX_COLOR_LIGHTEST);
|
|
|
|
darker_pixel = DWORD2Pixel (ptmi->dc, darker_dword);
|
|
lighter_pixel = DWORD2Pixel (ptmi->dc, lighter_dword);
|
|
|
|
if ((ptmi->rc.bottom > g_rcScr.bottom)
|
|
&& ((ptmi->rc.bottom - ptmi->rc.top) > g_rcScr.bottom)){
|
|
|
|
ptmi->show_rc.top = ptmi->rc.top;
|
|
ptmi->show_rc.left = ptmi->rc.left;
|
|
ptmi->show_rc.right = ptmi->rc.right;
|
|
ptmi->show_rc.bottom = g_rcScr.bottom -
|
|
GetSysFontHeight(SYSLOGFONT_MENU) + SHORTEN;
|
|
|
|
ptmi->bottom_scroll_rc.top = ptmi->show_rc.bottom;
|
|
ptmi->bottom_scroll_rc.left = ptmi->rc.left;
|
|
ptmi->bottom_scroll_rc.right = ptmi->rc.right;
|
|
ptmi->bottom_scroll_rc.bottom = g_rcScr.bottom;
|
|
|
|
ptmi->draw_bottom_flag = TRUE;
|
|
}
|
|
/*add end*/
|
|
|
|
/* draw background. */
|
|
x = ptmi->rc.left;
|
|
y = ptmi->rc.top;
|
|
|
|
pWin->we_rdr->draw_3dbox (ptmi->dc, &ptmi->show_rc, bgc,
|
|
LFRDR_3DBOX_FILLED | LFRDR_3DBOX_THICKFRAME);
|
|
|
|
x = ptmi->show_rc.left + marginlx;
|
|
y = ptmi->show_rc.top + marginy;
|
|
|
|
/* fix bug #4491: use == instead of & for mnutype. */
|
|
if (pmi->mnutype == MFT_BITMAP) {
|
|
|
|
if (pmi->mnustate & MFS_CHECKED)
|
|
bmp = pmi->checkedbmp;
|
|
else
|
|
bmp = (BITMAP*)pmi->typedata;
|
|
|
|
offy = (pmi->h - bmp->bmHeight) >> 1;
|
|
|
|
FillBoxWithBitmap (ptmi->dc, x, y + offy,
|
|
((BITMAP*)pmi->typedata)->bmWidth,
|
|
pmi->h - (offy << 1), bmp);
|
|
|
|
}
|
|
else if (pmi->mnutype == MFT_SEPARATOR) {
|
|
|
|
/** two horizontal separator */
|
|
SetPenColor (ptmi->dc, darker_pixel);
|
|
MoveTo (ptmi->dc,
|
|
x, y + (pmi->h>>1) - inter + 1);
|
|
LineTo (ptmi->dc,
|
|
ptmi->show_rc.right - marginrx, y + (pmi->h>>1) - inter + 1);
|
|
|
|
SetPenColor (ptmi->dc, lighter_pixel);
|
|
MoveTo (ptmi->dc,
|
|
x, y + (pmi->h>>1) - inter + 2);
|
|
LineTo (ptmi->dc,
|
|
ptmi->show_rc.right - marginrx, y + (pmi->h>>1) - inter + 2);
|
|
}
|
|
else if (pmi->mnutype == MFT_OWNERDRAW) {
|
|
}
|
|
else {
|
|
font_offy = (pmi->h - ((PLOGFONT)GetWindowElementAttr
|
|
(ptmi->hwnd, WE_FONT_MENU))->size) >> 1;
|
|
|
|
SelectFont (ptmi->dc, (PLOGFONT)GetWindowElementAttr
|
|
(ptmi->hwnd, WE_FONT_MENU));
|
|
|
|
if (pmi->type == TYPE_PPPMENU) {
|
|
old_mode = SetBkMode (ptmi->dc, BM_TRANSPARENT);
|
|
SetTextColor (ptmi->dc, GetWindowElementPixelEx
|
|
(ptmi->hwnd, ptmi->dc, WE_FGC_MENU));
|
|
TextOut (ptmi->dc, x + mioffx, y + font_offy,
|
|
(char*)pmi->typedata);
|
|
SetBkMode (ptmi->dc, old_mode);
|
|
|
|
SetPenColor (ptmi->dc, GetWindowElementPixelEx
|
|
(ptmi->hwnd, ptmi->dc, WE_FGC_MENU));
|
|
|
|
MoveTo (ptmi->dc, x, y + pmi->h - (inter<<1));
|
|
LineTo (ptmi->dc, ptmi->show_rc.right - marginrx,
|
|
y + pmi->h - (inter<<1));
|
|
MoveTo (ptmi->dc, x, y + pmi->h - inter);
|
|
LineTo (ptmi->dc, ptmi->show_rc.right - marginrx,
|
|
y + pmi->h - inter);
|
|
}
|
|
else {
|
|
int bmp_w = mioffx;
|
|
|
|
/** draw radio, checkmark or bitmap */
|
|
DrawMenuPic (ptmi->hwnd, ptmi->dc, x + 1, y, pmi, FALSE, &bmp_w);
|
|
|
|
/** menu text */
|
|
old_mode = SetBkMode (ptmi->dc, BM_TRANSPARENT);
|
|
if (pmi->mnustate & MFS_DISABLED)
|
|
SetTextColor (ptmi->dc, GetWindowElementPixelEx
|
|
(ptmi->hwnd, ptmi->dc, WE_FGC_DISABLED_ITEM));
|
|
else if (pmi->mnustate & MFS_HILITE)
|
|
SetTextColor (ptmi->dc, GetWindowElementPixelEx
|
|
(ptmi->hwnd, ptmi->dc, WE_FGC_HIGHLIGHT_ITEM));
|
|
else
|
|
SetTextColor (ptmi->dc, GetWindowElementPixelEx
|
|
(ptmi->hwnd, ptmi->dc, WE_FGC_MENU));
|
|
|
|
TextOut (ptmi->dc, x + bmp_w, y + font_offy,
|
|
(char*)pmi->typedata);
|
|
SetBkMode (ptmi->dc, old_mode);
|
|
|
|
/** draw menu sub */
|
|
if (pmi->submenu) {
|
|
DrawMenuPic (ptmi->hwnd, ptmi->dc,
|
|
ptmi->show_rc.right - mioffx - marginrx,
|
|
y, pmi, TRUE, 0);
|
|
}
|
|
}
|
|
}
|
|
y += pmi->h;
|
|
|
|
if (pmi->type == TYPE_PPPMENU)
|
|
psubmi = pmi->submenu;
|
|
else
|
|
psubmi = pmi->next;
|
|
|
|
while (psubmi) {
|
|
/*add*/
|
|
if (y >= ptmi->show_rc.bottom){
|
|
break;
|
|
}
|
|
/*add end*/
|
|
|
|
/* fix bug #4491: use == instead of & for mnutype. */
|
|
if (psubmi->mnutype == MFT_BITMAP) {
|
|
|
|
if (psubmi->mnustate & MFS_CHECKED)
|
|
bmp = psubmi->checkedbmp;
|
|
else
|
|
bmp = (BITMAP*)psubmi->typedata;
|
|
|
|
offy = (psubmi->h - bmp->bmHeight) >> 1;
|
|
|
|
FillBoxWithBitmap (ptmi->dc, x, y + offy,
|
|
((BITMAP*)psubmi->typedata)->bmWidth,
|
|
psubmi->h - (offy << 1), bmp);
|
|
|
|
/** draw menu sub */
|
|
if (psubmi->submenu) {
|
|
DrawMenuPic (ptmi->hwnd, ptmi->dc,
|
|
ptmi->show_rc.right - mioffx - marginrx,
|
|
y, psubmi, TRUE, 0);
|
|
}
|
|
|
|
}
|
|
else if (psubmi->mnutype == MFT_SEPARATOR) {
|
|
|
|
/** two horizontal separator */
|
|
SetPenColor (ptmi->dc, darker_pixel);
|
|
MoveTo (ptmi->dc, x, y + (psubmi->h>>1) - inter + 1);
|
|
LineTo (ptmi->dc, ptmi->show_rc.right - marginrx,
|
|
y + (psubmi->h>>1) - inter + 1);
|
|
|
|
SetPenColor (ptmi->dc, lighter_pixel);
|
|
MoveTo (ptmi->dc, x, y + (psubmi->h>>1) - inter + 2);
|
|
LineTo (ptmi->dc, ptmi->show_rc.right - marginrx,
|
|
y + (psubmi->h>>1) - inter + 2);
|
|
}
|
|
else if (pmi->mnutype == MFT_OWNERDRAW) {
|
|
}
|
|
else {
|
|
int old_mode, bmp_w = mioffx;
|
|
|
|
/** draw radio, checkmark or bitmap */
|
|
DrawMenuPic (ptmi->hwnd, ptmi->dc, x + 1, y, psubmi, FALSE, &bmp_w);
|
|
|
|
/** menu text */
|
|
SelectFont (ptmi->dc, (PLOGFONT)GetWindowElementAttr
|
|
(ptmi->hwnd, WE_FONT_MENU));
|
|
old_mode = SetBkMode (ptmi->dc, BM_TRANSPARENT);
|
|
if (psubmi->mnustate & MFS_DISABLED)
|
|
SetTextColor (ptmi->dc, GetWindowElementPixelEx
|
|
(ptmi->hwnd, ptmi->dc, WE_FGC_DISABLED_ITEM));
|
|
else if (psubmi->mnustate & MFS_HILITE)
|
|
SetTextColor (ptmi->dc, GetWindowElementPixelEx
|
|
(ptmi->hwnd, ptmi->dc, WE_FGC_HIGHLIGHT_ITEM));
|
|
else
|
|
SetTextColor (ptmi->dc, GetWindowElementPixelEx
|
|
(ptmi->hwnd, ptmi->dc, WE_FGC_MENU));
|
|
|
|
offy = (psubmi->h - ((PLOGFONT)GetWindowElementAttr
|
|
(ptmi->hwnd, WE_FONT_MENU))->size) >> 1;
|
|
|
|
TextOut (ptmi->dc, x + bmp_w, y + offy,
|
|
(char*)psubmi->typedata);
|
|
SetBkMode (ptmi->dc, old_mode);
|
|
|
|
/** draw menu sub */
|
|
if (psubmi->submenu) {
|
|
DrawMenuPic (ptmi->hwnd, ptmi->dc,
|
|
ptmi->show_rc.right - mioffx - marginrx,
|
|
y, psubmi, TRUE, 0);
|
|
}
|
|
}
|
|
|
|
y += psubmi->h;
|
|
|
|
psubmi = psubmi->next;
|
|
|
|
}
|
|
/*add*/
|
|
if (ptmi->draw_bottom_flag) {
|
|
draw_bottom_scroll_button(ptmi);
|
|
}
|
|
/*add end*/
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int get_start_to_end_height(PTRACKMENUINFO ptmi)
|
|
{
|
|
PMENUITEM pmi = ptmi->pstart_show_mi;
|
|
int h = 0;
|
|
|
|
while (pmi != NULL){
|
|
h = h + pmi->h;
|
|
pmi = pmi->next;
|
|
}
|
|
|
|
return h;
|
|
}
|
|
|
|
static void draw_up_arrowhead(PTRACKMENUINFO ptmi, HDC hdc)
|
|
{
|
|
int l, t, r, b, cx, cy;
|
|
|
|
l = ptmi->top_scroll_rc.left;
|
|
t = ptmi->top_scroll_rc.top;
|
|
r = ptmi->top_scroll_rc.right;
|
|
b = ptmi->top_scroll_rc.bottom;
|
|
|
|
cx = (l + r) / 2;
|
|
cy = (t + b) / 2;
|
|
|
|
SetPenColor(hdc, GetWindowElementPixelEx (ptmi->hwnd, hdc, WE_FGC_MENU));
|
|
|
|
MoveTo(hdc, cx-4, cy+2);
|
|
LineTo(hdc, cx+4, cy+2);
|
|
|
|
MoveTo(hdc, cx-3, cy+1);
|
|
LineTo(hdc, cx+3, cy+1);
|
|
|
|
MoveTo(hdc, cx-2, cy);
|
|
LineTo(hdc, cx+2, cy);
|
|
|
|
MoveTo(hdc, cx-1, cy-1);
|
|
LineTo(hdc, cx+1, cy-1);
|
|
|
|
MoveTo(hdc, cx, cy-2);
|
|
LineTo(hdc, cx, cy-2);
|
|
|
|
}
|
|
|
|
static void draw_top_scroll_button(PTRACKMENUINFO ptmi)
|
|
{
|
|
PMAINWIN pWin;
|
|
DWORD bgc;
|
|
|
|
pWin = (PMAINWIN) ptmi->hwnd;
|
|
if (NULL == pWin) return;
|
|
|
|
if (!pWin->we_rdr) {
|
|
_WRN_PRINTF ("LFRDR is NULL for window: %p\n", pWin);
|
|
return;
|
|
}
|
|
|
|
bgc = GetWindowElementAttr (ptmi->hwnd, WE_BGC_MENU);
|
|
|
|
pWin->we_rdr->draw_3dbox (ptmi->dc, &ptmi->top_scroll_rc, bgc,
|
|
LFRDR_3DBOX_FILLED | LFRDR_3DBOX_THICKFRAME);
|
|
|
|
draw_up_arrowhead(ptmi, ptmi->dc);
|
|
}
|
|
|
|
|
|
static int show_scroll_popup_menu (PTRACKMENUINFO ptmi)
|
|
{
|
|
PMENUITEM pmi = ptmi->pstart_show_mi;
|
|
PMENUITEM psubmi;
|
|
int x, y, offy;
|
|
|
|
int inter;
|
|
int mioffx;
|
|
int marginlx, marginrx;
|
|
int marginy;
|
|
int font_offy;
|
|
|
|
int h = 0;
|
|
int old_mode;
|
|
|
|
PBITMAP bmp;
|
|
|
|
PMAINWIN pWin;
|
|
DWORD bgc;
|
|
|
|
DWORD darker_dword;
|
|
DWORD lighter_dword;
|
|
DWORD bgc_dword;
|
|
gal_pixel darker_pixel;
|
|
gal_pixel lighter_pixel;
|
|
|
|
pWin = (PMAINWIN) ptmi->hwnd;
|
|
if (NULL == pWin) return -1;
|
|
|
|
if (!pWin->we_rdr) {
|
|
_WRN_PRINTF ("LFRDR is NULL for window: %p\n", pWin);
|
|
return -1;
|
|
}
|
|
|
|
bgc = GetWindowElementAttr (ptmi->hwnd, WE_BGC_MENU);
|
|
if (save_box_under_menu (ptmi)) {
|
|
_WRN_PRINTF ("Can not get DC to show scrolled popup menu: %p\n", pWin);
|
|
return -1;
|
|
}
|
|
|
|
inter = LFRDR_INTERMENUITEMY;
|
|
mioffx = LFRDR_MENUITEMOFFX;
|
|
marginlx = LFRDR_MENULEFTMARGIN;
|
|
marginrx = LFRDR_MENURIGHTMARGIN;
|
|
marginy = LFRDR_MENUTOPMARGIN;
|
|
|
|
/** get darker and lighter color according to backgroup color */
|
|
bgc_dword = GetWindowElementAttr (ptmi->hwnd, WE_BGC_MENU);
|
|
darker_dword = pWin->we_rdr->calc_3dbox_color
|
|
(bgc_dword, LFRDR_3DBOX_COLOR_DARKEST);
|
|
lighter_dword = pWin->we_rdr->calc_3dbox_color
|
|
(bgc_dword, LFRDR_3DBOX_COLOR_LIGHTEST);
|
|
|
|
darker_pixel = DWORD2Pixel (ptmi->dc, darker_dword);
|
|
lighter_pixel = DWORD2Pixel (ptmi->dc, lighter_dword);
|
|
|
|
h = get_start_to_end_height(ptmi);
|
|
if ( (h + ptmi->top_scroll_rc.bottom) <= ptmi->bottom_scroll_rc.bottom){
|
|
ptmi->show_rc.bottom = ptmi->bottom_scroll_rc.bottom;
|
|
|
|
ptmi->bottom_scroll_rc.left = 0;
|
|
ptmi->bottom_scroll_rc.top = 0;
|
|
ptmi->bottom_scroll_rc.right = 0;
|
|
ptmi->bottom_scroll_rc.bottom = 0;
|
|
|
|
ptmi->draw_bottom_flag = FALSE;
|
|
}
|
|
|
|
if (ptmi->pstart_show_mi == ptmi->pmi ){
|
|
ptmi->show_rc.top = ptmi->rc.top;
|
|
|
|
ptmi->top_scroll_rc.left = 0;
|
|
ptmi->top_scroll_rc.top = 0;
|
|
ptmi->top_scroll_rc.right = 0;
|
|
ptmi->top_scroll_rc.bottom = 0;
|
|
|
|
ptmi->draw_top_flag = FALSE;
|
|
|
|
}
|
|
|
|
// draw background.
|
|
x = ptmi->show_rc.left;
|
|
y = ptmi->show_rc.top;
|
|
|
|
pWin->we_rdr->draw_3dbox (ptmi->dc, &ptmi->show_rc, bgc,
|
|
LFRDR_3DBOX_FILLED | LFRDR_3DBOX_THICKFRAME);
|
|
|
|
x = ptmi->show_rc.left + marginlx;
|
|
y = ptmi->show_rc.top + marginy;
|
|
if (pmi->mnutype == MFT_BITMAP) {
|
|
|
|
if (pmi->mnustate & MFS_CHECKED)
|
|
bmp = pmi->checkedbmp;
|
|
else
|
|
bmp = (BITMAP*)pmi->typedata;
|
|
|
|
offy = (pmi->h - bmp->bmHeight) >> 1;
|
|
|
|
FillBoxWithBitmap (ptmi->dc, x, y + offy,
|
|
((BITMAP*)pmi->typedata)->bmWidth, pmi->h - (offy << 1), bmp);
|
|
}
|
|
else if (pmi->mnutype == MFT_SEPARATOR) {
|
|
|
|
/** two horizontal separator */
|
|
SetPenColor (ptmi->dc, darker_pixel);
|
|
MoveTo (ptmi->dc,
|
|
x, y + (pmi->h>>1) - inter + 1);
|
|
LineTo (ptmi->dc,
|
|
ptmi->show_rc.right - marginrx, y + (pmi->h>>1) - inter + 1);
|
|
|
|
SetPenColor (ptmi->dc, lighter_pixel);
|
|
MoveTo (ptmi->dc,
|
|
x, y + (pmi->h>>1) - inter + 2);
|
|
LineTo (ptmi->dc,
|
|
ptmi->show_rc.right - marginrx, y + (pmi->h>>1) - inter + 2);
|
|
}
|
|
else if (pmi->mnutype == MFT_OWNERDRAW) {
|
|
}
|
|
else {
|
|
font_offy = (pmi->h - ((PLOGFONT)GetWindowElementAttr
|
|
(ptmi->hwnd, WE_FONT_MENU))->size) >> 1;
|
|
|
|
SelectFont (ptmi->dc, (PLOGFONT)GetWindowElementAttr
|
|
(ptmi->hwnd, WE_FONT_MENU));
|
|
|
|
if (pmi->type == TYPE_PPPMENU) {
|
|
old_mode = SetBkMode (ptmi->dc, BM_TRANSPARENT);
|
|
SetTextColor (ptmi->dc, GetWindowElementPixelEx
|
|
(ptmi->hwnd, ptmi->dc, WE_FGC_MENU));
|
|
TextOut (ptmi->dc, x + mioffx, y + font_offy,
|
|
(char*)pmi->typedata);
|
|
SetBkMode (ptmi->dc, old_mode);
|
|
|
|
SetPenColor (ptmi->dc, GetWindowElementPixelEx
|
|
(ptmi->hwnd, ptmi->dc, WE_FGC_MENU));
|
|
|
|
/** two horizontal separator */
|
|
MoveTo (ptmi->dc,
|
|
x,
|
|
y + pmi->h - (inter<<1));
|
|
LineTo (ptmi->dc,
|
|
ptmi->show_rc.right - marginrx,
|
|
y + pmi->h - (inter<<1));
|
|
MoveTo (ptmi->dc,
|
|
x,
|
|
y + pmi->h - inter);
|
|
LineTo (ptmi->dc,
|
|
ptmi->show_rc.right - marginrx,
|
|
y + pmi->h - inter);
|
|
}
|
|
else {
|
|
int bmp_w = mioffx;
|
|
|
|
/** draw radio, checkmark or bitmap */
|
|
DrawMenuPic (ptmi->hwnd, ptmi->dc, x + 1, y, pmi, FALSE, &bmp_w);
|
|
|
|
/** menu text */
|
|
old_mode = SetBkMode (ptmi->dc, BM_TRANSPARENT);
|
|
if (pmi->mnustate & MFS_DISABLED)
|
|
SetTextColor (ptmi->dc, GetWindowElementPixelEx
|
|
(ptmi->hwnd, ptmi->dc, WE_FGC_DISABLED_ITEM));
|
|
else if (pmi->mnustate & MFS_HILITE)
|
|
SetTextColor (ptmi->dc, GetWindowElementPixelEx
|
|
(ptmi->hwnd, ptmi->dc, WE_FGC_HIGHLIGHT_ITEM));
|
|
else
|
|
SetTextColor (ptmi->dc, GetWindowElementPixelEx
|
|
(ptmi->hwnd, ptmi->dc, WE_FGC_MENU));
|
|
|
|
TextOut (ptmi->dc, x + bmp_w, y + font_offy,
|
|
(char*)pmi->typedata);
|
|
SetBkMode (ptmi->dc, old_mode);
|
|
|
|
/** draw menu sub */
|
|
if (pmi->submenu) {
|
|
DrawMenuPic (ptmi->hwnd, ptmi->dc,
|
|
ptmi->show_rc.right - mioffx - marginrx,
|
|
y, pmi, TRUE, 0);
|
|
}
|
|
}
|
|
}
|
|
y += pmi->h;
|
|
|
|
if (pmi->type == TYPE_PPPMENU)
|
|
psubmi = pmi->submenu;
|
|
else
|
|
psubmi = pmi->next;
|
|
|
|
while (psubmi) {
|
|
/*add*/
|
|
if (y > ptmi->show_rc.bottom) {
|
|
break;
|
|
}
|
|
/*add end*/
|
|
|
|
if (psubmi->mnutype == MFT_BITMAP) {
|
|
|
|
if (psubmi->mnustate & MFS_CHECKED)
|
|
bmp = psubmi->checkedbmp;
|
|
else
|
|
bmp = (BITMAP*)psubmi->typedata;
|
|
|
|
offy = (psubmi->h - bmp->bmHeight) >> 1;
|
|
|
|
FillBoxWithBitmap (ptmi->dc, x, y + offy,
|
|
((BITMAP*)psubmi->typedata)->bmWidth,
|
|
psubmi->h - (offy << 1), bmp);
|
|
|
|
/** draw menu sub */
|
|
if (psubmi->submenu) {
|
|
DrawMenuPic (ptmi->hwnd, ptmi->dc,
|
|
ptmi->show_rc.right - mioffx - marginrx,
|
|
y, psubmi, TRUE, 0);
|
|
}
|
|
}
|
|
else if (psubmi->mnutype == MFT_SEPARATOR) {
|
|
|
|
/** tow horizontal separator */
|
|
SetPenColor (ptmi->dc, darker_pixel);
|
|
MoveTo (ptmi->dc,
|
|
x, y + (psubmi->h>>1) - inter + 1);
|
|
LineTo (ptmi->dc,
|
|
ptmi->show_rc.right - marginrx, y + (psubmi->h>>1) - inter + 1);
|
|
|
|
SetPenColor (ptmi->dc, lighter_pixel);
|
|
MoveTo (ptmi->dc,
|
|
x, y + (psubmi->h>>1) - inter + 2);
|
|
LineTo (ptmi->dc,
|
|
ptmi->show_rc.right - marginrx, y + (psubmi->h>>1) - inter + 2);
|
|
}
|
|
else if (pmi->mnutype == MFT_OWNERDRAW) {
|
|
}
|
|
else {
|
|
int old_mode, bmp_w = mioffx;
|
|
|
|
/** draw radio, checkmark or bitmap */
|
|
DrawMenuPic (ptmi->hwnd, ptmi->dc, x + 1, y, psubmi, FALSE, &bmp_w);
|
|
|
|
/** menu text*/
|
|
SelectFont (ptmi->dc, (PLOGFONT)GetWindowElementAttr
|
|
(ptmi->hwnd, WE_FONT_MENU));
|
|
old_mode = SetBkMode (ptmi->dc, BM_TRANSPARENT);
|
|
if (psubmi->mnustate & MFS_DISABLED)
|
|
SetTextColor (ptmi->dc, GetWindowElementPixelEx
|
|
(ptmi->hwnd, ptmi->dc, WE_FGC_DISABLED_ITEM));
|
|
else if (psubmi->mnustate & MFS_HILITE)
|
|
SetTextColor (ptmi->dc, GetWindowElementPixelEx
|
|
(ptmi->hwnd, ptmi->dc, WE_FGC_HIGHLIGHT_ITEM));
|
|
else
|
|
SetTextColor (ptmi->dc, GetWindowElementPixelEx
|
|
(ptmi->hwnd, ptmi->dc, WE_FGC_MENU));
|
|
|
|
offy = (psubmi->h - ((PLOGFONT)GetWindowElementAttr
|
|
(ptmi->hwnd, WE_FONT_MENU))->size) >> 1;
|
|
|
|
TextOut (ptmi->dc, x + bmp_w, y + offy,
|
|
(char*)psubmi->typedata);
|
|
SetBkMode (ptmi->dc, old_mode);
|
|
|
|
/** draw menu sub */
|
|
if (psubmi->submenu) {
|
|
DrawMenuPic (ptmi->hwnd, ptmi->dc,
|
|
ptmi->show_rc.right - mioffx - marginrx,
|
|
y, psubmi, TRUE, 0);
|
|
}
|
|
}
|
|
|
|
y += psubmi->h;
|
|
|
|
psubmi = psubmi->next;
|
|
}
|
|
|
|
/*add*/
|
|
if (ptmi->draw_bottom_flag){
|
|
draw_bottom_scroll_button(ptmi);
|
|
}
|
|
|
|
if (ptmi->draw_top_flag){
|
|
draw_top_scroll_button(ptmi);
|
|
}
|
|
/*add end*/
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void mnuUnhiliteMenu (PMENUITEM pmi)
|
|
{
|
|
if (pmi->type == TYPE_PPPMENU)
|
|
pmi = pmi->submenu;
|
|
else {
|
|
if (pmi->mnustate & MFS_HILITE)
|
|
pmi->mnustate &= ~MFS_HILITE;
|
|
|
|
pmi = pmi->next;
|
|
}
|
|
|
|
while (pmi) {
|
|
if (pmi->mnustate & MFS_HILITE)
|
|
pmi->mnustate &= ~MFS_HILITE;
|
|
|
|
pmi = pmi->next;
|
|
}
|
|
}
|
|
|
|
static void mnuCloseMenu (PTRACKMENUINFO ptmi)
|
|
{
|
|
PTRACKMENUINFO phead, plast, ptemp;
|
|
HMENU hmnu;
|
|
UINT flags;
|
|
|
|
// menu bar info
|
|
HWND hwnd;
|
|
PMENUBAR pmb;
|
|
int barPos;
|
|
|
|
flags = ptmi->flags;
|
|
hmnu = (HMENU)ptmi->pmi;
|
|
|
|
// get first tracking menu.
|
|
phead = ptmi;
|
|
while (phead->prev) {
|
|
phead = phead->prev;
|
|
}
|
|
pmb = phead->pmb;
|
|
hwnd = phead->hwnd;
|
|
barPos = phead->barPos;
|
|
|
|
// get last tracking menu.
|
|
plast = ptmi;
|
|
while (plast->next) {
|
|
plast = plast->next;
|
|
}
|
|
|
|
while (plast) {
|
|
ptemp = plast->prev;
|
|
|
|
mnuUnhiliteMenu (plast->pmi);
|
|
|
|
SendMessage (HWND_DESKTOP,
|
|
MSG_ENDTRACKMENU, 0, (LPARAM)plast);
|
|
|
|
plast = ptemp;
|
|
}
|
|
|
|
if (pmb && barPos >= 0)
|
|
HiliteMenuBarItem (hwnd, barPos, LFRDR_MENU_STATE_NORMAL);
|
|
|
|
if (flags & TPM_DESTROY)
|
|
DestroyMenu (hmnu);
|
|
}
|
|
|
|
static PTRACKMENUINFO mnuHitTestMenu (PTRACKMENUINFO plast, int x, int y)
|
|
{
|
|
PTRACKMENUINFO ptemp;
|
|
|
|
// which popup menu mouse in.
|
|
ptemp = plast;
|
|
while (ptemp) {
|
|
|
|
if ( PtInRect(&ptemp->rc, x, y))
|
|
return ptemp;
|
|
|
|
ptemp = ptemp->prev;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
#if 0
|
|
static PMENUITEM mnuHitTestMenuItem (PTRACKMENUINFO ptmi, int x, int y)
|
|
{
|
|
PMENUITEM pmi = ptmi->pmi;
|
|
PMENUITEM psubmi;
|
|
RECT rc;
|
|
|
|
rc.left = ptmi->rc.left;
|
|
rc.right = ptmi->rc.right;
|
|
rc.top = ptmi->rc.top + LFRDR_MENUTOPMARGIN;
|
|
rc.bottom = rc.top + pmi->h;
|
|
|
|
if (PtInRect (&rc, x, y))
|
|
return pmi;
|
|
|
|
rc.top += pmi->h;
|
|
if (pmi->type == TYPE_PPPMENU)
|
|
psubmi = pmi->submenu;
|
|
else
|
|
psubmi = pmi->next;
|
|
|
|
while (psubmi) {
|
|
|
|
rc.bottom = rc.top + psubmi->h;
|
|
|
|
if (PtInRect (&rc, x, y))
|
|
return psubmi;
|
|
|
|
rc.top = rc.bottom;
|
|
psubmi = psubmi->next;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
#endif
|
|
|
|
static PMENUITEM get_selected_mi(PTRACKMENUINFO ptmi, int x, int y)
|
|
{
|
|
PMENUITEM pmi = ptmi->pstart_show_mi;
|
|
PMENUITEM psubmi;
|
|
RECT rc;
|
|
|
|
rc.left = ptmi->show_rc.left;
|
|
rc.right = ptmi->show_rc.right;
|
|
rc.top = ptmi->show_rc.top + LFRDR_MENUTOPMARGIN;
|
|
rc.bottom = rc.top + pmi->h;
|
|
|
|
if (PtInRect (&rc, x, y))
|
|
return pmi;
|
|
|
|
rc.top += pmi->h;
|
|
if (pmi->type == TYPE_PPPMENU)
|
|
psubmi = pmi->submenu;
|
|
else
|
|
psubmi = pmi->next;
|
|
|
|
while (psubmi) {
|
|
|
|
rc.bottom = rc.top + psubmi->h;
|
|
|
|
if (PtInRect (&rc, x, y)){
|
|
/*add*/
|
|
ptmi->selected_rc.left = rc.left;
|
|
ptmi->selected_rc.top = rc.top;
|
|
ptmi->selected_rc.right = rc.right;
|
|
ptmi->selected_rc.bottom = rc.bottom;
|
|
/*add end*/
|
|
return psubmi;
|
|
}
|
|
|
|
rc.top = rc.bottom;
|
|
psubmi = psubmi->next;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static void mnuHiliteMenuItem (PTRACKMENUINFO ptmi, PMENUITEM pmi, BOOL bHilite)
|
|
{
|
|
RECT rc;
|
|
PMENUITEM ptemp = ptmi->pstart_show_mi;
|
|
PMAINWIN pWin;
|
|
HWND hwnd = ptmi->hwnd;
|
|
PBITMAP bmp;
|
|
|
|
/** the menu item rect to be drawn*/
|
|
RECT rect;
|
|
// NUV int inter;
|
|
int mioffx;
|
|
int marginlx, marginrx;
|
|
int offy;
|
|
|
|
pWin = (PMAINWIN) hwnd;
|
|
if (NULL == pWin) return;
|
|
|
|
if (!pWin->we_rdr) {
|
|
_WRN_PRINTF ("LFRDR is NULL for window: %p\n", pWin);
|
|
return;
|
|
}
|
|
|
|
if (pmi->type == TYPE_PPPMENU) return;
|
|
|
|
// NUV inter = LFRDR_INTERMENUITEMY;
|
|
mioffx = LFRDR_MENUITEMOFFX;
|
|
marginlx = LFRDR_MENULEFTMARGIN;
|
|
marginrx = LFRDR_MENURIGHTMARGIN;
|
|
|
|
rc.left = ptmi->show_rc.left;
|
|
rc.right = ptmi->show_rc.right;
|
|
rc.top = ptmi->show_rc.top + LFRDR_MENUTOPMARGIN;
|
|
|
|
if (ptemp == pmi)
|
|
ptemp = pmi;
|
|
else {
|
|
rc.top += ptemp->h;
|
|
if (ptemp->type == TYPE_PPPMENU)
|
|
ptemp = ptemp->submenu;
|
|
else
|
|
ptemp = ptemp->next;
|
|
|
|
while (ptemp != pmi) {
|
|
if (ptemp == NULL) return;
|
|
rc.top += ptemp->h;
|
|
ptemp = ptemp->next;
|
|
}
|
|
}
|
|
|
|
rc.bottom = rc.top + ptemp->h;
|
|
|
|
if (ptemp->mnutype == MFT_SEPARATOR)
|
|
return;
|
|
|
|
if (bHilite)
|
|
ptemp->mnustate |= MFS_HILITE;
|
|
else
|
|
ptemp->mnustate &= ~MFS_HILITE;
|
|
|
|
/** rect to be drawn */
|
|
rect.left = rc.left + marginlx;
|
|
rect.top = rc.top;
|
|
rect.right = rect.left + RECTW (rc) - marginlx - marginrx;
|
|
rect.bottom = rect.top + RECTH (rc);
|
|
|
|
/** draw the rect, high priority for disabled item, */
|
|
if (ptemp->mnustate & MFS_DISABLED)
|
|
{
|
|
/** render a disabled item */
|
|
SetTextColor (ptmi->dc, GetWindowElementPixelEx
|
|
(hwnd, ptmi->dc, WE_FGC_DISABLED_ITEM));
|
|
if (ptemp->mnustate & MFS_HILITE)
|
|
pWin->we_rdr->draw_disabled_menu_item (hwnd, ptmi->dc, &rect,
|
|
GetWindowElementAttr (hwnd, WE_BGC_DISABLED_ITEM));
|
|
else
|
|
pWin->we_rdr->draw_disabled_menu_item (hwnd, ptmi->dc, &rect,
|
|
GetWindowElementAttr (hwnd, WE_BGC_MENU));
|
|
}
|
|
else if (ptemp->mnustate & MFS_HILITE)
|
|
{
|
|
/** render a hilite item */
|
|
SetTextColor (ptmi->dc, GetWindowElementPixelEx
|
|
(hwnd, ptmi->dc, WE_FGC_HIGHLIGHT_ITEM));
|
|
pWin->we_rdr->draw_hilite_menu_item (hwnd, ptmi->dc, &rect,
|
|
GetWindowElementAttr (hwnd, WE_BGC_HIGHLIGHT_ITEM));
|
|
}
|
|
else
|
|
{
|
|
/** render a normal item as unhilite */
|
|
SetTextColor (ptmi->dc, GetWindowElementPixelEx
|
|
(hwnd, ptmi->dc, WE_FGC_MENU));
|
|
|
|
pWin->we_rdr->draw_normal_menu_item (hwnd, ptmi->dc, &rect,
|
|
GetWindowElementAttr (hwnd, WE_BGC_MENU));
|
|
}
|
|
|
|
if (ptemp->mnutype == MFT_BITMAP) {
|
|
|
|
/** draw check or unchecked bitmap */
|
|
if (ptemp->mnustate & MFS_CHECKED)
|
|
bmp = ptemp->checkedbmp;
|
|
else if (bHilite)
|
|
bmp = ptemp->uncheckedbmp;
|
|
else
|
|
bmp = (BITMAP*)ptemp->typedata;
|
|
|
|
offy = (ptemp->h - bmp->bmHeight) >> 1;
|
|
|
|
FillBoxWithBitmap (ptmi->dc, rc.left + marginlx, rc.top + offy,
|
|
((BITMAP*)ptemp->typedata)->bmWidth,
|
|
ptemp->h - (offy << 1), bmp);
|
|
|
|
/** draw menu sub */
|
|
if (ptemp->submenu) {
|
|
DrawMenuPic (ptmi->hwnd, ptmi->dc,
|
|
rc.right - mioffx - marginrx,
|
|
rc.top, ptemp, TRUE, 0);
|
|
}
|
|
}
|
|
else if (ptemp->mnutype == MFT_OWNERDRAW) {
|
|
}
|
|
else {
|
|
int old_mode, bmp_w = mioffx;
|
|
|
|
/** draw radio, checkmark or bitmap */
|
|
DrawMenuPic (ptmi->hwnd, ptmi->dc,
|
|
rc.left + marginlx + 1, rc.top, ptemp, FALSE, &bmp_w);
|
|
|
|
/** menu text */
|
|
SelectFont (ptmi->dc, (PLOGFONT)GetWindowElementAttr
|
|
(ptmi->hwnd, WE_FONT_MENU));
|
|
old_mode = SetBkMode (ptmi->dc, BM_TRANSPARENT);
|
|
offy = (ptemp->h - ((PLOGFONT)GetWindowElementAttr
|
|
(ptmi->hwnd, WE_FONT_MENU))->size) >> 1;
|
|
|
|
TextOut (ptmi->dc, rc.left + bmp_w + marginlx, rc.top + offy,
|
|
(char*)ptemp->typedata);
|
|
SetBkMode (ptmi->dc, old_mode);
|
|
|
|
/** draw menu sub */
|
|
if (ptemp->submenu) {
|
|
DrawMenuPic (ptmi->hwnd, ptmi->dc,
|
|
rc.right - mioffx - marginrx, rc.top, ptemp, TRUE, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
static int mnuOpenNewSubMenu (PTRACKMENUINFO ptmi, PMENUITEM pmi,
|
|
int x, int y)
|
|
{
|
|
PTRACKMENUINFO pnewtmi;
|
|
|
|
pnewtmi = TrackMenuInfoAlloc ();
|
|
|
|
pnewtmi->rc.left = x;
|
|
pnewtmi->rc.top = y;
|
|
pnewtmi->pmi = pmi;
|
|
pnewtmi->pmb = ptmi->pmb;
|
|
pnewtmi->philite = NULL;
|
|
pnewtmi->hwnd = ptmi->hwnd;
|
|
pnewtmi->flags = ptmi->flags;
|
|
pnewtmi->next = NULL;
|
|
pnewtmi->prev = NULL;
|
|
|
|
if (SendMessage (HWND_DESKTOP, MSG_TRACKPOPUPMENU,
|
|
0, (LPARAM)(pnewtmi)) < 0) {
|
|
FreeTrackMenuInfo (pnewtmi);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PMENUITEM mnuGetNextMenuItem (PTRACKMENUINFO ptmi, PMENUITEM pmi)
|
|
{
|
|
PMENUITEM head = ptmi->pmi;
|
|
PMENUITEM next;
|
|
|
|
if (head->type == TYPE_PPPMENU)
|
|
head = head->submenu;
|
|
|
|
if (pmi == NULL)
|
|
next = head;
|
|
else if (pmi->next)
|
|
next = pmi->next;
|
|
else
|
|
next = head;
|
|
|
|
while (next && (next->mnutype == MFT_SEPARATOR))
|
|
next = next->next;
|
|
|
|
if (next == NULL)
|
|
next = head;
|
|
|
|
while (next && (next->mnutype == MFT_SEPARATOR))
|
|
next = next->next;
|
|
|
|
return next;
|
|
}
|
|
|
|
static PMENUITEM mnuGetPrevItem (PMENUITEM head, PMENUITEM pmi)
|
|
{
|
|
if (head == pmi)
|
|
return NULL;
|
|
|
|
while (head) {
|
|
if (head->next == pmi)
|
|
return head;
|
|
|
|
head = head->next;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static PMENUITEM mnuGetPrevMenuItem (PTRACKMENUINFO ptmi, PMENUITEM pmi)
|
|
{
|
|
PMENUITEM head = ptmi->pmi, tail;
|
|
PMENUITEM prev;
|
|
|
|
if (head->type == TYPE_PPPMENU)
|
|
head = head->submenu;
|
|
|
|
prev = pmi;
|
|
|
|
do {
|
|
prev = mnuGetPrevItem (head, prev);
|
|
|
|
if (prev) {
|
|
if (prev->mnutype == MFT_SEPARATOR)
|
|
continue;
|
|
else
|
|
return prev;
|
|
}
|
|
else
|
|
break;
|
|
}while (TRUE);
|
|
|
|
tail = head;
|
|
while (tail && tail->next)
|
|
tail = tail->next;
|
|
|
|
prev = tail;
|
|
do {
|
|
if (prev) {
|
|
if (!(prev->mnutype == MFT_SEPARATOR))
|
|
return prev;
|
|
}
|
|
else
|
|
break;
|
|
|
|
prev = mnuGetPrevItem (head, prev);
|
|
}while (TRUE);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static int mnuGetMenuItemY (PTRACKMENUINFO ptmi, PMENUITEM pmi)
|
|
{
|
|
//PMENUITEM head = ptmi->pmi;
|
|
//int y = ptmi->rc.top + LFRDR_MENUTOPMARGIN;
|
|
|
|
PMENUITEM head = ptmi->pstart_show_mi;
|
|
int y = ptmi->show_rc.top + LFRDR_MENUTOPMARGIN;
|
|
|
|
if (pmi == head) return y;
|
|
|
|
y += head->h;
|
|
|
|
if (head->type == TYPE_PPPMENU)
|
|
head = head->submenu;
|
|
else
|
|
head = head->next;
|
|
|
|
while (head) {
|
|
if (head == pmi)
|
|
return y;
|
|
|
|
y += head->h;
|
|
|
|
head = head->next;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int get_menu_item_y_from_pstart (PTRACKMENUINFO ptmi, PMENUITEM pmi)
|
|
{
|
|
PMENUITEM head = ptmi->pstart_show_mi;
|
|
int y = head->h;
|
|
|
|
if (pmi == head) return y;
|
|
|
|
y += head->h;
|
|
|
|
if (head->type == TYPE_PPPMENU)
|
|
head = head->submenu;
|
|
else
|
|
head = head->next;
|
|
|
|
while (head) {
|
|
if (head == pmi)
|
|
return y;
|
|
|
|
y += head->h;
|
|
|
|
head = head->next;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void mnu_scroll_menu (PTRACKMENUINFO ptmi, int x, int y);
|
|
|
|
static void cursor_block_down(PTRACKMENUINFO pcurtmi, PMENUITEM pcurmi)
|
|
{
|
|
PMENUITEM pnewmi;
|
|
int y;
|
|
|
|
pnewmi = mnuGetNextMenuItem (pcurtmi, pcurmi);
|
|
|
|
y = get_menu_item_y_from_pstart (pcurtmi, pnewmi);
|
|
|
|
if (pcurtmi->rc.bottom > g_rcScr.bottom){
|
|
|
|
if (pcurmi != NULL){
|
|
if (pcurmi->next == NULL){
|
|
mnuShowPopupMenu (pcurtmi);
|
|
mnuHiliteMenuItem (pcurtmi, pnewmi, TRUE);
|
|
pcurtmi->philite = pnewmi;
|
|
return;
|
|
|
|
}
|
|
if (pnewmi == pcurtmi->pmi){
|
|
mnuShowPopupMenu (pcurtmi);
|
|
mnuHiliteMenuItem (pcurtmi, pnewmi, TRUE);
|
|
pcurtmi->philite = pnewmi;
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ((y + pcurtmi->top_scroll_rc.bottom) >= pcurtmi->show_rc.bottom){
|
|
mnu_scroll_menu(pcurtmi, (pcurtmi->rc.left + pcurtmi->rc.right) /2,
|
|
g_rcScr.bottom - 1);
|
|
|
|
}
|
|
else{
|
|
if (pnewmi != pcurmi) {
|
|
|
|
if (pcurmi){
|
|
mnuHiliteMenuItem (pcurtmi, pcurmi, FALSE);
|
|
}
|
|
|
|
if (pnewmi) {
|
|
mnuHiliteMenuItem (pcurtmi, pnewmi, TRUE);
|
|
pcurtmi->philite = pnewmi;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
else{
|
|
if (pnewmi != pcurmi) {
|
|
if (pcurmi){
|
|
mnuHiliteMenuItem (pcurtmi, pcurmi, FALSE);
|
|
}
|
|
|
|
if (pnewmi) {
|
|
mnuHiliteMenuItem (pcurtmi, pnewmi, TRUE);
|
|
pcurtmi->philite = pnewmi;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
static void cursor_block_up(PTRACKMENUINFO pcurtmi, PMENUITEM pcurmi)
|
|
{
|
|
PMENUITEM pnewmi;
|
|
// NUV int y;
|
|
|
|
if (pcurmi == NULL) return;
|
|
|
|
pnewmi = mnuGetPrevMenuItem (pcurtmi, pcurmi);
|
|
|
|
// NUV y = get_menu_item_y_from_pstart(pcurtmi, pcurmi);
|
|
|
|
if (pcurtmi->rc.bottom > g_rcScr.bottom){
|
|
if (pnewmi == mnuGetPrevMenuItem(pcurtmi, pcurtmi->pmi)){
|
|
mnuShowPopupMenu (pcurtmi);
|
|
mnuHiliteMenuItem (pcurtmi, pcurmi, TRUE);
|
|
pcurtmi->philite = pcurmi;
|
|
return;
|
|
}
|
|
|
|
if (pnewmi == pcurtmi->pmi){
|
|
mnuShowPopupMenu (pcurtmi);
|
|
if (pcurmi){
|
|
mnuHiliteMenuItem (pcurtmi, pcurmi, FALSE);
|
|
}
|
|
mnuHiliteMenuItem (pcurtmi, pnewmi, TRUE);
|
|
pcurtmi->philite = pnewmi;
|
|
return;
|
|
}
|
|
|
|
if (pcurmi == pcurtmi->pstart_show_mi){
|
|
mnu_scroll_menu(pcurtmi, (pcurtmi->rc.left + pcurtmi->rc.right) /2,
|
|
pcurtmi->top_scroll_rc.top + 1);
|
|
}
|
|
else {
|
|
if (pnewmi != pcurmi) {
|
|
|
|
if (pcurmi){
|
|
mnuHiliteMenuItem (pcurtmi, pcurmi, FALSE);
|
|
draw_bottom_scroll_button(pcurtmi);
|
|
}
|
|
|
|
if (pnewmi) {
|
|
mnuHiliteMenuItem (pcurtmi, pnewmi, TRUE);
|
|
pcurtmi->philite = pnewmi;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (pnewmi != pcurmi) {
|
|
|
|
if (pcurmi){
|
|
mnuHiliteMenuItem (pcurtmi, pcurmi, FALSE);
|
|
}
|
|
|
|
if (pnewmi) {
|
|
mnuHiliteMenuItem (pcurtmi, pnewmi, TRUE);
|
|
pcurtmi->philite = pnewmi;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
static void mnuTrackMenuWithKey (PTRACKMENUINFO ptmi,
|
|
int message, int scan, DWORD status)
|
|
{
|
|
PTRACKMENUINFO phead, pcurtmi, pprevtmi;
|
|
PMENUITEM pcurmi;
|
|
HWND hwnd;
|
|
HMENU hmnu;
|
|
UINT flags;
|
|
int barItem;
|
|
int id;
|
|
|
|
flags = ptmi->flags;
|
|
hmnu = (HMENU)ptmi->pmi;
|
|
|
|
phead = ptmi;
|
|
while (phead->prev) {
|
|
phead = phead->prev;
|
|
}
|
|
|
|
// get last tracking menu, the last menu is the current menu.
|
|
pcurtmi = ptmi;
|
|
while (pcurtmi->next) {
|
|
pcurtmi = pcurtmi->next;
|
|
}
|
|
|
|
pprevtmi = pcurtmi->prev;
|
|
|
|
pcurmi = pcurtmi->philite;
|
|
|
|
if (message == MSG_KEYDOWN) {
|
|
switch (scan) {
|
|
case SCANCODE_CURSORBLOCKDOWN:
|
|
case SCANCODE_CURSORBLOCKUP:
|
|
if (scan == SCANCODE_CURSORBLOCKDOWN){
|
|
cursor_block_down(pcurtmi, pcurmi);
|
|
}
|
|
else{// scan == SCANCODE_CURSORBLOCKUP:
|
|
cursor_block_up(pcurtmi, pcurmi);
|
|
}
|
|
|
|
break;
|
|
|
|
case SCANCODE_CURSORBLOCKRIGHT:
|
|
if (pcurmi && pcurmi->submenu)
|
|
mnuOpenNewSubMenu (pcurtmi,
|
|
pcurmi->submenu,
|
|
pcurtmi->rc.right,
|
|
mnuGetMenuItemY (pcurtmi, pcurmi));
|
|
else {
|
|
if (phead->pmb) {
|
|
barItem = mnuGetNextMenuBarItem (phead->pmb,
|
|
phead->barPos);
|
|
if (barItem != phead->barPos) {
|
|
hwnd = phead->hwnd;
|
|
|
|
// close current popup menu.
|
|
SendMessage (HWND_DESKTOP, MSG_CLOSEMENU, 0, 0);
|
|
|
|
// open new popup menu.
|
|
TrackMenuBar (hwnd, barItem);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SCANCODE_ESCAPE:
|
|
if (pprevtmi) {
|
|
SendMessage (HWND_DESKTOP,
|
|
MSG_ENDTRACKMENU, 0, (LPARAM)pcurtmi);
|
|
}else{
|
|
SendMessage (HWND_DESKTOP, MSG_CLOSEMENU, 0, 1);
|
|
}
|
|
break;
|
|
|
|
case SCANCODE_CURSORBLOCKLEFT:
|
|
if (pprevtmi)
|
|
SendMessage (HWND_DESKTOP,
|
|
MSG_ENDTRACKMENU, 0, (LPARAM)pcurtmi);
|
|
else {
|
|
if (phead->pmb) {
|
|
barItem = mnuGetPrevMenuBarItem (phead->pmb,
|
|
phead->barPos);
|
|
if (barItem != phead->barPos) {
|
|
hwnd = phead->hwnd;
|
|
|
|
// close current popup menu.
|
|
SendMessage (HWND_DESKTOP, MSG_CLOSEMENU, 0, 0);
|
|
|
|
// open new popup menu.
|
|
TrackMenuBar (hwnd, barItem);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SCANCODE_ENTER:
|
|
if (pcurmi == NULL) return;
|
|
if (pcurmi->mnutype == MFT_SEPARATOR) return;
|
|
if (pcurmi->mnustate & MFS_DISABLED) return;
|
|
|
|
if (pcurmi->submenu) {
|
|
mnuOpenNewSubMenu (pcurtmi,
|
|
pcurmi->submenu,
|
|
pcurtmi->rc.right,
|
|
mnuGetMenuItemY (pcurtmi, pcurmi));
|
|
return;
|
|
}
|
|
|
|
if (pcurmi && pcurmi->type != TYPE_PPPMENU &&
|
|
pcurmi->submenu == NULL) {
|
|
|
|
hwnd = ptmi->hwnd;
|
|
id = pcurmi->id;
|
|
|
|
SendMessage (HWND_DESKTOP, MSG_CLOSEMENU, 0, 1);
|
|
|
|
if (flags & TPM_SYSCMD)
|
|
SendNotifyMessage (hwnd, MSG_SYSCOMMAND, id, 0);
|
|
else
|
|
SendNotifyMessage (hwnd, MSG_COMMAND, id, 0);
|
|
|
|
if (flags & TPM_DESTROY)
|
|
DestroyMenu (hmnu);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else if (message == MSG_KEYUP) {
|
|
switch (scan) {
|
|
case SCANCODE_LEFTALT:
|
|
case SCANCODE_RIGHTALT:
|
|
SendMessage (HWND_DESKTOP, MSG_CLOSEMENU, 0, 1);
|
|
|
|
if (flags & TPM_DESTROY)
|
|
DestroyMenu (hmnu);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void mnu_scroll_menu (PTRACKMENUINFO ptmi, int x, int y)
|
|
{
|
|
PTRACKMENUINFO phead, plast;
|
|
PTRACKMENUINFO pcurtmi, pclose, ptemp;
|
|
PMENUITEM pcurmi, pnewmi;
|
|
PMENUITEM philite;
|
|
int barItem;
|
|
HWND hwnd;
|
|
|
|
// get first tracking menu.
|
|
phead = ptmi;
|
|
while (phead->prev) {
|
|
phead = phead->prev;
|
|
}
|
|
|
|
// get last tracking menu.
|
|
plast = ptmi;
|
|
while (plast->next) {
|
|
plast = plast->next;
|
|
}
|
|
|
|
pcurtmi = mnuHitTestMenu (plast, x, y);
|
|
|
|
if (pcurtmi == NULL) {
|
|
if (plast->philite){
|
|
mnuHiliteMenuItem (plast, plast->philite, FALSE);
|
|
plast->mouse_leave_flag = TRUE;
|
|
draw_bottom_scroll_button(plast);
|
|
}
|
|
|
|
// check to see if move to the other sub menu of menu bar.
|
|
if (phead->pmb) {
|
|
barItem = MenuBarHitTest (phead->hwnd, x, y);
|
|
if (barItem >= 0 && barItem != phead->barPos) {
|
|
hwnd = phead->hwnd;
|
|
|
|
// close current popup menu.
|
|
SendMessage (HWND_DESKTOP, MSG_CLOSEMENU, 0, 0);
|
|
|
|
// open new popup menu.
|
|
TrackMenuBar (hwnd, barItem);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
pcurmi = get_selected_mi(pcurtmi, x, y);
|
|
|
|
if (PtInRect(&pcurtmi->bottom_scroll_rc, x, y)){
|
|
|
|
pcurtmi->top_scroll_rc.left = pcurtmi->rc.left;
|
|
pcurtmi->top_scroll_rc.top = 0;
|
|
pcurtmi->top_scroll_rc.right = pcurtmi->rc.right;
|
|
//pcurtmi->top_scroll_rc.bottom = pcurtmi->top_scroll_rc.top +
|
|
//pcurtmi->pmi->h - SHORTEN;
|
|
pcurtmi->top_scroll_rc.bottom = pcurtmi->top_scroll_rc.top +
|
|
GetSysFontHeight(SYSLOGFONT_MENU) - SHORTEN;
|
|
|
|
ptmi->show_rc.top = pcurtmi->top_scroll_rc.bottom;
|
|
ptmi->show_rc.left = pcurtmi->rc.left;
|
|
ptmi->show_rc.right = pcurtmi->rc.right;
|
|
//ptmi->show_rc.bottom = g_rcScr.bottom - ptmi->pmi->h + SHORTEN;
|
|
ptmi->show_rc.bottom = g_rcScr.bottom -
|
|
GetSysFontHeight(SYSLOGFONT_MENU) + SHORTEN;
|
|
|
|
pcurmi = get_selected_mi(pcurtmi, x, y);
|
|
pcurtmi->pstart_show_mi =
|
|
mnuGetNextMenuItem(pcurtmi, pcurtmi->pstart_show_mi);
|
|
|
|
pcurtmi->draw_top_flag = TRUE;
|
|
|
|
show_scroll_popup_menu(pcurtmi);
|
|
}
|
|
|
|
if (PtInRect(&pcurtmi->top_scroll_rc, x, y)){
|
|
|
|
pnewmi = mnuGetPrevMenuItem(pcurtmi, pcurtmi->pstart_show_mi);
|
|
|
|
if (pnewmi == mnuGetPrevMenuItem(pcurtmi, pcurtmi->pmi)){
|
|
mnuShowPopupMenu (pcurtmi);
|
|
//mnuHiliteMenuItem (pcurtmi, pcurtmi->pmi, TRUE);
|
|
//pcurtmi->philite = pcurmi;
|
|
return;
|
|
}
|
|
|
|
if (pnewmi == pcurtmi->pmi){
|
|
mnuShowPopupMenu (pcurtmi);
|
|
if (pcurtmi->philite) {
|
|
mnuHiliteMenuItem (pcurtmi, pcurtmi->philite, FALSE);
|
|
}
|
|
mnuHiliteMenuItem (pcurtmi, pnewmi, TRUE);
|
|
pcurtmi->philite = pnewmi;
|
|
return;
|
|
}
|
|
|
|
//pcurtmi->pstart_show_mi = mnuGetPrevMenuItem
|
|
//(pcurtmi, pcurtmi->pstart_show_mi);
|
|
pcurtmi->pstart_show_mi = pnewmi;
|
|
|
|
pcurtmi->show_rc.top = pcurtmi->top_scroll_rc.bottom;
|
|
pcurtmi->show_rc.left = pcurtmi->rc.left;
|
|
pcurtmi->show_rc.right = pcurtmi->rc.right;
|
|
//pcurtmi->show_rc.bottom = g_rcScr.bottom - pcurtmi->pmi->h + SHORTEN;
|
|
ptmi->show_rc.bottom = g_rcScr.bottom -
|
|
GetSysFontHeight(SYSLOGFONT_MENU) + SHORTEN;
|
|
|
|
pcurtmi->bottom_scroll_rc.top = pcurtmi->show_rc.bottom;
|
|
pcurtmi->bottom_scroll_rc.left = pcurtmi->rc.left;
|
|
pcurtmi->bottom_scroll_rc.right = pcurtmi->rc.right;
|
|
pcurtmi->bottom_scroll_rc.bottom = g_rcScr.bottom;
|
|
|
|
pcurtmi->draw_bottom_flag = TRUE;
|
|
pcurmi = pcurtmi->pstart_show_mi;
|
|
|
|
show_scroll_popup_menu(pcurtmi);
|
|
|
|
}
|
|
|
|
if (pcurtmi != plast) {
|
|
pclose = pcurtmi->next->next;
|
|
|
|
if (pclose != NULL) {
|
|
while (pclose != plast) {
|
|
ptemp = plast->prev;
|
|
SendMessage (HWND_DESKTOP, MSG_ENDTRACKMENU, 0, (LPARAM)plast);
|
|
plast = ptemp;
|
|
}
|
|
SendMessage (HWND_DESKTOP, MSG_ENDTRACKMENU, 0, (LPARAM)plast);
|
|
plast = pcurtmi->next;
|
|
}
|
|
|
|
if (plast->philite) {
|
|
mnuHiliteMenuItem (plast, plast->philite, FALSE);
|
|
plast->philite = NULL;
|
|
}
|
|
}
|
|
|
|
philite = pcurtmi->philite;
|
|
if ((pcurmi == philite) && !pcurtmi->mouse_leave_flag){
|
|
return;
|
|
}
|
|
pcurtmi->mouse_leave_flag = FALSE;// mouse come back pcurtmi
|
|
|
|
// current hilite menu item is a bottom most item.
|
|
if (philite) {
|
|
if (pcurtmi != plast)
|
|
SendMessage (HWND_DESKTOP, MSG_ENDTRACKMENU, 0, (LPARAM)plast);
|
|
mnuHiliteMenuItem (pcurtmi, philite, FALSE);
|
|
draw_bottom_scroll_button(pcurtmi);
|
|
}
|
|
|
|
pcurtmi->philite = pcurmi;
|
|
if (pcurmi == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (pcurmi->type == TYPE_PPPMENU) return;
|
|
|
|
|
|
mnuHiliteMenuItem (pcurtmi, pcurmi, TRUE);
|
|
|
|
if (pcurtmi->draw_bottom_flag){
|
|
draw_bottom_scroll_button(ptmi);
|
|
}
|
|
|
|
if (pcurmi->submenu)
|
|
mnuOpenNewSubMenu (pcurtmi, pcurmi->submenu,
|
|
pcurtmi->rc.right, mnuGetMenuItemY (pcurtmi, pcurmi));
|
|
}
|
|
|
|
#if 0
|
|
static void mnuTrackMenu (PTRACKMENUINFO ptmi, int x, int y)
|
|
{
|
|
PTRACKMENUINFO phead, plast;
|
|
PTRACKMENUINFO pcurtmi, pclose, ptemp;
|
|
PMENUITEM pcurmi;
|
|
PMENUITEM philite;
|
|
int barItem;
|
|
HWND hwnd;
|
|
|
|
// get first tracking menu.
|
|
phead = ptmi;
|
|
while (phead->prev) {
|
|
phead = phead->prev;
|
|
}
|
|
|
|
// get last tracking menu.
|
|
plast = ptmi;
|
|
while (plast->next) {
|
|
plast = plast->next;
|
|
}
|
|
|
|
pcurtmi = mnuHitTestMenu (plast, x, y);
|
|
|
|
|
|
if (pcurtmi == NULL) {
|
|
if (plast->philite)
|
|
mnuHiliteMenuItem (plast, plast->philite, FALSE);
|
|
|
|
// check to see if move to the other sub menu of menu bar.
|
|
if (phead->pmb) {
|
|
barItem = MenuBarHitTest (phead->hwnd, x, y);
|
|
if (barItem >= 0 && barItem != phead->barPos) {
|
|
|
|
hwnd = phead->hwnd;
|
|
|
|
// close current popup menu.
|
|
SendMessage (HWND_DESKTOP, MSG_CLOSEMENU, 0, 0);
|
|
|
|
// open new popup menu.
|
|
TrackMenuBar (hwnd, barItem);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
pcurmi = get_selected_mi(pcurtmi, x, y);
|
|
if (PtInRect(&pcurtmi->bottom_scroll_rc, x, y)){
|
|
|
|
pcurtmi->pstart_show_mi = pcurtmi->pstart_show_mi->next;
|
|
show_scroll_popup_menu(pcurtmi);
|
|
|
|
}
|
|
|
|
if (pcurtmi != plast) {
|
|
pclose = pcurtmi->next->next;
|
|
|
|
if (pclose != NULL) {
|
|
while (pclose != plast) {
|
|
ptemp = plast->prev;
|
|
SendMessage (HWND_DESKTOP, MSG_ENDTRACKMENU, 0, (LPARAM)plast);
|
|
plast = ptemp;
|
|
}
|
|
SendMessage (HWND_DESKTOP, MSG_ENDTRACKMENU, 0, (LPARAM)plast);
|
|
plast = pcurtmi->next;
|
|
}
|
|
|
|
if (plast->philite) {
|
|
mnuHiliteMenuItem (plast, plast->philite, FALSE);
|
|
plast->philite = NULL;
|
|
}
|
|
}
|
|
|
|
philite = pcurtmi->philite;
|
|
if (pcurmi == philite) return;
|
|
|
|
// current hilite menu item is a bottom most item.
|
|
if (philite) {
|
|
if (pcurtmi != plast)
|
|
SendMessage (HWND_DESKTOP, MSG_ENDTRACKMENU, 0, (LPARAM)plast);
|
|
mnuHiliteMenuItem (pcurtmi, philite, FALSE);
|
|
}
|
|
|
|
pcurtmi->philite = pcurmi;
|
|
if (pcurmi == NULL) return;
|
|
if (pcurmi->type == TYPE_PPPMENU) return;
|
|
|
|
|
|
mnuHiliteMenuItem (pcurtmi, pcurmi, TRUE);
|
|
|
|
if (pcurmi->submenu)
|
|
mnuOpenNewSubMenu (pcurtmi, pcurmi->submenu,
|
|
pcurtmi->rc.right, mnuGetMenuItemY (pcurtmi, pcurmi));
|
|
}
|
|
#endif
|
|
|
|
static int mnuTrackMenuOnButtonDown (PTRACKMENUINFO ptmi,
|
|
int message, int x, int y)
|
|
{
|
|
PTRACKMENUINFO plast, phead;
|
|
PTRACKMENUINFO pcurtmi;
|
|
HMENU hmnu;
|
|
UINT flags;
|
|
int barItem;
|
|
|
|
flags = ptmi->flags;
|
|
hmnu = (HMENU)ptmi->pmi;
|
|
|
|
// get first tracking menu.
|
|
phead = ptmi;
|
|
while (phead->prev) {
|
|
phead = phead->prev;
|
|
}
|
|
|
|
// get last tracking menu.
|
|
plast = ptmi;
|
|
while (plast->next) {
|
|
plast = plast->next;
|
|
}
|
|
|
|
pcurtmi = mnuHitTestMenu (plast, x, y);
|
|
|
|
if (pcurtmi == NULL) { // close menu.
|
|
if (phead->pmb) {
|
|
barItem = MenuBarHitTest (phead->hwnd, x, y);
|
|
if (barItem == phead->barPos)
|
|
return 0;
|
|
}
|
|
|
|
SendMessage (HWND_DESKTOP, MSG_CLOSEMENU, 0, 1);
|
|
|
|
if (flags & TPM_DESTROY)
|
|
DestroyMenu (hmnu);
|
|
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int mnuTrackMenuOnButtonUp (PTRACKMENUINFO ptmi,
|
|
int message, int x, int y)
|
|
{
|
|
PTRACKMENUINFO plast;
|
|
PTRACKMENUINFO pcurtmi;
|
|
PMENUITEM pcurmi;
|
|
HWND hwnd;
|
|
UINT flags;
|
|
int id;
|
|
HMENU hmnu;
|
|
|
|
// get last tracking menu.
|
|
plast = ptmi;
|
|
while (plast->next) {
|
|
plast = plast->next;
|
|
}
|
|
|
|
pcurtmi = mnuHitTestMenu (plast, x, y);
|
|
|
|
if (pcurtmi == NULL || pcurtmi->philite == NULL) return 0;
|
|
|
|
/*add*/
|
|
pcurmi = get_selected_mi(pcurtmi, x, y);
|
|
if (pcurmi == NULL) return 0;
|
|
/*add end*/
|
|
|
|
if (pcurmi->mnutype == MFT_SEPARATOR) return 0;
|
|
if (pcurmi->mnustate & MFS_DISABLED) return 0;
|
|
|
|
if (pcurmi->type != TYPE_PPPMENU &&
|
|
pcurmi->submenu == NULL)
|
|
{
|
|
hwnd = ptmi->hwnd;
|
|
flags = ptmi->flags;
|
|
id = pcurmi->id;
|
|
hmnu = (HMENU)ptmi->pmi;
|
|
|
|
|
|
SendMessage (HWND_DESKTOP, MSG_CLOSEMENU, 0, 1);
|
|
|
|
if (flags & TPM_SYSCMD)
|
|
SendNotifyMessage (hwnd, MSG_SYSCOMMAND, id, 0);
|
|
else
|
|
SendNotifyMessage (hwnd, MSG_COMMAND, id, 0);
|
|
|
|
if (flags & TPM_DESTROY)
|
|
DestroyMenu (hmnu);
|
|
|
|
return id;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Since 5.0.0 */
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
static void sync_update_ppp (PTRACKMENUINFO ptmi)
|
|
{
|
|
PTRACKMENUINFO phead;
|
|
|
|
// get first tracking menu.
|
|
phead = ptmi;
|
|
while (phead->prev) {
|
|
phead = phead->prev;
|
|
}
|
|
|
|
do {
|
|
if (phead->dc != HDC_INVALID)
|
|
SyncUpdateDC (phead->dc);
|
|
phead = phead->next;
|
|
} while (phead);
|
|
}
|
|
#else /* defined _MGSCHEMA_COMPOSITING */
|
|
static inline void sync_update_ppp (PTRACKMENUINFO ptmi)
|
|
{
|
|
SyncUpdateDC (HDC_SCREEN_SYS);
|
|
}
|
|
#endif /* not defined _MGSCHEMA_COMPOSITING */
|
|
|
|
int PopupMenuTrackProc (PTRACKMENUINFO ptmi,
|
|
int message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
int ret_value;
|
|
switch (message) {
|
|
case MSG_INITMENU:
|
|
mnuGetPopupMenuExtent (ptmi);
|
|
return create_memdc_for_menu (ptmi);
|
|
break;
|
|
|
|
case MSG_SHOWMENU:
|
|
if (GetCurrentCursor() != GetSystemCursor(IDC_ARROW))
|
|
SetCursor(GetSystemCursor(IDC_ARROW));
|
|
ret_value = mnuShowPopupMenu (ptmi);
|
|
/* Since 5.0.0 */
|
|
sync_update_ppp (ptmi);
|
|
return ret_value;
|
|
break;
|
|
|
|
case MSG_HIDEMENU:
|
|
restore_dc_under_menu (ptmi);
|
|
mnuUnhiliteMenu (ptmi->pmi);
|
|
break;
|
|
|
|
case MSG_ENDTRACKMENU:
|
|
delete_memdc_for_menu (ptmi);
|
|
if (ptmi->hwnd != HWND_DESKTOP)
|
|
SendNotifyMessage (ptmi->hwnd, MSG_ENDTRACKMENU,
|
|
(WPARAM)ptmi->pmi, (LPARAM)ptmi->pmb);
|
|
FreeTrackMenuInfo (ptmi);
|
|
break;
|
|
|
|
case MSG_CLOSEMENU:
|
|
mnuCloseMenu (ptmi);
|
|
break;
|
|
|
|
case MSG_LBUTTONDOWN:
|
|
case MSG_RBUTTONDOWN:
|
|
if (mnuTrackMenuOnButtonDown (ptmi,
|
|
message, (int)wParam, (int)lParam) < 0)
|
|
return 1;
|
|
/* Since 5.0.0 */
|
|
sync_update_ppp (ptmi);
|
|
break;
|
|
|
|
case MSG_LBUTTONUP:
|
|
case MSG_RBUTTONUP:
|
|
mnuTrackMenuOnButtonUp (ptmi, message, (int)wParam, (int)lParam);
|
|
/* Since 5.0.0 */
|
|
sync_update_ppp (ptmi);
|
|
return 1;
|
|
|
|
case MSG_MOUSEMOVE:
|
|
mnu_scroll_menu (ptmi, (int)wParam, (int)lParam);
|
|
/* Since 5.0.0 */
|
|
sync_update_ppp (ptmi);
|
|
break;
|
|
|
|
case MSG_KEYDOWN:
|
|
case MSG_KEYUP:
|
|
mnuTrackMenuWithKey (ptmi, message, (int)wParam, (DWORD)lParam);
|
|
/* Since 5.0.0 */
|
|
sync_update_ppp (ptmi);
|
|
break;
|
|
|
|
default:
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int GUIAPI TrackPopupMenu (HMENU hmnu, UINT uFlags, int x, int y, HWND hwnd)
|
|
{
|
|
PTRACKMENUINFO ptmi;
|
|
|
|
// close current menu firstly.
|
|
SendMessage (HWND_DESKTOP, MSG_CLOSEMENU, 0, 1);
|
|
|
|
ptmi = TrackMenuInfoAlloc ();
|
|
|
|
ptmi->rc.left = x;
|
|
ptmi->rc.top = y;
|
|
ptmi->pmi = (PMENUITEM)hmnu;
|
|
ptmi->pmb = NULL;
|
|
ptmi->barPos = -1;
|
|
ptmi->philite = NULL;
|
|
ptmi->hwnd = hwnd;
|
|
ptmi->flags = uFlags;
|
|
ptmi->next = NULL;
|
|
ptmi->prev = NULL;
|
|
|
|
if (ptmi->pmi == NULL) return ERR_INVALID_HANDLE;
|
|
if (ptmi->pmi->category != TYPE_HMENU) return ERR_INVALID_HANDLE;
|
|
|
|
SendMessage (hwnd, MSG_ACTIVEMENU, 0, (LPARAM)hmnu);
|
|
if (SendMessage (HWND_DESKTOP, MSG_TRACKPOPUPMENU,
|
|
0, (LPARAM)(ptmi)) < 0) {
|
|
FreeTrackMenuInfo (ptmi);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int GUIAPI TrackMenuBar (HWND hwnd, int pos)
|
|
{
|
|
PMENUITEM pppMenu;
|
|
PMENUBAR menuBar;
|
|
RECT rcMenuItem;
|
|
PTRACKMENUINFO ptmi;
|
|
|
|
menuBar = (PMENUBAR)GetMenu (hwnd);
|
|
if (!menuBar) return ERR_INVALID_HANDLE;
|
|
|
|
if (!(pppMenu = mnuGetMenuItem ((HMENU)menuBar, pos, MF_BYPOSITION))) {
|
|
return ERR_INVALID_HANDLE;
|
|
}
|
|
if (pppMenu->mnustate & MFS_DISABLED)
|
|
return -1;
|
|
|
|
pppMenu = pppMenu->submenu;
|
|
|
|
if (!pppMenu) return ERR_INVALID_HANDLE;
|
|
|
|
// close current menu firstly.
|
|
SendMessage (HWND_DESKTOP, MSG_CLOSEMENU, 0, 1);
|
|
|
|
ptmi = TrackMenuInfoAlloc ();
|
|
|
|
GetMenuBarItemRect (hwnd, pos, &rcMenuItem);
|
|
WindowToScreen (hwnd, &rcMenuItem.left, &rcMenuItem.bottom);
|
|
|
|
ptmi->rc.left = rcMenuItem.left - (LFRDR_MENUITEMOFFX>>1);
|
|
ptmi->rc.top = rcMenuItem.bottom;
|
|
ptmi->pmi = pppMenu;
|
|
ptmi->pmb = menuBar;
|
|
ptmi->barPos = pos;
|
|
ptmi->philite = NULL;
|
|
ptmi->hwnd = hwnd;
|
|
ptmi->flags = TPM_DEFAULT;
|
|
ptmi->next = NULL;
|
|
ptmi->prev = NULL;
|
|
|
|
HiliteMenuBarItem (hwnd, pos, LFRDR_MENU_STATE_NORMAL);
|
|
HiliteMenuBarItem (hwnd, pos, LFRDR_MENU_STATE_HILITE);
|
|
|
|
SendMessage (hwnd, MSG_ACTIVEMENU, pos, (LPARAM)pppMenu);
|
|
|
|
if (SendMessage (HWND_DESKTOP, MSG_TRACKPOPUPMENU,
|
|
0, (LPARAM)(ptmi)) < 0) {
|
|
FreeTrackMenuInfo (ptmi);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif /* defined _MGHAVE_MENU */
|
|
|