Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
fa3e750e
Commit
fa3e750e
authored
May 11, 2014
by
Nikolay Sivov
Committed by
Alexandre Julliard
May 12, 2014
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
comctl32/listview: Fix custom draw stage sequence.
parent
dcab5fe6
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
269 additions
and
135 deletions
+269
-135
listview.c
dlls/comctl32/listview.c
+200
-121
listview.c
dlls/comctl32/tests/listview.c
+69
-14
No files found.
dlls/comctl32/listview.c
View file @
fa3e750e
...
...
@@ -6,7 +6,7 @@
* Copyright 2000 Jason Mawdsley
* Copyright 2001 CodeWeavers Inc.
* Copyright 2002 Dimitrie O. Paun
* Copyright 2009-201
3
Nikolay Sivov
* Copyright 2009-201
4
Nikolay Sivov
* Copyright 2009 Owen Rudge for CodeWeavers
* Copyright 2012-2013 Daniel Jelinski
*
...
...
@@ -331,7 +331,6 @@ typedef struct tagLISTVIEW_INFO
WCHAR
szSearchParam
[
MAX_PATH
];
/* painting */
DWORD
cditemmode
;
/* Keep the custom draw flags for an item/row */
BOOL
bIsDrawing
;
/* Drawing in progress */
INT
nMeasureItemHeight
;
/* WM_MEASUREITEM result */
BOOL
bRedraw
;
/* WM_SETREDRAW switch */
...
...
@@ -1052,10 +1051,7 @@ static inline DWORD notify_customdraw (const LISTVIEW_INFO *infoPtr, DWORD dwDra
static
void
prepaint_setup
(
const
LISTVIEW_INFO
*
infoPtr
,
HDC
hdc
,
NMLVCUSTOMDRAW
*
lpnmlvcd
,
BOOL
SubItem
)
{
if
(
lpnmlvcd
->
clrTextBk
==
CLR_DEFAULT
)
lpnmlvcd
->
clrTextBk
=
comctl32_color
.
clrWindow
;
if
(
lpnmlvcd
->
clrText
==
CLR_DEFAULT
)
lpnmlvcd
->
clrText
=
comctl32_color
.
clrWindowText
;
COLORREF
backcolor
,
textcolor
;
/* apparently, for selected items, we have to override the returned values */
if
(
!
SubItem
)
...
...
@@ -1075,15 +1071,23 @@ static void prepaint_setup (const LISTVIEW_INFO *infoPtr, HDC hdc, NMLVCUSTOMDRA
}
}
backcolor
=
lpnmlvcd
->
clrTextBk
;
textcolor
=
lpnmlvcd
->
clrText
;
if
(
backcolor
==
CLR_DEFAULT
)
backcolor
=
comctl32_color
.
clrWindow
;
if
(
textcolor
==
CLR_DEFAULT
)
textcolor
=
comctl32_color
.
clrWindowText
;
/* Set the text attributes */
if
(
lpnmlvcd
->
clrTextBk
!=
CLR_NONE
)
if
(
backcolor
!=
CLR_NONE
)
{
SetBkMode
(
hdc
,
OPAQUE
);
SetBkColor
(
hdc
,
lpnmlvcd
->
clrTextBk
);
SetBkColor
(
hdc
,
backcolor
);
}
else
SetBkMode
(
hdc
,
TRANSPARENT
);
SetTextColor
(
hdc
,
lpnmlvcd
->
clrText
);
SetTextColor
(
hdc
,
textcolor
);
}
static
inline
DWORD
notify_postpaint
(
const
LISTVIEW_INFO
*
infoPtr
,
NMLVCUSTOMDRAW
*
lpnmlvcd
)
...
...
@@ -4543,87 +4547,28 @@ static inline BOOL LISTVIEW_FillBkgnd(const LISTVIEW_INFO *infoPtr, HDC hdc, con
return
FillRect
(
hdc
,
lprcBox
,
infoPtr
->
hBkBrush
);
}
/***
* DESCRIPTION:
* Draws an item.
*
* PARAMETER(S):
* [I] infoPtr : valid pointer to the listview structure
* [I] hdc : device context handle
* [I] nItem : item index
* [I] nSubItem : subitem index
* [I] pos : item position in client coordinates
* [I] cdmode : custom draw mode
*
* RETURN:
* Success: TRUE
* Failure: FALSE
*/
static
BOOL
LISTVIEW_DrawItem
(
LISTVIEW_INFO
*
infoPtr
,
HDC
hdc
,
INT
nItem
,
INT
nSubItem
,
POINT
pos
,
DWORD
cdmode
)
/* Draw main item or subitem */
static
void
LISTVIEW_DrawItemPart
(
LISTVIEW_INFO
*
infoPtr
,
LVITEMW
*
item
,
const
NMLVCUSTOMDRAW
*
nmlvcd
,
const
POINT
*
pos
)
{
UINT
uFormat
;
WCHAR
szDispText
[
DISP_TEXT_SIZE
]
=
{
'\0'
};
static
WCHAR
szCallback
[]
=
{
'('
,
'c'
,
'a'
,
'l'
,
'l'
,
'b'
,
'a'
,
'c'
,
'k'
,
')'
,
0
};
DWORD
cdsubitemmode
=
CDRF_DODEFAULT
;
LPRECT
lprcFocus
;
RECT
rcSelect
,
rcBox
,
rcIcon
,
rcLabel
,
rcStateIcon
;
NMLVCUSTOMDRAW
nmlvcd
;
RECT
rcSelect
,
rcLabel
,
rcBox
,
rcStateIcon
,
rcIcon
;
HIMAGELIST
himl
;
LVITEMW
lvItem
;
TRACE
(
"(hdc=%p, nItem=%d, nSubItem=%d, pos=%s)
\n
"
,
hdc
,
nItem
,
nSubItem
,
wine_dbgstr_point
(
&
pos
));
/* get information needed for drawing the item */
lvItem
.
mask
=
LVIF_TEXT
|
LVIF_IMAGE
|
LVIF_PARAM
;
if
(
nSubItem
==
0
)
lvItem
.
mask
|=
LVIF_STATE
;
if
(
infoPtr
->
uView
==
LV_VIEW_DETAILS
)
lvItem
.
mask
|=
LVIF_INDENT
;
lvItem
.
stateMask
=
LVIS_SELECTED
|
LVIS_FOCUSED
|
LVIS_STATEIMAGEMASK
|
LVIS_CUT
|
LVIS_OVERLAYMASK
;
lvItem
.
iItem
=
nItem
;
lvItem
.
iSubItem
=
nSubItem
;
lvItem
.
state
=
0
;
lvItem
.
lParam
=
0
;
lvItem
.
cchTextMax
=
DISP_TEXT_SIZE
;
lvItem
.
pszText
=
szDispText
;
if
(
!
LISTVIEW_GetItemW
(
infoPtr
,
&
lvItem
))
return
FALSE
;
if
(
nSubItem
>
0
&&
(
infoPtr
->
dwLvExStyle
&
LVS_EX_FULLROWSELECT
))
lvItem
.
state
=
LISTVIEW_GetItemState
(
infoPtr
,
nItem
,
LVIS_SELECTED
);
if
(
lvItem
.
pszText
==
LPSTR_TEXTCALLBACKW
)
lvItem
.
pszText
=
szCallback
;
TRACE
(
" lvItem=%s
\n
"
,
debuglvitem_t
(
&
lvItem
,
TRUE
));
UINT
format
;
RECT
*
focus
;
/* now check if we need to update the focus rectangle */
lprcFocus
=
infoPtr
->
bFocus
&&
(
lvItem
.
state
&
LVIS_FOCUSED
)
?
&
infoPtr
->
rcFocus
:
0
;
if
(
!
lprcFocus
)
lvItem
.
state
&=
~
LVIS_FOCUSED
;
LISTVIEW_GetItemMetrics
(
infoPtr
,
&
lvI
tem
,
&
rcBox
,
&
rcSelect
,
&
rcIcon
,
&
rcStateIcon
,
&
rcLabel
);
OffsetRect
(
&
rcBox
,
pos
.
x
,
pos
.
y
);
OffsetRect
(
&
rcSelect
,
pos
.
x
,
pos
.
y
);
OffsetRect
(
&
rcIcon
,
pos
.
x
,
pos
.
y
);
OffsetRect
(
&
rcStateIcon
,
pos
.
x
,
pos
.
y
);
OffsetRect
(
&
rcLabel
,
pos
.
x
,
pos
.
y
);
focus
=
infoPtr
->
bFocus
&&
(
item
->
state
&
LVIS_FOCUSED
)
?
&
infoPtr
->
rcFocus
:
0
;
if
(
!
focus
)
item
->
state
&=
~
LVIS_FOCUSED
;
LISTVIEW_GetItemMetrics
(
infoPtr
,
i
tem
,
&
rcBox
,
&
rcSelect
,
&
rcIcon
,
&
rcStateIcon
,
&
rcLabel
);
OffsetRect
(
&
rcBox
,
pos
->
x
,
pos
->
y
);
OffsetRect
(
&
rcSelect
,
pos
->
x
,
pos
->
y
);
OffsetRect
(
&
rcIcon
,
pos
->
x
,
pos
->
y
);
OffsetRect
(
&
rcStateIcon
,
pos
->
x
,
pos
->
y
);
OffsetRect
(
&
rcLabel
,
pos
->
x
,
pos
->
y
);
TRACE
(
" rcBox=%s, rcSelect=%s, rcIcon=%s. rcLabel=%s
\n
"
,
wine_dbgstr_rect
(
&
rcBox
),
wine_dbgstr_rect
(
&
rcSelect
),
wine_dbgstr_rect
(
&
rcIcon
),
wine_dbgstr_rect
(
&
rcLabel
));
/* fill in the custom draw structure */
customdraw_fill
(
&
nmlvcd
,
infoPtr
,
hdc
,
&
rcBox
,
&
lvItem
);
if
(
nSubItem
>
0
)
cdmode
=
infoPtr
->
cditemmode
;
if
(
cdmode
&
CDRF_SKIPDEFAULT
)
goto
postpaint
;
if
(
cdmode
&
CDRF_NOTIFYITEMDRAW
)
cdsubitemmode
=
notify_customdraw
(
infoPtr
,
CDDS_PREPAINT
,
&
nmlvcd
);
if
(
nSubItem
==
0
)
infoPtr
->
cditemmode
=
cdsubitemmode
;
if
(
cdsubitemmode
&
CDRF_SKIPDEFAULT
)
goto
postpaint
;
/* we have to send a CDDS_SUBITEM customdraw explicitly for subitem 0 */
if
(
nSubItem
==
0
&&
(
cdsubitemmode
&
CDRF_NOTIFYITEMDRAW
)
!=
0
)
{
cdsubitemmode
=
notify_customdraw
(
infoPtr
,
CDDS_SUBITEM
|
CDDS_ITEMPREPAINT
,
&
nmlvcd
);
if
(
cdsubitemmode
&
CDRF_SKIPDEFAULT
)
goto
postpaint
;
}
if
(
nSubItem
==
0
||
(
cdmode
&
CDRF_NOTIFYITEMDRAW
))
prepaint_setup
(
infoPtr
,
hdc
,
&
nmlvcd
,
FALSE
);
else
if
((
infoPtr
->
dwLvExStyle
&
LVS_EX_FULLROWSELECT
)
==
FALSE
)
prepaint_setup
(
infoPtr
,
hdc
,
&
nmlvcd
,
TRUE
);
/* FIXME: temporary hack */
rcSelect
.
left
=
rcLabel
.
left
;
...
...
@@ -4632,16 +4577,15 @@ static BOOL LISTVIEW_DrawItem(LISTVIEW_INFO *infoPtr, HDC hdc, INT nItem, INT nS
/* in detail mode, we want to paint background for label rect when
* item is not selected or listview has full row select; otherwise paint
* background for text only */
if
(
infoPtr
->
uView
==
LV_VIEW_ICON
||
(
infoPtr
->
uView
==
LV_VIEW_DETAILS
&&
(
!
(
lvItem
.
state
&
LVIS_SELECTED
)
||
(
infoPtr
->
dwLvExStyle
&
LVS_EX_FULLROWSELECT
)
!=
0
)))
if
(
infoPtr
->
uView
==
LV_VIEW_ICON
||
(
infoPtr
->
uView
==
LV_VIEW_DETAILS
&&
(
!
(
item
->
state
&
LVIS_SELECTED
)
||
(
infoPtr
->
dwLvExStyle
&
LVS_EX_FULLROWSELECT
))))
rcSelect
=
rcLabel
;
if
(
nmlvcd
.
clrTextBk
!=
CLR_NONE
)
ExtTextOutW
(
hdc
,
rcSelect
.
left
,
rcSelect
.
top
,
ETO_OPAQUE
,
&
rcSelect
,
NULL
,
0
,
NULL
);
if
(
nmlvcd
->
clrTextBk
!=
CLR_NONE
)
ExtTextOutW
(
nmlvcd
->
nmcd
.
hdc
,
rcSelect
.
left
,
rcSelect
.
top
,
ETO_OPAQUE
,
&
rcSelect
,
NULL
,
0
,
NULL
);
if
(
nSubItem
==
0
&&
infoPtr
->
nFocusedItem
==
nItem
)
if
(
item
->
state
&
LVIS_FOCUSED
)
{
if
(
infoPtr
->
uView
==
LV_VIEW_DETAILS
&&
(
infoPtr
->
dwLvExStyle
&
LVS_EX_FULLROWSELECT
))
{
...
...
@@ -4653,7 +4597,7 @@ static BOOL LISTVIEW_DrawItem(LISTVIEW_INFO *infoPtr, HDC hdc, INT nItem, INT nS
if
((
leftmost
=
SendMessageW
(
infoPtr
->
hwndHeader
,
HDM_ORDERTOINDEX
,
0
,
0
)))
{
INT
Originx
=
pos
.
x
-
LISTVIEW_GetColumnInfo
(
infoPtr
,
0
)
->
rcHeader
.
left
;
INT
Originx
=
pos
->
x
-
LISTVIEW_GetColumnInfo
(
infoPtr
,
0
)
->
rcHeader
.
left
;
INT
index
=
SendMessageW
(
infoPtr
->
hwndHeader
,
HDM_ORDERTOINDEX
,
DPA_GetPtrCount
(
infoPtr
->
hdpaColumns
)
-
1
,
0
);
...
...
@@ -4670,68 +4614,196 @@ static BOOL LISTVIEW_DrawItem(LISTVIEW_INFO *infoPtr, HDC hdc, INT nItem, INT nS
}
/* state icons */
if
(
infoPtr
->
himlState
&&
STATEIMAGEINDEX
(
lvItem
.
state
)
&&
(
n
SubItem
==
0
))
if
(
infoPtr
->
himlState
&&
STATEIMAGEINDEX
(
item
->
state
)
&&
(
item
->
i
SubItem
==
0
))
{
UINT
uStateImage
=
STATEIMAGEINDEX
(
lvItem
.
state
);
if
(
uStateI
mage
)
UINT
stateimage
=
STATEIMAGEINDEX
(
item
->
state
);
if
(
statei
mage
)
{
TRACE
(
"uStateImage=%d
\n
"
,
uStateImage
);
ImageList_Draw
(
infoPtr
->
himlState
,
uStateImage
-
1
,
hdc
,
rcStateIcon
.
left
,
rcStateIcon
.
top
,
ILD_NORMAL
);
TRACE
(
"stateimage=%d
\n
"
,
stateimage
);
ImageList_Draw
(
infoPtr
->
himlState
,
stateimage
-
1
,
nmlvcd
->
nmcd
.
hdc
,
rcStateIcon
.
left
,
rcStateIcon
.
top
,
ILD_NORMAL
);
}
}
/* item icons */
himl
=
(
infoPtr
->
uView
==
LV_VIEW_ICON
?
infoPtr
->
himlNormal
:
infoPtr
->
himlSmall
);
if
(
himl
&&
lvItem
.
iImage
>=
0
&&
!
IsRectEmpty
(
&
rcIcon
))
if
(
himl
&&
item
->
iImage
>=
0
&&
!
IsRectEmpty
(
&
rcIcon
))
{
UINT
style
;
TRACE
(
"iImage=%d
\n
"
,
lvItem
.
iImage
);
TRACE
(
"iImage=%d
\n
"
,
item
->
iImage
);
if
(
lvItem
.
state
&
(
LVIS_SELECTED
|
LVIS_CUT
)
&&
infoPtr
->
bFocus
)
if
(
item
->
state
&
(
LVIS_SELECTED
|
LVIS_CUT
)
&&
infoPtr
->
bFocus
)
style
=
ILD_SELECTED
;
else
style
=
ILD_NORMAL
;
ImageList_DrawEx
(
himl
,
lvItem
.
iImage
,
hdc
,
rcIcon
.
left
,
rcIcon
.
top
,
ImageList_DrawEx
(
himl
,
item
->
iImage
,
nmlvcd
->
nmcd
.
hdc
,
rcIcon
.
left
,
rcIcon
.
top
,
rcIcon
.
right
-
rcIcon
.
left
,
rcIcon
.
bottom
-
rcIcon
.
top
,
infoPtr
->
clrBk
,
lvItem
.
state
&
LVIS_CUT
?
RGB
(
255
,
255
,
255
)
:
CLR_DEFAULT
,
style
|
(
lvItem
.
state
&
LVIS_OVERLAYMASK
));
item
->
state
&
LVIS_CUT
?
RGB
(
255
,
255
,
255
)
:
CLR_DEFAULT
,
style
|
(
item
->
state
&
LVIS_OVERLAYMASK
));
}
/* Don't bother painting item being edited */
if
(
infoPtr
->
hwndEdit
&&
nItem
==
infoPtr
->
nEditLabelItem
&&
nSubItem
==
0
)
goto
postpaint
;
if
(
infoPtr
->
hwndEdit
&&
item
->
iItem
==
infoPtr
->
nEditLabelItem
&&
item
->
iSubItem
==
0
)
return
;
/* figure out the text drawing flags */
uFormat
=
(
infoPtr
->
uView
==
LV_VIEW_ICON
?
(
lprcF
ocus
?
LV_FL_DT_FLAGS
:
LV_ML_DT_FLAGS
)
:
LV_SL_DT_FLAGS
);
format
=
(
infoPtr
->
uView
==
LV_VIEW_ICON
?
(
f
ocus
?
LV_FL_DT_FLAGS
:
LV_ML_DT_FLAGS
)
:
LV_SL_DT_FLAGS
);
if
(
infoPtr
->
uView
==
LV_VIEW_ICON
)
uFormat
=
(
lprcF
ocus
?
LV_FL_DT_FLAGS
:
LV_ML_DT_FLAGS
);
else
if
(
n
SubItem
)
format
=
(
f
ocus
?
LV_FL_DT_FLAGS
:
LV_ML_DT_FLAGS
);
else
if
(
item
->
i
SubItem
)
{
switch
(
LISTVIEW_GetColumnInfo
(
infoPtr
,
n
SubItem
)
->
fmt
&
LVCFMT_JUSTIFYMASK
)
switch
(
LISTVIEW_GetColumnInfo
(
infoPtr
,
item
->
i
SubItem
)
->
fmt
&
LVCFMT_JUSTIFYMASK
)
{
case
LVCFMT_RIGHT
:
uF
ormat
|=
DT_RIGHT
;
break
;
case
LVCFMT_CENTER
:
uF
ormat
|=
DT_CENTER
;
break
;
default:
uF
ormat
|=
DT_LEFT
;
case
LVCFMT_RIGHT
:
f
ormat
|=
DT_RIGHT
;
break
;
case
LVCFMT_CENTER
:
f
ormat
|=
DT_CENTER
;
break
;
default:
f
ormat
|=
DT_LEFT
;
}
}
if
(
!
(
uF
ormat
&
(
DT_RIGHT
|
DT_CENTER
)))
if
(
!
(
f
ormat
&
(
DT_RIGHT
|
DT_CENTER
)))
{
if
(
himl
&&
lvItem
.
iImage
>=
0
&&
!
IsRectEmpty
(
&
rcIcon
))
rcLabel
.
left
+=
IMAGE_PADDING
;
if
(
himl
&&
item
->
iImage
>=
0
&&
!
IsRectEmpty
(
&
rcIcon
))
rcLabel
.
left
+=
IMAGE_PADDING
;
else
rcLabel
.
left
+=
LABEL_HOR_PADDING
;
}
else
if
(
uF
ormat
&
DT_RIGHT
)
rcLabel
.
right
-=
LABEL_HOR_PADDING
;
else
if
(
f
ormat
&
DT_RIGHT
)
rcLabel
.
right
-=
LABEL_HOR_PADDING
;
/* for GRIDLINES reduce the bottom so the text formats correctly */
if
(
infoPtr
->
uView
==
LV_VIEW_DETAILS
&&
infoPtr
->
dwLvExStyle
&
LVS_EX_GRIDLINES
)
rcLabel
.
bottom
--
;
DrawTextW
(
hdc
,
lvItem
.
pszText
,
-
1
,
&
rcLabel
,
uFormat
);
DrawTextW
(
nmlvcd
->
nmcd
.
hdc
,
item
->
pszText
,
-
1
,
&
rcLabel
,
format
);
}
/***
* DESCRIPTION:
* Draws an item.
*
* PARAMETER(S):
* [I] infoPtr : valid pointer to the listview structure
* [I] hdc : device context handle
* [I] nItem : item index
* [I] nSubItem : subitem index
* [I] pos : item position in client coordinates
* [I] cdmode : custom draw mode
*
* RETURN:
* Success: TRUE
* Failure: FALSE
*/
static
BOOL
LISTVIEW_DrawItem
(
LISTVIEW_INFO
*
infoPtr
,
HDC
hdc
,
INT
nItem
,
ITERATOR
*
subitems
,
POINT
pos
,
DWORD
cdmode
)
{
WCHAR
szDispText
[
DISP_TEXT_SIZE
]
=
{
'\0'
};
static
WCHAR
callbackW
[]
=
{
'('
,
'c'
,
'a'
,
'l'
,
'l'
,
'b'
,
'a'
,
'c'
,
'k'
,
')'
,
0
};
DWORD
cdsubitemmode
=
CDRF_DODEFAULT
;
RECT
*
focus
,
rcBox
;
NMLVCUSTOMDRAW
nmlvcd
;
LVITEMW
lvItem
;
TRACE
(
"(hdc=%p, nItem=%d, subitems=%p, pos=%s)
\n
"
,
hdc
,
nItem
,
subitems
,
wine_dbgstr_point
(
&
pos
));
/* get information needed for drawing the item */
lvItem
.
mask
=
LVIF_TEXT
|
LVIF_IMAGE
|
LVIF_PARAM
|
LVIF_STATE
;
if
(
infoPtr
->
uView
==
LV_VIEW_DETAILS
)
lvItem
.
mask
|=
LVIF_INDENT
;
lvItem
.
stateMask
=
LVIS_SELECTED
|
LVIS_FOCUSED
|
LVIS_STATEIMAGEMASK
|
LVIS_CUT
|
LVIS_OVERLAYMASK
;
lvItem
.
iItem
=
nItem
;
lvItem
.
iSubItem
=
0
;
lvItem
.
state
=
0
;
lvItem
.
lParam
=
0
;
lvItem
.
cchTextMax
=
DISP_TEXT_SIZE
;
lvItem
.
pszText
=
szDispText
;
if
(
!
LISTVIEW_GetItemW
(
infoPtr
,
&
lvItem
))
return
FALSE
;
if
(
lvItem
.
pszText
==
LPSTR_TEXTCALLBACKW
)
lvItem
.
pszText
=
callbackW
;
TRACE
(
" lvItem=%s
\n
"
,
debuglvitem_t
(
&
lvItem
,
TRUE
));
/* now check if we need to update the focus rectangle */
focus
=
infoPtr
->
bFocus
&&
(
lvItem
.
state
&
LVIS_FOCUSED
)
?
&
infoPtr
->
rcFocus
:
0
;
if
(
!
focus
)
lvItem
.
state
&=
~
LVIS_FOCUSED
;
LISTVIEW_GetItemMetrics
(
infoPtr
,
&
lvItem
,
&
rcBox
,
NULL
,
NULL
,
NULL
,
NULL
);
OffsetRect
(
&
rcBox
,
pos
.
x
,
pos
.
y
);
/* Full custom draw stage sequence looks like this:
LV_VIEW_DETAILS:
- CDDS_ITEMPREPAINT
- CDDS_ITEMPREPAINT|CDDS_SUBITEM | => sent n times, where n is number of subitems,
CDDS_ITEMPOSTPAINT|CDDS_SUBITEM | including item iself
- CDDS_ITEMPOSTPAINT
other styles:
- CDDS_ITEMPREPAINT
- CDDS_ITEMPOSTPAINT
*/
/* fill in the custom draw structure */
customdraw_fill
(
&
nmlvcd
,
infoPtr
,
hdc
,
&
rcBox
,
&
lvItem
);
if
(
cdmode
&
CDRF_NOTIFYITEMDRAW
)
cdsubitemmode
=
notify_customdraw
(
infoPtr
,
CDDS_ITEMPREPAINT
,
&
nmlvcd
);
if
(
cdsubitemmode
&
CDRF_SKIPDEFAULT
)
goto
postpaint
;
if
(
subitems
)
{
while
(
iterator_next
(
subitems
))
{
DWORD
subitemstage
=
CDRF_DODEFAULT
;
/* We need to query for each subitem, item's data (subitem == 0) is already here at this point */
if
(
subitems
->
nItem
)
{
lvItem
.
mask
=
LVIF_TEXT
|
LVIF_IMAGE
|
LVIF_PARAM
|
LVIF_INDENT
;
lvItem
.
stateMask
=
LVIS_SELECTED
|
LVIS_FOCUSED
|
LVIS_STATEIMAGEMASK
|
LVIS_CUT
|
LVIS_OVERLAYMASK
;
lvItem
.
iItem
=
nItem
;
lvItem
.
iSubItem
=
subitems
->
nItem
;
lvItem
.
state
=
0
;
lvItem
.
lParam
=
0
;
lvItem
.
cchTextMax
=
DISP_TEXT_SIZE
;
lvItem
.
pszText
=
szDispText
;
if
(
!
LISTVIEW_GetItemW
(
infoPtr
,
&
lvItem
))
return
FALSE
;
if
(
infoPtr
->
dwLvExStyle
&
LVS_EX_FULLROWSELECT
)
lvItem
.
state
=
LISTVIEW_GetItemState
(
infoPtr
,
nItem
,
LVIS_SELECTED
);
if
(
lvItem
.
pszText
==
LPSTR_TEXTCALLBACKW
)
lvItem
.
pszText
=
callbackW
;
TRACE
(
" lvItem=%s
\n
"
,
debuglvitem_t
(
&
lvItem
,
TRUE
));
/* update custom draw data */
LISTVIEW_GetItemMetrics
(
infoPtr
,
&
lvItem
,
&
nmlvcd
.
nmcd
.
rc
,
NULL
,
NULL
,
NULL
,
NULL
);
OffsetRect
(
&
nmlvcd
.
nmcd
.
rc
,
pos
.
x
,
pos
.
y
);
nmlvcd
.
iSubItem
=
subitems
->
nItem
;
}
if
(
cdsubitemmode
&
CDRF_NOTIFYSUBITEMDRAW
)
subitemstage
=
notify_customdraw
(
infoPtr
,
CDDS_SUBITEM
|
CDDS_ITEMPREPAINT
,
&
nmlvcd
);
else
{
nmlvcd
.
clrTextBk
=
infoPtr
->
clrTextBk
;
nmlvcd
.
clrText
=
infoPtr
->
clrText
;
}
if
(
subitems
->
nItem
==
0
||
(
cdmode
&
CDRF_NOTIFYITEMDRAW
))
prepaint_setup
(
infoPtr
,
hdc
,
&
nmlvcd
,
FALSE
);
else
if
(
!
(
infoPtr
->
dwLvExStyle
&
LVS_EX_FULLROWSELECT
))
prepaint_setup
(
infoPtr
,
hdc
,
&
nmlvcd
,
TRUE
);
if
(
!
(
subitemstage
&
CDRF_SKIPDEFAULT
))
LISTVIEW_DrawItemPart
(
infoPtr
,
&
lvItem
,
&
nmlvcd
,
&
pos
);
if
(
subitemstage
&
CDRF_NOTIFYPOSTPAINT
)
subitemstage
=
notify_customdraw
(
infoPtr
,
CDDS_SUBITEM
|
CDDS_ITEMPOSTPAINT
,
&
nmlvcd
);
}
}
else
{
prepaint_setup
(
infoPtr
,
hdc
,
&
nmlvcd
,
FALSE
);
LISTVIEW_DrawItemPart
(
infoPtr
,
&
lvItem
,
&
nmlvcd
,
&
pos
);
}
postpaint:
if
(
cdsubitemmode
&
CDRF_NOTIFYPOSTPAINT
)
notify_postpaint
(
infoPtr
,
&
nmlvcd
);
{
nmlvcd
.
iSubItem
=
0
;
notify_customdraw
(
infoPtr
,
CDDS_ITEMPOSTPAINT
,
&
nmlvcd
);
}
return
TRUE
;
}
...
...
@@ -4858,10 +4930,15 @@ static void LISTVIEW_RefreshReport(LISTVIEW_INFO *infoPtr, ITERATOR *i, HDC hdc,
/* iterate through the invalidated rows */
while
(
iterator_next
(
i
))
{
RANGES
subitems
;
ITERATOR
k
;
SelectObject
(
hdc
,
infoPtr
->
hFont
);
LISTVIEW_GetItemOrigin
(
infoPtr
,
i
->
nItem
,
&
Position
);
Position
.
y
+=
Origin
.
y
;
subitems
=
ranges_create
(
DPA_GetPtrCount
(
infoPtr
->
hdpaColumns
));
/* iterate through the invalidated columns */
while
(
iterator_next
(
&
j
))
{
...
...
@@ -4876,8 +4953,12 @@ static void LISTVIEW_RefreshReport(LISTVIEW_INFO *infoPtr, ITERATOR *i, HDC hdc,
if
(
!
RectVisible
(
hdc
,
&
rcItem
))
continue
;
}
LISTVIEW_DrawItem
(
infoPtr
,
hdc
,
i
->
nItem
,
j
.
nItem
,
Position
,
cdmode
);
ranges_additem
(
subitems
,
j
.
nItem
);
}
iterator_rangesitems
(
&
k
,
subitems
);
LISTVIEW_DrawItem
(
infoPtr
,
hdc
,
i
->
nItem
,
&
k
,
Position
,
cdmode
);
iterator_destroy
(
&
k
);
}
iterator_destroy
(
&
j
);
}
...
...
@@ -5011,7 +5092,7 @@ static void LISTVIEW_RefreshList(LISTVIEW_INFO *infoPtr, ITERATOR *i, HDC hdc, D
Position
.
x
+=
Origin
.
x
;
Position
.
y
+=
Origin
.
y
;
LISTVIEW_DrawItem
(
infoPtr
,
hdc
,
i
->
nItem
,
0
,
Position
,
cdmode
);
LISTVIEW_DrawItem
(
infoPtr
,
hdc
,
i
->
nItem
,
NULL
,
Position
,
cdmode
);
}
}
...
...
@@ -5087,8 +5168,6 @@ static void LISTVIEW_Refresh(LISTVIEW_INFO *infoPtr, HDC hdc, const RECT *prcEra
hdcOrig
,
infoPtr
->
rcList
.
left
,
infoPtr
->
rcList
.
top
,
SRCCOPY
);
}
infoPtr
->
cditemmode
=
CDRF_DODEFAULT
;
GetClientRect
(
infoPtr
->
hwndSelf
,
&
rcClient
);
customdraw_fill
(
&
nmlvcd
,
infoPtr
,
hdc
,
&
rcClient
,
0
);
cdmode
=
notify_customdraw
(
infoPtr
,
CDDS_PREPAINT
,
&
nmlvcd
);
...
...
@@ -5350,7 +5429,7 @@ static HIMAGELIST LISTVIEW_CreateDragImage(LISTVIEW_INFO *infoPtr, INT iItem, LP
FillRect
(
hdc
,
&
rcItem
,
infoPtr
->
hBkBrush
);
pos
.
x
=
pos
.
y
=
0
;
if
(
LISTVIEW_DrawItem
(
infoPtr
,
hdc
,
iItem
,
0
,
pos
,
infoPtr
->
cditemmode
))
if
(
LISTVIEW_DrawItem
(
infoPtr
,
hdc
,
iItem
,
NULL
,
pos
,
CDRF_DODEFAULT
))
{
dragList
=
ImageList_Create
(
size
.
cx
,
size
.
cy
,
ILC_COLOR
,
10
,
10
);
SelectObject
(
hdc
,
hOldbmp
);
...
...
dlls/comctl32/tests/listview.c
View file @
fa3e750e
...
...
@@ -3,7 +3,7 @@
*
* Copyright 2006 Mike McCormack for CodeWeavers
* Copyright 2007 George Gov
* Copyright 2009-201
3
Nikolay Sivov
* Copyright 2009-201
4
Nikolay Sivov
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
...
...
@@ -28,12 +28,15 @@
#include "v6util.h"
#include "msg.h"
#define PARENT_SEQ_INDEX 0
#define PARENT_FULL_SEQ_INDEX 1
#define LISTVIEW_SEQ_INDEX 2
#define EDITBOX_SEQ_INDEX 3
#define COMBINED_SEQ_INDEX 4
#define NUM_MSG_SEQUENCES 5
enum
seq_index
{
PARENT_SEQ_INDEX
,
PARENT_FULL_SEQ_INDEX
,
PARENT_CD_SEQ_INDEX
,
LISTVIEW_SEQ_INDEX
,
EDITBOX_SEQ_INDEX
,
COMBINED_SEQ_INDEX
,
NUM_MSG_SEQUENCES
};
#define LISTVIEW_ID 0
#define HEADER_ID 1
...
...
@@ -389,6 +392,26 @@ static const struct message parent_insert_focused_seq[] = {
{
0
}
};
static
const
struct
message
parent_report_cd_seq
[]
=
{
{
WM_NOTIFY
,
sent
|
id
|
custdraw
,
0
,
0
,
NM_CUSTOMDRAW
,
CDDS_PREPAINT
},
{
WM_NOTIFY
,
sent
|
id
|
custdraw
,
0
,
0
,
NM_CUSTOMDRAW
,
CDDS_ITEMPREPAINT
},
{
WM_NOTIFY
,
sent
|
id
|
custdraw
,
0
,
0
,
NM_CUSTOMDRAW
,
CDDS_ITEMPREPAINT
|
CDDS_SUBITEM
},
{
WM_NOTIFY
,
sent
|
id
|
custdraw
,
0
,
0
,
NM_CUSTOMDRAW
,
CDDS_ITEMPOSTPAINT
|
CDDS_SUBITEM
},
{
WM_NOTIFY
,
sent
|
id
|
custdraw
,
0
,
0
,
NM_CUSTOMDRAW
,
CDDS_ITEMPREPAINT
|
CDDS_SUBITEM
},
{
WM_NOTIFY
,
sent
|
id
|
custdraw
,
0
,
0
,
NM_CUSTOMDRAW
,
CDDS_ITEMPOSTPAINT
|
CDDS_SUBITEM
},
{
WM_NOTIFY
,
sent
|
id
|
custdraw
,
0
,
0
,
NM_CUSTOMDRAW
,
CDDS_ITEMPOSTPAINT
},
{
WM_NOTIFY
,
sent
|
id
|
custdraw
,
0
,
0
,
NM_CUSTOMDRAW
,
CDDS_POSTPAINT
},
{
0
}
};
static
const
struct
message
parent_list_cd_seq
[]
=
{
{
WM_NOTIFY
,
sent
|
id
|
custdraw
,
0
,
0
,
NM_CUSTOMDRAW
,
CDDS_PREPAINT
},
{
WM_NOTIFY
,
sent
|
id
|
custdraw
,
0
,
0
,
NM_CUSTOMDRAW
,
CDDS_ITEMPREPAINT
},
{
WM_NOTIFY
,
sent
|
id
|
custdraw
,
0
,
0
,
NM_CUSTOMDRAW
,
CDDS_ITEMPOSTPAINT
},
{
WM_NOTIFY
,
sent
|
id
|
custdraw
,
0
,
0
,
NM_CUSTOMDRAW
,
CDDS_POSTPAINT
},
{
0
}
};
static
LRESULT
WINAPI
parent_wnd_proc
(
HWND
hwnd
,
UINT
message
,
WPARAM
wParam
,
LPARAM
lParam
)
{
static
LONG
defwndproc_counter
=
0
;
...
...
@@ -1758,24 +1781,36 @@ static void test_redraw(void)
DestroyWindow
(
hwnd
);
}
static
LRESULT
WINAPI
cd_wndproc
(
HWND
hwnd
,
UINT
m
sg
,
WPARAM
wp
,
LPARAM
lp
)
static
LRESULT
WINAPI
cd_wndproc
(
HWND
hwnd
,
UINT
m
essage
,
WPARAM
wParam
,
LPARAM
lParam
)
{
COLORREF
clr
,
c0ffee
=
RGB
(
0xc0
,
0xff
,
0xee
);
if
(
m
sg
==
WM_NOTIFY
)
{
NMHDR
*
nmhdr
=
(
PVOID
)
lp
;
if
(
m
essage
==
WM_NOTIFY
)
{
NMHDR
*
nmhdr
=
(
NMHDR
*
)
lParam
;
if
(
nmhdr
->
code
==
NM_CUSTOMDRAW
)
{
NMLVCUSTOMDRAW
*
nmlvcd
=
(
NMLVCUSTOMDRAW
*
)
nmhdr
;
struct
message
msg
;
msg
.
message
=
message
;
msg
.
flags
=
sent
|
wparam
|
lparam
|
custdraw
;
msg
.
wParam
=
wParam
;
msg
.
lParam
=
lParam
;
msg
.
id
=
nmhdr
->
code
;
msg
.
stage
=
nmlvcd
->
nmcd
.
dwDrawStage
;
add_message
(
sequences
,
PARENT_CD_SEQ_INDEX
,
&
msg
);
switch
(
nmlvcd
->
nmcd
.
dwDrawStage
)
{
case
CDDS_PREPAINT
:
SetBkColor
(
nmlvcd
->
nmcd
.
hdc
,
c0ffee
);
return
CDRF_NOTIFYITEMDRAW
;
return
CDRF_NOTIFYITEMDRAW
|
CDRF_NOTIFYPOSTPAINT
;
case
CDDS_ITEMPREPAINT
:
nmlvcd
->
clrTextBk
=
CLR_DEFAULT
;
return
CDRF_NOTIFYSUBITEMDRAW
;
nmlvcd
->
clrText
=
RGB
(
0
,
255
,
0
);
return
CDRF_NOTIFYSUBITEMDRAW
|
CDRF_NOTIFYPOSTPAINT
;
case
CDDS_ITEMPREPAINT
|
CDDS_SUBITEM
:
clr
=
GetBkColor
(
nmlvcd
->
nmcd
.
hdc
);
ok
(
nmlvcd
->
clrTextBk
==
CLR_DEFAULT
,
"got 0x%x
\n
"
,
nmlvcd
->
clrTextBk
);
ok
(
nmlvcd
->
clrText
==
RGB
(
0
,
255
,
0
),
"got 0x%x
\n
"
,
nmlvcd
->
clrText
);
if
(
nmlvcd
->
iSubItem
)
todo_wine
ok
(
clr
==
c0ffee
,
"clr=%.8x
\n
"
,
clr
);
else
...
...
@@ -1784,13 +1819,15 @@ static LRESULT WINAPI cd_wndproc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
case
CDDS_ITEMPOSTPAINT
|
CDDS_SUBITEM
:
clr
=
GetBkColor
(
nmlvcd
->
nmcd
.
hdc
);
todo_wine
ok
(
clr
==
c0ffee
,
"clr=%.8x
\n
"
,
clr
);
ok
(
nmlvcd
->
clrTextBk
==
CLR_DEFAULT
,
"got 0x%x
\n
"
,
nmlvcd
->
clrTextBk
);
ok
(
nmlvcd
->
clrText
==
RGB
(
0
,
255
,
0
),
"got 0x%x
\n
"
,
nmlvcd
->
clrText
);
return
CDRF_DODEFAULT
;
}
return
CDRF_DODEFAULT
;
}
}
return
DefWindowProcA
(
hwnd
,
m
sg
,
wp
,
lp
);
return
DefWindowProcA
(
hwnd
,
m
essage
,
wParam
,
lParam
);
}
static
void
test_customdraw
(
void
)
...
...
@@ -1810,9 +1847,27 @@ static void test_customdraw(void)
InvalidateRect
(
hwnd
,
NULL
,
TRUE
);
UpdateWindow
(
hwnd
);
SetWindowLongPtrA
(
hwndparent
,
GWLP_WNDPROC
,
(
LONG_PTR
)
oldwndproc
);
/* message tests */
flush_sequences
(
sequences
,
NUM_MSG_SEQUENCES
);
InvalidateRect
(
hwnd
,
NULL
,
TRUE
);
UpdateWindow
(
hwnd
);
ok_sequence
(
sequences
,
PARENT_CD_SEQ_INDEX
,
parent_report_cd_seq
,
"parent customdraw, LVS_REPORT"
,
FALSE
);
DestroyWindow
(
hwnd
);
hwnd
=
create_listview_control
(
LVS_LIST
);
insert_column
(
hwnd
,
0
);
insert_column
(
hwnd
,
1
);
insert_item
(
hwnd
,
0
);
flush_sequences
(
sequences
,
NUM_MSG_SEQUENCES
);
InvalidateRect
(
hwnd
,
NULL
,
TRUE
);
UpdateWindow
(
hwnd
);
ok_sequence
(
sequences
,
PARENT_CD_SEQ_INDEX
,
parent_list_cd_seq
,
"parent customdraw, LVS_LIST"
,
FALSE
);
SetWindowLongPtrA
(
hwndparent
,
GWLP_WNDPROC
,
(
LONG_PTR
)
oldwndproc
);
DestroyWindow
(
hwnd
);
}
static
void
test_icon_spacing
(
void
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment