user32: combobox[1/2]: the text area height should be font_height+4 (fixes bug #7491)

Mikołaj Zalewski mikolaj at zalewski.pl
Mon Mar 26 06:12:06 CDT 2007


The tests shows that CBGetTextAreaHeight is using a bad formula. Under 
Wine some tests may be skipped when running with the builtin Marlett 
font as the height is slightly different.
-------------- next part --------------
From 474abd0d453a604cfd3291a4b9af151830a72a2e Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Miko=C5=82aj_Zalewski?= <mikolaj at zalewski.pl>
Date: Mon, 26 Mar 2007 11:25:21 +0200
Subject: [PATCH] user32: combobox: the text area height should be font_height+4

---
 dlls/user32/combo.c           |   12 +---
 dlls/user32/tests/Makefile.in |    1 +
 dlls/user32/tests/combo.c     |  141 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 145 insertions(+), 9 deletions(-)

diff --git a/dlls/user32/combo.c b/dlls/user32/combo.c
index 7e54ea8..4be67cc 100644
--- a/dlls/user32/combo.c
+++ b/dlls/user32/combo.c
@@ -205,8 +205,9 @@ static LRESULT COMBO_NCDestroy( LPHEADCOMBO lphc )
  * The height of the text area is set in two ways.
  * It can be set explicitly through a combobox message or through a
  * WM_MEASUREITEM callback.
- * If this is not the case, the height is set to 13 dialog units.
+ * If this is not the case, the height is set to font height + 4px
  * This height was determined through experimentation.
+ * CBCalcPlacement will add 2*COMBO_YBORDERSIZE pixels for the border
  */
 static INT CBGetTextAreaHeight(
   HWND        hwnd,
@@ -237,14 +238,7 @@ static INT CBGetTextAreaHeight(
 
     ReleaseDC(hwnd, hDC);
 
-    iTextItemHeight = ((13 * baseUnitY) / 8);
-
-    /*
-     * This "formula" calculates the height of the complete control.
-     * To calculate the height of the text area, we have to remove the
-     * borders.
-     */
-    iTextItemHeight -= 2*COMBO_YBORDERSIZE();
+    iTextItemHeight = baseUnitY + 4;
   }
 
   /*
diff --git a/dlls/user32/tests/Makefile.in b/dlls/user32/tests/Makefile.in
index a50a8ee..505d62d 100644
--- a/dlls/user32/tests/Makefile.in
+++ b/dlls/user32/tests/Makefile.in
@@ -8,6 +8,7 @@ IMPORTS   = user32 gdi32 advapi32 kernel32
 CTESTS = \
 	class.c \
 	clipboard.c \
+	combo.c \
 	cursoricon.c \
 	dce.c \
 	dde.c \
diff --git a/dlls/user32/tests/combo.c b/dlls/user32/tests/combo.c
new file mode 100644
index 0000000..bf777c7
--- /dev/null
+++ b/dlls/user32/tests/combo.c
@@ -0,0 +1,141 @@
+/* Unit test suite for combo boxes.
+ *
+ * Copyright 2007 Mikolaj Zalewski
+ *
+ * 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
+ */
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#include "wine/test.h"
+
+HWND hMainWnd;
+
+#define expect_eq(expr, value, type, fmt); { type val = expr; ok(val == (value), #expr " expected " #fmt " got " #fmt "\n", (value), val); }
+#define expect_rect(r, _left, _top, _right, _bottom) ok(r.left == _left && r.top == _top && \
+    r.bottom == _bottom && r.right == _right, "Invalid rect (%d,%d) (%d,%d) vs (%d,%d) (%d,%d)\n", \
+    r.left, r.top, r.right, r.bottom, _left, _top, _right, _bottom);
+
+static HWND build_combo(DWORD style)
+{
+    return CreateWindow("ComboBox", "Combo", WS_VISIBLE|WS_CHILD|style, 5, 5, 100, 100, hMainWnd, NULL, NULL, 0);
+}
+
+static int font_height(HFONT hFont)
+{
+    TEXTMETRIC tm;
+    HFONT hFontOld;
+    HDC hDC;
+
+    hDC = CreateCompatibleDC(NULL);
+    hFontOld = SelectObject(hDC, hFont);
+    GetTextMetrics(hDC, &tm);
+    SelectObject(hDC, hFontOld);
+    DeleteDC(hDC);
+
+    return tm.tmHeight;
+}
+
+static INT CALLBACK is_font_installed_proc(const LOGFONT *elf, const TEXTMETRIC *tm, DWORD type, LPARAM lParam)
+{
+    return 0;
+}
+
+static int is_font_installed(const char *name)
+{
+    HDC hdc = GetDC(NULL);
+    BOOL ret = !EnumFontFamilies(hdc, name, is_font_installed_proc, 0);
+    ReleaseDC(NULL, hdc);
+    return ret;
+}
+
+static void test_setfont(DWORD style)
+{
+    HWND hCombo = build_combo(style);
+    HFONT hFont1 = CreateFont(10, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH|FF_DONTCARE, "Marlett");
+    HFONT hFont2 = CreateFont(8, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH|FF_DONTCARE, "Marlett");
+    RECT r;
+    int i;
+
+    trace("Style %x\n", style);
+    GetClientRect(hCombo, &r);
+    expect_rect(r, 0, 0, 100, 24);
+    SendMessageA(hCombo, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)&r);
+    MapWindowPoints(HWND_DESKTOP, hMainWnd, (LPPOINT)&r, 2);
+    todo_wine expect_rect(r, 5, 5, 105, 105);
+
+    if (!is_font_installed("Marlett"))
+    {
+        skip("Marlett font not available\n");
+        return;
+    }
+
+    if (font_height(hFont1) == 10 && font_height(hFont2) == 8)
+    {
+        SendMessage(hCombo, WM_SETFONT, (WPARAM)hFont1, FALSE);
+        GetClientRect(hCombo, &r);
+        expect_rect(r, 0, 0, 100, 18);
+        SendMessageA(hCombo, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)&r);
+        MapWindowPoints(HWND_DESKTOP, hMainWnd, (LPPOINT)&r, 2);
+        todo_wine expect_rect(r, 5, 5, 105, 99);
+
+        SendMessage(hCombo, WM_SETFONT, (WPARAM)hFont2, FALSE);
+        GetClientRect(hCombo, &r);
+        expect_rect(r, 0, 0, 100, 16);
+        SendMessageA(hCombo, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)&r);
+        MapWindowPoints(HWND_DESKTOP, hMainWnd, (LPPOINT)&r, 2);
+        todo_wine expect_rect(r, 5, 5, 105, 97);
+
+        SendMessage(hCombo, WM_SETFONT, (WPARAM)hFont1, FALSE);
+        GetClientRect(hCombo, &r);
+        expect_rect(r, 0, 0, 100, 18);
+        SendMessageA(hCombo, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)&r);
+        MapWindowPoints(HWND_DESKTOP, hMainWnd, (LPPOINT)&r, 2);
+        todo_wine expect_rect(r, 5, 5, 105, 99);
+    }
+    else
+        skip("Invalid Marlett font heights\n");
+
+    for (i = 1; i < 30; i++)
+    {
+        HFONT hFont = CreateFont(i, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH|FF_DONTCARE, "Marlett");
+        int height = font_height(hFont);
+
+        SendMessage(hCombo, WM_SETFONT, (WPARAM)hFont, FALSE);
+        GetClientRect(hCombo, &r);
+        expect_eq(r.bottom - r.top, height + 8, int, "%d");
+        SendMessage(hCombo, WM_SETFONT, 0, FALSE);
+        DeleteObject(hFont);
+    }
+
+    DestroyWindow(hCombo);
+    DeleteObject(hFont1);
+    DeleteObject(hFont2);
+}
+
+START_TEST(combo)
+{
+    hMainWnd = CreateWindow("static", "Test", WS_OVERLAPPEDWINDOW, 10, 10, 300, 300, NULL, NULL, NULL, 0);
+    ShowWindow(hMainWnd, SW_SHOW);
+
+    test_setfont(CBS_DROPDOWN);
+    test_setfont(CBS_DROPDOWNLIST);
+    DestroyWindow(hMainWnd);
+}
-- 
1.4.4.2


More information about the wine-patches mailing list