mirror of
https://github.com/VincentWei/MiniGUI.git
synced 2026-09-28 16:17:09 +08:00
886 lines
23 KiB
C
886 lines
23 KiB
C
/*
|
|
* 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~2018, 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/>.
|
|
*/
|
|
/*
|
|
** button.c: the Menu Button Control module.
|
|
**
|
|
** Create date: 2000/11/16
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "common.h"
|
|
|
|
#ifdef _MGCTRL_MENUBUTTON
|
|
#include "minigui.h"
|
|
#include "gdi.h"
|
|
#include "window.h"
|
|
#include "ctrl/ctrlhelper.h"
|
|
#include "ctrl/menubutton.h"
|
|
#include "cliprect.h"
|
|
#include "internals.h"
|
|
#include "ctrlclass.h"
|
|
#include "ctrlmisc.h"
|
|
|
|
#define _USE_FIXSTR 1
|
|
|
|
#include "menubutton_impl.h"
|
|
|
|
#define _WIDTH_BORDER 4
|
|
#define _WIDTH_MENUBAR 12
|
|
#define _HEIGHT_MENUBAR 8
|
|
|
|
#define _INTER_BARTEXT 4
|
|
|
|
static LRESULT MenuButtonCtrlProc (HWND hWnd, UINT message, WPARAM wParam,
|
|
LPARAM lParam);
|
|
|
|
BOOL RegisterMenuButtonControl (void)
|
|
{
|
|
WNDCLASS WndClass;
|
|
|
|
WndClass.spClassName = CTRL_MENUBUTTON;
|
|
WndClass.dwStyle = WS_NONE;
|
|
WndClass.dwExStyle = WS_EX_NONE;
|
|
WndClass.hCursor = GetSystemCursor (IDC_ARROW);
|
|
WndClass.iBkColor =
|
|
GetWindowElementPixel (HWND_NULL, WE_MAINC_THREED_BODY);
|
|
WndClass.WinProc = MenuButtonCtrlProc;
|
|
|
|
return AddNewControlClass (&WndClass) == ERR_OK;
|
|
}
|
|
|
|
static BOOL mbInitMenuButtonData (MENUBTNDATA* mb_data, int len)
|
|
{
|
|
int i;
|
|
PMBITEM pmbi;
|
|
|
|
mb_data->str_cmp = strncmp;
|
|
|
|
mb_data->cur_sel = MB_INV_ITEM;
|
|
|
|
// init item buffer.
|
|
if (!(mb_data->buff_head = malloc (len * sizeof (MBITEM))))
|
|
return FALSE;
|
|
|
|
mb_data->buff_len = len;
|
|
mb_data->buff_tail = mb_data->buff_head + len;
|
|
mb_data->free_list = mb_data->buff_head;
|
|
|
|
pmbi = mb_data->free_list;
|
|
for (i = 0; i < len - 1; i++) {
|
|
pmbi->next = pmbi + 1;
|
|
pmbi ++;
|
|
}
|
|
pmbi->next = NULL;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void mbMenuButtonCleanUp (MENUBTNDATA* mb_data)
|
|
{
|
|
PMBITEM pmbi;
|
|
PMBITEM next;
|
|
|
|
pmbi = mb_data->first_item;
|
|
while (pmbi) {
|
|
#if _USE_FIXSTR
|
|
FreeFixStr (pmbi->text);
|
|
#else
|
|
free (pmbi->text);
|
|
#endif
|
|
next = pmbi->next;
|
|
if (pmbi < mb_data->buff_head || pmbi > mb_data->buff_tail)
|
|
free (pmbi);
|
|
|
|
pmbi = next;
|
|
}
|
|
|
|
free (mb_data->buff_head);
|
|
}
|
|
|
|
static void mbResetMenuButtonContent (PMENUBTNDATA mb_data)
|
|
{
|
|
int i;
|
|
PMBITEM pmbi, next;
|
|
|
|
mb_data->item_count = 0;
|
|
mb_data->cur_sel = MB_INV_ITEM;
|
|
|
|
pmbi = mb_data->first_item;
|
|
while (pmbi) {
|
|
#if _USE_FIXSTR
|
|
FreeFixStr (pmbi->text);
|
|
#else
|
|
free (pmbi->text);
|
|
#endif
|
|
next = pmbi->next;
|
|
if (pmbi < mb_data->buff_head || pmbi > mb_data->buff_tail)
|
|
free (pmbi);
|
|
|
|
pmbi = next;
|
|
}
|
|
|
|
mb_data->first_item = NULL;
|
|
mb_data->free_list = mb_data->buff_head;
|
|
|
|
pmbi = mb_data->free_list;
|
|
for (i = 0; i < mb_data->buff_len - 1; i++) {
|
|
pmbi->next = pmbi + 1;
|
|
pmbi ++;
|
|
}
|
|
pmbi->next = NULL;
|
|
}
|
|
|
|
static PMBITEM mbAllocItem (PMENUBTNDATA mb_data)
|
|
{
|
|
PMBITEM pmbi;
|
|
|
|
if (mb_data->free_list) {
|
|
pmbi = mb_data->free_list;
|
|
mb_data->free_list = pmbi->next;
|
|
}
|
|
else
|
|
pmbi = (PMBITEM) malloc (sizeof (MBITEM));
|
|
|
|
return pmbi;
|
|
}
|
|
|
|
static void mbFreeItem (PMENUBTNDATA mb_data, PMBITEM pmbi)
|
|
{
|
|
if (pmbi < mb_data->buff_head || pmbi > mb_data->buff_tail)
|
|
free (pmbi);
|
|
else {
|
|
pmbi->next = mb_data->free_list;
|
|
mb_data->free_list = pmbi;
|
|
}
|
|
}
|
|
|
|
static int mbAddNewItem (DWORD dwStyle,
|
|
PMENUBTNDATA mb_data, PMBITEM newItem, int pos)
|
|
{
|
|
PMBITEM pmbi;
|
|
PMBITEM insPosItem = NULL;
|
|
int insPos = 0;
|
|
|
|
newItem->next = NULL;
|
|
if (!mb_data->first_item)
|
|
insPosItem = NULL;
|
|
else if (dwStyle & MBS_SORT) {
|
|
pmbi = mb_data->first_item;
|
|
|
|
if (mb_data->str_cmp (newItem->text, pmbi->text, (size_t)-1) < 0) {
|
|
insPosItem = NULL;
|
|
insPos = 0;
|
|
}
|
|
else {
|
|
while (pmbi->next) {
|
|
if (mb_data->str_cmp (newItem->text, pmbi->next->text,
|
|
(size_t)-1) <= 0)
|
|
break;
|
|
|
|
pmbi = pmbi->next;
|
|
insPos ++;
|
|
}
|
|
insPosItem = pmbi;
|
|
}
|
|
}
|
|
else {
|
|
pmbi = mb_data->first_item;
|
|
|
|
if (pos < 0) {
|
|
while (pmbi->next) {
|
|
pmbi = pmbi->next;
|
|
insPos ++;
|
|
}
|
|
insPosItem = pmbi;
|
|
}
|
|
else if (pos > 0) {
|
|
int index = 0;
|
|
|
|
while (pmbi->next) {
|
|
if (pos == index)
|
|
break;
|
|
pmbi = pmbi->next;
|
|
index ++;
|
|
insPos ++;
|
|
}
|
|
insPosItem = pmbi;
|
|
}
|
|
}
|
|
|
|
if (insPosItem) {
|
|
pmbi = insPosItem->next;
|
|
insPosItem->next = newItem;
|
|
newItem->next = pmbi;
|
|
|
|
insPos ++;
|
|
}
|
|
else {
|
|
pmbi = mb_data->first_item;
|
|
mb_data->first_item = newItem;
|
|
newItem->next = pmbi;
|
|
}
|
|
|
|
mb_data->item_count ++;
|
|
|
|
return insPos;
|
|
}
|
|
|
|
#if 0
|
|
static PMBITEM mbRemoveItem (PMENUBTNDATA mb_data, int* pos)
|
|
{
|
|
int index = 0;
|
|
PMBITEM pmbi, prev;
|
|
|
|
if (!mb_data->first_item)
|
|
return NULL;
|
|
|
|
if (*pos < 0) {
|
|
prev = mb_data->first_item;
|
|
pmbi = mb_data->first_item;
|
|
while (pmbi->next) {
|
|
prev = pmbi;
|
|
pmbi = pmbi->next;
|
|
index ++;
|
|
}
|
|
|
|
if (pmbi == mb_data->first_item) {
|
|
mb_data->first_item = mb_data->first_item->next;
|
|
*pos = 0;
|
|
return pmbi;
|
|
}
|
|
else {
|
|
prev->next = pmbi->next;
|
|
*pos = index;
|
|
return pmbi;
|
|
}
|
|
}
|
|
else if (*pos == 0) {
|
|
pmbi = mb_data->first_item;
|
|
mb_data->first_item = pmbi->next;
|
|
return pmbi;
|
|
}
|
|
else {
|
|
index = 0;
|
|
prev = mb_data->first_item;
|
|
pmbi = mb_data->first_item;
|
|
while (pmbi->next) {
|
|
if (*pos == index)
|
|
break;
|
|
|
|
prev = pmbi;
|
|
pmbi = pmbi->next;
|
|
index ++;
|
|
}
|
|
|
|
if (pmbi == mb_data->first_item) {
|
|
mb_data->first_item = mb_data->first_item->next;
|
|
*pos = 0;
|
|
return pmbi;
|
|
}
|
|
else {
|
|
prev->next = pmbi->next;
|
|
*pos = index;
|
|
return pmbi;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
#else
|
|
static PMBITEM mbRemoveItem (PMENUBTNDATA mb_data, int* pos)
|
|
{
|
|
int index = 0;
|
|
PMBITEM pmbi, prev;
|
|
|
|
if (!mb_data->first_item)
|
|
return NULL;
|
|
|
|
if (*pos < 0) {
|
|
return NULL;
|
|
}
|
|
else if (*pos == 0) {
|
|
pmbi = mb_data->first_item;
|
|
mb_data->first_item = pmbi->next;
|
|
return pmbi;
|
|
}
|
|
else { /* index > 0 */
|
|
index = 0;
|
|
prev = mb_data->first_item;
|
|
pmbi = mb_data->first_item;
|
|
while (pmbi->next) {
|
|
if (*pos == index) {
|
|
break;
|
|
}
|
|
|
|
prev = pmbi;
|
|
pmbi = pmbi->next;
|
|
index ++;
|
|
}
|
|
|
|
if (*pos <= index) {
|
|
prev->next = pmbi->next;
|
|
return pmbi;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
#endif
|
|
|
|
static PMBITEM mbGetItem (PMENUBTNDATA mb_data, int pos)
|
|
{
|
|
int index = 0;
|
|
PMBITEM pmbi;
|
|
|
|
pmbi = mb_data->first_item;
|
|
|
|
while (pmbi) {
|
|
if (index == pos)
|
|
break;
|
|
|
|
index ++;
|
|
pmbi = pmbi->next;
|
|
}
|
|
|
|
return pmbi;
|
|
}
|
|
|
|
static void mbGetRects (HWND hWnd, DWORD dwStyle,
|
|
RECT* prcClient,
|
|
RECT* prcText,
|
|
RECT* prcMenuBar)
|
|
{
|
|
GetClientRect (hWnd, prcClient);
|
|
prcClient->right --;
|
|
prcClient->bottom --;
|
|
|
|
if (dwStyle & MBS_LEFTARROW) {
|
|
SetRect (prcMenuBar, prcClient->left + _WIDTH_BORDER,
|
|
(prcClient->top + prcClient->bottom - _HEIGHT_MENUBAR) >> 1,
|
|
prcClient->left + _WIDTH_BORDER + _WIDTH_MENUBAR,
|
|
(prcClient->top + prcClient->bottom + _HEIGHT_MENUBAR) >> 1);
|
|
|
|
SetRect (prcText, prcMenuBar->right + _INTER_BARTEXT,
|
|
prcClient->top + _WIDTH_BORDER,
|
|
prcClient->right - _INTER_BARTEXT,
|
|
prcClient->bottom - _WIDTH_BORDER);
|
|
|
|
}
|
|
else {
|
|
SetRect (prcText, prcClient->left + _WIDTH_BORDER,
|
|
prcClient->top + _WIDTH_BORDER,
|
|
prcClient->right - _WIDTH_MENUBAR - (_INTER_BARTEXT << 1),
|
|
prcClient->bottom - _WIDTH_BORDER);
|
|
|
|
SetRect (prcMenuBar, prcText->right + _INTER_BARTEXT,
|
|
(prcClient->top + prcClient->bottom - _HEIGHT_MENUBAR) >> 1,
|
|
prcClient->right - _INTER_BARTEXT,
|
|
(prcClient->top + prcClient->bottom + _HEIGHT_MENUBAR) >> 1);
|
|
}
|
|
}
|
|
|
|
#define _OFF_CMDID 100
|
|
|
|
static HMENU mbPopupMenu (HWND hWnd)
|
|
{
|
|
HMENU hmnu;
|
|
MENUITEMINFO mii;
|
|
PMENUBTNDATA mb_data;
|
|
int index = 0;
|
|
PMBITEM pmbi;
|
|
RECT rc;
|
|
|
|
mb_data = (PMENUBTNDATA)GetWindowAdditionalData2 (hWnd);
|
|
|
|
memset (&mii, 0, sizeof(MENUITEMINFO));
|
|
mii.type = MFT_STRING;
|
|
mii.id = 0;
|
|
mii.typedata = (DWORD)GetWindowCaption (hWnd);
|
|
if (!(hmnu = CreatePopupMenu (&mii)))
|
|
return 0;
|
|
|
|
pmbi = mb_data->first_item;
|
|
while (pmbi) {
|
|
|
|
memset (&mii, 0, sizeof(MENUITEMINFO));
|
|
mii.state = 0;
|
|
mii.id = index + _OFF_CMDID;
|
|
if (pmbi->text && pmbi->bmp) {
|
|
mii.type = MFT_BMPSTRING;
|
|
mii.uncheckedbmp = pmbi->bmp;
|
|
mii.checkedbmp= pmbi->bmp;
|
|
mii.typedata = (DWORD)pmbi->text;
|
|
}
|
|
else if (pmbi->text) {
|
|
mii.type = MFT_STRING;
|
|
mii.typedata = (DWORD)pmbi->text;
|
|
}
|
|
else if (pmbi->bmp) {
|
|
mii.type = MFT_BITMAP;
|
|
mii.typedata = (DWORD)pmbi->bmp;
|
|
}
|
|
else
|
|
goto error;
|
|
|
|
if (InsertMenuItem (hmnu, index, TRUE, &mii))
|
|
goto error;
|
|
|
|
index ++;
|
|
pmbi = pmbi->next;
|
|
}
|
|
|
|
if (index == 0) goto error;
|
|
|
|
GetClientRect (hWnd, &rc);
|
|
ClientToScreen (hWnd, &rc.left, &rc.top);
|
|
TrackPopupMenu (GetPopupSubMenu (hmnu), TPM_LEFTALIGN,
|
|
rc.left, rc.top, hWnd);
|
|
|
|
return hmnu;
|
|
|
|
error:
|
|
DestroyMenu (hmnu);
|
|
return 0;
|
|
}
|
|
|
|
static LRESULT MenuButtonCtrlProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
PMENUBTNDATA mb_data;
|
|
WINDOWINFO *wnd_info;
|
|
|
|
wnd_info = (WINDOWINFO*)GetWindowInfo (hWnd);
|
|
if (wnd_info == NULL)
|
|
return -1;
|
|
|
|
switch (message) {
|
|
case MSG_CREATE:
|
|
if ((mb_data = (MENUBTNDATA *) calloc (1, sizeof(MENUBTNDATA))) == NULL)
|
|
return -1;
|
|
|
|
SetWindowAdditionalData2 (hWnd, (DWORD) mb_data);
|
|
if (!mbInitMenuButtonData (mb_data, DEF_MB_BUFFER_LEN)) {
|
|
free (mb_data);
|
|
return -1;
|
|
}
|
|
break;
|
|
|
|
case MSG_DESTROY:
|
|
mb_data = (PMENUBTNDATA)GetWindowAdditionalData2 (hWnd);
|
|
mbMenuButtonCleanUp (mb_data);
|
|
free (mb_data);
|
|
break;
|
|
|
|
case MBM_SETSTRCMPFUNC:
|
|
mb_data = (PMENUBTNDATA)GetWindowAdditionalData2 (hWnd);
|
|
if (mb_data->item_count == 0 && lParam) {
|
|
mb_data->str_cmp = (STRCMP)lParam;
|
|
return MB_OKAY;
|
|
}
|
|
return MB_ERR;
|
|
|
|
case MBM_ADDITEM:
|
|
{
|
|
PMBITEM newItem;
|
|
int pos;
|
|
PMENUBUTTONITEM want = (PMENUBUTTONITEM)lParam;
|
|
DWORD style = GetWindowStyle (hWnd);
|
|
#if _USE_FIXSTR
|
|
int len;
|
|
#endif
|
|
|
|
mb_data = (PMENUBTNDATA)GetWindowAdditionalData2 (hWnd);
|
|
newItem = mbAllocItem (mb_data);
|
|
if (!newItem) {
|
|
NotifyParent (hWnd, GetDlgCtrlID (hWnd), MBN_ERRSPACE);
|
|
return MB_ERR_SPACE;
|
|
}
|
|
|
|
#if _USE_FIXSTR
|
|
if (want->text) {
|
|
len = strlen (want->text);
|
|
newItem->text = FixStrAlloc (len);
|
|
if (!newItem->text) {
|
|
mbFreeItem (mb_data, newItem);
|
|
return MB_ERR_SPACE;
|
|
}
|
|
if (len > 0)
|
|
strcpy (newItem->text, want->text);
|
|
}
|
|
else {
|
|
newItem->text = "";
|
|
}
|
|
#else
|
|
if (want->text) {
|
|
newItem->text = strdup (want->text);
|
|
if (!newItem->text) {
|
|
mbFreeItem (mb_data, newItem);
|
|
return MB_ERR_SPACE;
|
|
}
|
|
}
|
|
else {
|
|
newItem->text = "";
|
|
}
|
|
#endif
|
|
|
|
newItem->bmp = want->bmp;
|
|
newItem->data = want->data;
|
|
pos = mbAddNewItem (style, mb_data, newItem, (int)wParam);
|
|
return pos;
|
|
}
|
|
|
|
case MBM_DELITEM:
|
|
{
|
|
PMBITEM removed;
|
|
int delete = (int)wParam;
|
|
|
|
mb_data = (PMENUBTNDATA) GetWindowAdditionalData2 (hWnd);
|
|
removed = mbRemoveItem (mb_data, &delete);
|
|
if (removed) {
|
|
#if _USE_FIXSTR
|
|
FreeFixStr (removed->text);
|
|
#else
|
|
free (removed->text);
|
|
#endif
|
|
mbFreeItem (mb_data, removed);
|
|
|
|
mb_data->item_count --;
|
|
|
|
if (mb_data->cur_sel == delete) {
|
|
mb_data->cur_sel = MB_INV_ITEM;
|
|
UpdateWindow(hWnd, TRUE);
|
|
}
|
|
|
|
if (mb_data->cur_sel > 0 && mb_data->cur_sel > delete)
|
|
mb_data->cur_sel -= 1;
|
|
|
|
return MB_OKAY;
|
|
}
|
|
return MB_INV_ITEM;
|
|
}
|
|
|
|
case MBM_RESETCTRL:
|
|
mb_data = (PMENUBTNDATA)GetWindowAdditionalData2 (hWnd);
|
|
mbResetMenuButtonContent (mb_data);
|
|
InvalidateRect (hWnd, NULL, TRUE);
|
|
return MB_OKAY;
|
|
|
|
case MBM_GETCURITEM:
|
|
mb_data = (PMENUBTNDATA)GetWindowAdditionalData2 (hWnd);
|
|
return mb_data->cur_sel;
|
|
|
|
case MBM_SETCURITEM:
|
|
{
|
|
int old, new;
|
|
|
|
new = (int)wParam;
|
|
mb_data = (PMENUBTNDATA)GetWindowAdditionalData2 (hWnd);
|
|
old = mb_data->cur_sel;
|
|
if (new >= 0 && new < mb_data->item_count) {
|
|
mb_data->cur_sel = new;
|
|
InvalidateRect (hWnd, NULL, TRUE);
|
|
}
|
|
|
|
return old;
|
|
}
|
|
|
|
case MBM_SETITEMDATA:
|
|
{
|
|
PMBITEM pmbi;
|
|
PMENUBUTTONITEM want = (PMENUBUTTONITEM)lParam;
|
|
|
|
mb_data = (PMENUBTNDATA)GetWindowAdditionalData2 (hWnd);
|
|
pmbi = mbGetItem (mb_data, (int)wParam);
|
|
if (pmbi == NULL)
|
|
return MB_INV_ITEM;
|
|
|
|
if (want->which & MB_WHICH_TEXT) {
|
|
#if _USE_FIXSTR
|
|
int len;
|
|
|
|
FreeFixStr (pmbi->text);
|
|
len = strlen (want->text);
|
|
pmbi->text = FixStrAlloc (len);
|
|
if (!pmbi->text) {
|
|
pmbi->text = "";
|
|
return MB_ERR_SPACE;
|
|
}
|
|
if (len > 0)
|
|
strcpy (pmbi->text, want->text);
|
|
#else
|
|
free (pmbi->text);
|
|
pmbi->text = strdup (want->text);
|
|
if (!pmbi->text) {
|
|
pmbi->text = "";
|
|
return MB_ERR_SPACE;
|
|
}
|
|
#endif
|
|
}
|
|
if (want->which & MB_WHICH_BMP) {
|
|
pmbi->bmp = want->bmp;
|
|
}
|
|
if (want->which & MB_WHICH_ATTDATA) {
|
|
pmbi->data = want->data;
|
|
}
|
|
|
|
if ((int)wParam == mb_data->cur_sel)
|
|
InvalidateRect (hWnd, NULL, TRUE);
|
|
return MB_OKAY;
|
|
}
|
|
|
|
case MBM_GETITEMDATA:
|
|
{
|
|
PMBITEM pmbi;
|
|
PMENUBUTTONITEM want = (PMENUBUTTONITEM)lParam;
|
|
|
|
mb_data = (PMENUBTNDATA)GetWindowAdditionalData2 (hWnd);
|
|
pmbi = mbGetItem (mb_data, (int)wParam);
|
|
if (pmbi == NULL)
|
|
return MB_INV_ITEM;
|
|
|
|
if (want->which & MB_WHICH_TEXT) {
|
|
want->text = pmbi->text;
|
|
}
|
|
if (want->which & MB_WHICH_BMP) {
|
|
want->bmp = pmbi->bmp;
|
|
}
|
|
if (want->which & MB_WHICH_ATTDATA) {
|
|
want->data = pmbi->data;
|
|
}
|
|
return MB_OKAY;
|
|
}
|
|
|
|
case MSG_CHAR:
|
|
if (wParam == ' ') {
|
|
mb_data = (PMENUBTNDATA)GetWindowAdditionalData2 (hWnd);
|
|
mb_data->hmnu = mbPopupMenu (hWnd);
|
|
if (mb_data->hmnu)
|
|
NotifyParent (hWnd, GetDlgCtrlID (hWnd), MBN_STARTMENU);
|
|
}
|
|
break;
|
|
|
|
case MSG_LBUTTONDOWN:
|
|
SetCapture (hWnd);
|
|
break;
|
|
|
|
case MSG_LBUTTONUP:
|
|
{
|
|
int x, y;
|
|
RECT rcClient, rcText, rcMenuBar;
|
|
|
|
if (GetCapture() != hWnd)
|
|
break;
|
|
ReleaseCapture ();
|
|
|
|
x = LOSWORD(lParam);
|
|
y = HISWORD(lParam);
|
|
ScreenToClient (hWnd, &x, &y);
|
|
mbGetRects (hWnd, GetWindowStyle (hWnd),
|
|
&rcClient, &rcText, &rcMenuBar);
|
|
if (PtInRect (&rcMenuBar, x, y)) {
|
|
mb_data = (PMENUBTNDATA)GetWindowAdditionalData2 (hWnd);
|
|
mb_data->hmnu = mbPopupMenu (hWnd);
|
|
if (mb_data->hmnu)
|
|
NotifyParent (hWnd, GetDlgCtrlID (hWnd), MBN_STARTMENU);
|
|
}
|
|
else if (PtInRect (&rcClient, x, y)) {
|
|
NotifyParent (hWnd, GetDlgCtrlID (hWnd), MBN_CLICKED);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case MSG_ENDTRACKMENU:
|
|
{
|
|
mb_data = (PMENUBTNDATA)GetWindowAdditionalData2 (hWnd);
|
|
if (mb_data->hmnu) {
|
|
DestroyMenu (mb_data->hmnu);
|
|
NotifyParent (hWnd, GetDlgCtrlID (hWnd), MBN_ENDMENU);
|
|
mb_data->hmnu = 0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case MSG_COMMAND:
|
|
{
|
|
int index = wParam - _OFF_CMDID;
|
|
|
|
mb_data = (PMENUBTNDATA)GetWindowAdditionalData2 (hWnd);
|
|
if (index < mb_data->item_count && index >= 0) {
|
|
if (index != mb_data->cur_sel) {
|
|
mb_data->cur_sel = index;
|
|
InvalidateRect (hWnd, NULL, TRUE);
|
|
NotifyParent (hWnd, GetDlgCtrlID (hWnd), MBN_CHANGED);
|
|
}
|
|
NotifyParent (hWnd, GetDlgCtrlID (hWnd), MBN_SELECTED);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case MSG_PAINT:
|
|
{
|
|
HDC hdc;
|
|
RECT rcClient, rcText, rcMenuBar;
|
|
UINT uFormat;
|
|
DWORD dwStyle = GetWindowStyle (hWnd), dwExStyle = GetWindowExStyle(hWnd);
|
|
const char* text;
|
|
BITMAP* bmp;
|
|
DWORD fg_color;
|
|
gal_pixel fc;
|
|
|
|
mb_data = (PMENUBTNDATA)GetWindowAdditionalData2 (hWnd);
|
|
mbGetRects (hWnd, dwStyle,
|
|
&rcClient, &rcText, &rcMenuBar);
|
|
|
|
if (mb_data->cur_sel < 0) {
|
|
text = GetWindowCaption (hWnd);
|
|
bmp = NULL;
|
|
}
|
|
else {
|
|
PMBITEM pmbi = mbGetItem (mb_data, mb_data->cur_sel);
|
|
text = pmbi->text;
|
|
bmp = pmbi->bmp;
|
|
}
|
|
|
|
hdc = BeginPaint (hWnd);
|
|
if (!(dwStyle & MBS_NOBUTTON)){
|
|
fg_color = GetWindowElementAttr (hWnd, WE_MAINC_THREED_BODY);
|
|
|
|
if (dwExStyle & WS_EX_TRANSPARENT)
|
|
wnd_info->we_rdr->draw_3dbox (hdc, &rcClient, fg_color,0);
|
|
else
|
|
wnd_info->we_rdr->draw_3dbox (hdc, &rcClient, fg_color,
|
|
LFRDR_3DBOX_FILLED);
|
|
}
|
|
|
|
if (bmp) {
|
|
static int top = 0, height = 0;
|
|
if (rcText.bottom - rcText.top < bmp->bmHeight) {
|
|
top = rcText.top;
|
|
height = rcText.bottom - rcText.top;
|
|
}
|
|
else {
|
|
top = (rcText.top + rcText.bottom - bmp->bmHeight) >>1;
|
|
height = bmp->bmHeight;
|
|
}
|
|
|
|
if (dwStyle & MBS_LEFTARROW) {
|
|
FillBoxWithBitmapPart (hdc,
|
|
rcMenuBar.right + _INTER_BARTEXT,
|
|
top,
|
|
bmp->bmWidth,
|
|
height,
|
|
0, 0,
|
|
bmp,
|
|
0,
|
|
0);
|
|
/*
|
|
FillBoxWithBitmap (hdc,
|
|
rcMenuBar.right + _INTER_BARTEXT,
|
|
//(rcText.top + rcText.bottom - bmp->bmHeight) >> 1,
|
|
top,
|
|
0, 0, bmp);
|
|
*/
|
|
rcText.left += bmp->bmWidth + _INTER_BARTEXT;
|
|
}
|
|
else {
|
|
FillBoxWithBitmapPart (hdc,
|
|
rcMenuBar.left - _INTER_BARTEXT - bmp->bmWidth,
|
|
top,
|
|
bmp->bmWidth,
|
|
height,
|
|
0, 0,
|
|
bmp,
|
|
0,
|
|
0);
|
|
/*
|
|
FillBoxWithBitmap (hdc,
|
|
rcMenuBar.left - _INTER_BARTEXT - bmp->bmWidth,
|
|
(rcText.top + rcText.bottom - bmp->bmHeight) >> 1,
|
|
0, 0, bmp);
|
|
*/
|
|
rcText.right -= bmp->bmWidth + _INTER_BARTEXT;
|
|
}
|
|
}
|
|
|
|
rcText.left += (_INTER_BARTEXT >> 1);
|
|
|
|
if (text) {
|
|
uFormat = DT_SINGLELINE | DT_VCENTER;
|
|
switch (dwStyle & MBS_ALIGNMASK) {
|
|
case MBS_ALIGNRIGHT:
|
|
uFormat |= DT_RIGHT;
|
|
break;
|
|
case MBS_ALIGNCENTER:
|
|
uFormat |= DT_CENTER;
|
|
break;
|
|
default:
|
|
uFormat |= DT_LEFT;
|
|
break;
|
|
}
|
|
SetBkMode (hdc, BM_TRANSPARENT);
|
|
|
|
if (dwStyle & WS_DISABLED) {
|
|
wnd_info->we_rdr->disabled_text_out (hWnd, hdc, text, &rcText,
|
|
uFormat);
|
|
}
|
|
else {
|
|
fg_color = GetWindowElementAttr (hWnd, WE_FGC_WINDOW);
|
|
fc = RGBA2Pixel (hdc, GetRValue(fg_color), GetGValue(fg_color),
|
|
GetBValue(fg_color), GetAValue(fg_color));
|
|
SetTextColor (hdc, fc);
|
|
DrawText (hdc, text, -1, &rcText, uFormat);
|
|
}
|
|
}
|
|
|
|
fg_color = GetWindowElementAttr (hWnd, WE_FGC_THREED_BODY);
|
|
wnd_info->we_rdr->draw_arrow (hWnd, hdc, &rcMenuBar,
|
|
fg_color, LFRDR_ARROW_DOWN);
|
|
|
|
EndPaint (hWnd, hdc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return DefaultControlProc (hWnd, message, wParam, lParam);
|
|
}
|
|
|
|
#endif /* _MGCTRL_MENUBUTTON */
|