Menu with multi columns fix take 2

Rein Klazes wijn at wanadoo.nl
Tue May 10 07:26:01 CDT 2005


Hi, 

Take 2:
  1 Add a column space also if the very first item has a menu column
break flag set;
  2 Added conformance test and verified from Win95 to WinXP.

This fixes a problem described on the user list:

http://www.winehq.org/hypermail/wine-users/2005/05/0010.html

Changelog:

dlls/user	: menu.c
dlls/user/tests	: menu.c

Multi column popup menu's have 4 pixel space between the columns. With
conformance test.

Rein.
-------------- next part --------------
--- wine/dlls/user/menu.c	2005-04-20 16:40:48.000000000 +0200
+++ mywine/dlls/user/menu.c	2005-05-10 14:19:51.000000000 +0200
@@ -142,6 +142,9 @@ typedef struct
   /* Height of a separator item */
 #define SEPARATOR_HEIGHT 5
 
+  /* Space between 2 columns */
+#define MENU_COL_SPACE 4
+
   /* (other menu->FocusedItem values give the position of the focused item) */
 #define NO_SELECTED_ITEM  0xffff
 
@@ -1026,6 +1029,8 @@ static void MENU_PopupMenuCalcSize( LPPO
     {
 	lpitem = &lppop->items[start];
 	orgX = maxX;
+        if( lpitem->fType & MF_MENUBREAK)
+            orgX += MENU_COL_SPACE; 
 	orgY = 3;
 
 	maxTab = maxTabWidth = 0;
--- wine/dlls/user/tests/menu.c	2005-04-14 15:57:27.000000000 +0200
+++ mywine/dlls/user/tests/menu.c	2005-05-10 12:00:24.000000000 +0200
@@ -23,6 +23,7 @@
 
 #include <stdlib.h>
 #include <stdarg.h>
+#include <assert.h>
 
 #include "windef.h"
 #include "winbase.h"
@@ -46,6 +47,48 @@ static LRESULT WINAPI menu_check_wnd_pro
     return DefWindowProc(hwnd, msg, wparam, lparam);
 }
 
+/* globals to communicate between test and wndproc */
+unsigned int MOD_maxid;
+RECT MOD_rc[4];
+/* wndproc used by test_menu_ownerdraw() */
+static LRESULT WINAPI menu_ownerdraw_wnd_proc(HWND hwnd, UINT msg,
+        WPARAM wparam, LPARAM lparam)
+{
+    switch (msg)
+    {
+    case WM_MEASUREITEM:
+        if( winetest_debug)
+            trace("WM_MEASUREITEM received %d,%d\n",
+			((MEASUREITEMSTRUCT*)lparam)->itemWidth	,
+			((MEASUREITEMSTRUCT*)lparam)->itemHeight);
+        ((MEASUREITEMSTRUCT*)lparam)->itemWidth = 10;
+        ((MEASUREITEMSTRUCT*)lparam)->itemHeight = 10;
+        return TRUE;
+    case WM_DRAWITEM:
+        {
+        DRAWITEMSTRUCT * pdis;
+        HPEN oldpen;
+        pdis = (DRAWITEMSTRUCT *) lparam;
+        /* store the rectangl */
+        MOD_rc[pdis->itemID] = pdis->rcItem;
+        if( winetest_debug) {
+            trace("WM_DRAWITEM received item %d rc %ld,%ld-%ld,%ld \n",
+                    pdis->itemID, pdis->rcItem.left, pdis->rcItem.top,
+                    pdis->rcItem.right,pdis->rcItem.bottom );
+            oldpen=SelectObject( pdis->hDC, GetStockObject(
+                        pdis->itemState & ODS_SELECTED ? WHITE_PEN :BLACK_PEN));
+            Rectangle( pdis->hDC, pdis->rcItem.left,pdis->rcItem.top,
+                    pdis->rcItem.right,pdis->rcItem.bottom );
+            SelectObject( pdis->hDC, oldpen);
+        }
+        if( pdis->itemID == MOD_maxid) PostMessage(hwnd, WM_CANCELMODE, 0, 0);
+        return TRUE;
+        }
+
+    }
+    return DefWindowProc(hwnd, msg, wparam, lparam);
+}
+
 static void register_menu_check_class(void)
 {
     WNDCLASS wc =
@@ -101,9 +144,64 @@ static void test_menu_locked_by_window()
     DestroyWindow(hwnd);
 }
 
+static void test_menu_ownerdraw()
+{
+    int i,j,k;
+    BOOL ret;
+    HMENU hmenu;
+    LONG leftcol;
+    HWND hwnd = CreateWindowEx(0, MAKEINTATOM(atomMenuCheckClass), NULL,
+            WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+            NULL, NULL, NULL, NULL);
+    ok(hwnd != NULL, "CreateWindowEx failed with error %ld\n", GetLastError());
+    if( !hwnd) return;
+    SetWindowLong( hwnd, GWL_WNDPROC, (LONG)menu_ownerdraw_wnd_proc);
+    hmenu = CreatePopupMenu();
+    ok(hmenu != NULL, "CreateMenu failed with error %ld\n", GetLastError());
+    if( !hmenu) { DestroyWindow(hwnd);return;}
+    k=0;
+    for( j=0;j<2;j++) /* create columns */
+        for(i=0;i<2;i++) { /* create rows */
+            ret = AppendMenu( hmenu, MF_OWNERDRAW | 
+                    (i==0 ? MF_MENUBREAK : 0), k++, 0);
+            ok( ret, "AppendMenu failed for %d\n", k-1);
+        }
+    MOD_maxid = k-1;
+    assert( k <= sizeof(MOD_rc)/sizeof(RECT));
+    /* display the menu */
+    ret = TrackPopupMenu( hmenu, 0x100, 100,100, 0, hwnd, NULL);
+
+    /* columns have a 4 pixel gap between them */
+    ok( MOD_rc[0].right + 4 ==  MOD_rc[2].left,
+            "item rectangles are not separated by 4 pixels space\n");
+    /* height should be what the MEASUREITEM message has returned */
+    ok( MOD_rc[0].bottom - MOD_rc[0].top == 10,
+            "menu item has wrong height: %d should be %d\n",
+            MOD_rc[0].bottom - MOD_rc[0].top, 10);
+    /* no gaps between the rows */
+    ok( MOD_rc[0].bottom - MOD_rc[1].top == 0,
+            "There should not be a space between the rows, gap is %d\n",
+            MOD_rc[0].bottom - MOD_rc[1].top);
+
+    leftcol= MOD_rc[0].left;
+    ModifyMenu( hmenu, 0, MF_BYCOMMAND| MF_OWNERDRAW, 0, 0); 
+    /* display the menu */
+    ret = TrackPopupMenu( hmenu, 0x100, 100,100, 0, hwnd, NULL);
+
+    /* left should be 4 pixels less now */
+    ok( leftcol == MOD_rc[0].left + 4, 
+            "columns should be 4 pixels to the left (actual %d).\n",
+            leftcol - MOD_rc[0].left);
+
+    trace("done\n");
+    DestroyMenu( hmenu);
+    DestroyWindow(hwnd);
+}
+
 START_TEST(menu)
 {
     register_menu_check_class();
 
     test_menu_locked_by_window();
+    test_menu_ownerdraw();
 }


More information about the wine-patches mailing list