v2: Formatting fixes, add some tests.
v3: Add v6 tests, make v6 behaviour the default one.
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/comctl32/listview.c | 81 +++++++++++++++++++++++++++++++---
dlls/comctl32/tests/listview.c | 78 ++++++++++++++++++++++++++++++++
2 files changed, 152 insertions(+), 7 deletions(-)
diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c
index 730bf4aaddd..0ad88f779b7 100644
--- a/dlls/comctl32/listview.c
+++ b/dlls/comctl32/listview.c
@@ -91,7 +91,7 @@
*
* Messages:
* -- LVM_ENABLEGROUPVIEW
- * -- LVM_GETBKIMAGE, LVM_SETBKIMAGE
+ * -- LVM_GETBKIMAGE
* -- LVM_GETGROUPINFO, LVM_SETGROUPINFO
* -- LVM_GETGROUPMETRICS, LVM_SETGROUPMETRICS
* -- LVM_GETINSERTMARK, LVM_SETINSERTMARK
@@ -297,6 +297,7 @@ typedef struct tagLISTVIEW_INFO
COLORREF clrBk;
COLORREF clrText;
COLORREF clrTextBk;
+ HBITMAP hBkBitmap;
/* font */
HFONT hDefaultFont;
@@ -4565,13 +4566,32 @@ static INT LISTVIEW_GetTopIndex(const LISTVIEW_INFO *infoPtr)
* Success: TRUE
* Failure: FALSE
*/
-static inline BOOL LISTVIEW_FillBkgnd(const LISTVIEW_INFO *infoPtr, HDC hdc, const RECT *lprcBox)
+static BOOL LISTVIEW_FillBkgnd(const LISTVIEW_INFO *infoPtr, HDC hdc, const RECT *lprcBox)
{
- if (!infoPtr->hBkBrush) return FALSE;
+ BOOL ret = FALSE;
- TRACE("(hdc=%p, lprcBox=%s, hBkBrush=%p)\n", hdc, wine_dbgstr_rect(lprcBox), infoPtr->hBkBrush);
+ if (infoPtr->hBkBrush)
+ {
+ TRACE("(hdc=%p, lprcBox=%s, hBkBrush=%p)\n", hdc, wine_dbgstr_rect(lprcBox), infoPtr->hBkBrush);
+
+ ret = FillRect(hdc, lprcBox, infoPtr->hBkBrush);
+ }
+
+ if (infoPtr->hBkBitmap)
+ {
+ HDC hdc_src = CreateCompatibleDC(hdc);
+
+ TRACE("(hdc=%p, lprcBox=%s, hBkBitmap=%p)\n", hdc, wine_dbgstr_rect(lprcBox), infoPtr->hBkBitmap);
+
+ SelectObject(hdc_src, infoPtr->hBkBitmap);
+ BitBlt(hdc, lprcBox->left, lprcBox->top, lprcBox->right - lprcBox->left,
+ lprcBox->bottom - lprcBox->top, hdc_src, lprcBox->left, lprcBox->top, SRCCOPY);
+
+ DeleteDC(hdc_src);
+ ret = TRUE;
+ }
- return FillRect(hdc, lprcBox, infoPtr->hBkBrush);
+ return ret;
}
/* Draw main item or subitem */
@@ -8028,7 +8048,51 @@ static BOOL LISTVIEW_SetBkColor(LISTVIEW_INFO *infoPtr, COLORREF color)
return TRUE;
}
-/* LISTVIEW_SetBkImage */
+static BOOL LISTVIEW_SetBkImage(LISTVIEW_INFO *infoPtr, const LVBKIMAGEW *image, BOOL isW)
+{
+ TRACE("%08lx, %p, %p, %u, %d, %d\n", image->ulFlags, image->hbm, image->pszImage,
+ image->cchImageMax, image->xOffsetPercent, image->yOffsetPercent);
+
+ if (image->ulFlags & ~LVBKIF_SOURCE_MASK)
+ FIXME("not supported flags %08lx\n", image->ulFlags & ~LVBKIF_SOURCE_MASK);
+
+ if (image->xOffsetPercent || image->yOffsetPercent)
+ FIXME("not supported offset %d,%d\n", image->xOffsetPercent, image->yOffsetPercent);
+
+ switch (image->ulFlags & LVBKIF_SOURCE_MASK)
+ {
+ case LVBKIF_SOURCE_NONE:
+ if (infoPtr->hBkBitmap)
+ {
+ DeleteObject(infoPtr->hBkBitmap);
+ infoPtr->hBkBitmap = 0;
+ }
+ break;
+
+ case LVBKIF_SOURCE_HBITMAP:
+ {
+ BITMAP bm;
+
+ if (infoPtr->hBkBitmap)
+ {
+ DeleteObject(infoPtr->hBkBitmap);
+ infoPtr->hBkBitmap = 0;
+ }
+ if (GetObjectW(image->hbm, sizeof(bm), &bm) == sizeof(bm))
+ {
+ infoPtr->hBkBitmap = image->hbm;
+ return TRUE;
+ }
+ break;
+ }
+
+ case LVBKIF_SOURCE_URL:
+ FIXME("LVBKIF_SOURCE_URL: %s\n", isW ? debugstr_w(image->pszImage) : debugstr_a((LPCSTR)image->pszImage));
+ break;
+ }
+
+ return FALSE;
+}
/*** Helper for {Insert,Set}ColumnT *only* */
static void column_fill_hditem(const LISTVIEW_INFO *infoPtr, HDITEMW *lphdi, INT nColumn,
@@ -10406,6 +10470,7 @@ static LRESULT LISTVIEW_NCDestroy(LISTVIEW_INFO *infoPtr)
infoPtr->hFont = 0;
if (infoPtr->hDefaultFont) DeleteObject(infoPtr->hDefaultFont);
if (infoPtr->clrBk != CLR_NONE) DeleteObject(infoPtr->hBkBrush);
+ if (infoPtr->hBkBitmap) DeleteObject(infoPtr->hBkBitmap);
SetWindowLongPtrW(infoPtr->hwndSelf, 0, 0);
@@ -11554,7 +11619,9 @@ LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
case LVM_SETBKCOLOR:
return LISTVIEW_SetBkColor(infoPtr, (COLORREF)lParam);
- /* case LVM_SETBKIMAGE: */
+ case LVM_SETBKIMAGEA:
+ case LVM_SETBKIMAGEW:
+ return LISTVIEW_SetBkImage(infoPtr, (LVBKIMAGEW *)lParam, uMsg == LVM_SETBKIMAGEW);
case LVM_SETCALLBACKMASK:
infoPtr->uCallbackMask = (UINT)wParam;
diff --git a/dlls/comctl32/tests/listview.c b/dlls/comctl32/tests/listview.c
index 6ac7f53137d..3a78f5f670c 100644
--- a/dlls/comctl32/tests/listview.c
+++ b/dlls/comctl32/tests/listview.c
@@ -23,6 +23,7 @@
#include <stdio.h>
#include <windows.h>
#include <commctrl.h>
+#include <objbase.h>
#include "wine/test.h"
#include "v6util.h"
@@ -6924,6 +6925,81 @@ static void test_LVM_GETNEXTITEMINDEX(void)
DestroyWindow(hwnd);
}
+static void test_LVM_SETBKIMAGE(BOOL is_v6)
+{
+ HWND hwnd;
+ int ret;
+ HBITMAP hbmp;
+ BITMAP bm;
+ LVBKIMAGEA image;
+
+ CoInitialize(NULL);
+
+ hbmp = CreateBitmap(32, 32, 1, 1, NULL);
+ hwnd = create_listview_control(LVS_REPORT);
+
+ image.ulFlags = LVBKIF_SOURCE_NONE;
+ image.hbm = 0;
+ image.pszImage = NULL;
+ image.cchImageMax = 0;
+ image.xOffsetPercent = 0;
+ image.yOffsetPercent = 0;
+ ret = SendMessageA(hwnd, LVM_SETBKIMAGEA, 0, (LPARAM)&image);
+ ok(!ret, "got %d\n", ret);
+
+ ret = GetObjectA(hbmp, sizeof(bm), &bm);
+ ok(ret == sizeof(bm), "got %d\n", ret);
+
+ image.ulFlags = LVBKIF_SOURCE_HBITMAP;
+ image.hbm = hbmp;
+ ret = SendMessageA(hwnd, LVM_SETBKIMAGEA, 0, (LPARAM)&image);
+ if (is_v6)
+ ok(ret, "got %d\n", ret);
+ else
+ todo_wine ok(!ret, "got %d\n", ret);
+
+ ret = GetObjectA(hbmp, sizeof(bm), &bm);
+ ok(ret == sizeof(bm), "got %d\n", ret);
+
+ image.ulFlags = LVBKIF_SOURCE_NONE;
+ image.hbm = 0;
+ ret = SendMessageA(hwnd, LVM_SETBKIMAGEA, 0, (LPARAM)&image);
+ ok(!ret, "got %d\n", ret);
+
+ ret = GetObjectA(hbmp, sizeof(bm), &bm);
+ ok(!ret, "got %d\n", ret);
+
+ hbmp = CreateBitmap(32, 32, 1, 1, NULL);
+
+ image.ulFlags = LVBKIF_SOURCE_HBITMAP;
+ image.hbm = hbmp;
+ ret = SendMessageA(hwnd, LVM_SETBKIMAGEA, 0, (LPARAM)&image);
+ if (is_v6)
+ ok(ret, "got %d\n", ret);
+ else
+ todo_wine ok(!ret, "got %d\n", ret);
+
+ ret = GetObjectA(hbmp, sizeof(bm), &bm);
+ ok(ret == sizeof(bm), "got %d\n", ret);
+
+ image.ulFlags = LVBKIF_SOURCE_HBITMAP;
+ image.hbm = hbmp;
+ ret = SendMessageA(hwnd, LVM_SETBKIMAGEA, 0, (LPARAM)&image);
+ ok(!ret, "got %d\n", ret);
+
+ ret = GetObjectA(hbmp, sizeof(bm), &bm);
+ ok(!ret, "got %d\n", ret);
+
+ image.ulFlags = LVBKIF_SOURCE_NONE;
+ image.hbm = 0;
+ ret = SendMessageA(hwnd, LVM_SETBKIMAGEA, 0, (LPARAM)&image);
+ ok(!ret, "got %d\n", ret);
+
+ DestroyWindow(hwnd);
+
+ CoUninitialize();
+}
+
START_TEST(listview)
{
ULONG_PTR ctx_cookie;
@@ -6987,6 +7063,7 @@ START_TEST(listview)
test_LVN_ENDLABELEDIT();
test_LVM_GETCOUNTPERPAGE();
test_item_state_change();
+ test_LVM_SETBKIMAGE(FALSE);
if (!load_v6_module(&ctx_cookie, &hCtx))
{
@@ -7034,6 +7111,7 @@ START_TEST(listview)
test_item_state_change();
test_selected_column();
test_LVM_GETNEXTITEMINDEX();
+ test_LVM_SETBKIMAGE(TRUE);
unload_v6_module(ctx_cookie, hCtx);
--
2.36.1