📄 scroll.c
字号:
//make sure there is room for the buttons
vbarheight = rect.bottom - rect.top;
//check that we can fit any left/right buttons in the available space
if(sb->nButSizeAfter < (vbarheight - MIN_COOLSB_SIZE))
{
//adjust the scrollbar rectangle to fit the buttons into
sb->fButVisibleAfter = TRUE;
rect.bottom -= sb->nButSizeAfter;
updown |= SBBP_BOTTOM;
//check that there is enough space for the right buttons
if(sb->nButSizeBefore + sb->nButSizeAfter < (vbarheight - MIN_COOLSB_SIZE))
{
sb->fButVisibleBefore = TRUE;
rect.top += sb->nButSizeBefore;
updown |= SBBP_TOP;
}
else
sb->fButVisibleBefore = FALSE;
}
else
sb->fButVisibleAfter = FALSE;
DrawVertButtons(sb, hdc, &rect, updown);
#endif // INCLUDE_BUTTONS
if(uCurrentScrollbar == SB_VERT)
fCustomDraw |= NCDrawVScrollbar(sb, hwnd, hdc, &rect, uScrollTimerPortion);
else
fCustomDraw |= NCDrawVScrollbar(sb, hwnd, hdc, &rect, HTSCROLL_NONE);
}
//Call the default window procedure for WM_NCPAINT, with the
//new window region. ** region must be in SCREEN coordinates **
dwStyle = GetWindowLong(hwnd, GWL_STYLE);
// If the window has WS_(H-V)SCROLL bits set, we should reset them
// to avoid windows taking the scrollbars into account.
// We temporarily set a flag preventing the subsecuent
// WM_STYLECHANGING/WM_STYLECHANGED to be forwarded to
// the original window procedure
if ( dwStyle & (WS_VSCROLL|WS_HSCROLL) )
{
sw->bPreventStyleChange = TRUE;
SetWindowLong(hwnd, GWL_STYLE, dwStyle & ~(WS_VSCROLL|WS_HSCROLL));
}
ret = CallWindowProc(sw->oldproc, hwnd, WM_NCPAINT, (WPARAM)hrgn, lParam);
if ( dwStyle & (WS_VSCROLL|WS_HSCROLL) )
{
SetWindowLong(hwnd, GWL_STYLE, dwStyle);
sw->bPreventStyleChange = FALSE;
}
// DRAW THE DEAD AREA
// only do this if the horizontal and vertical bars are visible
if(sw->sbarHorz.fScrollVisible && sw->sbarVert.fScrollVisible)
{
GetWindowRect(hwnd, &rect);
OffsetRect(&rect, -winrect.left, -winrect.top);
rect.bottom -= sw->cyBottomEdge;
rect.top = rect.bottom - GetScrollMetric(&sw->sbarHorz, SM_CYHORZSB);
if(sw->fLeftScrollbar)
{
rect.left += sw->cxLeftEdge;
rect.right = rect.left + GetScrollMetric(&sw->sbarVert, SM_CXVERTSB);
}
else
{
rect.right -= sw->cxRightEdge;
rect.left = rect.right - GetScrollMetric(&sw->sbarVert, SM_CXVERTSB);
}
if(fCustomDraw)
PostCustomDrawNotify(hwnd, hdc, SB_BOTH, &rect, 32, 0, 0, 0);
else
{
//calculate the position of THIS window's dead area
//with the position of the PARENT window's client rectangle.
//if THIS window has been positioned such that its bottom-right
//corner sits in the parent's bottom-right corner, then we should
//show the sizing-grip.
//Otherwise, assume this window is not in the right place, and
//just draw a blank rectangle
RECT parent;
RECT rect2;
HWND hwndParent = GetParent(hwnd);
GetClientRect(hwndParent, &parent);
MapWindowPoints(hwndParent, 0, (POINT *)&parent, 2);
CopyRect(&rect2, &rect);
OffsetRect(&rect2, winrect.left, winrect.top);
if(!sw->fLeftScrollbar && parent.right == rect2.right+sw->cxRightEdge && parent.bottom == rect2.bottom+sw->cyBottomEdge
|| sw->fLeftScrollbar && parent.left == rect2.left -sw->cxLeftEdge && parent.bottom == rect2.bottom+sw->cyBottomEdge)
DrawFrameControl(hdc, &rect, DFC_SCROLL, sw->fLeftScrollbar ? DFCS_SCROLLSIZEGRIPRIGHT : DFCS_SCROLLSIZEGRIP );
else
PaintRect(hdc, &rect, GetSysColor(COLOR_3DFACE));
}
}
UNREFERENCED_PARAMETER(clip);
ReleaseDC(hwnd, hdc);
return ret;
}
//
// Need to detect if we have clicked in the scrollbar region or not
//
static LRESULT NCHitTest(SCROLLWND *sw, HWND hwnd, WPARAM wParam, LPARAM lParam)
{
RECT hrect;
RECT vrect;
POINT pt;
pt.x = LOWORD(lParam);
pt.y = HIWORD(lParam);
//work out exactly where the Horizontal and Vertical scrollbars are
GetHScrollRect(sw, hwnd, &hrect);
GetVScrollRect(sw, hwnd, &vrect);
//Clicked in the horizontal scrollbar area
if(sw->sbarHorz.fScrollVisible && PtInRect(&hrect, pt))
{
return HTHSCROLL;
}
//Clicked in the vertical scrollbar area
else if(sw->sbarVert.fScrollVisible && PtInRect(&vrect, pt))
{
return HTVSCROLL;
}
//clicked somewhere else
else
{
return CallWindowProc(sw->oldproc, hwnd, WM_NCHITTEST, wParam, lParam);
}
}
//
// Return a HT* value indicating what part of the scrollbar was clicked
// Rectangle is not adjusted
//
static UINT GetHorzPortion(SCROLLBAR *sb, HWND hwnd, RECT *rect, int x, int y)
{
RECT rc = *rect;
if(y < rc.top || y >= rc.bottom) return HTSCROLL_NONE;
#ifdef INCLUDE_BUTTONS
if(sb->fButVisibleBefore)
{
//clicked on the buttons to the left of the scrollbar
if(x >= rc.left && x < rc.left + sb->nButSizeBefore)
return HTSCROLL_INSERTED;
//adjust the rectangle to exclude the left-side buttons, now that we
//know we havn't clicked on them
rc.left += sb->nButSizeBefore;
}
if(sb->fButVisibleAfter)
{
//clicked on the buttons to the right of the scrollbar
if(x >= rc.right - sb->nButSizeAfter && x < rc.right)
return HTSCROLL_INSERTED;
//adjust the rectangle to exclude the right-side buttons, now that we
//know we havn't clicked on them
rc.right -= sb->nButSizeAfter;
}
#endif INCLUDE_BUTTONS
//Now we have the rectangle for the scrollbar itself, so work out
//what part we clicked on.
return GetHorzScrollPortion(sb, hwnd, &rc, x, y);
}
//
// Just call the horizontal version, with adjusted coordinates
//
static UINT GetVertPortion(SCROLLBAR *sb, HWND hwnd, RECT *rect, int x, int y)
{
UINT ret;
RotateRect(rect);
ret = GetHorzPortion(sb, hwnd, rect, y, x);
RotateRect(rect);
return ret;
}
//
// Wrapper function for GetHorzPortion and GetVertPortion
//
static UINT GetPortion(SCROLLBAR *sb, HWND hwnd, RECT *rect, int x, int y)
{
if(sb->nBarType == SB_HORZ)
return GetHorzPortion(sb, hwnd, rect, x, y);
else if(sb->nBarType == SB_VERT)
return GetVertPortion(sb, hwnd, rect, x, y);
else
return HTSCROLL_NONE;
}
//
// Input: rectangle of the total scrollbar area
// Output: adjusted to take the inserted buttons into account
//
static void GetRealHorzScrollRect(SCROLLBAR *sb, RECT *rect)
{
if(sb->fButVisibleBefore) rect->left += sb->nButSizeBefore;
if(sb->fButVisibleAfter) rect->right -= sb->nButSizeAfter;
}
//
// Input: rectangle of the total scrollbar area
// Output: adjusted to take the inserted buttons into account
//
static void GetRealVertScrollRect(SCROLLBAR *sb, RECT *rect)
{
if(sb->fButVisibleBefore) rect->top += sb->nButSizeBefore;
if(sb->fButVisibleAfter) rect->bottom -= sb->nButSizeAfter;
}
//
// Decide which type of scrollbar we have before calling
// the real function to do the job
//
static void GetRealScrollRect(SCROLLBAR *sb, RECT *rect)
{
if(sb->nBarType == SB_HORZ)
{
GetRealHorzScrollRect(sb, rect);
}
else if(sb->nBarType == SB_VERT)
{
GetRealVertScrollRect(sb, rect);
}
}
//
// All button code shoule be collected together
//
//
#ifdef INCLUDE_BUTTONS
//
// Return the index of the button covering the specified point
// rect - rectangle of the whole scrollbar area
// pt - screen coords of the mouse
// fReturnRect - do/don't modify the rect to return the button's area
//
static UINT GetHorzButtonFromPt(SCROLLBAR *sb, RECT *rect, POINT pt, BOOL fReturnRect)
{
int leftpos = rect->left, rightpos = rect->right;
int i;
int butwidth;
SCROLLBUT *sbut = sb->sbButtons;
if(!PtInRect(rect, pt))
return -1;
if(sb->fButVisibleAfter)
rightpos -= sb->nButSizeAfter;
for(i = 0; i < sb->nButtons; i++)
{
if(sb->fButVisibleBefore && sbut[i].uPlacement == SBBP_LEFT)
{
butwidth = GetSingleButSize(sb, &sbut[i]);
//if the current button is under the specified point
if(pt.x >= leftpos && pt.x < leftpos + butwidth)
{
//if the caller wants us to return the rectangle of the button
if(fReturnRect)
{
rect->left = leftpos;
rect->right = leftpos + butwidth;
}
return i;
}
leftpos += butwidth;
}
else if(sb->fButVisibleAfter && sbut[i].uPlacement == SBBP_RIGHT)
{
butwidth = GetSingleButSize(sb, &sbut[i]);
//if the current button is under the specified point
if(pt.x >= rightpos && pt.x < rightpos + butwidth)
{
//if the caller wants us to return the rectangle of the button
if(fReturnRect)
{
rect->left = rightpos;
rect->right = rightpos + butwidth;
}
return i;
}
rightpos += butwidth;
}
}
return -1;
}
static UINT GetVertButtonFromPt(SCROLLBAR *sb, RECT *rect, POINT pt, BOOL fReturnRect)
{
UINT ret;
int temp;
//swap the X/Y coords
temp = pt.x;
pt.x = pt.y;
pt.y = temp;
//swap the rectangle
RotateRect(rect);
ret = GetHorzButtonFromPt(sb, rect, pt, fReturnRect);
RotateRect(rect);
return ret;
}
//
//
//
static UINT GetButtonFromPt(SCROLLBAR *sb, RECT *rect, POINT pt, BOOL fReturnRect)
{
if(sb->nBarType == SB_HORZ)
{
return GetHorzButtonFromPt(sb, rect, pt, fReturnRect);
}
else
{
return GetVertButtonFromPt(sb, rect, pt, fReturnRect);
}
}
//
// Find the coordinates (in RECT format) of the specified button index
//
static UINT GetHorzButtonRectFromId(SCROLLBAR *sb, RECT *rect, UINT index)
{
UINT i;
SCROLLBUT *sbut = sb->sbButtons;
int leftpos = rect->left, rightpos = rect->right;
if(sb->fButVisibleAfter)
rightpos -= sb->nButSizeAfter;
//find the particular button in question
for(i = 0; i < index; i++)
{
if(sb->fButVisibleBefore && sbut[i].uPlacement == SBBP_LEFT)
{
leftpos += GetSingleButSize(sb, &sbut[i]);
}
else if(sb->fButVisibleAfter && sbut[i].uPlacement == SBBP_RIGHT)
{
rightpos += GetSingleButSize(sb, &sbut[i]);
}
}
//now return the rectangle
if(sbut[i].uPlacement == SBBP_LEFT)
{
rect->left = leftpos;
rect->right = leftpos + GetSingleButSize(sb, &sbut[i]);
}
else
{
rect->left = rightpos;
rect->right = rightpos + GetSingleButSize(sb, &sbut[i]);
}
return 0;
}
static UINT GetVertButtonRectFromId(SCROLLBAR *sb, RECT *rect, UINT index)
{
UINT ret;
RotateRect(rect);
ret = GetHorzButtonRectFromId(sb, rect, index);
RotateRect(rect);
return ret;
}
static UINT GetButtonRectFromId(SCROLLBAR *sb, RECT *rect, UINT index)
{
if(sb->nBarType == SB_HORZ)
{
return GetHorzButtonRectFromId(sb, rect, index);
}
else
{
return GetVertButtonRectFromId(sb, rect, index);
}
}
#endif //INCLUDE_BUTTONS
//
// Left button click in the non-client area
//
static LRESULT NCLButtonDown(SCROLLWND *sw, HWND hwnd, WPARAM wParam, LPARAM lParam)
{
RECT rect, winrect;
HDC hdc;
SCROLLBAR *sb;
SCROLLBUT *sbut = 0;
POINT pt;
pt.x = LOWORD(lParam);
pt.y = HIWORD(lParam);
hwndCurCoolSB = hwnd;
//
// HORIZONTAL SCROLLBAR PROCESSING
//
if(wParam == HTHSCROLL)
{
uScrollTimerMsg = WM_HSCROLL;
uCurrentScrollbar = SB_HORZ;
sb = &sw->sbarHorz;
//get the total area of the normal Horz scrollbar area
GetHScrollRect(sw, hwnd, &rect);
uCurrentScrollPortion = GetHorzPortion(sb, hwnd, &rect, LOWORD(lParam), HIWORD(lParam));
}
//
// VERTICAL SCROLLBAR PROCESSING
//
else if(wParam == HTVSCROLL)
{
uScrollTimerMsg = WM_VSCROLL;
uCurrentScrollbar = SB_VERT;
sb = &sw->sbarVert;
//get the total area of the normal Horz scrollbar area
GetVScrollRect(sw, hwnd, &rect);
uCurrentScrollPortion = GetVertPortion(sb, hwnd, &rect, LOWORD(lParam), HIWORD(lParam));
}
//
// NORMAL PROCESSING
//
else
{
uCurrentScrollPortion = HTSCROLL_NONE;
return CallWindowProc(sw->oldproc, hwnd, WM_NCLBUTTONDOWN, wParam, lParam);
}
//
// we can now share the same code for vertical
// and horizontal scrollbars
//
switch(uCurrentScrollPortion)
{
//inserted buttons to the left/right
#ifdef INCLUDE_BUTTONS
case HTSCROLL_INSERTED:
#ifdef HOT_TRACKING
KillTimer(hwnd, uMouseOverId);
uMouseOverId = 0;
uMouseOverScrollbar = COOLSB_NONE;
#endif
//find the index of the button that has been clicked
//adjust the rectangle to give the button's rectangle
uCurrentButton = GetButtonFromPt(sb, &rect, pt, TRUE);
sbut = &sb->sbButtons[uCurrentButton];
//post a notification message
PostMouseNotify(hwnd, NM_CLICK, sb->nBarType, &rect, sbut->uCmdId, pt);
GetWindowRect(hwnd, &winrect);
OffsetRect(&rect, -winrect.left, -winrect.top);
hdc = GetWindowDC(hwnd);
DrawScrollButton(sbut, hdc, &rect, SBBS_PUSHED);
ReleaseDC(hwnd, hdc);
break;
#endif //INCLUDE_BUTTONS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -