📄 header.c
字号:
/**
* Prepare callback items
* depends on NMHDDISPINFOW having same structure as NMHDDISPINFOA
* (so we handle the two cases only doing a specific cast for pszText).
* Checks if any of the required field are callback. If there are sends a
* NMHDISPINFO notify to retrieve these items. The items are stored in the
* HEADER_ITEM pszText and iImage fields. They should be freed with
* HEADER_FreeCallbackItems.
*
* @param hwnd : hwnd header container handler
* @param iItem : the header item id
* @param reqMask : required fields. If any of them is callback this function will fetch it
*
* @return TRUE on success, else FALSE
*/
static BOOL
HEADER_PrepareCallbackItems(HWND hwnd, INT iItem, INT reqMask)
{
HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
HEADER_ITEM *lpItem = &infoPtr->items[iItem];
DWORD mask = reqMask & lpItem->callbackMask;
NMHDDISPINFOW dispInfo;
void *pvBuffer = NULL;
if (mask == 0)
return TRUE;
if (mask&HDI_TEXT && lpItem->pszText != NULL)
{
ERR("(): function called without a call to FreeCallbackItems\n");
Free(lpItem->pszText);
lpItem->pszText = NULL;
}
memset(&dispInfo, 0, sizeof(NMHDDISPINFOW));
dispInfo.hdr.hwndFrom = hwnd;
dispInfo.hdr.idFrom = GetWindowLongPtrW (hwnd, GWLP_ID);
if (infoPtr->nNotifyFormat == NFR_UNICODE)
{
dispInfo.hdr.code = HDN_GETDISPINFOW;
if (mask & HDI_TEXT)
pvBuffer = Alloc(MAX_HEADER_TEXT_LEN * sizeof(WCHAR));
}
else
{
dispInfo.hdr.code = HDN_GETDISPINFOA;
if (mask & HDI_TEXT)
pvBuffer = Alloc(MAX_HEADER_TEXT_LEN * sizeof(CHAR));
}
dispInfo.pszText = (LPWSTR)pvBuffer;
dispInfo.cchTextMax = (pvBuffer!=NULL?MAX_HEADER_TEXT_LEN:0);
dispInfo.iItem = iItem;
dispInfo.mask = mask;
dispInfo.lParam = lpItem->lParam;
TRACE("Sending HDN_GETDISPINFO%c\n", infoPtr->nNotifyFormat == NFR_UNICODE?'W':'A');
SendMessageW(infoPtr->hwndNotify, WM_NOTIFY,
(WPARAM) dispInfo.hdr.idFrom,
(LPARAM) &dispInfo);
TRACE("SendMessage returns(mask:0x%x,str:%s,lParam:%p)\n",
dispInfo.mask,
(infoPtr->nNotifyFormat == NFR_UNICODE ? debugstr_w(dispInfo.pszText) : (LPSTR) dispInfo.pszText),
(void*) dispInfo.lParam);
if (mask & HDI_IMAGE)
lpItem->iImage = dispInfo.iImage;
if (mask & HDI_TEXT)
{
if (infoPtr->nNotifyFormat == NFR_UNICODE)
{
lpItem->pszText = (LPWSTR)pvBuffer;
/* the user might have used his own buffer */
if (dispInfo.pszText != lpItem->pszText)
Str_GetPtrW(dispInfo.pszText, lpItem->pszText, MAX_HEADER_TEXT_LEN);
}
else
{
Str_SetPtrAtoW(&lpItem->pszText, (LPSTR)dispInfo.pszText);
Free(pvBuffer);
}
}
if (dispInfo.mask & HDI_DI_SETITEM)
{
/* make the items permanent */
lpItem->callbackMask &= ~dispInfo.mask;
}
return TRUE;
}
/***
* DESCRIPTION:
* Free the items that might be allocated with HEADER_PrepareCallbackItems
*
* PARAMETER(S):
* [I] lpItem : the item to free the data
*
*/
static void
HEADER_FreeCallbackItems(HEADER_ITEM *lpItem)
{
if (lpItem->callbackMask&HDI_TEXT && lpItem->pszText != NULL)
{
Free(lpItem->pszText);
lpItem->pszText = NULL;
}
if (lpItem->callbackMask&HDI_IMAGE)
lpItem->iImage = I_IMAGECALLBACK;
}
static LRESULT
HEADER_CreateDragImage (HWND hwnd, WPARAM wParam)
{
HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd);
HEADER_ITEM *lpItem;
HIMAGELIST himl;
HBITMAP hMemory, hOldBitmap;
LRESULT lCDFlags;
RECT rc;
HDC hMemoryDC;
HDC hDeviceDC;
int height, width;
if (wParam < 0 || wParam >= infoPtr->uNumItem)
return FALSE;
if (!infoPtr->bRectsValid)
HEADER_SetItemBounds(hwnd);
lpItem = &infoPtr->items[wParam];
width = lpItem->rect.right - lpItem->rect.left;
height = lpItem->rect.bottom - lpItem->rect.top;
hDeviceDC = GetDC(NULL);
hMemoryDC = CreateCompatibleDC(hDeviceDC);
hMemory = CreateCompatibleBitmap(hDeviceDC, width, height);
ReleaseDC(NULL, hDeviceDC);
hOldBitmap = SelectObject(hMemoryDC, hMemory);
SetViewportOrgEx(hMemoryDC, -lpItem->rect.left, -lpItem->rect.top, NULL);
GetClientRect(hwnd, &rc);
lCDFlags = HEADER_SendCtrlCustomDraw(hwnd, CDDS_PREPAINT, hMemoryDC, &rc);
HEADER_DrawItem(hwnd, hMemoryDC, wParam, FALSE, lCDFlags);
if (lCDFlags & CDRF_NOTIFYPOSTPAINT)
HEADER_SendCtrlCustomDraw(hwnd, CDDS_POSTPAINT, hMemoryDC, &rc);
hMemory = SelectObject(hMemoryDC, hOldBitmap);
DeleteDC(hMemoryDC);
if (hMemory == NULL) /* if anything failed */
return FALSE;
himl = ImageList_Create(width, height, ILC_COLORDDB, 1, 1);
ImageList_Add(himl, hMemory, NULL);
DeleteObject(hMemory);
return (LRESULT)himl;
}
static LRESULT
HEADER_SetHotDivider(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd);
INT iDivider;
RECT r;
if (wParam)
{
POINT pt;
UINT flags;
pt.x = (INT)(SHORT)LOWORD(lParam);
pt.y = 0;
HEADER_InternalHitTest (hwnd, &pt, &flags, &iDivider);
if (flags & HHT_TOLEFT)
iDivider = 0;
else if (flags & HHT_NOWHERE || flags & HHT_TORIGHT)
iDivider = infoPtr->uNumItem;
else
{
HEADER_ITEM *lpItem = &infoPtr->items[iDivider];
if (pt.x > (lpItem->rect.left+lpItem->rect.right)/2)
iDivider = HEADER_NextItem(hwnd, iDivider);
}
}
else
iDivider = (INT)lParam;
/* Note; wParam==FALSE, lParam==-1 is valid and is used to clear the hot divider */
if (iDivider<-1 || iDivider>(int)infoPtr->uNumItem)
return iDivider;
if (iDivider != infoPtr->iHotDivider)
{
if (infoPtr->iHotDivider != -1)
{
HEADER_GetHotDividerRect(hwnd, infoPtr, &r);
InvalidateRect(hwnd, &r, FALSE);
}
infoPtr->iHotDivider = iDivider;
if (iDivider != -1)
{
HEADER_GetHotDividerRect(hwnd, infoPtr, &r);
InvalidateRect(hwnd, &r, FALSE);
}
}
return iDivider;
}
static LRESULT
HEADER_DeleteItem (HWND hwnd, WPARAM wParam)
{
HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd);
INT iItem = (INT)wParam;
INT iOrder;
INT i;
TRACE("[iItem=%d]\n", iItem);
if ((iItem < 0) || (iItem >= (INT)infoPtr->uNumItem))
return FALSE;
for (i = 0; i < infoPtr->uNumItem; i++)
TRACE("%d: order=%d, iOrder=%d, ->iOrder=%d\n", i, infoPtr->order[i], infoPtr->items[i].iOrder, infoPtr->items[infoPtr->order[i]].iOrder);
iOrder = infoPtr->items[iItem].iOrder;
HEADER_DisposeItem(&infoPtr->items[iItem]);
infoPtr->uNumItem--;
memmove(&infoPtr->items[iItem], &infoPtr->items[iItem + 1],
(infoPtr->uNumItem - iItem) * sizeof(HEADER_ITEM));
memmove(&infoPtr->order[iOrder], &infoPtr->order[iOrder + 1],
(infoPtr->uNumItem - iOrder) * sizeof(INT));
infoPtr->items = ReAlloc(infoPtr->items, sizeof(HEADER_ITEM) * infoPtr->uNumItem);
infoPtr->order = ReAlloc(infoPtr->order, sizeof(INT) * infoPtr->uNumItem);
/* Correct the orders */
for (i = 0; i < infoPtr->uNumItem; i++)
{
if (infoPtr->order[i] > iItem)
infoPtr->order[i]--;
if (i >= iOrder)
infoPtr->items[infoPtr->order[i]].iOrder = i;
}
for (i = 0; i < infoPtr->uNumItem; i++)
TRACE("%d: order=%d, iOrder=%d, ->iOrder=%d\n", i, infoPtr->order[i], infoPtr->items[i].iOrder, infoPtr->items[infoPtr->order[i]].iOrder);
HEADER_SetItemBounds (hwnd);
InvalidateRect(hwnd, NULL, FALSE);
return TRUE;
}
static LRESULT
HEADER_GetImageList (HWND hwnd)
{
HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
return (LRESULT)infoPtr->himl;
}
static LRESULT
HEADER_GetItemT (HWND hwnd, INT nItem, LPHDITEMW phdi, BOOL bUnicode)
{
HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
HEADER_ITEM *lpItem;
UINT mask;
if (!phdi)
return FALSE;
TRACE("[nItem=%d]\n", nItem);
mask = phdi->mask;
if (mask == 0)
return TRUE;
if ((nItem < 0) || (nItem >= (INT)infoPtr->uNumItem))
return FALSE;
if (mask & HDI_UNKNOWN_FIELDS)
{
TRACE("mask %x contains unknown fields. Using only comctl32 4.0 fields\n", mask);
mask &= HDI_COMCTL32_4_0_FIELDS;
}
lpItem = &infoPtr->items[nItem];
HEADER_PrepareCallbackItems(hwnd, nItem, mask);
if (mask & HDI_BITMAP)
phdi->hbm = lpItem->hbm;
if (mask & HDI_FORMAT)
phdi->fmt = lpItem->fmt;
if (mask & HDI_WIDTH)
phdi->cxy = lpItem->cxy;
if (mask & HDI_LPARAM)
phdi->lParam = lpItem->lParam;
if (mask & HDI_IMAGE)
phdi->iImage = lpItem->iImage;
if (mask & HDI_ORDER)
phdi->iOrder = lpItem->iOrder;
if (mask & HDI_TEXT)
{
if (bUnicode)
Str_GetPtrW (lpItem->pszText, phdi->pszText, phdi->cchTextMax);
else
Str_GetPtrWtoA (lpItem->pszText, (LPSTR)phdi->pszText, phdi->cchTextMax);
}
HEADER_FreeCallbackItems(lpItem);
return TRUE;
}
inline static LRESULT
HEADER_GetItemCount (HWND hwnd)
{
HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
return infoPtr->uNumItem;
}
static LRESULT
HEADER_GetItemRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
INT iItem = (INT)wParam;
LPRECT lpRect = (LPRECT)lParam;
if ((iItem < 0) || (iItem >= (INT)infoPtr->uNumItem))
return FALSE;
lpRect->left = infoPtr->items[iItem].rect.left;
lpRect->right = infoPtr->items[iItem].rect.right;
lpRect->top = infoPtr->items[iItem].rect.top;
lpRect->bottom = infoPtr->items[iItem].rect.bottom;
return TRUE;
}
static LRESULT
HEADER_GetOrderArray(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
LPINT order = (LPINT) lParam;
HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
if ((unsigned int)wParam <infoPtr->uNumItem)
return FALSE;
memcpy(order, infoPtr->order, infoPtr->uNumItem * sizeof(INT));
return TRUE;
}
static LRESULT
HEADER_SetOrderArray(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
int i;
LPINT order = (LPINT) lParam;
HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
HEADER_ITEM *lpItem;
if ((unsigned int)wParam <infoPtr->uNumItem)
return FALSE;
memcpy(infoPtr->order, order, infoPtr->uNumItem * sizeof(INT));
for (i=0; i<(int)wParam; i++)
{
lpItem = &infoPtr->items[*order++];
lpItem->iOrder=i;
}
infoPtr->bRectsValid=0;
InvalidateRect(hwnd, NULL, FALSE);
return TRUE;
}
inline static LRESULT
HEADER_GetUnicodeFormat (HWND hwnd)
{
HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
return (infoPtr->nNotifyFormat == NFR_UNICODE);
}
static LRESULT
HEADER_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
LPHDHITTESTINFO phti = (LPHDHITTESTINFO)lParam;
HEADER_InternalHitTest (hwnd, &phti->pt, &phti->flags, &phti->iItem);
if (phti->flags == HHT_NOWHERE)
return -1;
else
return phti->iItem;
}
static LRESULT
HEADER_InsertItemT (HWND hwnd, INT nItem, LPHDITEMW phdi, BOOL bUnicode)
{
HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
HEADER_ITEM *lpItem;
INT iOrder;
UINT i;
UINT copyMask;
if ((phdi == NULL) || (nItem < 0) || (phdi->mask == 0))
return -1;
if (nItem > infoPtr->uNumItem)
nItem = infoPtr->uNumItem;
iOrder = (phdi->mask & HDI_ORDER) ? phdi->iOrder : nItem;
if (iOrder < 0)
iOrder = 0;
else if (infoPtr->uNumItem < iOrder)
iOrder = infoPtr->uNumItem;
infoPtr->uNumItem++;
infoPtr->items = ReAlloc(infoPtr->items, sizeof(HEADER_ITEM) * infoPtr->uNumItem);
infoPtr->order = ReAlloc(infoPtr->order, sizeof(INT) * infoPtr->uNumItem);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -