📄 header.c
字号:
else /* HDF_RIGHT */
cx = r.right - cw;
/* clip cx & cw */
if (cx < r.left)
cx = r.left;
if (cx + cw > r.right)
cw = r.right - cx;
tx = cx + infoPtr->iMargin;
/* since cw might have changed we have to recalculate tw */
tw = cw - infoPtr->iMargin * 2;
if (iw || bw) {
tw -= *w;
if (phdi->fmt & HDF_BITMAP_ON_RIGHT) {
/* put pic behind text */
*x = cx + tw + infoPtr->iMargin * 3;
} else {
*x = cx + infoPtr->iMargin;
/* move text behind pic */
tx += *w;
}
}
if (iw && bw) {
/* since we're done with the layout we can
now calculate the position of bmp which
has no influence on alignment and layout
because of img */
if ((phdi->fmt & HDF_JUSTIFYMASK) == HDF_RIGHT)
bx = cx - bw + infoPtr->iMargin;
else
bx = cx + cw + infoPtr->iMargin;
}
if (iw || bw) {
HDC hClipDC = GetDC(hwnd);
HRGN hClipRgn = CreateRectRgn(r.left, r.top, r.right, r.bottom);
SelectClipRgn(hClipDC, hClipRgn);
if (bw) {
HDC hdcBitmap = CreateCompatibleDC (hClipDC);
SelectObject (hdcBitmap, phdi->hbm);
BitBlt (hClipDC, bx, r.top + ((INT)rh - bmp.bmHeight) / 2,
bmp.bmWidth, bmp.bmHeight, hdcBitmap, 0, 0, SRCCOPY);
DeleteDC (hdcBitmap);
}
if (iw) {
ImageList_DrawEx (infoPtr->himl, phdi->iImage, hClipDC,
ix, r.top + ((INT)rh - infoPtr->himl->cy) / 2,
infoPtr->himl->cx, infoPtr->himl->cy, CLR_DEFAULT, CLR_DEFAULT, 0);
}
DeleteObject(hClipRgn);
ReleaseDC(hwnd, hClipDC);
}
if (((phdi->fmt & HDF_STRING)
|| (!(phdi->fmt & (HDF_OWNERDRAW|HDF_STRING|HDF_BITMAP|
HDF_BITMAP_ON_RIGHT|HDF_IMAGE)))) /* no explicit format specified? */
&& (phdi->pszText)) {
oldBkMode = SetBkMode(hdc, TRANSPARENT);
r.left = tx;
r.right = tx + tw;
DrawTextW (hdc, phdi->pszText, -1,
&r, DT_LEFT|DT_END_ELLIPSIS|DT_VCENTER|DT_SINGLELINE);
if (oldBkMode != TRANSPARENT)
SetBkMode(hdc, oldBkMode);
}
HEADER_FreeCallbackItems(phdi);
}/*Ownerdrawn*/
return phdi->rect.right;
}
static void
HEADER_DrawHotDivider(HWND hwnd, HDC hdc)
{
HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
HBRUSH brush;
RECT r;
HEADER_GetHotDividerRect(hwnd, infoPtr, &r);
brush = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
FillRect(hdc, &r, brush);
DeleteObject(brush);
}
static void
HEADER_Refresh (HWND hwnd, HDC hdc)
{
HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
HFONT hFont, hOldFont;
RECT rect, rcRest;
HBRUSH hbrBk;
UINT i;
INT x;
LRESULT lCDFlags;
HTHEME theme = GetWindowTheme (hwnd);
if (!infoPtr->bRectsValid)
HEADER_SetItemBounds(hwnd);
/* get rect for the bar, adjusted for the border */
GetClientRect (hwnd, &rect);
lCDFlags = HEADER_SendCtrlCustomDraw(hwnd, CDDS_PREPAINT, hdc, &rect);
if (infoPtr->bDragging)
ImageList_DragShowNolock(FALSE);
hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject (SYSTEM_FONT);
hOldFont = SelectObject (hdc, hFont);
/* draw Background */
if (infoPtr->uNumItem == 0 && theme == NULL) {
hbrBk = GetSysColorBrush(COLOR_3DFACE);
FillRect(hdc, &rect, hbrBk);
}
x = rect.left;
for (i = 0; x <= rect.right && i < infoPtr->uNumItem; i++) {
int idx = HEADER_OrderToIndex(hwnd,i);
if (RectVisible(hdc, &infoPtr->items[idx].rect))
HEADER_DrawItem(hwnd, hdc, idx, infoPtr->iHotItem == idx, lCDFlags);
x = infoPtr->items[idx].rect.right;
}
rcRest = rect;
rcRest.left = x;
if ((x <= rect.right) && RectVisible(hdc, &rcRest) && (infoPtr->uNumItem > 0)) {
if (theme != NULL) {
DrawThemeBackground(theme, hdc, HP_HEADERITEM, HIS_NORMAL, &rcRest, NULL);
}
else {
if (GetWindowLongW (hwnd, GWL_STYLE) & HDS_BUTTONS)
DrawEdge (hdc, &rcRest, EDGE_RAISED, BF_TOP|BF_LEFT|BF_BOTTOM|BF_SOFT|BF_MIDDLE);
else
DrawEdge (hdc, &rcRest, EDGE_ETCHED, BF_BOTTOM|BF_MIDDLE);
}
}
if (infoPtr->iHotDivider != -1)
HEADER_DrawHotDivider(hwnd, hdc);
if (infoPtr->bDragging)
ImageList_DragShowNolock(TRUE);
SelectObject (hdc, hOldFont);
if (lCDFlags & CDRF_NOTIFYPOSTPAINT)
HEADER_SendCtrlCustomDraw(hwnd, CDDS_POSTPAINT, hdc, &rect);
}
static void
HEADER_RefreshItem (HWND hwnd, HDC hdc, INT iItem)
{
HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
if (!infoPtr->bRectsValid)
HEADER_SetItemBounds(hwnd);
InvalidateRect(hwnd, &infoPtr->items[iItem].rect, FALSE);
}
static void
HEADER_InternalHitTest (HWND hwnd, LPPOINT lpPt, UINT *pFlags, INT *pItem)
{
HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
RECT rect, rcTest;
UINT iCount;
INT width;
BOOL bNoWidth;
GetClientRect (hwnd, &rect);
*pFlags = 0;
bNoWidth = FALSE;
if (PtInRect (&rect, *lpPt))
{
if (infoPtr->uNumItem == 0) {
*pFlags |= HHT_NOWHERE;
*pItem = 1;
TRACE("NOWHERE\n");
return;
}
else {
/* somewhere inside */
for (iCount = 0; iCount < infoPtr->uNumItem; iCount++) {
rect = infoPtr->items[iCount].rect;
width = rect.right - rect.left;
if (width == 0) {
bNoWidth = TRUE;
continue;
}
if (PtInRect (&rect, *lpPt)) {
if (width <= 2 * DIVIDER_WIDTH) {
*pFlags |= HHT_ONHEADER;
*pItem = iCount;
TRACE("ON HEADER %d\n", iCount);
return;
}
if (HEADER_IndexToOrder(hwnd, iCount) > 0) {
rcTest = rect;
rcTest.right = rcTest.left + DIVIDER_WIDTH;
if (PtInRect (&rcTest, *lpPt)) {
if (bNoWidth) {
*pFlags |= HHT_ONDIVOPEN;
*pItem = HEADER_PrevItem(hwnd, iCount);
TRACE("ON DIVOPEN %d\n", *pItem);
return;
}
else {
*pFlags |= HHT_ONDIVIDER;
*pItem = HEADER_PrevItem(hwnd, iCount);
TRACE("ON DIVIDER %d\n", *pItem);
return;
}
}
}
rcTest = rect;
rcTest.left = rcTest.right - DIVIDER_WIDTH;
if (PtInRect (&rcTest, *lpPt)) {
*pFlags |= HHT_ONDIVIDER;
*pItem = iCount;
TRACE("ON DIVIDER %d\n", *pItem);
return;
}
*pFlags |= HHT_ONHEADER;
*pItem = iCount;
TRACE("ON HEADER %d\n", iCount);
return;
}
}
/* check for last divider part (on nowhere) */
rect = infoPtr->items[infoPtr->uNumItem-1].rect;
rect.left = rect.right;
rect.right += DIVIDER_WIDTH;
if (PtInRect (&rect, *lpPt)) {
if (bNoWidth) {
*pFlags |= HHT_ONDIVOPEN;
*pItem = infoPtr->uNumItem - 1;
TRACE("ON DIVOPEN %d\n", *pItem);
return;
}
else {
*pFlags |= HHT_ONDIVIDER;
*pItem = infoPtr->uNumItem-1;
TRACE("ON DIVIDER %d\n", *pItem);
return;
}
}
*pFlags |= HHT_NOWHERE;
*pItem = 1;
TRACE("NOWHERE\n");
return;
}
}
else {
if (lpPt->x < rect.left) {
TRACE("TO LEFT\n");
*pFlags |= HHT_TOLEFT;
}
else if (lpPt->x > rect.right) {
TRACE("TO RIGHT\n");
*pFlags |= HHT_TORIGHT;
}
if (lpPt->y < rect.top) {
TRACE("ABOVE\n");
*pFlags |= HHT_ABOVE;
}
else if (lpPt->y > rect.bottom) {
TRACE("BELOW\n");
*pFlags |= HHT_BELOW;
}
}
*pItem = 1;
TRACE("flags=0x%X\n", *pFlags);
return;
}
static void
HEADER_DrawTrackLine (HWND hwnd, HDC hdc, INT x)
{
RECT rect;
HPEN hOldPen;
INT oldRop;
GetClientRect (hwnd, &rect);
hOldPen = SelectObject (hdc, GetStockObject (BLACK_PEN));
oldRop = SetROP2 (hdc, R2_XORPEN);
MoveToEx (hdc, x, rect.top, NULL);
LineTo (hdc, x, rect.bottom);
SetROP2 (hdc, oldRop);
SelectObject (hdc, hOldPen);
}
/***
* DESCRIPTION:
* Convert a HDITEM into the correct format (ANSI/Unicode) to send it in a notify
*
* PARAMETER(S):
* [I] infoPtr : the header that wants to send the notify
* [O] dest : The buffer to store the HDITEM for notify. It may be set to a HDITEMA of HDITEMW
* [I] src : The source HDITEM. It may be a HDITEMA or HDITEMW
* [I] fSourceUnicode : is src a HDITEMW or HDITEMA
* [O] ppvScratch : a pointer to a scratch buffer that needs to be freed after
* the HDITEM is no longer in use or NULL if none was needed
*
* NOTE: We depend on HDITEMA and HDITEMW having the same structure
*/
static void HEADER_CopyHDItemForNotify(HEADER_INFO *infoPtr, HDITEMW *dest,
HDITEMW *src, BOOL fSourceUnicode, LPVOID *ppvScratch)
{
*ppvScratch = NULL;
*dest = *src;
if (src->mask & HDI_TEXT && src->pszText != LPSTR_TEXTCALLBACKW) /* covers TEXTCALLBACKA as well */
{
if (fSourceUnicode && infoPtr->nNotifyFormat != NFR_UNICODE)
{
dest->pszText = NULL;
Str_SetPtrWtoA((LPSTR *)&dest->pszText, src->pszText);
*ppvScratch = dest->pszText;
}
if (!fSourceUnicode && infoPtr->nNotifyFormat == NFR_UNICODE)
{
dest->pszText = NULL;
Str_SetPtrAtoW(&dest->pszText, (LPSTR)src->pszText);
*ppvScratch = dest->pszText;
}
}
}
static UINT HEADER_NotifyCodeWtoA(UINT code)
{
/* we use the fact that all the unicode messages are in HDN_FIRST_UNICODE..HDN_LAST*/
if (code >= HDN_LAST && code <= HDN_FIRST_UNICODE)
return code + HDN_UNICODE_OFFSET;
else
return code;
}
static LRESULT
HEADER_SendNotify(HWND hwnd, UINT code, NMHDR *nmhdr)
{
HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
nmhdr->hwndFrom = hwnd;
nmhdr->idFrom = GetWindowLongPtrW (hwnd, GWLP_ID);
nmhdr->code = code;
return SendMessageW(infoPtr->hwndNotify, WM_NOTIFY,
(WPARAM)nmhdr->idFrom, (LPARAM)nmhdr);
}
static BOOL
HEADER_SendSimpleNotify (HWND hwnd, UINT code)
{
NMHDR nmhdr;
return (BOOL)HEADER_SendNotify(hwnd, code, &nmhdr);
}
static LRESULT
HEADER_SendCtrlCustomDraw(HWND hwnd, DWORD dwDrawStage, HDC hdc, RECT *rect)
{
NMCUSTOMDRAW nm;
nm.dwDrawStage = dwDrawStage;
nm.hdc = hdc;
nm.rc = *rect;
nm.dwItemSpec = 0;
nm.uItemState = 0;
nm.lItemlParam = 0;
return HEADER_SendNotify(hwnd, NM_CUSTOMDRAW, (NMHDR *)&nm);
}
static BOOL
HEADER_SendNotifyWithHDItemT(HWND hwnd, UINT code, INT iItem, HDITEMW *lpItem)
{
HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
NMHEADERW nmhdr;
if (infoPtr->nNotifyFormat != NFR_UNICODE)
code = HEADER_NotifyCodeWtoA(code);
nmhdr.iItem = iItem;
nmhdr.iButton = 0;
nmhdr.pitem = lpItem;
return (BOOL)HEADER_SendNotify(hwnd, code, (NMHDR *)&nmhdr);
}
static BOOL
HEADER_SendNotifyWithIntFieldT(HWND hwnd, UINT code, INT iItem, INT mask, INT iValue)
{
HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
HDITEMW nmitem;
/* copying only the iValue should be ok but to make the code more robust we copy everything */
nmitem.cxy = infoPtr->items[iItem].cxy;
nmitem.hbm = infoPtr->items[iItem].hbm;
nmitem.pszText = NULL;
nmitem.cchTextMax = 0;
nmitem.fmt = infoPtr->items[iItem].fmt;
nmitem.lParam = infoPtr->items[iItem].lParam;
nmitem.iOrder = infoPtr->items[iItem].iOrder;
nmitem.iImage = infoPtr->items[iItem].iImage;
nmitem.mask = mask;
switch (mask)
{
case HDI_WIDTH:
nmitem.cxy = iValue;
break;
case HDI_ORDER:
nmitem.iOrder = iValue;
break;
default:
ERR("invalid mask value 0x%x\n", iValue);
}
return HEADER_SendNotifyWithHDItemT(hwnd, code, iItem, &nmitem);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -