📄 rebar.c
字号:
{
if (lprbbi->hwndChild) {
lpBand->hwndChild = lprbbi->hwndChild;
lpBand->hwndPrevParent =
SetParent (lpBand->hwndChild, hwnd);
/* below in trace from WinRAR */
ShowWindow(lpBand->hwndChild, SW_SHOWNOACTIVATE | SW_SHOWNORMAL);
/* above in trace from WinRAR */
}
else {
TRACE("child: %p prev parent: %p\n",
lpBand->hwndChild, lpBand->hwndPrevParent);
lpBand->hwndChild = 0;
lpBand->hwndPrevParent = 0;
}
bChanged = TRUE;
}
if( (lprbbi->fMask & RBBIM_CHILDSIZE) &&
( (lpBand->cxMinChild != lprbbi->cxMinChild) ||
(lpBand->cyMinChild != lprbbi->cyMinChild ) ||
( (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) &&
( (lpBand->cyChild != lprbbi->cyChild ) ||
(lpBand->cyMaxChild != lprbbi->cyMaxChild ) ||
(lpBand->cyIntegral != lprbbi->cyIntegral ) ) ) ||
( (lprbbi->cbSize < sizeof (REBARBANDINFOA)) &&
( (lpBand->cyChild ||
lpBand->cyMaxChild ||
lpBand->cyIntegral ) ) ) ) )
{
lpBand->cxMinChild = lprbbi->cxMinChild;
lpBand->cyMinChild = lprbbi->cyMinChild;
/* These fields where added in WIN32_IE == 0x400 and are set only for RBBS_VARIABLEHEIGHT bands */
if (lprbbi->cbSize >= sizeof (REBARBANDINFOA) && (lpBand->fStyle & RBBS_VARIABLEHEIGHT)) {
lpBand->cyMaxChild = lprbbi->cyMaxChild;
lpBand->cyIntegral = lprbbi->cyIntegral;
lpBand->cyChild = lpBand->cyMinChild;
round_child_height(lpBand, lprbbi->cyChild); /* try to increase cyChild */
}
else {
lpBand->cyChild = lpBand->cyMinChild;
lpBand->cyMaxChild = 0x7fffffff;
lpBand->cyIntegral = 0;
}
bChanged = TRUE;
}
if( (lprbbi->fMask & RBBIM_SIZE) &&
(lpBand->cx != lprbbi->cx ) )
{
lpBand->cx = lprbbi->cx;
bChanged = TRUE;
}
if( (lprbbi->fMask & RBBIM_BACKGROUND) &&
( lpBand->hbmBack != lprbbi->hbmBack ) )
{
lpBand->hbmBack = lprbbi->hbmBack;
bChanged = TRUE;
}
if( (lprbbi->fMask & RBBIM_ID) &&
(lpBand->wID != lprbbi->wID ) )
{
lpBand->wID = lprbbi->wID;
bChanged = TRUE;
}
/* check for additional data */
if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) {
if( (lprbbi->fMask & RBBIM_IDEALSIZE) &&
( lpBand->cxIdeal != lprbbi->cxIdeal ) )
{
lpBand->cxIdeal = lprbbi->cxIdeal;
bChanged = TRUE;
}
if( (lprbbi->fMask & RBBIM_LPARAM) &&
(lpBand->lParam != lprbbi->lParam ) )
{
lpBand->lParam = lprbbi->lParam;
bChanged = TRUE;
}
if( (lprbbi->fMask & RBBIM_HEADERSIZE) &&
(lpBand->cxHeader != lprbbi->cxHeader ) )
{
lpBand->cxHeader = lprbbi->cxHeader;
lpBand->fStyle |= RBBS_UNDOC_FIXEDHEADER;
bChanged = TRUE;
}
}
return bChanged;
}
static LRESULT
REBAR_InternalEraseBkGnd (const REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam, const RECT *clip)
/* Function: This erases the background rectangle by drawing */
/* each band with its background color (or the default) and */
/* draws each bands right separator if necessary. The row */
/* separators are drawn on the first band of the next row. */
{
REBAR_BAND *lpBand;
UINT i;
INT oldrow;
HDC hdc = (HDC)wParam;
RECT cr;
COLORREF old = CLR_NONE, new;
HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);
GetClientRect (infoPtr->hwndSelf, &cr);
oldrow = -1;
for(i=0; i<infoPtr->uNumBands; i++) {
RECT rcBand;
lpBand = &infoPtr->bands[i];
if (HIDDENBAND(lpBand)) continue;
translate_rect(infoPtr, &rcBand, &lpBand->rcBand);
/* draw band separator between rows */
if (lpBand->iRow != oldrow) {
oldrow = lpBand->iRow;
if (infoPtr->dwStyle & RBS_BANDBORDERS) {
RECT rcRowSep;
rcRowSep = rcBand;
if (infoPtr->dwStyle & CCS_VERT) {
rcRowSep.right += SEP_WIDTH_SIZE;
rcRowSep.bottom = infoPtr->calcSize.cx;
if (theme)
DrawThemeEdge (theme, hdc, RP_BAND, 0, &rcRowSep, EDGE_ETCHED, BF_RIGHT, NULL);
else
DrawEdge (hdc, &rcRowSep, EDGE_ETCHED, BF_RIGHT);
}
else {
rcRowSep.bottom += SEP_WIDTH_SIZE;
rcRowSep.right = infoPtr->calcSize.cx;
if (theme)
DrawThemeEdge (theme, hdc, RP_BAND, 0, &rcRowSep, EDGE_ETCHED, BF_BOTTOM, NULL);
else
DrawEdge (hdc, &rcRowSep, EDGE_ETCHED, BF_BOTTOM);
}
TRACE ("drawing band separator bottom (%d,%d)-(%d,%d)\n",
rcRowSep.left, rcRowSep.top,
rcRowSep.right, rcRowSep.bottom);
}
}
/* draw band separator between bands in a row */
if (infoPtr->dwStyle & RBS_BANDBORDERS && lpBand->rcBand.left > 0) {
RECT rcSep;
rcSep = rcBand;
if (infoPtr->dwStyle & CCS_VERT) {
rcSep.bottom = rcSep.top;
rcSep.top -= SEP_WIDTH_SIZE;
if (theme)
DrawThemeEdge (theme, hdc, RP_BAND, 0, &rcSep, EDGE_ETCHED, BF_BOTTOM, NULL);
else
DrawEdge (hdc, &rcSep, EDGE_ETCHED, BF_BOTTOM);
}
else {
rcSep.right = rcSep.left;
rcSep.left -= SEP_WIDTH_SIZE;
if (theme)
DrawThemeEdge (theme, hdc, RP_BAND, 0, &rcSep, EDGE_ETCHED, BF_RIGHT, NULL);
else
DrawEdge (hdc, &rcSep, EDGE_ETCHED, BF_RIGHT);
}
TRACE("drawing band separator right (%d,%d)-(%d,%d)\n",
rcSep.left, rcSep.top, rcSep.right, rcSep.bottom);
}
/* draw the actual background */
if (lpBand->clrBack != CLR_NONE) {
new = (lpBand->clrBack == CLR_DEFAULT) ? infoPtr->clrBtnFace :
lpBand->clrBack;
#if GLATESTING
/* testing only - make background green to see it */
new = RGB(0,128,0);
#endif
}
else {
/* In the absence of documentation for Rebar vs. CLR_NONE,
* we will use the default BtnFace color. Note documentation
* exists for Listview and Imagelist.
*/
new = infoPtr->clrBtnFace;
#if GLATESTING
/* testing only - make background green to see it */
new = RGB(0,128,0);
#endif
}
if (theme)
{
/* When themed, the background color is ignored (but not a
* background bitmap */
DrawThemeBackground (theme, hdc, 0, 0, &cr, &rcBand);
}
else
{
old = SetBkColor (hdc, new);
TRACE("%s background color=0x%06x, band (%d,%d)-(%d,%d), clip (%d,%d)-(%d,%d)\n",
(lpBand->clrBack == CLR_NONE) ? "none" :
((lpBand->clrBack == CLR_DEFAULT) ? "dft" : ""),
GetBkColor(hdc),
rcBand.left,rcBand.top,
rcBand.right,rcBand.bottom,
clip->left, clip->top,
clip->right, clip->bottom);
ExtTextOutW (hdc, 0, 0, ETO_OPAQUE, &rcBand, NULL, 0, 0);
if (lpBand->clrBack != CLR_NONE)
SetBkColor (hdc, old);
}
}
return TRUE;
}
static void
REBAR_InternalHitTest (const REBAR_INFO *infoPtr, const POINT *lpPt, UINT *pFlags, INT *pBand)
{
REBAR_BAND *lpBand;
RECT rect;
UINT iCount;
GetClientRect (infoPtr->hwndSelf, &rect);
*pFlags = RBHT_NOWHERE;
if (PtInRect (&rect, *lpPt))
{
if (infoPtr->uNumBands == 0) {
*pFlags = RBHT_NOWHERE;
if (pBand)
*pBand = -1;
TRACE("NOWHERE\n");
return;
}
else {
/* somewhere inside */
for (iCount = 0; iCount < infoPtr->uNumBands; iCount++) {
RECT rcBand;
lpBand = &infoPtr->bands[iCount];
translate_rect(infoPtr, &rcBand, &lpBand->rcBand);
if (HIDDENBAND(lpBand)) continue;
if (PtInRect (&rcBand, *lpPt)) {
if (pBand)
*pBand = iCount;
if (PtInRect (&lpBand->rcGripper, *lpPt)) {
*pFlags = RBHT_GRABBER;
TRACE("ON GRABBER %d\n", iCount);
return;
}
else if (PtInRect (&lpBand->rcCapImage, *lpPt)) {
*pFlags = RBHT_CAPTION;
TRACE("ON CAPTION %d\n", iCount);
return;
}
else if (PtInRect (&lpBand->rcCapText, *lpPt)) {
*pFlags = RBHT_CAPTION;
TRACE("ON CAPTION %d\n", iCount);
return;
}
else if (PtInRect (&lpBand->rcChild, *lpPt)) {
*pFlags = RBHT_CLIENT;
TRACE("ON CLIENT %d\n", iCount);
return;
}
else if (PtInRect (&lpBand->rcChevron, *lpPt)) {
*pFlags = RBHT_CHEVRON;
TRACE("ON CHEVRON %d\n", iCount);
return;
}
else {
*pFlags = RBHT_NOWHERE;
TRACE("NOWHERE %d\n", iCount);
return;
}
}
}
*pFlags = RBHT_NOWHERE;
if (pBand)
*pBand = -1;
TRACE("NOWHERE\n");
return;
}
}
else {
*pFlags = RBHT_NOWHERE;
if (pBand)
*pBand = -1;
TRACE("NOWHERE\n");
return;
}
}
static void
REBAR_HandleLRDrag (REBAR_INFO *infoPtr, const POINT *ptsmove)
/* Function: This will implement the functionality of a */
/* Gripper drag within a row. It will not implement "out- */
/* of-row" drags. (They are detected and handled in */
/* REBAR_MouseMove.) */
/* **** FIXME Switching order of bands in a row not **** */
/* **** yet implemented. **** */
{
REBAR_BAND *hitBand;
INT iHitBand, iRowBegin, iRowEnd;
INT movement, xBand;
/* on first significant mouse movement, issue notify */
if (!(infoPtr->fStatus & BEGIN_DRAG_ISSUED)) {
if (REBAR_Notify_NMREBAR (infoPtr, -1, RBN_BEGINDRAG)) {
/* Notify returned TRUE - abort drag */
infoPtr->dragStart.x = 0;
infoPtr->dragStart.y = 0;
infoPtr->dragNow = infoPtr->dragStart;
infoPtr->iGrabbedBand = -1;
ReleaseCapture ();
return ;
}
infoPtr->fStatus |= BEGIN_DRAG_ISSUED;
}
iHitBand = infoPtr->iGrabbedBand;
iRowBegin = get_row_begin_for_band(infoPtr, iHitBand);
iRowEnd = get_row_end_for_band(infoPtr, iHitBand);
hitBand = &infoPtr->bands[iHitBand];
xBand = hitBand->rcBand.left;
movement = (infoPtr->dwStyle&CCS_VERT ? ptsmove->y : ptsmove->x)
- (xBand + REBAR_PRE_GRIPPER - infoPtr->ihitoffset);
if (movement < 0) {
int cxLeft = REBAR_ShrinkBandsRTL(infoPtr, iRowBegin, iHitBand, -movement, TRUE);
hitBand->cxEffective += -movement - cxLeft;
hitBand->cx = hitBand->cxEffective;
} else if (movement > 0) {
int cxLeft = REBAR_ShrinkBandsLTR(infoPtr, iHitBand, iRowEnd, movement, TRUE);
REBAR_BAND *lpPrev = &infoPtr->bands[prev_band(infoPtr, iHitBand)];
lpPrev->cxEffective += movement - cxLeft;
lpPrev->cx = lpPrev->cxEffective;
}
REBAR_SetRowRectsX(infoPtr, iRowBegin, iRowEnd);
if (infoPtr->dwStyle & CCS_VERT)
REBAR_CalcVertBand(infoPtr, 0, infoPtr->uNumBands);
else
REBAR_CalcHorzBand(infoPtr, 0, infoPtr->uNumBands);
REBAR_MoveChildWindows(infoPtr, iRowBegin, iRowEnd);
}
/* << REBAR_BeginDrag >> */
static LRESULT
REBAR_DeleteBand (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
{
UINT uBand = (UINT)wParam;
REBAR_BAND *lpBand;
if (uBand >= infoPtr->uNumBands)
return FALSE;
TRACE("deleting band %u!\n", uBand);
lpBand = &infoPtr->bands[uBand];
REBAR_Notify_NMREBAR (infoPtr, uBand, RBN_DELETINGBAND);
/* TODO: a return of 1 should probably cancel the deletion */
if (lpBand->hwndChild)
ShowWindow(lpBand->hwndChild, SW_HIDE);
Free(lpBand->lpText);
infoPtr->uNumBands--;
memmove(&infoPtr->bands[uBand], &infoPtr->bands[uBand+1],
(infoPtr->uNumBands - uBand) * sizeof(REBAR_BAND));
infoPtr->bands = ReAlloc(infoPtr->bands, infoPtr->uNumBands * sizeof(REBAR_BAND));
REBAR_Notify_NMREBAR (infoPtr, -1, RBN_D
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -