📄 listview.c
字号:
/*
* Listview control
*
* Copyright 1998, 1999 Eric Kohl
* Copyright 1999 Luc Tourangeau
* Copyright 2000 Jason Mawdsley
* Copyright 2001 CodeWeavers Inc.
* Copyright 2002 Dimitrie O. Paun
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
* NOTES
*
* This code was audited for completeness against the documented features
* of Comctl32.dll version 6.0 on May. 20, 2005, by James Hawkins.
*
* Unless otherwise noted, we believe this code to be complete, as per
* the specification mentioned above.
* If you discover missing features, or bugs, please note them below.
*
* TODO:
*
* Default Message Processing
* -- EN_KILLFOCUS should be handled in WM_COMMAND
* -- WM_CREATE: create the icon and small icon image lists at this point only if
* the LVS_SHAREIMAGELISTS style is not specified.
* -- WM_ERASEBKGND: forward this message to the parent window if the bkgnd
* color is CLR_NONE.
* -- WM_WINDOWPOSCHANGED: arrange the list items if the current view is icon
* or small icon and the LVS_AUTOARRANGE style is specified.
* -- WM_TIMER
* -- WM_WININICHANGE
*
* Features
* -- Hot item handling, mouse hovering
* -- Workareas support
* -- Tilemode support
* -- Groups support
*
* Bugs
* -- Expand large item in ICON mode when the cursor is flying over the icon or text.
* -- Support CustomDraw options for _WIN32_IE >= 0x560 (see NMLVCUSTOMDRAW docs).
* -- LVA_SNAPTOGRID not implemented
* -- LISTVIEW_ApproximateViewRect partially implemented
* -- LISTVIEW_[GS]etColumnOrderArray stubs
* -- LISTVIEW_SetColumnWidth ignores header images & bitmap
* -- LISTVIEW_SetIconSpacing is incomplete
* -- LISTVIEW_SortItems is broken
* -- LISTVIEW_StyleChanged doesn't handle some changes too well
*
* Speedups
* -- LISTVIEW_GetNextItem needs to be rewritten. It is currently
* linear in the number of items in the list, and this is
* unacceptable for large lists.
* -- in sorted mode, LISTVIEW_InsertItemT sorts the array,
* instead of inserting in the right spot
* -- we should keep an ordered array of coordinates in iconic mode
* this would allow to frame items (iterator_frameditems),
* and find nearest item (LVFI_NEARESTXY) a lot more efficiently
*
* Flags
* -- LVIF_COLUMNS
* -- LVIF_GROUPID
* -- LVIF_NORECOMPUTE
*
* States
* -- LVIS_ACTIVATING (not currently supported by comctl32.dll version 6.0)
* -- LVIS_CUT
* -- LVIS_DROPHILITED
* -- LVIS_OVERLAYMASK
*
* Styles
* -- LVS_NOLABELWRAP
* -- LVS_NOSCROLL (see Q137520)
* -- LVS_SORTASCENDING, LVS_SORTDESCENDING
* -- LVS_ALIGNTOP
* -- LVS_TYPESTYLEMASK
*
* Extended Styles
* -- LVS_EX_BORDERSELECT
* -- LVS_EX_FLATSB
* -- LVS_EX_GRIDLINES
* -- LVS_EX_HEADERDRAGDROP
* -- LVS_EX_INFOTIP
* -- LVS_EX_LABELTIP
* -- LVS_EX_MULTIWORKAREAS
* -- LVS_EX_ONECLICKACTIVATE
* -- LVS_EX_REGIONAL
* -- LVS_EX_SIMPLESELECT
* -- LVS_EX_TRACKSELECT
* -- LVS_EX_TWOCLICKACTIVATE
* -- LVS_EX_UNDERLINECOLD
* -- LVS_EX_UNDERLINEHOT
*
* Notifications:
* -- LVN_BEGINSCROLL, LVN_ENDSCROLL
* -- LVN_GETINFOTIP
* -- LVN_HOTTRACK
* -- LVN_MARQUEEBEGIN
* -- LVN_ODFINDITEM
* -- LVN_SETDISPINFO
* -- NM_HOVER
* -- LVN_BEGINRDRAG
*
* Messages:
* -- LVM_CANCELEDITLABEL
* -- LVM_ENABLEGROUPVIEW
* -- LVM_GETBKIMAGE, LVM_SETBKIMAGE
* -- LVM_GETGROUPINFO, LVM_SETGROUPINFO
* -- LVM_GETGROUPMETRICS, LVM_SETGROUPMETRICS
* -- LVM_GETINSERTMARK, LVM_SETINSERTMARK
* -- LVM_GETINSERTMARKCOLOR, LVM_SETINSERTMARKCOLOR
* -- LVM_GETINSERTMARKRECT
* -- LVM_GETNUMBEROFWORKAREAS
* -- LVM_GETOUTLINECOLOR, LVM_SETOUTLINECOLOR
* -- LVM_GETSELECTEDCOLUMN, LVM_SETSELECTEDCOLUMN
* -- LVM_GETISEARCHSTRINGW, LVM_GETISEARCHSTRINGA
* -- LVM_GETTILEINFO, LVM_SETTILEINFO
* -- LVM_GETTILEVIEWINFO, LVM_SETTILEVIEWINFO
* -- LVM_GETUNICODEFORMAT, LVM_SETUNICODEFORMAT
* -- LVM_GETVIEW, LVM_SETVIEW
* -- LVM_GETWORKAREAS, LVM_SETWORKAREAS
* -- LVM_HASGROUP, LVM_INSERTGROUP, LVM_REMOVEGROUP, LVM_REMOVEALLGROUPS
* -- LVM_INSERTGROUPSORTED
* -- LVM_INSERTMARKHITTEST
* -- LVM_ISGROUPVIEWENABLED
* -- LVM_MAPIDTOINDEX, LVM_MAPINDEXTOID
* -- LVM_MOVEGROUP
* -- LVM_MOVEITEMTOGROUP
* -- LVM_SETINFOTIP
* -- LVM_SETTILEWIDTH
* -- LVM_SORTGROUPS
* -- LVM_SORTITEMSEX
*
* Macros:
* -- ListView_GetCheckSate, ListView_SetCheckState
* -- ListView_GetHoverTime, ListView_SetHoverTime
* -- ListView_GetISearchString
* -- ListView_GetNumberOfWorkAreas
* -- ListView_GetOrigin
* -- ListView_GetTextBkColor
* -- ListView_GetUnicodeFormat, ListView_SetUnicodeFormat
* -- ListView_GetWorkAreas, ListView_SetWorkAreas
* -- ListView_SortItemsEx
*
* Functions:
* -- LVGroupComparE
*
* Known differences in message stream from native control (not known if
* these differences cause problems):
* LVM_INSERTITEM issues LVM_SETITEMSTATE and LVM_SETITEM in certain cases.
* LVM_SETITEM does not always issue LVN_ITEMCHANGING/LVN_ITEMCHANGED.
* WM_CREATE does not issue WM_QUERYUISTATE and associated registry
* processing for "USEDOUBLECLICKTIME".
*/
#include "config.h"
#include "wine/port.h"
#include <assert.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include "windef.h"
#include "winbase.h"
#include "winnt.h"
#include "wingdi.h"
#include "winuser.h"
#include "winnls.h"
#include "commctrl.h"
#include "comctl32.h"
#include "uxtheme.h"
#include "wine/debug.h"
#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(listview);
/* make sure you set this to 0 for production use! */
#define DEBUG_RANGES 1
typedef struct tagCOLUMN_INFO
{
RECT rcHeader; /* tracks the header's rectangle */
int fmt; /* same as LVCOLUMN.fmt */
} COLUMN_INFO;
typedef struct tagITEMHDR
{
LPWSTR pszText;
INT iImage;
} ITEMHDR, *LPITEMHDR;
typedef struct tagSUBITEM_INFO
{
ITEMHDR hdr;
INT iSubItem;
} SUBITEM_INFO;
typedef struct tagITEM_INFO
{
ITEMHDR hdr;
UINT state;
LPARAM lParam;
INT iIndent;
} ITEM_INFO;
typedef struct tagRANGE
{
INT lower;
INT upper;
} RANGE;
typedef struct tagRANGES
{
HDPA hdpa;
} *RANGES;
typedef struct tagITERATOR
{
INT nItem;
INT nSpecial;
RANGE range;
RANGES ranges;
INT index;
} ITERATOR;
typedef struct tagDELAYED_ITEM_EDIT
{
BOOL fEnabled;
INT iItem;
} DELAYED_ITEM_EDIT;
typedef struct tagLISTVIEW_INFO
{
HWND hwndSelf;
HBRUSH hBkBrush;
COLORREF clrBk;
COLORREF clrText;
COLORREF clrTextBk;
HIMAGELIST himlNormal;
HIMAGELIST himlSmall;
HIMAGELIST himlState;
BOOL bLButtonDown;
BOOL bRButtonDown;
POINT ptClickPos; /* point where the user clicked */
BOOL bNoItemMetrics; /* flags if item metrics are not yet computed */
INT nItemHeight;
INT nItemWidth;
RANGES selectionRanges;
INT nSelectionMark;
INT nHotItem;
SHORT notifyFormat;
HWND hwndNotify;
RECT rcList; /* This rectangle is really the window
* client rectangle possibly reduced by the
* horizontal scroll bar and/or header - see
* LISTVIEW_UpdateSize. This rectangle offset
* by the LISTVIEW_GetOrigin value is in
* client coordinates */
SIZE iconSize;
SIZE iconSpacing;
SIZE iconStateSize;
UINT uCallbackMask;
HWND hwndHeader;
HCURSOR hHotCursor;
HFONT hDefaultFont;
HFONT hFont;
INT ntmHeight; /* Some cached metrics of the font used */
INT ntmMaxCharWidth; /* by the listview to draw items */
INT nEllipsisWidth;
BOOL bRedraw; /* Turns on/off repaints & invalidations */
BOOL bAutoarrange; /* Autoarrange flag when NOT in LVS_AUTOARRANGE */
BOOL bFocus;
BOOL bDoChangeNotify; /* send change notification messages? */
INT nFocusedItem;
RECT rcFocus;
DWORD dwStyle; /* the cached window GWL_STYLE */
DWORD dwLvExStyle; /* extended listview style */
INT nItemCount; /* the number of items in the list */
HDPA hdpaItems; /* array ITEM_INFO pointers */
HDPA hdpaPosX; /* maintains the (X, Y) coordinates of the */
HDPA hdpaPosY; /* items in LVS_ICON, and LVS_SMALLICON modes */
HDPA hdpaColumns; /* array of COLUMN_INFO pointers */
POINT currIconPos; /* this is the position next icon will be placed */
PFNLVCOMPARE pfnCompare;
LPARAM lParamSort;
HWND hwndEdit;
WNDPROC EditWndProc;
INT nEditLabelItem;
DWORD dwHoverTime;
HWND hwndToolTip;
DWORD cditemmode; /* Keep the custom draw flags for an item/row */
DWORD lastKeyPressTimestamp;
WPARAM charCode;
INT nSearchParamLength;
WCHAR szSearchParam[ MAX_PATH ];
BOOL bIsDrawing;
INT nMeasureItemHeight;
INT xTrackLine; /* The x coefficient of the track line or -1 if none */
DELAYED_ITEM_EDIT itemEdit; /* Pointer to this structure will be the timer ID */
} LISTVIEW_INFO;
/*
* constants
*/
/* How many we debug buffer to allocate */
#define DEBUG_BUFFERS 20
/* The size of a single debug bbuffer */
#define DEBUG_BUFFER_SIZE 256
/* Internal interface to LISTVIEW_HScroll and LISTVIEW_VScroll */
#define SB_INTERNAL -1
/* maximum size of a label */
#define DISP_TEXT_SIZE 512
/* padding for items in list and small icon display modes */
#define WIDTH_PADDING 12
/* padding for items in list, report and small icon display modes */
#define HEIGHT_PADDING 1
/* offset of items in report display mode */
#define REPORT_MARGINX 2
/* padding for icon in large icon display mode
* ICON_TOP_PADDING_NOTHITABLE - space between top of box and area
* that HITTEST will see.
* ICON_TOP_PADDING_HITABLE - spacing between above and icon.
* ICON_TOP_PADDING - sum of the two above.
* ICON_BOTTOM_PADDING - between bottom of icon and top of text
* LABEL_HOR_PADDING - between text and sides of box
* LABEL_VERT_PADDING - between bottom of text and end of box
*
* ICON_LR_PADDING - additional width above icon size.
* ICON_LR_HALF - half of the above value
*/
#define ICON_TOP_PADDING_NOTHITABLE 2
#define ICON_TOP_PADDING_HITABLE 2
#define ICON_TOP_PADDING (ICON_TOP_PADDING_NOTHITABLE + ICON_TOP_PADDING_HITABLE)
#define ICON_BOTTOM_PADDING 4
#define LABEL_HOR_PADDING 5
#define LABEL_VERT_PADDING 7
#define ICON_LR_PADDING 16
#define ICON_LR_HALF (ICON_LR_PADDING/2)
/* default label width for items in list and small icon display modes */
#define DEFAULT_LABEL_WIDTH 40
/* default column width for items in list display mode */
#define DEFAULT_COLUMN_WIDTH 128
/* Size of "line" scroll for V & H scrolls */
#define LISTVIEW_SCROLL_ICON_LINE_SIZE 37
/* Padding betwen image and label */
#define IMAGE_PADDING 2
/* Padding behind the label */
#define TRAILING_LABEL_PADDING 12
#define TRAILING_HEADER_PADDING 11
/* Border for the icon caption */
#define CAPTION_BORDER 2
/* Standard DrawText flags */
#define LV_ML_DT_FLAGS (DT_TOP | DT_NOPREFIX | DT_EDITCONTROL | DT_CENTER | DT_WORDBREAK | DT_WORD_ELLIPSIS | DT_END_ELLIPSIS)
#define LV_FL_DT_FLAGS (DT_TOP | DT_NOPREFIX | DT_EDITCONTROL | DT_CENTER | DT_WORDBREAK | DT_NOCLIP)
#define LV_SL_DT_FLAGS (DT_VCENTER | DT_NOPREFIX | DT_EDITCONTROL | DT_SINGLELINE | DT_WORD_ELLIPSIS | DT_END_ELLIPSIS)
/* Image index from state */
#define STATEIMAGEINDEX(x) (((x) & LVIS_STATEIMAGEMASK) >> 12)
/* The time in milliseconds to reset the search in the list */
#define KEY_DELAY 450
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -