📄 ylscrollwidget.c
字号:
#include "YLScrollWidget.h"
#include "AEEWProperties.h"
#include "wutil.h"
#include "widget_res.h"
#include "AEEDisplayCanvas.h"
//#define SBBORDER_WIDTH 1 //modified by 曾念荣
#define SBBORDER_WIDTH 0
#define SBWIDTH (me->nHandleWidth + (2 * SBBORDER_WIDTH))
#define SBARROW_HEIGHT 10 //单个箭头的高度(含箭头外面的矩形框)
#define DEFAULT_YLSCROLLBORDER_COLOR MAKE_RGBA(0, 0, 0, 255);
#define DEFAULT_YLSCROLLHANDLE_COLOR MAKE_RGBA(97, 97, 97, 255);
static __inline YLScrollbarWidget *DECORATOR_TO_YLSCROLLBARWIDGET(IDecorator *po) {
return (YLScrollbarWidget*)po;
}
static __inline YLScrollbarWidget *CONTAINER_TO_YLSCROLLBARWIDGET(IContainer *po) {
return (YLScrollbarWidget*)po->pMe;
}
#define YLSCROLLBAR_FROM_DECORATOR YLScrollbarWidget *me = DECORATOR_TO_YLSCROLLBARWIDGET(po)
#define YLSCROLLBAR_FROM_CONTAINER YLScrollbarWidget *me = CONTAINER_TO_YLSCROLLBARWIDGET(po)
// compute scrollbar handle size
//
// The ratio of the scrollbar handle's size to the total
// scrollbar size is the same as the ratio of the
// ScrollEvent's visible member to its total range. That
// is:
//
// scrollbar handle (c) visible (v)
// ---------------------- == ------------
// total scrollbar (d) range (r)
//
// So:
//
// c = d * (v / r)
//
static __inline uint16 YLScrollbarWidget_ComputeSize(uint32 d, uint32 r, uint32 v)
{
uint32 c = 0;
// non-zero range must have been specified
if (r > 0) {
c = (d * v) / r;
}
return (uint16)c;
}
// compute scrollbar handle position
//
// Valid handle pixel positions (c) are within the range of 0
// to the total scrollbar size (d) minus the scrollbar handle
// size. 0 < c < ScrollbarWidget_ComputeSize(d, r, v)
//
// The ScrollEvent's position (p) falls with the same range of 0
// to the total range (r) minus the visible (v). 0 < p < r - v.
// Any position beyond that range is treated as fully scrolled.
//
// To set the scroll handle to its maximum position, p >= r-v.
//
// For all other positions, the ratio of the pixel position of
// the handle (c) to the total pixel range of the scroll bar handle
// (d - ScrollbarWidget_ComputeSize(d, r, v)) is the same as the
// ratio of the ScrollEvent's position (p) to the total scroll range
// minus the visisible (d - v). That is:
//
// c / (d - ScrollbarWidget_ComputeSize(d, r, v)) == p / (r - v)
//
// So:
//
// c = (p * (d - ScrollbarWidget_ComputeSize(d, r, v))) / (r - v)
//
// This can be simplified as follows:
//
// c = (p * (d - (d * v/r)) / (r - v)
//
// c = (p * ((dr - dv)/r) / (r - v)
//
// c = (p * d * (r - v) * (1 / r) * 1/(r- v)
//
// Ultimately, the scoll handle's pixel position can be computed
// from the total scroll bar pixel size (d), the ScrollEvent's
// position (p) and the ScrollEvent's total range (r) as:
//
// c = p * d / r
//
static __inline uint16 YLScrollbarWidget_ComputePosition(uint32 d, uint32 p, uint32 r, uint32 v)
{
uint32 c = 0;
// non-zero range must have been specified
if (r > 0) {
// scrollbar is 100& scrolled if position is greater than or equal to range - visible.
if (p >= (r - v)) {
// 100% scrolled, make sure scroll bar is at the bottom for any value
// of p beyond (r - v).
c = d - (d * v / r);
} else {
// compute scrollbar position. Do our best to avoid overflow and roundoff errors.
// Position, range and visible may be large or small, so let's assume the worst.
c = p * d;
c /= r;
}
}
return (uint16)c;
}
void YLScrollbarWidget_Ctor(YLScrollbarWidget *me, AEEVTBL(IDecorator) *pvt, IShell *piShell,
IModule *piModule, PFNHANDLER pfnDefHandler)
{
ScrollbarWidget* psb = (ScrollbarWidget*)me;
ScrollbarWidget_Ctor(psb, pvt, piShell, piModule, pfnDefHandler);
me->rgbStartBlank = MAKE_RGB(230,230,230);
me->rgbStartHandle = MAKE_RGB(230,230,230);
me->rgbStartArrow = MAKE_RGB(230,230,230);
me->nGradientStyle = GRADIENT_STYLE_HORZ;//颜色水平渐变
psb->rgbBorder[RGBINDEX_ACTIVE] = MAKE_RGB(111,125,79);
psb->rgbBorder[RGBINDEX_INACTIVE] = MAKE_RGB(158,173,150);
psb->rgbHandle[RGBINDEX_ACTIVE] =
psb->rgbHandle[RGBINDEX_INACTIVE] = DEFAULT_YLSCROLLHANDLE_COLOR;
psb->rgbFill = RGB_WHITE;
psb->nHandleWidth = 11;
psb->nPad = 0;
psb->nEndPad = 0;
pvt->Draw = YLScrollbarWidget_Draw;
}
int YLScrollbarWidget_New(IDecorator **ppo, IShell *piShell, IModule *piModule)
{
YLScrollbarWidget *me = MALLOCREC_VTBL(YLScrollbarWidget, IDecorator);
if (!me)
return ENOMEMORY;
YLScrollbarWidget_Ctor(me, GETVTBL(me,IDecorator), piShell, piModule, 0);
*ppo = YLSCROLLBARWIDGET_TO_IDECORATOR(me);
return 0;
}
void YLSbArrows_DrawVertArrows(SbArrows *me, IDisplay *piDisplay, AEERect *prc,
RGBVAL rgbUp, RGBVAL rgbDown, boolean bReduce,
int nEndPad)
{
AEERect rcLine;
int x, y;
// ensure resource image is loaded
if (!TILEDIMAGE_HASIMAGE(&me->tiVArrows) &&
me->piShell &&
0 != TiledImage_LoadResBitmap(&me->tiVArrows, me->piShell, "widgets.mif", IDB_VSBARROWS, 2)) {
return;
}
x = prc->x + ((prc->dx - me->tiVArrows.cxTile) / 2);
y = prc->y;
if (rgbUp != RGB_NONE) {
//TiledImage_ReplaceColor(&me->tiVArrows, RGB_BLACK, rgbUp);
//TiledImage_DrawTile(&me->tiVArrows, piDisplay, x, y, 0);
TiledImage_DrawTile(&me->tiVArrows, piDisplay, x, y+4, 0);
}
rcLine.x = prc->x+1;
rcLine.y = prc->y;
rcLine.dx = prc->dx - 2;
rcLine.dy = 1;
IDISPLAY_DrawRect(piDisplay, &rcLine, RGB_NONE, rgbUp, IDF_RECT_FILL);//上边线
rcLine.y = prc->y + SBARROW_HEIGHT - 1;
IDISPLAY_DrawRect(piDisplay, &rcLine, RGB_NONE, rgbUp, IDF_RECT_FILL);//下边线
rcLine.x = prc->x;
rcLine.y = prc->y + 1;
rcLine.dx = 1;
rcLine.dy = SBARROW_HEIGHT - 2;
IDISPLAY_DrawRect(piDisplay, &rcLine, RGB_NONE, rgbUp, IDF_RECT_FILL);//左边线
rcLine.x = prc->x + prc->dx -1;
IDISPLAY_DrawRect(piDisplay, &rcLine, RGB_NONE, rgbUp, IDF_RECT_FILL);//右边线
//y = prc->y + prc->dy - me->tiVArrows.cyTile;
y = prc->y + prc->dy - SBARROW_HEIGHT;
if (rgbDown != RGB_NONE) {
//TiledImage_ReplaceColor(&me->tiVArrows, RGB_BLACK, rgbDown);
//TiledImage_DrawTile(&me->tiVArrows, piDisplay, x, y, 1);
TiledImage_DrawTile(&me->tiVArrows, piDisplay, x, y+3, 1);
}
rcLine.x = prc->x+1;
rcLine.y = y;
rcLine.dx = prc->dx - 2;
rcLine.dy = 1;
IDISPLAY_DrawRect(piDisplay, &rcLine, RGB_NONE, rgbUp, IDF_RECT_FILL);//上边线
rcLine.y = y + SBARROW_HEIGHT - 1;
IDISPLAY_DrawRect(piDisplay, &rcLine, RGB_NONE, rgbUp, IDF_RECT_FILL);//下边线
rcLine.x = prc->x;
rcLine.y = y + 1;
rcLine.dx = 1;
rcLine.dy = SBARROW_HEIGHT- 2;
IDISPLAY_DrawRect(piDisplay, &rcLine, RGB_NONE, rgbUp, IDF_RECT_FILL);//左边线
rcLine.x = prc->x + prc->dx -1;
IDISPLAY_DrawRect(piDisplay, &rcLine, RGB_NONE, rgbUp, IDF_RECT_FILL);//右边线
if (bReduce) {
//INFLATERECT(prc, 0, -(MAX(nEndPad, me->tiVArrows.cyTile+1)));
INFLATERECT(prc, 0, -SBARROW_HEIGHT);
}
}
void YLScrollbarWidget_Draw(IDecorator *po, ICanvas *piCanvas, int x, int y)
{
YLSCROLLBAR_FROM_DECORATOR;
ScrollbarWidget* psb = &me->base;
AEERect rc;
AEERect rcFill;
IDisplay *piDisplay = 0;
RGBVAL rgbBorder = psb->rgbBorder[psb->border.bActive];
Border_Draw(&psb->border, piCanvas, x, y);
if (SUCCESS != ICANVAS_GetDisplay(piCanvas, &piDisplay)) {
return;
}
if (psb->nScrollStyle == SCROLL_VERT || psb->nScrollStyle == SCROLL_BOTH) {
// Get scrollbar rect
ScrollbarWidget_GetScrollbarRect(psb, 0, &rc);
if (rc.dx && rc.dy) {
ScrollInfo *psi = &psb->scroll[SCROLL_VERT];
// inset by drawing location
rc.x += x;
rc.y += y;
//if (psb->dwFlags & SBWF_ARROWS) {
if ((psb->dwFlags & SBWF_ARROWS) && (rc.dy > SBARROW_HEIGHT*4)) {//绘画区域高度大于4倍的箭头高度
YLSbArrows_DrawVertArrows(&psb->arrows, piDisplay, &rc, rgbBorder, rgbBorder, 1,
psb->nEndPad);//箭头
} else {
INFLATERECT(&rc, 0, -psb->nEndPad);
}
//不需要画边框 曾念荣
/* if (rgbBorder != RGBA_NONE) {
DrawAndInsetBorder(piDisplay, &rc, SBBORDER_WIDTH, rgbBorder);//画边框
}
*/
//IDISPLAY_DrawRect(piDisplay, &rc, RGB_NONE, RGBA_STRIPALPHA(psb->rgbFill), IDF_RECT_FILL);//填充空白处
//IDISPLAY_DrawRect(piDisplay, &rcFill, RGB_NONE, RGBA_STRIPALPHA(psb->rgbFill), IDF_RECT_FILL);//填充空白处
IDisplay_FillRectGradient(piDisplay, &rc, me->rgbStartBlank, psb->rgbFill, 0, 0, 1);//填充空白处
if (psi->range > psi->visible)
{
int dyMin = MIN(4, rc.dy);
int yMax = rc.y + rc.dy;
if((psb->dwFlags & SBWF_FOCUSTRACK) && psb->numItems > 0) {
rc.y += (rc.dy * psb->focusIndex) / psb->numItems;
rc.dy = rc.dy / psb->numItems;
}
else {
rc.y += YLScrollbarWidget_ComputePosition(rc.dy, psi->position, psi->range, psi->visible);
rc.dy = YLScrollbarWidget_ComputeSize(rc.dy, psi->range, psi->visible);
}
rc.dy = MAX(dyMin, rc.dy);
rc.y = MIN(rc.y, yMax - rc.dy);
//IDISPLAY_DrawRect(piDisplay, &rc, RGB_NONE, RGBA_STRIPALPHA(psb->rgbHandle[psb->border.bActive]), IDF_RECT_FILL);
IDisplay_FillRectGradient(piDisplay, &rc, me->rgbStartHandle, RGBA_STRIPALPHA(psb->rgbHandle[psb->border.bActive]), 0, 0, 1);
//add by 曾念荣 2006.5.23
//画滑块边框
rcFill.y = rc.y;
rcFill.dy = 1;
rcFill.x = rc.x+1;
rcFill.dx = rc.dx - 2;
IDISPLAY_DrawRect(piDisplay, &rcFill, RGB_NONE, RGBA_STRIPALPHA(psb->rgbHandle[psb->border.bActive]), IDF_RECT_FILL);//上边线
rcFill.y = rc.y + rc.dy-1;
IDISPLAY_DrawRect(piDisplay, &rcFill, RGB_NONE, RGBA_STRIPALPHA(psb->rgbHandle[psb->border.bActive]), IDF_RECT_FILL);//下边线
rcFill.x = rc.x;
rcFill.y = rc.y +1;
rcFill.dx = 1;
rcFill.dy = rc.dy -2;
IDISPLAY_DrawRect(piDisplay, &rcFill, RGB_NONE, RGBA_STRIPALPHA(psb->rgbHandle[psb->border.bActive]), IDF_RECT_FILL);//左边线
rcFill.x = rc.x + rc.dx-1;
IDISPLAY_DrawRect(piDisplay, &rcFill, RGB_NONE, RGBA_STRIPALPHA(psb->rgbHandle[psb->border.bActive]), IDF_RECT_FILL);//右边线
//end add
}
}
}
//不需要支持横向的滚动条。
/* if (psb->nScrollStyle == SCROLL_HORZ || psb->nScrollStyle == SCROLL_BOTH) {
ScrollbarWidget_GetScrollbarRect(psb, 1, &rc);
if (rc.dx && rc.dy) {
ScrollInfo *psi = &psb->scroll[SCROLL_HORZ];
// Get scrollbar rect
// inset by drawing location
rc.x += x;
rc.y += y;
if (psb->dwFlags & SBWF_ARROWS) {
SbArrows_DrawHorzArrows(&psb->arrows, piDisplay, &rc, rgbBorder, rgbBorder, 1,
psb->nEndPad);
} else {
INFLATERECT(& rc, -psb->nEndPad, 0);
}
if (rgbBorder != RGBA_NONE) {
DrawAndInsetBorder(piDisplay, &rc, SBBORDER_WIDTH, rgbBorder);
}
IDISPLAY_DrawRect(piDisplay, &rc, RGB_NONE, RGBA_STRIPALPHA(psb->rgbFill), IDF_RECT_FILL);
if (psi->range > psi->visible) {
int dxMin = MIN(4, rc.dx);
if((psb->dwFlags & SBWF_FOCUSTRACK) && psb->numItems > 0) {
rc.x += (rc.dx * psb->focusIndex) / psb->numItems;
rc.dx = rc.dx / psb->numItems;
}
else {
rc.x += YLScrollbarWidget_ComputePosition(rc.dx, psi->position, psi->range, psi->visible);
rc.dx = YLScrollbarWidget_ComputeSize(rc.dx, psi->range, psi->visible);
}
rc.dx = MAX(dxMin, rc.dx);
IDISPLAY_DrawRect(piDisplay, &rc, RGB_NONE, RGBA_STRIPALPHA(psb->rgbHandle[psb->border.bActive]), IDF_RECT_FILL);
}
}
}
*/
RELEASEIF(piDisplay);
Decorator_Draw(po, piCanvas, psb->border.rcClient.x + x, psb->border.rcClient.y + y);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -