📄 header.c
字号:
/* make space for the new item */
memmove(&infoPtr->items[nItem + 1], &infoPtr->items[nItem],
(infoPtr->uNumItem - nItem - 1) * sizeof(HEADER_ITEM));
memmove(&infoPtr->order[iOrder + 1], &infoPtr->order[iOrder],
(infoPtr->uNumItem - iOrder - 1) * sizeof(INT));
/* update the order array */
infoPtr->order[iOrder] = nItem;
for (i = 0; i < infoPtr->uNumItem; i++)
{
if (i != iOrder && infoPtr->order[i] >= nItem)
infoPtr->order[i]++;
infoPtr->items[infoPtr->order[i]].iOrder = i;
}
lpItem = &infoPtr->items[nItem];
ZeroMemory(lpItem, sizeof(HEADER_ITEM));
/* cxy, fmt and lParam are copied even if not in the HDITEM mask */
copyMask = phdi->mask | HDI_WIDTH | HDI_FORMAT | HDI_LPARAM;
HEADER_StoreHDItemInHeader(lpItem, copyMask, phdi, bUnicode);
lpItem->iOrder = iOrder;
/* set automatically some format bits */
if (phdi->mask & HDI_TEXT)
lpItem->fmt |= HDF_STRING;
else
lpItem->fmt &= ~HDF_STRING;
if (lpItem->hbm != NULL)
lpItem->fmt |= HDF_BITMAP;
else
lpItem->fmt &= ~HDF_BITMAP;
if (phdi->mask & HDI_IMAGE)
lpItem->fmt |= HDF_IMAGE;
HEADER_SetItemBounds (hwnd);
InvalidateRect(hwnd, NULL, FALSE);
return nItem;
}
static LRESULT
HEADER_Layout (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
LPHDLAYOUT lpLayout = (LPHDLAYOUT)lParam;
lpLayout->pwpos->hwnd = hwnd;
lpLayout->pwpos->hwndInsertAfter = 0;
lpLayout->pwpos->x = lpLayout->prc->left;
lpLayout->pwpos->y = lpLayout->prc->top;
lpLayout->pwpos->cx = lpLayout->prc->right - lpLayout->prc->left;
if (GetWindowLongW (hwnd, GWL_STYLE) & HDS_HIDDEN)
lpLayout->pwpos->cy = 0;
else {
lpLayout->pwpos->cy = infoPtr->nHeight;
lpLayout->prc->top += infoPtr->nHeight;
}
lpLayout->pwpos->flags = SWP_NOZORDER;
TRACE("Layout x=%d y=%d cx=%d cy=%d\n",
lpLayout->pwpos->x, lpLayout->pwpos->y,
lpLayout->pwpos->cx, lpLayout->pwpos->cy);
infoPtr->bRectsValid = FALSE;
return TRUE;
}
static LRESULT
HEADER_SetImageList (HWND hwnd, HIMAGELIST himl)
{
HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
HIMAGELIST himlOld;
TRACE("(himl %p)\n", himl);
himlOld = infoPtr->himl;
infoPtr->himl = himl;
/* FIXME: Refresh needed??? */
return (LRESULT)himlOld;
}
static LRESULT
HEADER_GetBitmapMargin(HWND hwnd)
{
HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd);
return infoPtr->iMargin;
}
static LRESULT
HEADER_SetBitmapMargin(HWND hwnd, WPARAM wParam)
{
HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
INT oldMargin = infoPtr->iMargin;
infoPtr->iMargin = (INT)wParam;
return oldMargin;
}
static LRESULT
HEADER_SetItemT (HWND hwnd, INT nItem, LPHDITEMW phdi, BOOL bUnicode)
{
HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
HEADER_ITEM *lpItem;
HDITEMW hdNotify;
void *pvScratch;
if (phdi == NULL)
return FALSE;
if ((nItem < 0) || (nItem >= (INT)infoPtr->uNumItem))
return FALSE;
TRACE("[nItem=%d]\n", nItem);
HEADER_CopyHDItemForNotify(infoPtr, &hdNotify, phdi, bUnicode, &pvScratch);
if (HEADER_SendNotifyWithHDItemT(hwnd, HDN_ITEMCHANGINGW, nItem, &hdNotify))
{
if (pvScratch) Free(pvScratch);
return FALSE;
}
lpItem = &infoPtr->items[nItem];
HEADER_StoreHDItemInHeader(lpItem, phdi->mask, phdi, bUnicode);
if (phdi->mask & HDI_ORDER)
if (phdi->iOrder >= 0 && phdi->iOrder < infoPtr->uNumItem)
HEADER_ChangeItemOrder(infoPtr, nItem, phdi->iOrder);
HEADER_SendNotifyWithHDItemT(hwnd, HDN_ITEMCHANGEDW, nItem, &hdNotify);
HEADER_SetItemBounds (hwnd);
InvalidateRect(hwnd, NULL, FALSE);
if (pvScratch != NULL)
Free(pvScratch);
return TRUE;
}
inline static LRESULT
HEADER_SetUnicodeFormat (HWND hwnd, WPARAM wParam)
{
HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
BOOL bTemp = (infoPtr->nNotifyFormat == NFR_UNICODE);
infoPtr->nNotifyFormat = ((BOOL)wParam ? NFR_UNICODE : NFR_ANSI);
return bTemp;
}
static LRESULT
HEADER_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
HEADER_INFO *infoPtr;
TEXTMETRICW tm;
HFONT hOldFont;
HDC hdc;
infoPtr = (HEADER_INFO *)Alloc (sizeof(HEADER_INFO));
SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr);
infoPtr->hwndNotify = ((LPCREATESTRUCTA)lParam)->hwndParent;
infoPtr->uNumItem = 0;
infoPtr->hFont = 0;
infoPtr->items = 0;
infoPtr->order = 0;
infoPtr->bRectsValid = FALSE;
infoPtr->hcurArrow = LoadCursorW (0, (LPWSTR)IDC_ARROW);
infoPtr->hcurDivider = LoadCursorW (COMCTL32_hModule, MAKEINTRESOURCEW(IDC_DIVIDER));
infoPtr->hcurDivopen = LoadCursorW (COMCTL32_hModule, MAKEINTRESOURCEW(IDC_DIVIDEROPEN));
infoPtr->bPressed = FALSE;
infoPtr->bTracking = FALSE;
infoPtr->iMoveItem = 0;
infoPtr->himl = 0;
infoPtr->iHotItem = -1;
infoPtr->iHotDivider = -1;
infoPtr->iMargin = 3*GetSystemMetrics(SM_CXEDGE);
infoPtr->nNotifyFormat =
SendMessageW (infoPtr->hwndNotify, WM_NOTIFYFORMAT, (WPARAM)hwnd, NF_QUERY);
hdc = GetDC (0);
hOldFont = SelectObject (hdc, GetStockObject (SYSTEM_FONT));
GetTextMetricsW (hdc, &tm);
infoPtr->nHeight = tm.tmHeight + VERT_BORDER;
SelectObject (hdc, hOldFont);
ReleaseDC (0, hdc);
OpenThemeData(hwnd, themeClass);
return 0;
}
static LRESULT
HEADER_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
HEADER_ITEM *lpItem;
INT nItem;
HTHEME theme;
if (infoPtr->items) {
lpItem = infoPtr->items;
for (nItem = 0; nItem < infoPtr->uNumItem; nItem++, lpItem++) {
HEADER_DisposeItem(lpItem);
}
Free (infoPtr->items);
}
if (infoPtr->order)
Free(infoPtr->order);
if (infoPtr->himl)
ImageList_Destroy (infoPtr->himl);
SetWindowLongPtrW (hwnd, 0, 0);
Free (infoPtr);
theme = GetWindowTheme(hwnd);
CloseThemeData(theme);
return 0;
}
static inline LRESULT
HEADER_GetFont (HWND hwnd)
{
HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
return (LRESULT)infoPtr->hFont;
}
static BOOL
HEADER_IsDragDistance(HEADER_INFO *infoPtr, POINT *pt)
{
/* Windows allows for a mouse movement before starting the drag. We use the
* SM_CXDOUBLECLICK/SM_CYDOUBLECLICK as that distance.
*/
return (abs(infoPtr->ptLButtonDown.x - pt->x)>GetSystemMetrics(SM_CXDOUBLECLK) ||
abs(infoPtr->ptLButtonDown.y - pt->y)>GetSystemMetrics(SM_CYDOUBLECLK));
}
static LRESULT
HEADER_LButtonDblClk (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
POINT pt;
UINT flags;
INT nItem;
pt.x = (short)LOWORD(lParam);
pt.y = (short)HIWORD(lParam);
HEADER_InternalHitTest (hwnd, &pt, &flags, &nItem);
if ((GetWindowLongW (hwnd, GWL_STYLE) & HDS_BUTTONS) && (flags == HHT_ONHEADER))
HEADER_SendNotifyWithHDItemT(hwnd, HDN_ITEMDBLCLICKW, nItem, NULL);
else if ((flags == HHT_ONDIVIDER) || (flags == HHT_ONDIVOPEN))
HEADER_SendNotifyWithHDItemT(hwnd, HDN_DIVIDERDBLCLICKW, nItem, NULL);
return 0;
}
static LRESULT
HEADER_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
DWORD dwStyle = GetWindowLongW (hwnd, GWL_STYLE);
POINT pt;
UINT flags;
INT nItem;
HDC hdc;
pt.x = (short)LOWORD(lParam);
pt.y = (short)HIWORD(lParam);
HEADER_InternalHitTest (hwnd, &pt, &flags, &nItem);
if ((dwStyle & HDS_BUTTONS) && (flags == HHT_ONHEADER)) {
SetCapture (hwnd);
infoPtr->bCaptured = TRUE;
infoPtr->bPressed = TRUE;
infoPtr->bDragging = FALSE;
infoPtr->iMoveItem = nItem;
infoPtr->ptLButtonDown = pt;
infoPtr->items[nItem].bDown = TRUE;
/* Send WM_CUSTOMDRAW */
hdc = GetDC (hwnd);
HEADER_RefreshItem (hwnd, hdc, nItem);
ReleaseDC (hwnd, hdc);
TRACE("Pressed item %d!\n", nItem);
}
else if ((flags == HHT_ONDIVIDER) || (flags == HHT_ONDIVOPEN)) {
INT iCurrWidth = infoPtr->items[nItem].cxy;
if (!HEADER_SendNotifyWithIntFieldT(hwnd, HDN_BEGINTRACKW, nItem, HDI_WIDTH, iCurrWidth))
{
SetCapture (hwnd);
infoPtr->bCaptured = TRUE;
infoPtr->bTracking = TRUE;
infoPtr->iMoveItem = nItem;
infoPtr->xTrackOffset = infoPtr->items[nItem].rect.right - pt.x;
if (!(dwStyle & HDS_FULLDRAG)) {
infoPtr->xOldTrack = infoPtr->items[nItem].rect.right;
hdc = GetDC (hwnd);
HEADER_DrawTrackLine (hwnd, hdc, infoPtr->xOldTrack);
ReleaseDC (hwnd, hdc);
}
TRACE("Begin tracking item %d!\n", nItem);
}
}
return 0;
}
static LRESULT
HEADER_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
DWORD dwStyle = GetWindowLongW (hwnd, GWL_STYLE);
POINT pt;
UINT flags;
INT nItem;
HDC hdc;
pt.x = (INT)(SHORT)LOWORD(lParam);
pt.y = (INT)(SHORT)HIWORD(lParam);
HEADER_InternalHitTest (hwnd, &pt, &flags, &nItem);
if (infoPtr->bPressed) {
if (infoPtr->bDragging)
{
HEADER_ITEM *lpItem = &infoPtr->items[infoPtr->iMoveItem];
INT iNewOrder;
ImageList_DragShowNolock(FALSE);
ImageList_EndDrag();
lpItem->bDown=FALSE;
if (infoPtr->iHotDivider == -1)
iNewOrder = -1;
else if (infoPtr->iHotDivider == infoPtr->uNumItem)
iNewOrder = infoPtr->uNumItem-1;
else
{
iNewOrder = HEADER_IndexToOrder(hwnd, infoPtr->iHotDivider);
if (iNewOrder > lpItem->iOrder)
iNewOrder--;
}
if (iNewOrder != -1 &&
!HEADER_SendNotifyWithIntFieldT(hwnd, HDN_ENDDRAG, infoPtr->iMoveItem, HDI_ORDER, iNewOrder))
{
HEADER_ChangeItemOrder(infoPtr, infoPtr->iMoveItem, iNewOrder);
infoPtr->bRectsValid = FALSE;
InvalidateRect(hwnd, NULL, FALSE);
}
else
InvalidateRect(hwnd, &infoPtr->items[infoPtr->iMoveItem].rect, FALSE);
HEADER_SetHotDivider(hwnd, FALSE, -1);
}
else if (!(dwStyle&HDS_DRAGDROP) || !HEADER_IsDragDistance(infoPtr, &pt))
{
infoPtr->items[infoPtr->iMoveItem].bDown = FALSE;
hdc = GetDC (hwnd);
HEADER_RefreshItem (hwnd, hdc, infoPtr->iMoveItem);
ReleaseDC (hwnd, hdc);
HEADER_SendNotifyWithHDItemT(hwnd, HDN_ITEMCLICKW, infoPtr->iMoveItem, NULL);
}
TRACE("Released item %d!\n", infoPtr->iMoveItem);
infoPtr->bPressed = FALSE;
}
else if (infoPtr->bTracking) {
INT iNewWidth = pt.x - infoPtr->items[infoPtr->iMoveItem].rect.left + infoPtr->xTrackOffset;
if (iNewWidth < 0)
iNewWidth = 0;
TRACE("End tracking item %d!\n", infoPtr->iMoveItem);
infoPtr->bTracking = FALSE;
HEADER_SendNotifyWithIntFieldT(hwnd, HDN_ENDTRACKW, infoPtr->iMoveItem, HDI_WIDTH, iNewWidth);
if (!(dwStyle & HDS_FULLDRAG)) {
hdc = GetDC (hwnd);
HEADER_DrawTrackLine (hwnd, hdc, infoPtr->xOldTrack);
ReleaseDC (hwnd, hdc);
}
if (!HEADER_SendNotifyWithIntFieldT(hwnd, HDN_ITEMCHANGINGW, infoPtr->iMoveItem, HDI_WIDTH, iNewWidth))
{
infoPtr->items[infoPtr->iMoveItem].cxy = iNewWidth;
HEADER_SendNotifyWithIntFieldT(hwnd, HDN_ITEMCHANGEDW, infoPtr->iMoveItem, HDI_WIDTH, iNewWidth);
}
HEADER_SetItemBounds (hwnd);
InvalidateRect(hwnd, NULL, TRUE);
}
if (infoPtr->bCaptured) {
infoPtr->bCaptured = FALSE;
ReleaseCapture ();
HEADER_SendSimpleNotify (hwnd, NM_RELEASEDCAPTURE);
}
return 0;
}
static LRESULT
HEADER_NotifyFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
switch (lParam)
{
case NF_QUERY:
return infoPtr->nNotifyFormat;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -