1 Star 0 Fork 27

MicroOS/MiniGUI

forked from Gitee 极速下载/MiniGUI 
加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
button.c 30.93 KB
一键复制 编辑 原始数据 按行查看 历史
Vincent Wei 提交于 2019-07-15 14:17 +08:00 . prepend excpetion list statement
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059
///////////////////////////////////////////////////////////////////////////////
//
// 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~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/en/about/licensing-policy/>.
*/
/*
** button.c: the Button Control module.
**
** Create date: 1999/8/23
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "common.h"
#ifdef _MGCTRL_BUTTON
#include "minigui.h"
#include "gdi.h"
#include "window.h"
#include "ctrl/ctrlhelper.h"
#include "ctrl/button.h"
#include "cliprect.h"
#include "internals.h"
#include "ctrlclass.h"
#include "fixedmath.h"
#include "button_impl.h"
#include "ctrlmisc.h"
# define BTN_WIDTH_BMP 20
# define BTN_HEIGHT_BMP 20
# define BTN_INTER_BMPTEXT 2
#define BUTTON_STATUS(pctrl) (((PBUTTONDATA)((pctrl)->dwAddData2))->status)
#define BUTTON_DATA(pctrl) (((PBUTTONDATA)((pctrl)->dwAddData2))->data)
#define BUTTON_TYPE(pctrl) ((pctrl)->dwStyle & BS_TYPEMASK)
#define BUTTON_IS_AUTO(pctrl) \
(BUTTON_TYPE(pctrl) == BS_AUTO3STATE || \
BUTTON_TYPE(pctrl) == BS_AUTOCHECKBOX || \
BUTTON_TYPE(pctrl) == BS_AUTORADIOBUTTON)
#define BUTTON_IS_PUSHBTN(pctrl) \
(BUTTON_TYPE(pctrl) == BS_PUSHBUTTON || \
BUTTON_TYPE(pctrl) == BS_DEFPUSHBUTTON)
#define BUTTON_IS_RADIOBTN(pctrl) \
(BUTTON_TYPE(pctrl) == BS_AUTORADIOBUTTON || \
BUTTON_TYPE(pctrl) == BS_RADIOBUTTON)
#define BUTTON_IS_CHECKBTN(pctrl) \
(BUTTON_TYPE(pctrl) == BS_AUTOCHECKBOX || \
BUTTON_TYPE(pctrl) == BS_CHECKBOX)
#define BUTTON_IS_3STATEBTN(pctrl) \
(BUTTON_TYPE(pctrl) == BS_AUTOCHECKBOX || \
BUTTON_TYPE(pctrl) == BS_CHECKBOX)
#define BUTTON_SET_POSE(pctrl, status) \
do { \
BUTTON_STATUS(pctrl) &= ~BST_POSE_MASK; \
BUTTON_STATUS(pctrl) |= status; \
}while(0)
#define BUTTON_SET_CHECK(pctrl, check) \
do { \
BUTTON_STATUS(pctrl) &= ~BST_CHECK_MASK;\
BUTTON_STATUS(pctrl) |= check;\
}while(0)
#define BUTTON_GET_POSE(pctrl) \
(BUTTON_STATUS(pctrl) & BST_POSE_MASK)
#define BUTTON_GET_CHECK(pctrl) \
(BUTTON_STATUS(pctrl) & BST_CHECK_MASK)
#define BUTTON_OFFSET 1
static LRESULT ButtonCtrlProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static void btnGetRects (PCONTROL pctrl, RECT* prcClient,
RECT* prcContent,
RECT* prcBitmap);
/*when check a radio button, uncheck others in the same group*/
static void btnUncheckOthers (PCONTROL pctrl)
{
PCONTROL pGroupLeader = pctrl;
PCONTROL pOthers;
DWORD type = BUTTON_TYPE(pctrl);
while (pGroupLeader) {
if (pGroupLeader->dwStyle & WS_GROUP)
break;
pGroupLeader = pGroupLeader->prev;
}
if(!pGroupLeader)
return ;
pOthers = pGroupLeader;
do{
if (BUTTON_TYPE(pOthers)!= type)
break;
if ((pOthers != pctrl) &&
(BUTTON_GET_CHECK(pOthers)!= BST_UNCHECKED)) {
BUTTON_SET_CHECK(pOthers, BST_UNCHECKED);
InvalidateRect ((HWND)pOthers, NULL, TRUE);
}
pOthers = pOthers->next;
} while (pOthers && !(pOthers->dwStyle & WS_GROUP));
}
/*
* change_checked:
* This function change check status.
* return -1: can't change(the button in disable status)
* 0 : new check is old check, didn't change
* 1 : changed
* Author: XuguangWang
* Date: 2007-12-7
*/
static int change_checked (PCONTROL pctrl, int check_status)
{
int old_status = BUTTON_STATUS(pctrl) & BST_CHECK_MASK;
/*if push button return*/
MG_CHECK_RET (BUTTON_TYPE(pctrl) != BS_PUSHBUTTON, -1);
MG_CHECK_RET (old_status != check_status, 0);
switch (pctrl->dwStyle & BS_TYPEMASK)
{
case BS_RADIOBUTTON:
case BS_AUTORADIOBUTTON:
MG_CHECK_RET (check_status != BST_INDETERMINATE, -1);
BUTTON_SET_CHECK (pctrl, check_status);
btnUncheckOthers (pctrl);
break;
case BS_CHECKBOX:
case BS_AUTOCHECKBOX:
MG_CHECK_RET (check_status != BST_INDETERMINATE, -1);
BUTTON_SET_CHECK (pctrl, check_status);
break;
case BS_3STATE:
case BS_AUTO3STATE:
BUTTON_SET_CHECK (pctrl, check_status);
break;
}
return 1;
}
/**
* switch_check:
* switch check status when the button is clicked
* return: new check status
* Author: XuguangWang
* Date: 2007-12-7
*/
static int switch_check (PCONTROL pctrl)
{
int old_check = BUTTON_GET_CHECK(pctrl);
/*calc new ckeck status*/
switch (BUTTON_TYPE(pctrl))
{
case BS_RADIOBUTTON:
case BS_AUTORADIOBUTTON:
return BST_CHECKED;
case BS_CHECKBOX:
case BS_AUTOCHECKBOX:
return old_check==BST_CHECKED ? BST_UNCHECKED : BST_CHECKED;
case BS_3STATE:
case BS_AUTO3STATE:
return old_check==BST_UNCHECKED ? BST_CHECKED : (
BUTTON_GET_CHECK(pctrl) == BST_CHECKED ?
BST_INDETERMINATE : BST_UNCHECKED
);
default:
return -1;
}
}
/*change_status_from_pose
* change button status (pose and check status), and invalidate window.
* pose status -- normal, hilite, pressed(pushed), disable.
* check status -- unchecked, checked, indeterminate.
*
* param noti_pose_changing: indicating if the status changing is from key or
* mouse lbutton up and down.
* TRUE -- the button(if it is auto) should notify parent
* FALSE -- the pose changing is from mouse moving, so button need
* not notify parent
*
* param change_valid: if to normal(new_pose) is valid(it can change check status)
* TRUE -- key up or mouse lbutton up on the button
* FALSE -- key lbutton up is not on the button, so it's not a full
* click
* */
static void change_status_from_pose (PCONTROL pctrl, int new_pose,
BOOL noti_pose_changing, BOOL change_valid)
{
static int nt_code[3][3] = {
/*normal->nochange, hilite, pressed*/
{ 0, BN_HILITE, BN_PUSHED},
/*hilite->normal, nochange, pressed*/
{BN_UNHILITE, 0, BN_PUSHED},
/*pressed->normal, hilite, nochange*/
{BN_UNPUSHED, BN_UNPUSHED, 0},
};
DWORD dwStyle = pctrl->dwStyle;
int old_pose = BUTTON_GET_POSE(pctrl);
int new_check;
RECT rcClient;
RECT rcContent;
RECT rcBitmap;
/*make sure it can be changed, and avoid changing more than once*/
MG_CHECK (old_pose!= BST_DISABLE && old_pose != new_pose);
/*set new pose*/
BUTTON_SET_POSE(pctrl, new_pose);
if ((dwStyle & BS_NOTIFY) && noti_pose_changing)
{
if (new_pose != BST_DISABLE)
NotifyParent ((HWND)pctrl, pctrl->id,
nt_code[old_pose][new_pose]);
/*disable the button*/
else
{
/*before to disable, firstly to normal*/
switch (old_pose)
{
case BST_PUSHED:
NotifyParent ((HWND)pctrl, pctrl->id, BN_UNPUSHED);
case BST_HILITE:
NotifyParent ((HWND)pctrl, pctrl->id, BN_UNHILITE);
case BST_NORMAL:
NotifyParent ((HWND)pctrl, pctrl->id, BN_DISABLE);
break;
default:
assert (0);
break;
}
}
}
/*complete a click if the click if valid
* (mouse lbutton up in button )*/
if (old_pose == BST_PUSHED && new_pose != BST_DISABLE
&& change_valid)
{
if (!BUTTON_IS_PUSHBTN(pctrl) && BUTTON_IS_AUTO(pctrl))
{
new_check = switch_check(pctrl);
change_checked(pctrl, new_check);
}
NotifyParent ((HWND)pctrl, pctrl->id, BN_CLICKED);
}
/* DK: When the radio or check button state changes do not erase the background,
* and the prospects for direct rendering */
btnGetRects (pctrl, &rcClient, &rcContent, &rcBitmap);
if (BUTTON_IS_PUSHBTN(pctrl) || (pctrl->dwStyle & BS_PUSHLIKE))
InvalidateRect((HWND)pctrl, NULL, TRUE);
else
InvalidateRect((HWND)pctrl, &rcBitmap, FALSE);
}
/*btnGetRects:
* get the client rect(draw body of button), the content rect
* (draw contern), and bitmap rect(draw a little icon)
*/
static void btnGetRects (PCONTROL pctrl, RECT* prcClient,
RECT* prcContent,
RECT* prcBitmap)
{
GetClientRect ((HWND)pctrl, prcClient);
if (BUTTON_IS_PUSHBTN(pctrl) || (pctrl->dwStyle & BS_PUSHLIKE))
{
SetRect (prcContent, (prcClient->left + BTN_WIDTH_BORDER),
(prcClient->top + BTN_WIDTH_BORDER),
(prcClient->right - BTN_WIDTH_BORDER),
(prcClient->bottom - BTN_WIDTH_BORDER));
if (BUTTON_GET_POSE(pctrl) == BST_PUSHED)
{
prcContent->left ++;
prcContent->top ++;
prcContent->right ++;
prcContent->bottom++;
}
SetRectEmpty (prcBitmap);
return;
}
if (pctrl->dwStyle & BS_LEFTTEXT) {
SetRect (prcContent, prcClient->left + 1,
prcClient->top + 1,
prcClient->right - BTN_WIDTH_BMP - BTN_INTER_BMPTEXT,
prcClient->bottom - 1);
SetRect (prcBitmap, prcClient->right - BTN_WIDTH_BMP,
prcClient->top + 1,
prcClient->right - 1,
prcClient->bottom - 1);
}
else {
SetRect (prcContent, prcClient->left + BTN_WIDTH_BMP + BTN_INTER_BMPTEXT,
prcClient->top + 1,
prcClient->right - 1,
prcClient->bottom - 1);
SetRect (prcBitmap, prcClient->left + 1,
prcClient->top + 1,
prcClient->left + BTN_WIDTH_BMP,
prcClient->bottom - 1);
}
}
/**
* calc DrawText format from button style
*/
static int btnGetTextFmt (int dwStyle)
{
UINT dt_fmt;
if (dwStyle & BS_MULTLINE)
dt_fmt = DT_WORDBREAK;
else
dt_fmt = DT_SINGLELINE;
if ((dwStyle & BS_TYPEMASK) == BS_PUSHBUTTON
|| (dwStyle & BS_TYPEMASK) == BS_DEFPUSHBUTTON
|| (dwStyle & BS_PUSHLIKE))
dt_fmt |= DT_CENTER | DT_VCENTER;
else {
if ((dwStyle & BS_ALIGNMASK) == BS_RIGHT)
dt_fmt = DT_WORDBREAK | DT_RIGHT;
else if ((dwStyle & BS_ALIGNMASK) == BS_CENTER)
dt_fmt = DT_WORDBREAK | DT_CENTER;
else dt_fmt = DT_WORDBREAK | DT_LEFT;
if ((dwStyle & BS_ALIGNMASK) == BS_TOP)
dt_fmt |= DT_SINGLELINE | DT_TOP;
else if ((dwStyle & BS_ALIGNMASK) == BS_BOTTOM)
dt_fmt |= DT_SINGLELINE | DT_BOTTOM;
else dt_fmt |= DT_SINGLELINE | DT_VCENTER;
}
return dt_fmt;
}
/**
* draw bitmap content in button with BS_BITMAP style
*/
static void draw_bitmap_button (PCONTROL pctrl, HDC hdc, DWORD dwStyle,
RECT *prcText)
{
if (BUTTON_DATA(pctrl)) {
int x = prcText->left;
int y = prcText->top;
int w = RECTWP (prcText);
int h = RECTHP (prcText);
PBITMAP bmp = (PBITMAP)(BUTTON_DATA(pctrl));
RECT prcClient;
GetClientRect ((HWND)pctrl, &prcClient);
if (dwStyle & BS_REALSIZEIMAGE) {
x += (w - bmp->bmWidth) >> 1;
y += (h - bmp->bmHeight) >> 1;
w = h = 0;
if (bmp->bmWidth > RECTW(prcClient)){
x = prcClient.left + BTN_WIDTH_BORDER;
w = RECTW(prcClient) - 2*BTN_WIDTH_BORDER-1;
}
if (bmp->bmHeight > RECTH(prcClient)){
y = prcClient.top + BTN_WIDTH_BORDER;
h = RECTH(prcClient) - 2*BTN_WIDTH_BORDER-1;
}
}
else {
x = prcClient.top + BTN_WIDTH_BORDER;
y = prcClient.left + BTN_WIDTH_BORDER;
w = RECTW (prcClient) - 2*BTN_WIDTH_BORDER-1;
h = RECTH (prcClient) - 2*BTN_WIDTH_BORDER-1;
}
FillBoxWithBitmap (hdc, x, y, w, h, bmp);
}
}
/**
* draw bitmap content in button with BS_ICON style
*/
static void draw_icon_button(PCONTROL pctrl, HDC hdc, DWORD dwStyle, RECT *prcText)
{
if (BUTTON_DATA(pctrl)) {
int x = prcText->left;
int y = prcText->top;
int w = RECTWP (prcText);
int h = RECTHP (prcText);
HICON icon = (HICON)(BUTTON_DATA(pctrl));
RECT prcClient;
if (dwStyle & BS_REALSIZEIMAGE) {
int iconw, iconh;
GetIconSize (icon, &iconw, &iconh);
x += (w - iconw) >> 1;
y += (h - iconh) >> 1;
w = h = 0;
}
else {
GetClientRect ((HWND)pctrl, &prcClient);
x = prcClient.top;
y = prcClient.left;
w = RECTW (prcClient);
h = RECTH (prcClient);
}
DrawIcon (hdc, x, y, w, h, icon);
}
}
/**
* paint_content_focus:
* draw content in button and focusRect (if it have focus)
* Author: XuguangWang
* Date: 2007-12-7
*/
static void paint_content_focus(HDC hdc, PCONTROL pctrl, RECT* prc_cont)
{
DWORD dt_fmt = 0;
DWORD fg_color = 0xFFFF;
DWORD text_pixel;
BOOL is_get_fg = FALSE;
BOOL is_get_fmt = FALSE;
gal_pixel old_pixel;
RECT focus_rc;
const WINDOW_ELEMENT_RENDERER* win_rdr;
/* Not used vars.
int status, type;
status = BUTTON_STATUS (pctrl);
type = BUTTON_TYPE (pctrl);
*/
win_rdr = GetWindowInfo((HWND)pctrl)->we_rdr;
/*draw button content*/
switch (pctrl->dwStyle & BS_CONTENTMASK)
{
case BS_BITMAP:
draw_bitmap_button(pctrl, hdc, pctrl->dwStyle, prc_cont);
break;
case BS_ICON:
draw_icon_button(pctrl, hdc, pctrl->dwStyle, prc_cont);
break;
default:
fg_color = GetWindowElementAttr((HWND)pctrl, WE_FGC_THREED_BODY);
is_get_fg = TRUE;
text_pixel = RGBA2Pixel(hdc, GetRValue(fg_color),
GetGValue(fg_color), GetBValue(fg_color),
GetAValue(fg_color));
old_pixel = SetTextColor(hdc, text_pixel);
dt_fmt = btnGetTextFmt(pctrl->dwStyle);
is_get_fmt = TRUE;
SetBkMode (hdc, BM_TRANSPARENT);
DrawText (hdc, pctrl->spCaption, -1, prc_cont, dt_fmt);
SetTextColor(hdc, old_pixel);
/*disable draw text*/
if ((BUTTON_GET_POSE(pctrl) == BST_DISABLE)
| (pctrl->dwStyle & WS_DISABLED))
win_rdr->disabled_text_out ((HWND)pctrl, hdc, pctrl->spCaption,
prc_cont, dt_fmt);
}
/*draw focus frame*/
if (BUTTON_STATUS(pctrl) & BST_FOCUS)
{
focus_rc = *prc_cont;
if (!BUTTON_IS_PUSHBTN(pctrl) &&
!(pctrl->dwStyle & BS_PUSHLIKE) &&
is_get_fmt)
{
dt_fmt |= DT_CALCRECT;
DrawText (hdc, pctrl->spCaption, -1, &focus_rc, dt_fmt);
}
if (!is_get_fg)
fg_color = GetWindowElementAttr((HWND)pctrl, WE_FGC_THREED_BODY);
win_rdr->draw_focus_frame(hdc, &focus_rc, fg_color);
}
}
/**
* paint_push_btn:
* draw push or pushlike button
* Author: XuguangWang
* Date: 2007-12-7
*/
static void paint_push_btn (HDC hdc, PCONTROL pctrl)
{
const WINDOW_ELEMENT_RENDERER* win_rdr;
DWORD main_color;
RECT rcClient;
RECT rcContent;
RECT rcBitmap;
win_rdr = GetWindowInfo((HWND)pctrl)->we_rdr;
main_color = GetWindowElementAttr((HWND)pctrl, WE_MAINC_THREED_BODY);
btnGetRects (pctrl, &rcClient, &rcContent, &rcBitmap);
win_rdr->draw_push_button((HWND)pctrl, hdc, &rcClient, main_color,
0xFFFFFFFF, BUTTON_STATUS(pctrl));
paint_content_focus(hdc, pctrl, &rcContent);
}
#if 1
/*a matrix from button control status to renderer status*/
static int ctrlst_rdrst[12] = {
/*unckecked*/
LFRDR_BTN_STATUS_NORMAL,
LFRDR_BTN_STATUS_HILITE,
LFRDR_BTN_STATUS_PRESSED,
LFRDR_BTN_STATUS_DISABLED,
/*checked*/
LFRDR_BTN_STATUS_NORMAL|LFRDR_BTN_STATUS_SELECTED,
LFRDR_BTN_STATUS_HILITE|LFRDR_BTN_STATUS_SELECTED,
LFRDR_BTN_STATUS_PRESSED|LFRDR_BTN_STATUS_SELECTED,
LFRDR_BTN_STATUS_DISABLED|LFRDR_BTN_STATUS_SELECTED,
/*indeterminate*/
LFRDR_BTN_STATUS_DISABLED,
LFRDR_BTN_STATUS_DISABLED,
LFRDR_BTN_STATUS_DISABLED,
LFRDR_BTN_STATUS_DISABLED,
};
#else
static int ctrlst_rdrst[12] = {
/*unckecked*/
BST_NORMAL,
BST_HILITE,
BST_PUSHED,
BST_DISABLE,
/*checked*/
BST_NORMAL | BST_CHECKED,
BST_HILITE | BST_CHECKED,
BST_PUSHED | BST_CHECKED,
BST_DISABLE | BST_CHECKED,
/*indeterminate*/
BST_DISABLE,
BST_DISABLE,
BST_DISABLE,
BST_DISABLE,
};
#endif
/**
* paint_check_radio_btn:
* draw check button, radio button and 3state button
* Author: XuguangWang
* Date: 2007-12-7
*/
static void paint_check_radio_btn (HDC hdc, PCONTROL pctrl)
{
const WINDOW_ELEMENT_RENDERER* win_rdr;
int rdr_st;
RECT rcClient;
RECT rcContent;
RECT rcBitmap;
win_rdr = GetWindowInfo((HWND)pctrl)->we_rdr;
/* Not used vars
gal_pixel text_pixel;
text_pixel = GetWindowElementPixelEx((HWND)pctrl, hdc, WE_FGC_WINDOW);
*/
rdr_st = ctrlst_rdrst [ BUTTON_STATUS (pctrl) &
(BST_POSE_MASK|BST_CHECK_MASK) ];
btnGetRects (pctrl, &rcClient, &rcContent, &rcBitmap);
if (BUTTON_IS_RADIOBTN(pctrl))
win_rdr->draw_radio_button((HWND)pctrl, hdc, &rcBitmap, rdr_st);
else
win_rdr->draw_check_button((HWND)pctrl, hdc, &rcBitmap, rdr_st);
/* DK: just draw text after background has been erased.*/
paint_content_focus(hdc, pctrl, &rcContent);
}
BOOL RegisterButtonControl (void)
{
WNDCLASS WndClass;
WndClass.spClassName = CTRL_BUTTON;
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 = ButtonCtrlProc;
return AddNewControlClass (&WndClass) == ERR_OK;
}
/**
* mouse_in_client:
* calc if mouse is in client
* Author: XuguangWang
* Date: 2007-12-7
*/
static inline BOOL mouse_in_client(LPARAM lParam, PCONTROL pctrl)
{
int x, y;
x = LOSWORD(lParam);
y = HISWORD(lParam);
ScreenToClient (GetParent ((HWND)pctrl), &x, &y);
return (PtInRect ((PRECT) &(pctrl->cl), x, y));
}
static LRESULT ButtonCtrlProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PCONTROL pctrl;
DWORD dwStyle;
PBUTTONDATA pData;
pctrl = gui_Control(hWnd);
dwStyle = pctrl->dwStyle;
switch(uMsg)
{
case MSG_CREATE:
pData = (BUTTONDATA*) calloc (1, sizeof(BUTTONDATA));
SetWindowBkColor (hWnd, GetWindowElementPixel (hWnd,
WE_MAINC_THREED_BODY));
if (pData == NULL)
return -1;
pData->status = 0;
pData->data = pctrl->dwAddData;
pctrl->dwAddData2 = (DWORD) pData;
if (!BUTTON_IS_PUSHBTN(pctrl) && dwStyle & BS_CHECKED)
BUTTON_SET_CHECK(pctrl, BST_CHECKED);
break;
case MSG_DESTROY:
free ((void*) pctrl->dwAddData2);
break;
case BM_GETCHECK:
if (!BUTTON_IS_PUSHBTN(pctrl))
return BUTTON_GET_CHECK(pctrl);
else
return -1;
case BM_SETCHECK:
{
int set_ret;
UINT old_check;
// MG_CHECK_RET(BUTTON_IS_PUSHBTN(pctrl), -1);
old_check = BUTTON_GET_CHECK(pctrl);
set_ret = change_checked(pctrl,wParam);
if (set_ret == 1)
InvalidateRect (hWnd, NULL, TRUE);
return old_check;
}
case BM_GETSTATE:
return (int)(BUTTON_GET_POSE(pctrl));
case BM_SETSTATE:
{
DWORD old_pose = BUTTON_GET_POSE(pctrl);
if (wParam)
BUTTON_SET_POSE(pctrl, BST_PUSHED);
else
BUTTON_SET_POSE(pctrl, BST_NORMAL);
if (old_pose != BUTTON_GET_POSE(pctrl))
InvalidateRect (hWnd, NULL, TRUE);
return old_pose;
}
case BM_ENABLE:
{
if (wParam == FALSE)
{
/*disable a button*/
MG_CHECK_RET (BUTTON_GET_POSE(pctrl) != BST_DISABLE, 0);
change_status_from_pose (pctrl, BST_DISABLE, TRUE, FALSE);
}
else
{
/*enable a button*/
MG_CHECK_RET (BUTTON_GET_POSE(pctrl) == BST_DISABLE, 0);
BUTTON_SET_POSE (pctrl, BST_NORMAL);
NotifyParent(hWnd, pctrl->id, BN_ENABLE);
}
InvalidateRect (hWnd, NULL, TRUE);
return 0;
}
case BM_GETIMAGE:
{
int* image_type = (int*) wParam;
if (dwStyle & BS_BITMAP) {
if (image_type) {
*image_type = BM_IMAGE_BITMAP;
}
return (int)(BUTTON_DATA (pctrl));
}
else if (dwStyle & BS_ICON) {
if (image_type) {
*image_type = BM_IMAGE_ICON;
}
return (int)(BUTTON_DATA (pctrl));
}
}
return 0;
case BM_SETIMAGE:
{
int oldImage = (int)BUTTON_DATA (pctrl);
if (wParam == BM_IMAGE_BITMAP) {
pctrl->dwStyle &= ~BS_ICON;
pctrl->dwStyle |= BS_BITMAP;
}
else if (wParam == BM_IMAGE_ICON){
pctrl->dwStyle &= ~BS_BITMAP;
pctrl->dwStyle |= BS_ICON;
}
if (lParam) {
BUTTON_DATA (pctrl) = (DWORD)lParam;
InvalidateRect (hWnd, NULL, TRUE);
}
return oldImage;
}
break;
case BM_CLICK:
{
int new_check;
if (BUTTON_IS_AUTO(pctrl))
{
new_check = switch_check(pctrl);
change_checked(pctrl, new_check);
InvalidateRect (hWnd, NULL, TRUE);
}
NotifyParent (hWnd, pctrl->id, BN_CLICKED);
}
break;
case MSG_SETTEXT:
{
int len = strlen((char*)lParam);
FreeFixStr (pctrl->spCaption);
pctrl->spCaption = FixStrAlloc (len);
if (len > 0)
strcpy (pctrl->spCaption, (char*)lParam);
InvalidateRect (hWnd, NULL, TRUE);
break;
}
case BM_SETSTYLE:
pctrl->dwStyle &= 0xFFFF0000;
pctrl->dwStyle |= (DWORD)(wParam & 0x0000FFFF);
if (LOWORD (lParam))
InvalidateRect (hWnd, NULL, TRUE);
break;
case MSG_CHAR:
if (HIBYTE (wParam)==0 && BUTTON_IS_CHECKBTN (pctrl)) {
int old_check = BUTTON_GET_CHECK(pctrl);
if (LOBYTE(wParam) == '+' || LOBYTE(wParam) == '=')
BUTTON_SET_CHECK(pctrl, BST_CHECKED);
else if (LOBYTE(wParam) == '-')
BUTTON_SET_CHECK(pctrl, BST_UNCHECKED);
if (old_check != BUTTON_GET_CHECK(pctrl))
InvalidateRect (hWnd, NULL, TRUE);
}
break;
case MSG_ENABLE:
if (wParam && (dwStyle & WS_DISABLED))
pctrl->dwStyle &= ~WS_DISABLED;
else if (!wParam && !(dwStyle & WS_DISABLED))
pctrl->dwStyle |= WS_DISABLED;
else
return 0;
InvalidateRect (hWnd, NULL, TRUE);
return 0;
case MSG_GETDLGCODE:
switch (dwStyle & BS_TYPEMASK) {
case BS_CHECKBOX:
case BS_AUTOCHECKBOX:
return DLGC_WANTCHARS | DLGC_BUTTON;
case BS_RADIOBUTTON:
case BS_AUTORADIOBUTTON:
return DLGC_RADIOBUTTON | DLGC_BUTTON;
case BS_DEFPUSHBUTTON:
return DLGC_DEFPUSHBUTTON;
case BS_PUSHBUTTON:
return DLGC_PUSHBUTTON;
case BS_3STATE:
case BS_AUTO3STATE:
return DLGC_3STATE;
default:
return 0;
}
break;
case MSG_NCHITTEST:
{
int x, y;
x = (int)wParam;
y = (int)lParam;
if (PtInRect ((PRECT) &(pctrl->cl), x, y))
return HT_CLIENT;
else
return HT_OUT;
}
break;
case MSG_KILLFOCUS:
BUTTON_STATUS(pctrl) &= (~BST_FOCUS);
if (GetCapture() == hWnd) {
ReleaseCapture ();
BUTTON_SET_POSE(pctrl, BST_NORMAL);
}
if (dwStyle & BS_NOTIFY)
NotifyParent (hWnd, pctrl->id, BN_KILLFOCUS);
InvalidateRect (hWnd, NULL, TRUE);
break;
case MSG_SETFOCUS:
BUTTON_STATUS(pctrl) |= BST_FOCUS;
if (dwStyle & BS_NOTIFY)
NotifyParent (hWnd, pctrl->id, BN_SETFOCUS);
InvalidateRect (hWnd, NULL, TRUE);
break;
case MSG_KEYDOWN:
if (wParam != SCANCODE_SPACE
&& wParam != SCANCODE_ENTER
&& wParam != SCANCODE_KEYPADENTER)
break;
if (GetCapture () == hWnd)
break;
SetCapture (hWnd);
//FIXME not needed
//BUTTON_STATUS(pctrl) |= BST_FOCUS;
change_status_from_pose(pctrl, BST_PUSHED, TRUE, TRUE);
break;
case MSG_KEYUP:
{
if (wParam != SCANCODE_SPACE
&& wParam != SCANCODE_ENTER
&& wParam != SCANCODE_KEYPADENTER)
break;
if (GetCapture () == hWnd)
{
ReleaseCapture ();
change_status_from_pose(pctrl, BST_NORMAL, TRUE, TRUE);
}
}
break;
case MSG_LBUTTONDBLCLK:
if (dwStyle & BS_NOTIFY &&
BUTTON_GET_POSE(pctrl) != BST_DISABLE)
NotifyParent (hWnd, pctrl->id, BN_DBLCLK);
break;
case MSG_LBUTTONDOWN:
if (GetCapture () == hWnd)
break;
SetCapture (hWnd);
BUTTON_STATUS(pctrl) |= BST_FOCUS;
change_status_from_pose(pctrl, BST_PUSHED, TRUE, TRUE);
break;
case MSG_LBUTTONUP:
{
if (GetCapture() == hWnd)
{
ReleaseCapture ();
if (mouse_in_client(lParam, pctrl))
change_status_from_pose(pctrl, BST_HILITE, TRUE, TRUE);
else
change_status_from_pose(pctrl, BST_NORMAL, TRUE, FALSE);
}
return 0;
}
case MSG_MOUSEMOVEIN:
{
/*leave a button, nomralize it*/
if (!wParam)
change_status_from_pose(pctrl, BST_NORMAL, TRUE, FALSE);
/*because if lbutton downed on space out of the button,
* and then move to it, it will receive MSG_MOUSEMOVEIN,
* but it should not be hilited by MSG_MOUSEMOVEIN(wParam == TRUE)
* */
break;
}
case MSG_MOUSEMOVE:
{
/*left button is not downed*/
if (!(wParam & KS_LEFTBUTTON))
{
/*mouse not captured by keydowning on other button*/
if (GetCapture()==HWND_NULL)
change_status_from_pose(pctrl, BST_HILITE, TRUE, FALSE);
break;
}
/*the button capture mouse by mouse*/
if (GetCapture() == hWnd)
{
/*normal -- pushed, while lbutton is being downed*/
if (mouse_in_client(lParam, pctrl))
change_status_from_pose(pctrl, BST_PUSHED, FALSE, FALSE);
else
change_status_from_pose(pctrl, BST_NORMAL, FALSE, FALSE);
}
break;
}
case MSG_PAINT:
{
hdc = BeginPaint (hWnd);
SelectFont (hdc, GetWindowFont(hWnd));
if (BUTTON_IS_PUSHBTN(pctrl) || (pctrl->dwStyle & BS_PUSHLIKE))
paint_push_btn(hdc, pctrl);
else
paint_check_radio_btn(hdc, pctrl);
EndPaint (hWnd, hdc);
return 0;
}
default:
break;
}
return DefaultControlProc (hWnd, uMsg, wParam, lParam);
}
#endif /* _MGCTRL_BUTTON */
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C
1
https://gitee.com/MicroOS/MiniGUI.git
git@gitee.com:MicroOS/MiniGUI.git
MicroOS
MiniGUI
MiniGUI
master

搜索帮助