您的位置:首页 > 产品设计 > UI/UE

MINIGUI源码分析(1) ------ 滚动条管理分析

2011-08-29 10:55 363 查看
http://xuyacao.bokee.com/3753615.html

http://blog.chinaunix.net/space.php?uid=9563036&do=blog&id=352405

//水平滚动条消息处理

static BOOL wndHandleHScrollBar (PMAINWIN pWin, int message, int x, int y)

{

static int downPos = SBPOS_UNKNOWN;

static int movePos = SBPOS_UNKNOWN;

static int sbCode;

static int oldBarStart;

static int oldThumbPos;

static int oldx;

int curPos;

RECT rcBar;

//获取水平滚动条矩形区域.

wndGetHScrollBarRect (pWin, &rcBar);

//计算滚动条除左右按钮后的矩形区域.

rcBar.left += GetMainWinMetrics (MWM_CXHSCROLL);

rcBar.right -= GetMainWinMetrics (MWM_CXHSCROLL);

//计算顶点对应的滚动条逻辑位置.

curPos = wndGetHScrollBarPos (pWin, x, y);

//若在滚动条区域外,则返回.

if (curPos == SBPOS_UNKNOWN && downPos == SBPOS_UNKNOWN)

{

return FALSE;

}

switch( message )

{

//若为鼠标左键按下。

case MSG_NCLBUTTONDOWN:

//记录开始位置

oldBarStart = pWin->hscroll.barStart;

oldThumbPos = pWin->hscroll.curPos;

oldx = x;

//保存当前位置。

downPos = curPos;

movePos = curPos;

//左按钮,向左翻页。

if (curPos == SBPOS_LEFTARROW)

{

sbDownButton (pWin, curPos);

if (pWin->hscroll.curPos == pWin->hscroll.minPos)

break;

sbCode = SB_LINELEFT;

}

//右按钮,向右翻页。

else if (curPos == SBPOS_RIGHTARROW)

{

sbDownButton (pWin, curPos);

if (pWin->hscroll.curPos == pWin->hscroll.maxPos)

break;

sbCode = SB_LINERIGHT;

}

//点击在滑块左边,向左滚动一单位。

else if (curPos == SBPOS_LEFTSPACE)

{

if (pWin->hscroll.curPos == pWin->hscroll.minPos)

break;

sbCode = SB_PAGELEFT;

}

//点击在滑块右边,向左滚动一单位。

else if (curPos == SBPOS_RIGHTSPACE)

{

if (pWin->hscroll.curPos == pWin->hscroll.maxPos)

break;

sbCode = SB_PAGERIGHT;

}

//拖动滑块.

else if (curPos == SBPOS_THUMB)

{

sbCode = SB_THUMBTRACK;

break;

}

//处理消息

SendNotifyMessage ((HWND)pWin, MSG_HSCROLL, sbCode, 0);

/*

设置默认自动回复消息,即按下按钮,按下滚动条除滑块以外的区域不动时,

会自动产生此消息.即当用户按住滚动条按钮不动时,将不停的发送翻页消息,

直到翻页到最边界的情况。

*/

SetAutoRepeatMessage ((HWND)pWin, MSG_HSCROLL, sbCode, 0);

break;

/*

若为左键松开

*/

case MSG_NCLBUTTONUP:

/*

若开始为拖动滑块。

*/

if (sbCode == SB_THUMBTRACK && downPos == SBPOS_THUMB)

{

/*

计算滑块被拖动的距离(象素为单位)

*/

int newBarStart = oldBarStart + x - oldx;

/*

根据滑块被拖动的距离计算滑块被拖动的逻辑滚动距离,然后当前滑块对应的逻辑位置。

*/

int newThumbPos = newBarStart

* (pWin->hscroll.maxPos - pWin->hscroll.minPos + 1)

/ (rcBar.right - rcBar.left) + pWin->hscroll.minPos;

/*

若计算出来的逻辑位置合法,则更新滚动条,发送拖动滑块完成消息(SB_THUMBPOSITION)。

*/

if (newThumbPos != oldThumbPos

&& newThumbPos >= pWin->hscroll.minPos

&& newThumbPos <= pWin->hscroll.maxPos)

SendNotifyMessage ((HWND)pWin,

MSG_HSCROLL, SB_THUMBPOSITION, newThumbPos);

/*

此时用户对滚动条的操作已经完成,清空上一次保存的位置信息,

确保下一次的滚动条操作开始时的参数正确。

*/

downPos = SBPOS_UNKNOWN;

movePos = SBPOS_UNKNOWN;

break;

}

/*

若为翻页,滚动信息,则处理消息.生成滚动条操作完成消息,取消自动恢复消息。

更新按钮显示状态。

*/

if (downPos != SBPOS_UNKNOWN)

{

sbUpButton (pWin, curPos);

SendNotifyMessage ((HWND)pWin, MSG_HSCROLL, SB_ENDSCROLL, 0);

SetAutoRepeatMessage (HWND_DESKTOP, 0, 0, 0);

}

downPos = SBPOS_UNKNOWN;

movePos = SBPOS_UNKNOWN;

break;

/*

若为鼠标移动信息

*/

case MSG_NCMOUSEMOVE:

/*

若用户曾按下滑块。则转换为拖动滑块消息.

*/

if (sbCode == SB_THUMBTRACK && downPos == SBPOS_THUMB)

{

/*

计算滑块拖动的距离(象素)

*/

int newBarStart = oldBarStart + x - oldx;

/*

根据前面计算的滑块拖动距离,计算滑块拖动的逻辑滚动距离,然后当前滑块对应的逻辑位置。

*/

int newThumbPos = newBarStart

* (pWin->hscroll.maxPos - pWin->hscroll.minPos + 1)

/ (rcBar.right - rcBar.left) + pWin->hscroll.minPos;

/*

若计算出来的逻辑位置合法,则更新滚动条,发送拖动滑块消息(SB_THUMBTRACK)。

*/

if (newThumbPos != oldThumbPos

&& newThumbPos >= pWin->hscroll.minPos

&& newThumbPos <= pWin->hscroll.maxPos)

{

SendNotifyMessage ((HWND)pWin,

MSG_HSCROLL, SB_THUMBTRACK, newThumbPos);

/*

更新上次拖动位置。

*/

oldThumbPos = newThumbPos;

}

movePos = curPos;

break;

}

//更新按钮显示状态。

if (movePos == downPos && curPos != downPos)

{

sbUpButton (pWin, downPos);

}

else if (movePos != downPos && curPos == downPos)

{

sbDownButton (pWin, downPos);

}

movePos = curPos;

break;

}

return TRUE;

}

//处理垂直滚动条事件,与水平滚动条处理方式一致.

static BOOL wndHandleVScrollBar (PMAINWIN pWin, int message, int x, int y)

{

static int downPos = SBPOS_UNKNOWN;

static int movePos = SBPOS_UNKNOWN;

static int sbCode;

static int oldBarStart;

static int oldThumbPos;

static int oldy;

int curPos;

RECT rcBar;

int newBarStart;

int newThumbPos;

wndGetVScrollBarRect (pWin, &rcBar);

rcBar.top += GetMainWinMetrics (MWM_CYVSCROLL);

rcBar.bottom -= GetMainWinMetrics (MWM_CYVSCROLL);

curPos = wndGetVScrollBarPos (pWin, x, y);

if (curPos == SBPOS_UNKNOWN && downPos == SBPOS_UNKNOWN)

return FALSE;

switch (message)

{

case MSG_NCLBUTTONDOWN:

oldBarStart = pWin->vscroll.barStart;

oldThumbPos = pWin->vscroll.curPos;

oldy = y;

downPos = curPos;

movePos = curPos;

if (curPos == SBPOS_UPARROW) {

sbDownButton (pWin, curPos);

if (pWin->vscroll.curPos == pWin->vscroll.minPos)

break;

sbCode = SB_LINEUP;

}

else if (curPos == SBPOS_DOWNARROW) {

sbDownButton (pWin, curPos);

if (pWin->vscroll.curPos == pWin->vscroll.maxPos)

break;

sbCode = SB_LINEDOWN;

}

else if (curPos == SBPOS_UPSPACE) {

if (pWin->vscroll.curPos == pWin->vscroll.minPos)

break;

sbCode = SB_PAGEUP;

}

else if (curPos == SBPOS_DOWNSPACE) {

if (pWin->vscroll.curPos == pWin->vscroll.maxPos)

break;

sbCode = SB_PAGEDOWN;

}

else if (curPos == SBPOS_THUMB) {

sbCode = SB_THUMBTRACK;

break;

}

SendNotifyMessage ((HWND)pWin, MSG_VSCROLL, sbCode, 0);

SetAutoRepeatMessage ((HWND)pWin, MSG_VSCROLL, sbCode, 0);

break;

case MSG_NCLBUTTONUP:

if (sbCode == SB_THUMBTRACK && downPos == SBPOS_THUMB) {

newBarStart = oldBarStart + y - oldy;

newThumbPos = newBarStart

* (pWin->vscroll.maxPos - pWin->vscroll.minPos + 1)

/ (rcBar.bottom - rcBar.top) + pWin->vscroll.minPos;

if (newThumbPos != oldThumbPos

&& newThumbPos >= pWin->vscroll.minPos

&& newThumbPos <= pWin->vscroll.maxPos)

SendNotifyMessage ((HWND)pWin,

MSG_VSCROLL, SB_THUMBPOSITION, newThumbPos);

downPos = SBPOS_UNKNOWN;

movePos = SBPOS_UNKNOWN;

break;

}

if (downPos != SBPOS_UNKNOWN) {

sbUpButton (pWin, curPos);

SendNotifyMessage ((HWND)pWin, MSG_VSCROLL, SB_ENDSCROLL, 0);

SetAutoRepeatMessage (HWND_DESKTOP, 0, 0, 0);

}

downPos = SBPOS_UNKNOWN;

movePos = SBPOS_UNKNOWN;

break;

case MSG_NCMOUSEMOVE:

if (sbCode == SB_THUMBTRACK && downPos == SBPOS_THUMB) {

newBarStart = oldBarStart + y - oldy;

newThumbPos = newBarStart

* (pWin->vscroll.maxPos - pWin->vscroll.minPos + 1)

/ (rcBar.bottom - rcBar.top) + pWin->vscroll.minPos;

if (newThumbPos != oldThumbPos

&& newThumbPos >= pWin->vscroll.minPos

&& newThumbPos <= pWin->vscroll.maxPos) {

SendNotifyMessage ((HWND)pWin,

MSG_VSCROLL, SB_THUMBTRACK, newThumbPos);

oldThumbPos = newThumbPos;

}

movePos = curPos;

break;

}

if (movePos == downPos && curPos != downPos)

sbUpButton (pWin, downPos);

else if (movePos != downPos && curPos == downPos)

sbDownButton (pWin, downPos);

movePos = curPos;

break;

}

return TRUE;

}

//计算滚动条滑块大小和位置。

static void wndScrollBarPos (PMAINWIN pWin, BOOL bIsHBar, RECT* rcBar)

{

UINT moveRange;

PSCROLLBARINFO pSBar;

if (bIsHBar)

{

pSBar = &pWin->hscroll;

}

else

{

pSBar = &pWin->vscroll;

}

//若滚动区间为空,则隐藏滚动条.

if (pSBar->minPos == pSBar->maxPos)

{

pSBar->status |= SBS_HIDE;

return;

}

//计算滚动条可用区域(即滚动滑块可以滑动的区间象素个数)

if (bIsHBar)

{

moveRange = RECTWP (rcBar) - (GetMainWinMetrics (MWM_CXHSCROLL)<<1);

}

else

{

moveRange = RECTHP (rcBar) - (GetMainWinMetrics (MWM_CYVSCROLL)<<1);

}

//若页面间隔为0,则取默认滚动滑块长度为当前滑块长度,并进行合法性修正.

if (pSBar->pageStep == 0)

{

pSBar->barLen = GetMainWinMetrics (MWM_DEFBARLEN);

if (pSBar->barLen > moveRange)

{

pSBar->barLen = GetMainWinMetrics (MWM_MINBARLEN);

}

}

/*

否则,计算滚动滑块大小.并对合法性进行修正.

计算方程: 每滚动间隔对应象素大小为 moveRange / ScrollRange ;

pageStep:每页大小即控件能显示的区域,所对应的滚动条滚动间隔数.

ScrollRange - PageStep, 就是滚动条的逻辑活动的范围.

对应于 moveRange - barLen 就是滚动条能滚定的象素范围.即一一对应关系.

那么滚动条滑块的长度就是 PageStep 对应的象素大小.

-> pSBar->barLen = moveRange * PageStep / ScrollRange ;

ScrollRange = pSBar->maxPos - pSBar->minPos ;

(滚动范围以0为开始, 如 0 - 99 表示 100 个滚动范围)

(若以 1 开始, 则出错 因为 1 - 99 才99 个滚动范围).

"+ 0.5" 是四舍五入的方法。便于取整.

*/

else

{

pSBar->barLen = (int) (moveRange*pSBar->pageStep * 1.0f/

(pSBar->maxPos - pSBar->minPos + 1) + 0.5);

/*

修正合法值.

*/

if (pSBar->barLen < GetMainWinMetrics (MWM_MINBARLEN))

{

pSBar->barLen = GetMainWinMetrics (MWM_MINBARLEN);

}

}

/*

计算滚动滑块开始位置.

计算方程: BarStart = PixelPerScrollGap * CurScrollRange ;

= moveRange * CurScrollRange / ScrollRange ;

即开始位置为每逻辑滚动间隔对应象素大小*当前逻辑滚动间隔 ;

ScrollRange = pSBar->maxPos - pSBar->minPos ;

(滚动范围以0为开始, 如 0 - 99 表示 100 个滚动范围)

(若以 1 开始, 则出错 因为 1 - 99 才99 个滚动范围).

"+ 0.5" 是四舍五入的方法。便于取整.

*/

pSBar->barStart = (int) (moveRange*(pSBar->curPos - pSBar->minPos) * 1.0f/

(pSBar->maxPos - pSBar->minPos + 1) + 0.5);

/*

修正非法值。

*/

if (pSBar->barStart + pSBar->barLen > moveRange)

{

pSBar->barStart = moveRange - pSBar->barLen;

}

if (pSBar->barStart < 0)

{

pSBar->barStart = 0;

}

}

//计算垂直滚动条矩形区域.

static BOOL wndGetVScrollBarRect (const MAINWIN* pWin,

RECT* rcVBar)

{

if (pWin->dwStyle & WS_VSCROLL)

{

//取边界宽度

int iBorder = wndGetBorder (pWin);

//计算滚动条左边和右边

rcVBar->left = pWin->right - GetMainWinMetrics (MWM_CXVSCROLL) - iBorder;

rcVBar->right = pWin->right - iBorder;

//计算矩形顶点和底边

#ifdef _FLAT_WINDOW_STYLE

rcVBar->top = pWin->ct - 1;

#else

rcVBar->top = pWin->ct;

#endif

rcVBar->bottom = pWin->bottom - iBorder;

//若存在水平滚动条,则减去水平滚动条高度

if (pWin->dwStyle & WS_HSCROLL && !(pWin->hscroll.status & SBS_HIDE))

{

rcVBar->bottom -= GetMainWinMetrics (MWM_CYHSCROLL);

}

#ifdef _FLAT_WINDOW_STYLE

if (iBorder > 0)

OffsetRect (rcVBar, 1, 0);

#endif

return TRUE;

}

return FALSE;

}

//计算水平滚动条矩形区域.与垂直情况相似

static BOOL wndGetHScrollBarRect (const MAINWIN* pWin,

RECT* rcHBar)

{

if (pWin->dwStyle & WS_HSCROLL) {

int iBorder = wndGetBorder (pWin);

rcHBar->top = pWin->bottom - GetMainWinMetrics (MWM_CYHSCROLL)

- iBorder;

rcHBar->bottom = pWin->bottom - iBorder;

#ifdef _FLAT_WINDOW_STYLE

rcHBar->left = pWin->cl - 1;

#else

rcHBar->left = pWin->cl;

#endif

rcHBar->right = pWin->right - iBorder;

if (pWin->dwStyle & WS_VSCROLL && !(pWin->vscroll.status & SBS_HIDE))

rcHBar->right -= GetMainWinMetrics (MWM_CXVSCROLL);

#ifdef _FLAT_WINDOW_STYLE

if (iBorder > 0)

OffsetRect (rcHBar, 0, 1);

#endif

return TRUE;

}

return FALSE;

}

//计算点击垂直滚动条上逻辑位置分类.

static int wndGetVScrollBarPos (PMAINWIN pWin, int x, int y)

{

RECT rcBar;

RECT rcArea;

if (pWin->vscroll.status & SBS_DISABLED)

{

return SBPOS_UNKNOWN;

}

//获取垂直滚动条矩形区域.

wndGetVScrollBarRect (pWin, &rcBar);

//若点不再矩形区域内,则返回空.

if (!PtInRect (&rcBar, x, y))

{

return SBPOS_UNKNOWN;

}

rcArea.left = rcBar.left;

rcArea.right = rcBar.right;

//是否为顶部的按钮.

// Left arrow area

rcArea.top = rcBar.top;

rcArea.bottom = rcArea.top + GetMainWinMetrics (MWM_CYVSCROLL);

if (PtInRect (&rcArea, x, y))

{

return SBPOS_UPARROW;

}

//是否为底部的按钮.

// Right arrow area

rcArea.top = rcBar.bottom - GetMainWinMetrics (MWM_CYVSCROLL);

rcArea.bottom = rcBar.bottom;

if (PtInRect (&rcArea, x, y))

{

return SBPOS_DOWNARROW;

}

//是否在滑块上边

if (y < (rcBar.top + pWin->vscroll.barStart

+ GetMainWinMetrics (MWM_CYVSCROLL)))

return SBPOS_UPSPACE;

//是否为滑块下边

if (y > (rcBar.top + pWin->vscroll.barStart + pWin->vscroll.barLen

+ GetMainWinMetrics (MWM_CYVSCROLL)))

return SBPOS_DOWNSPACE;

//在滑块上

return SBPOS_THUMB;

}

//计算点击水平滚动条上逻辑位置分类.与垂直情况类似。

static int wndGetHScrollBarPos (PMAINWIN pWin, int x, int y)

{

RECT rcBar;

RECT rcArea;

if (pWin->hscroll.status & SBS_DISABLED)

return SBPOS_UNKNOWN;

wndGetHScrollBarRect (pWin, &rcBar);

if (!PtInRect (&rcBar, x, y))

return SBPOS_UNKNOWN;

rcArea.top = rcBar.top;

rcArea.bottom = rcBar.bottom;

// Left arrow area

rcArea.left = rcBar.left;

rcArea.right = rcArea.left + GetMainWinMetrics (MWM_CXHSCROLL);

if (PtInRect (&rcArea, x, y))

return SBPOS_LEFTARROW;

// Right arrow area

rcArea.left = rcBar.right - GetMainWinMetrics (MWM_CXHSCROLL);

rcArea.right = rcBar.right;

if (PtInRect (&rcArea, x, y))

return SBPOS_RIGHTARROW;

if (x < (rcBar.left + pWin->hscroll.barStart

+ GetMainWinMetrics (MWM_CXHSCROLL)))

return SBPOS_LEFTSPACE;

if (x > (rcBar.left + pWin->hscroll.barStart + pWin->hscroll.barLen

+ GetMainWinMetrics (MWM_CXHSCROLL)))

return SBPOS_RIGHTSPACE;

return SBPOS_THUMB;

}

//获取滚动条信息结构

static PSCROLLBARINFO wndGetScrollBar (MAINWIN* pWin, int iSBar)

{

//水平

if (iSBar == SB_HORZ)

{

if (pWin->dwStyle & WS_HSCROLL)

{

return &pWin->hscroll;

}

}

//垂直

else if (iSBar == SB_VERT)

{

if (pWin->dwStyle & WS_VSCROLL)

{

return &pWin->vscroll;

}

}

return NULL;

}

//设置滚动条是否可用,与设置滚动条是否可见的逻辑相似

BOOL GUIAPI EnableScrollBar (HWND hWnd, int iSBar, BOOL bEnable)

{

PSCROLLBARINFO pSBar;

PMAINWIN pWin;

BOOL bPrevState;

RECT rcBar;

pWin = (PMAINWIN)hWnd;

if ( !(pSBar = wndGetScrollBar (pWin, iSBar)) )

{

return FALSE;

}

bPrevState = !(pSBar->status & SBS_DISABLED);

if (bEnable && !bPrevState)

{

pSBar->status &= ~SBS_DISABLED;

}

else if (!bEnable && bPrevState)

{

pSBar->status |= SBS_DISABLED;

}

else

{

return FALSE;

}

if (iSBar == SB_VERT)

{

wndGetVScrollBarRect (pWin, &rcBar);

}

else

{

wndGetHScrollBarRect (pWin, &rcBar);

}

rcBar.left -= pWin->left;

rcBar.top -= pWin->top;

rcBar.right -= pWin->left;

rcBar.bottom -= pWin->top;

SendAsyncMessage (hWnd, MSG_NCPAINT, 0, (LPARAM)(&rcBar));

return TRUE;

}

//获取滚动条逻辑滚动位置

BOOL GUIAPI GetScrollPos (HWND hWnd, int iSBar, int* pPos)

{

PSCROLLBARINFO pSBar;

PMAINWIN pWin;

pWin = (PMAINWIN)hWnd;

if ( !(pSBar = wndGetScrollBar (pWin, iSBar)) )

{

return FALSE;

}

*pPos = pSBar->curPos;

return TRUE;

}

//获取滚动条逻辑滚动范围。

BOOL GUIAPI GetScrollRange (HWND hWnd, int iSBar, int* pMinPos, int* pMaxPos)

{

PSCROLLBARINFO pSBar;

PMAINWIN pWin;

pWin = (PMAINWIN)hWnd;

if ( !(pSBar = wndGetScrollBar (pWin, iSBar)) )

{

return FALSE;

}

*pMinPos = pSBar->minPos;

*pMaxPos = pSBar->maxPos;

return TRUE;

}

//设置滚动条当前逻辑滚动位置,与设置滚动条滚动信息类似

BOOL GUIAPI SetScrollPos (HWND hWnd, int iSBar, int iNewPos)

{

PSCROLLBARINFO pSBar;

PMAINWIN pWin;

RECT rcBar;

pWin = (PMAINWIN)hWnd;

if ( !(pSBar = wndGetScrollBar (pWin, iSBar)) )

{

return FALSE;

}

if (iNewPos < pSBar->minPos)

{

pSBar->curPos = pSBar->minPos;

}

else

{

pSBar->curPos = iNewPos;

}

if(1)

{

int max = pSBar->maxPos;

max -= ((pSBar->pageStep - 1) > 0)?(pSBar->pageStep - 1):0;

if (pSBar->curPos > max)

pSBar->curPos = max;

}

if (iSBar == SB_VERT)

{

wndGetVScrollBarRect (pWin, &rcBar);

}

else

{

wndGetHScrollBarRect (pWin, &rcBar);

}

rcBar.left -= pWin->left;

rcBar.top -= pWin->top;

rcBar.right -= pWin->left;

rcBar.bottom -= pWin->top;

wndScrollBarPos (pWin, iSBar == SB_HORZ, &rcBar);

if (iSBar == SB_VERT)

{

rcBar.top += GetMainWinMetrics (MWM_CYVSCROLL);

rcBar.bottom -= GetMainWinMetrics (MWM_CYVSCROLL);

}

else

{

rcBar.left += GetMainWinMetrics (MWM_CXHSCROLL);

rcBar.right -= GetMainWinMetrics (MWM_CXHSCROLL);

}

SendAsyncMessage (hWnd, MSG_NCPAINT, 0, (LPARAM)(&rcBar));

return TRUE;

}

/*

设置滚动条逻辑滚动范围,与设置滚动条滚动信息类似

*/

BOOL GUIAPI SetScrollRange (HWND hWnd, int iSBar, int iMinPos, int iMaxPos)

{

PSCROLLBARINFO pSBar;

PMAINWIN pWin;

RECT rcBar;

pWin = (PMAINWIN)hWnd;

if ( !(pSBar = wndGetScrollBar (pWin, iSBar)) )

{

return FALSE;

}

pSBar->minPos = (iMinPos < iMaxPos)?iMinPos:iMaxPos;

pSBar->maxPos = (iMinPos > iMaxPos)?iMinPos:iMaxPos;

// validate parameters.

if (pSBar->curPos < pSBar->minPos)

{

pSBar->curPos = pSBar->minPos;

}

if (pSBar->pageStep <= 0)

{

pSBar->pageStep = 0;

}

else if (pSBar->pageStep > (pSBar->maxPos - pSBar->minPos + 1))

{

pSBar->pageStep = pSBar->maxPos - pSBar->minPos + 1;

}

if(1)

{

int max = pSBar->maxPos;

max -= ((pSBar->pageStep - 1) > 0)?(pSBar->pageStep - 1):0;

if (pSBar->curPos > max)

{

pSBar->curPos = max;

}

}

if (iSBar == SB_VERT)

{

wndGetVScrollBarRect (pWin, &rcBar);

}

else

{

wndGetHScrollBarRect (pWin, &rcBar);

}

rcBar.left -= pWin->left;

rcBar.top -= pWin->top;

rcBar.right -= pWin->left;

rcBar.bottom -= pWin->top;

wndScrollBarPos (pWin, iSBar == SB_HORZ, &rcBar);

if (iSBar == SB_VERT)

{

rcBar.top += GetMainWinMetrics (MWM_CYVSCROLL);

rcBar.bottom -= GetMainWinMetrics (MWM_CYVSCROLL);

}

else

{

rcBar.left += GetMainWinMetrics (MWM_CXHSCROLL);

rcBar.right -= GetMainWinMetrics (MWM_CXHSCROLL);

}

SendAsyncMessage (hWnd, MSG_NCPAINT, 0, (LPARAM)(&rcBar));

return TRUE;

}

//设置滚动条信息

BOOL GUIAPI SetScrollInfo (HWND hWnd, int iSBar,

const SCROLLINFO* lpsi, BOOL fRedraw)

{

PSCROLLBARINFO pSBar;

PMAINWIN pWin;

RECT rcBar;

pWin = (PMAINWIN)hWnd;

//找到滚动条信息。

if ( !(pSBar = wndGetScrollBar (pWin, iSBar)) )

{

return FALSE;

}

//设置滚定区间大小

if( lpsi->fMask & SIF_RANGE )

{

pSBar->minPos = (lpsi->nMin < lpsi->nMax)?lpsi->nMin:lpsi->nMax;

pSBar->maxPos = (lpsi->nMin < lpsi->nMax)?lpsi->nMax:lpsi->nMin;

}

//设置滚动位置

if( lpsi->fMask & SIF_POS )

{

pSBar->curPos = lpsi->nPos;

}

//设置滚动页面大小.

if( lpsi->fMask & SIF_PAGE )

{

pSBar->pageStep = lpsi->nPage;

}

//矫正非法数据.

// validate parameters.

if (pSBar->curPos < pSBar->minPos)

{

pSBar->curPos = pSBar->minPos;

}

//计算页面大小.

if (pSBar->pageStep <= 0)

{

pSBar->pageStep = 0;

}

else if (pSBar->pageStep > (pSBar->maxPos - pSBar->minPos + 1))

{

pSBar->pageStep = pSBar->maxPos - pSBar->minPos + 1;

}

/*

重新计算滚动滑块的逻辑位置. 若PageSize增大, 则滑块可滚动的逻辑区域会变小,

所以需要修正滑块的当前逻辑位置.

*/

if(1)

{

int max = pSBar->maxPos;

/*

滑块的可滚动区域。

*/

max -= ((pSBar->pageStep - 1) > 0)?(pSBar->pageStep - 1):0;

if (pSBar->curPos > max)

{

pSBar->curPos = max;

}

}

//重绘滚动条

if(fRedraw)

{

//获取滚动条矩形区域(相对于窗口原点坐标)

if (iSBar == SB_VERT)

{

wndGetVScrollBarRect (pWin, &rcBar);

}

else

{

wndGetHScrollBarRect (pWin, &rcBar);

}

rcBar.left -= pWin->left;

rcBar.top -= pWin->top;

rcBar.right -= pWin->left;

rcBar.bottom -= pWin->top;

//计算滚动条滑块大小和位置.

wndScrollBarPos (pWin, iSBar == SB_HORZ, &rcBar);

//重绘滚动条.

if (iSBar == SB_VERT)

{

rcBar.top += GetMainWinMetrics (MWM_CYVSCROLL);

rcBar.bottom -= GetMainWinMetrics (MWM_CYVSCROLL);

}

else

{

rcBar.left += GetMainWinMetrics (MWM_CXHSCROLL);

rcBar.right -= GetMainWinMetrics (MWM_CXHSCROLL);

}

SendAsyncMessage (hWnd, MSG_NCPAINT, 0, (LPARAM)(&rcBar));

}

return TRUE;

}

// 获取滚动条信息.

BOOL GUIAPI GetScrollInfo(HWND hWnd, int iSBar, PSCROLLINFO lpsi)

{

PSCROLLBARINFO pSBar;

PMAINWIN pWin;

pWin = (PMAINWIN)hWnd;

//找到滚动条

if (!(pSBar = wndGetScrollBar (pWin, iSBar)))

{

return FALSE;

}

//逻辑滚动区间大小

if (lpsi->fMask & SIF_RANGE)

{

lpsi->nMin = pSBar->minPos;

lpsi->nMax = pSBar->maxPos;

}

//当前滑块逻辑位置

if (lpsi->fMask & SIF_POS)

{

lpsi->nPos = pSBar->curPos;

}

//滚动页大小,即窗口显示内容所占的逻辑滚动数.

if (lpsi->fMask & SIF_PAGE)

{

lpsi->nPage = pSBar->pageStep;

}

return TRUE;

}

//显示滚动条.

BOOL GUIAPI ShowScrollBar (HWND hWnd, int iSBar, BOOL bShow)

{

PSCROLLBARINFO pSBar;

PMAINWIN pWin;

BOOL bPrevState;

RECT rcBar;

pWin = (PMAINWIN)hWnd;

//获取滚动条信息。

if ( !(pSBar = wndGetScrollBar (pWin, iSBar)) )

{

return FALSE;

}

//前一状态是否为显示状态.(包括disbale,mormal);

bPrevState = !(pSBar->status & SBS_HIDE);

//若前一状态为隐藏,且当前命令为显示命令.则修改当前状态为非隐藏状态.

if (bShow && !bPrevState)

{

pSBar->status &= ~SBS_HIDE;

}

//若前一状态为显示状态,且当前命令为隐藏命令,则隐藏.

else if (!bShow && bPrevState)

{

pSBar->status |= SBS_HIDE;

}

//否则,前一状态与命令状态相同,直接返回.(FALSE???返回失败)

else

{

return FALSE;

}

//重新计算非客户区.

SendAsyncMessage (hWnd, MSG_CHANGESIZE, 0, 0);

//获取滚动条位置.

if (iSBar == SB_VERT)

{

wndGetVScrollBarRect (pWin, &rcBar);

}

else

{

wndGetHScrollBarRect (pWin, &rcBar);

}

//扩大2象素(left--,top--,right++,bottom++)

InflateRect (&rcBar, 1, 1);

//重新计算客户区.

RecalcClientArea (hWnd);

//非客户区重绘.

if (bShow)

{

//若为显示滚动条,则直接发送重绘消息.此时没有重绘客户区.

SendAsyncMessage (hWnd, MSG_NCPAINT, 0, 0);

}

else

{

//若隐藏滚动条,则重绘非客户区,并重绘客户区(滚动条相对对于客户区坐标原点的矩形区域).

rcBar.left -= pWin->cl;

rcBar.top -= pWin->ct;

rcBar.right -= pWin->cl;

rcBar.bottom -= pWin->ct;

SendAsyncMessage (hWnd, MSG_NCPAINT, 0, 0);

InvalidateRect (hWnd, &rcBar, TRUE);

}

return TRUE;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: