merged changes from wine to button and combobox code.
authorSebastian Gasiorek <sebastian.gasiorek@reactos.org>
Sat, 10 Dec 2005 00:15:17 +0000 (00:15 +0000)
committerSebastian Gasiorek <sebastian.gasiorek@reactos.org>
Sat, 10 Dec 2005 00:15:17 +0000 (00:15 +0000)
svn path=/trunk/; revision=20032

reactos/lib/user32/controls/button.c
reactos/lib/user32/controls/combo.c

index db477ee..ea872de 100644 (file)
@@ -24,8 +24,8 @@
 /* GetWindowLong offsets for window extra information */
 #define STATE_GWL_OFFSET  0
 #define HFONT_GWL_OFFSET  (sizeof(LONG))
-#define HIMAGE_GWL_OFFSET (2*sizeof(LONG))
-#define NB_EXTRA_BYTES    (3*sizeof(LONG))
+#define HIMAGE_GWL_OFFSET (HFONT_GWL_OFFSET*sizeof(LONG))
+#define NB_EXTRA_BYTES    (HIMAGE_GWL_OFFSET*sizeof(LONG))
 
   /* Button state values */
 #define BUTTON_UNCHECKED       0x00
 #define BUTTON_UNKNOWN2        0x20
 #define BUTTON_UNKNOWN3        0x10
 
+#define BUTTON_NOTIFY_PARENT(hWnd, code) \
+    do { /* Notify parent which has created this button control */ \
+        TRACE("notification " #code " sent to hwnd=%p\n", GetParent(hWnd)); \
+        SendMessageW(GetParent(hWnd), WM_COMMAND, \
+                     MAKEWPARAM(GetWindowLongPtrW((hWnd),GWLP_ID), (code)), \
+                     (LPARAM)(hWnd)); \
+    } while(0)
+
 static UINT BUTTON_CalcLabelRect( HWND hwnd, HDC hdc, RECT *rc );
 static void PB_Paint( HWND hwnd, HDC hDC, UINT action );
 static void CB_Paint( HWND hwnd, HDC hDC, UINT action );
@@ -116,22 +124,22 @@ const struct builtin_class_descr BUTTON_builtin_class =
 
 __inline static LONG get_button_state( HWND hwnd )
 {
-    return GetWindowLongA( hwnd, STATE_GWL_OFFSET );
+    return GetWindowLongW( hwnd, STATE_GWL_OFFSET );
 }
 
 __inline static void set_button_state( HWND hwnd, LONG state )
 {
-    SetWindowLongA( hwnd, STATE_GWL_OFFSET, state );
+    SetWindowLongW( hwnd, STATE_GWL_OFFSET, state );
 }
 
 __inline static HFONT get_button_font( HWND hwnd )
 {
-    return (HFONT)GetWindowLongA( hwnd, HFONT_GWL_OFFSET );
+    return (HFONT)GetWindowLongPtrW( hwnd, HFONT_GWL_OFFSET );
 }
 
 __inline static void set_button_font( HWND hwnd, HFONT font )
 {
-    SetWindowLongA( hwnd, HFONT_GWL_OFFSET, (LONG)font );
+    SetWindowLongPtrW( hwnd, HFONT_GWL_OFFSET, (LONG)font );
 }
 
 __inline static UINT get_button_type( LONG window_style )
@@ -167,7 +175,7 @@ static LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg,
 {
     RECT rect;
     POINT pt;
-    LONG style = GetWindowLongA( hWnd, GWL_STYLE );
+    LONG style = GetWindowLongW( hWnd, GWL_STYLE );
     UINT btn_type = get_button_type( style );
     LONG state;
     HANDLE oldHbitmap;
@@ -180,10 +188,12 @@ static LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg,
     case WM_GETDLGCODE:
         switch(btn_type)
         {
+        case BS_USERBUTTON:
         case BS_PUSHBUTTON:      return DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON;
         case BS_DEFPUSHBUTTON:   return DLGC_BUTTON | DLGC_DEFPUSHBUTTON;
         case BS_RADIOBUTTON:
         case BS_AUTORADIOBUTTON: return DLGC_BUTTON | DLGC_RADIOBUTTON;
+        case BS_GROUPBOX:        return DLGC_STATIC;
         default:                 return DLGC_BUTTON;
         }
 
@@ -222,6 +232,7 @@ static LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg,
         }
         return 1;
 
+    case WM_PRINTCLIENT:
     case WM_PAINT:
         if (btnPaintFunc[btn_type])
         {
@@ -248,17 +259,15 @@ static LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg,
            btn_type == BS_USERBUTTON ||
            btn_type == BS_OWNERDRAW)
         {
-            SendMessageW( GetParent(hWnd), WM_COMMAND,
-                          MAKEWPARAM( GetWindowLongA(hWnd,GWL_ID), BN_DOUBLECLICKED ),
-                          (LPARAM)hWnd);
+            BUTTON_NOTIFY_PARENT(hWnd, BN_DOUBLECLICKED);
             break;
         }
         /* fall through */
     case WM_LBUTTONDOWN:
         SetCapture( hWnd );
         SetFocus( hWnd );
-        SendMessageW( hWnd, BM_SETSTATE, TRUE, 0 );
         set_button_state( hWnd, get_button_state( hWnd ) | BUTTON_BTNPRESSED );
+        SendMessageW( hWnd, BM_SETSTATE, TRUE, 0 );
         break;
 
     case WM_KEYUP:
@@ -294,8 +303,7 @@ static LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg,
                                 (state & BUTTON_3STATE) ? 0 : ((state & 3) + 1), 0 );
                 break;
             }
-            SendMessageW( GetParent(hWnd), WM_COMMAND,
-                          MAKEWPARAM( GetWindowLongA(hWnd,GWL_ID), BN_CLICKED ), (LPARAM)hWnd);
+            BUTTON_NOTIFY_PARENT(hWnd, BN_CLICKED);
         }
         break;
 
@@ -361,11 +369,20 @@ static LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg,
     case WM_SETFOCUS:
         set_button_state( hWnd, get_button_state(hWnd) | BUTTON_HASFOCUS );
         paint_button( hWnd, btn_type, ODA_FOCUS );
+        if (style & BS_NOTIFY)
+            BUTTON_NOTIFY_PARENT(hWnd, BN_SETFOCUS);
         break;
 
     case WM_KILLFOCUS:
-        set_button_state( hWnd, get_button_state(hWnd) & ~BUTTON_HASFOCUS );
+        state = get_button_state( hWnd );
+        set_button_state( hWnd, state & ~BUTTON_HASFOCUS );
        paint_button( hWnd, btn_type, ODA_FOCUS );
+
+        if ((state & BUTTON_BTNPRESSED) && GetCapture() == hWnd)
+            ReleaseCapture();
+        if (style & BS_NOTIFY)
+            BUTTON_NOTIFY_PARENT(hWnd, BN_KILLFOCUS);
+
         break;
 
     case WM_SYSCOLORCHANGE:
@@ -379,7 +396,7 @@ static LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg,
         if ((wParam & 0x0f) >= MAX_BTN_TYPE) break;
         btn_type = wParam & 0x0f;
         style = (style & ~0x0f) | btn_type;
-        SetWindowLongA( hWnd, GWL_STYLE, style );
+        SetWindowLongW( hWnd, GWL_STYLE, style );
 
         /* Only redraw if lParam flag is set.*/
         if (lParam)
@@ -405,12 +422,12 @@ static LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg,
         default:
             return 0;
         }
-        oldHbitmap = (HBITMAP)SetWindowLongA( hWnd, HIMAGE_GWL_OFFSET, lParam );
+        oldHbitmap = (HBITMAP)SetWindowLongPtrW( hWnd, HIMAGE_GWL_OFFSET, lParam );
        InvalidateRect( hWnd, NULL, FALSE );
        return (LRESULT)oldHbitmap;
 
     case BM_GETIMAGE:
-        return GetWindowLongA( hWnd, HIMAGE_GWL_OFFSET );
+        return GetWindowLongPtrW( hWnd, HIMAGE_GWL_OFFSET );
 
 #ifndef __REACTOS__
     case BM_GETCHECK16:
@@ -428,7 +445,7 @@ static LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg,
         {
             if (wParam) style |= WS_TABSTOP;
             else style &= ~WS_TABSTOP;
-            SetWindowLongA( hWnd, GWL_STYLE, style );
+            SetWindowLongW( hWnd, GWL_STYLE, style );
         }
         if ((state & 3) != wParam)
         {
@@ -556,7 +573,7 @@ static UINT BUTTON_BStoDT(DWORD style)
  */
 static UINT BUTTON_CalcLabelRect(HWND hwnd, HDC hdc, RECT *rc)
 {
-   LONG style = GetWindowLongA( hwnd, GWL_STYLE );
+   LONG style = GetWindowLongW( hwnd, GWL_STYLE );
    WCHAR *text;
    ICONINFO    iconInfo;
    BITMAP      bm;
@@ -579,7 +596,7 @@ static UINT BUTTON_CalcLabelRect(HWND hwnd, HDC hdc, RECT *rc)
           break;
 
       case BS_ICON:
-         if (!GetIconInfo((HICON)GetWindowLongA( hwnd, HIMAGE_GWL_OFFSET ), &iconInfo))
+         if (!GetIconInfo((HICON)GetWindowLongPtrW( hwnd, HIMAGE_GWL_OFFSET ), &iconInfo))
             goto empty_rect;
 
          GetObjectW (iconInfo.hbmColor, sizeof(BITMAP), &bm);
@@ -592,7 +609,7 @@ static UINT BUTTON_CalcLabelRect(HWND hwnd, HDC hdc, RECT *rc)
          break;
 
       case BS_BITMAP:
-         if (!GetObjectW( (HANDLE)GetWindowLongA( hwnd, HIMAGE_GWL_OFFSET ), sizeof(BITMAP), &bm))
+         if (!GetObjectW( (HANDLE)GetWindowLongPtrW( hwnd, HIMAGE_GWL_OFFSET ), sizeof(BITMAP), &bm))
             goto empty_rect;
 
          r.right  = r.left + bm.bmWidth;
@@ -601,8 +618,8 @@ static UINT BUTTON_CalcLabelRect(HWND hwnd, HDC hdc, RECT *rc)
 
       default:
       empty_rect:
-         r.right = r.left;
-         r.bottom = r.top;
+         rc->right = r.left;
+         rc->bottom = r.top;
          return (UINT)(LONG)-1;
    }
 
@@ -671,7 +688,7 @@ static void BUTTON_DrawLabel(HWND hwnd, HDC hdc, UINT dtFlags, RECT *rc)
    HBRUSH hbr = 0;
    UINT flags = IsWindowEnabled(hwnd) ? DSS_NORMAL : DSS_DISABLED;
    LONG state = get_button_state( hwnd );
-   LONG style = GetWindowLongA( hwnd, GWL_STYLE );
+   LONG style = GetWindowLongW( hwnd, GWL_STYLE );
    WCHAR *text = NULL;
 
    /* FIXME: To draw disabled label in Win31 look-and-feel, we probably
@@ -697,12 +714,12 @@ static void BUTTON_DrawLabel(HWND hwnd, HDC hdc, UINT dtFlags, RECT *rc)
 
       case BS_ICON:
          flags |= DST_ICON;
-         lp = GetWindowLongA( hwnd, HIMAGE_GWL_OFFSET );
+         lp = GetWindowLongPtrW( hwnd, HIMAGE_GWL_OFFSET );
          break;
 
       case BS_BITMAP:
          flags |= DST_BITMAP;
-         lp = GetWindowLongA( hwnd, HIMAGE_GWL_OFFSET );
+         lp = GetWindowLongPtrW( hwnd, HIMAGE_GWL_OFFSET );
          break;
 
       default:
@@ -711,7 +728,7 @@ static void BUTTON_DrawLabel(HWND hwnd, HDC hdc, UINT dtFlags, RECT *rc)
 
    DrawStateW(hdc, hbr, lpOutputProc, lp, wp, rc->left, rc->top,
               rc->right - rc->left, rc->bottom - rc->top, flags);
-   if (text) HeapFree( GetProcessHeap(), 0, text );
+   HeapFree( GetProcessHeap(), 0, text );
 }
 
 /**********************************************************************
@@ -721,14 +738,13 @@ static void PB_Paint( HWND hwnd, HDC hDC, UINT action )
 {
     RECT     rc, focus_rect, r;
     UINT     dtFlags, uState;
-    HRGN     hRgn;
     HPEN     hOldPen;
     HBRUSH   hOldBrush;
     INT      oldBkMode;
     COLORREF oldTxtColor;
     HFONT hFont;
     LONG state = get_button_state( hwnd );
-    LONG style = GetWindowLongA( hwnd, GWL_STYLE );
+    LONG style = GetWindowLongW( hwnd, GWL_STYLE );
     BOOL pushedState = (state & BUTTON_HIGHLIGHTED);
     HWND parent;
 
@@ -782,16 +798,13 @@ static void PB_Paint( HWND hwnd, HDC hDC, UINT action )
     if (pushedState)
        OffsetRect(&r, 1, 1);
 
-    hRgn = CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom);
-    SelectClipRgn(hDC, hRgn);
+    IntersectClipRect(hDC, rc.left, rc.top, rc.right, rc.bottom);
 
     oldTxtColor = SetTextColor( hDC, GetSysColor(COLOR_BTNTEXT) );
 
     BUTTON_DrawLabel(hwnd, hDC, dtFlags, &r);
 
     SetTextColor( hDC, oldTxtColor );
-    SelectClipRgn(hDC, 0);
-    DeleteObject(hRgn);
 
     if (state & BUTTON_HASFOCUS)
     {
@@ -806,6 +819,7 @@ static void PB_Paint( HWND hwnd, HDC hDC, UINT action )
     SetBkMode(hDC, oldBkMode);
 }
 
+
 /**********************************************************************
  *       Check Box & Radio Button Functions
  */
@@ -816,10 +830,9 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action )
     HBRUSH hBrush;
     int delta;
     UINT dtFlags;
-    HRGN hRgn;
     HFONT hFont;
     LONG state = get_button_state( hwnd );
-    LONG style = GetWindowLongA( hwnd, GWL_STYLE );
+    LONG style = GetWindowLongW( hwnd, GWL_STYLE );
     HWND parent;
 
     if (style & BS_PUSHLIKE)
@@ -853,7 +866,7 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action )
         rtext.left += checkBoxWidth + 4;
         rbox.right = checkBoxWidth;
     }
-
     /* Since WM_ERASEBKGND does nothing, first prepare background */
     if (action == ODA_SELECT) FillRect( hDC, &rbox, hBrush );
     if (action == ODA_DRAWENTIRE) FillRect( hDC, &client, hBrush );
@@ -861,9 +874,14 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action )
     /* Draw label */
     client = rtext;
     dtFlags = BUTTON_CalcLabelRect(hwnd, hDC, &rtext);
+    
+    /* Only adjust rbox when rtext is valid */
+    if (dtFlags != (UINT)-1L)
+    {
+       rbox.top = rtext.top;
+       rbox.bottom = rtext.bottom;
+    }
 
-    rbox.top = rtext.top;
-    rbox.bottom = rtext.bottom;
     /* Draw the check-box bitmap */
     if (action == ODA_DRAWENTIRE || action == ODA_SELECT)
     {
@@ -881,20 +899,20 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action )
 
        /* rbox must have the correct height */
        delta = rbox.bottom - rbox.top - checkBoxHeight;
-
+       
        if (style & BS_TOP) {
            if (delta > 0) {
                rbox.bottom = rbox.top + checkBoxHeight;
-           } else {
+           } else { 
                rbox.top -= -delta/2 + 1;
-               rbox.bottom += rbox.top + checkBoxHeight;
+               rbox.bottom = rbox.top + checkBoxHeight;
            }
        } else if (style & BS_BOTTOM) {
            if (delta > 0) {
                rbox.top = rbox.bottom - checkBoxHeight;
            } else {
                rbox.bottom += -delta/2 + 1;
-               rbox.top = rbox.bottom -= checkBoxHeight;
+               rbox.top = rbox.bottom - checkBoxHeight;
            }
        } else { /* Default */
            if (delta > 0) {
@@ -913,9 +931,8 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action )
 
     if (dtFlags == (UINT)-1L) /* Noting to draw */
        return;
-    hRgn = CreateRectRgn(client.left, client.top, client.right, client.bottom);
-    SelectClipRgn(hDC, hRgn);
-    DeleteObject(hRgn);
+
+    IntersectClipRect(hDC, client.left, client.top, client.right, client.bottom);
 
     if (action == ODA_DRAWENTIRE)
        BUTTON_DrawLabel(hwnd, hDC, dtFlags, &rtext);
@@ -929,7 +946,6 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action )
        IntersectRect(&rtext, &rtext, &client);
        DrawFocusRect( hDC, &rtext );
     }
-    SelectClipRgn(hDC, 0);
 }
 
 
@@ -949,7 +965,7 @@ static void BUTTON_CheckAutoRadioButton( HWND hwnd )
     {
         if (!sibling) break;
         if ((hwnd != sibling) &&
-            ((GetWindowLongA( sibling, GWL_STYLE) & 0x0f) == BS_AUTORADIOBUTTON))
+            ((GetWindowLongW( sibling, GWL_STYLE) & 0x0f) == BS_AUTORADIOBUTTON))
             SendMessageW( sibling, BM_SETCHECK, BUTTON_UNCHECKED, 0 );
         sibling = GetNextDlgGroupItem( parent, sibling, FALSE );
     } while (sibling != start);
@@ -967,7 +983,7 @@ static void GB_Paint( HWND hwnd, HDC hDC, UINT action )
     HFONT hFont;
     UINT dtFlags;
     TEXTMETRICW tm;
-    LONG style = GetWindowLongA( hwnd, GWL_STYLE );
+    LONG style = GetWindowLongW( hwnd, GWL_STYLE );
     HWND parent;
 
     if ((hFont = get_button_font( hwnd ))) SelectObject( hDC, hFont );
@@ -1037,7 +1053,6 @@ static void UB_Paint( HWND hwnd, HDC hDC, UINT action )
         DrawFocusRect( hDC, &rc );
 }
 
-
 /**********************************************************************
  *       Ownerdrawn Button Functions
  */
@@ -1048,8 +1063,9 @@ static void OB_Paint( HWND hwnd, HDC hDC, UINT action )
     DRAWITEMSTRUCT dis;
     HRGN clipRegion;
     RECT clipRect;
-    UINT id = GetWindowLongA( hwnd, GWL_ID );
+    LONG_PTR id = GetWindowLongPtrW( hwnd, GWLP_ID );
     HWND parent;
+    HFONT hFont, hPrevFont = 0;
 
     dis.CtlType    = ODT_BUTTON;
     dis.CtlID      = id;
@@ -1073,9 +1089,11 @@ static void OB_Paint( HWND hwnd, HDC hDC, UINT action )
     DPtoLP(hDC, (LPPOINT) &clipRect, 2);
     IntersectClipRect(hDC, clipRect.left,  clipRect.top, clipRect.right, clipRect.bottom);
 
+    if ((hFont = get_button_font( hwnd ))) hPrevFont = SelectObject( hDC, hFont );
     parent = GetParent(hwnd);
     if (!parent) parent = hwnd;
     SendMessageW( parent, WM_CTLCOLORBTN, (WPARAM)hDC, (LPARAM)hwnd );
     SendMessageW( GetParent(hwnd), WM_DRAWITEM, id, (LPARAM)&dis );
+    if (hPrevFont) SelectObject(hDC, hPrevFont);
     SelectClipRgn(hDC, clipRegion);
 }
index 54aa7ee..b786908 100644 (file)
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * FIXME: roll up in Netscape 3.01.
+ * NOTES
+ *
+ * This code was audited for completeness against the documented features
+ * of Comctl32.dll version 6.0 on Oct. 4, 2004, by Dimitrie O. Paun.
+ * 
+ * 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:
+ *   - ComboBox_[GS]etMinVisible()
+ *   - CB_GETMINVISIBLE, CB_SETMINVISIBLE
+ *   - CB_LIMITTEXT
+ *   - CB_SETTOPINDEX
  */
 
 #include <user32.h>
@@ -36,7 +49,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(combo);
 
 #define CB_NOTIFY( lphc, code ) \
     (SendMessageW((lphc)->owner, WM_COMMAND, \
-                  MAKEWPARAM(GetWindowLongA((lphc)->self,GWL_ID), (code)), (LPARAM)(lphc)->self))
+                  MAKEWPARAM(GetWindowLongPtrW((lphc)->self,GWLP_ID), (code)), (LPARAM)(lphc)->self))
 
 #define CB_DISABLED( lphc )   (!IsWindowEnabled((lphc)->self))
 #define CB_OWNERDRAWN( lphc ) ((lphc)->dwStyle & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE))
@@ -136,23 +149,23 @@ static LRESULT COMBO_NCCreate(HWND hwnd, LONG style)
     if (COMBO_Init() && (lphc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HEADCOMBO))) )
     {
         lphc->self = hwnd;
-        SetWindowLongA( hwnd, 0, (LONG)lphc );
+        SetWindowLongW( hwnd, 0, (LONG)lphc );
 
        /* some braindead apps do try to use scrollbar/border flags */
 
        lphc->dwStyle = style & ~(WS_BORDER | WS_HSCROLL | WS_VSCROLL);
-        SetWindowLongA( hwnd, GWL_STYLE, style & ~(WS_BORDER | WS_HSCROLL | WS_VSCROLL) );
+        SetWindowLongW( hwnd, GWL_STYLE, style & ~(WS_BORDER | WS_HSCROLL | WS_VSCROLL) );
 
        /*
         * We also have to remove the client edge style to make sure
         * we don't end-up with a non client area.
         */
-        SetWindowLongA( hwnd, GWL_EXSTYLE,
-                        GetWindowLongA( hwnd, GWL_EXSTYLE ) & ~WS_EX_CLIENTEDGE );
+        SetWindowLongW( hwnd, GWL_EXSTYLE,
+                        GetWindowLongW( hwnd, GWL_EXSTYLE ) & ~WS_EX_CLIENTEDGE );
 
        if( !(style & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)) )
               lphc->dwStyle |= CBS_HASSTRINGS;
-       if( !(GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) )
+       if( !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) )
              lphc->wState |= CBF_NOTIFY;
 
         TRACE("[%p], style = %08x\n", lphc, lphc->dwStyle );
@@ -174,7 +187,7 @@ static LRESULT COMBO_NCDestroy( LPHEADCOMBO lphc )
        if( (CB_GETTYPE(lphc) != CBS_SIMPLE) && lphc->hWndLBox )
           DestroyWindow( lphc->hWndLBox );
 
-       SetWindowLongA( lphc->self, 0, 0 );
+       SetWindowLongPtrW( lphc->self, 0, 0 );
        HeapFree( GetProcessHeap(), 0, lphc );
    }
    return 0;
@@ -240,7 +253,7 @@ static INT CBGetTextAreaHeight(
     MEASUREITEMSTRUCT measureItem;
     RECT              clientRect;
     INT               originalItemHeight = iTextItemHeight;
-    UINT id = GetWindowLongA( lphc->self, GWL_ID );
+    UINT id = GetWindowLongPtrW( lphc->self, GWLP_ID );
 
     /*
      * We use the client rect for the width of the item.
@@ -542,8 +555,11 @@ static LRESULT COMBO_Create( HWND hwnd, LPHEADCOMBO lphc, HWND hwndParent, LONG
        if( CB_GETTYPE(lphc) == CBS_DROPDOWN )
          lphc->droppedRect.left += COMBO_EDITBUTTONSPACE();
 
-       ClientToScreen(hwnd, (LPPOINT)&lphc->droppedRect);
-       ClientToScreen(hwnd, (LPPOINT)&lphc->droppedRect.right);
+        if (lphc->droppedRect.bottom < lphc->droppedRect.top)
+            lphc->droppedRect.bottom = lphc->droppedRect.top;
+        if (lphc->droppedRect.right < lphc->droppedRect.left)
+            lphc->droppedRect.right = lphc->droppedRect.left;
+        MapWindowPoints( hwnd, 0, (LPPOINT)&lphc->droppedRect, 2 );
       }
 
       /* create listbox popup */
@@ -583,7 +599,7 @@ static LRESULT COMBO_Create( HWND hwnd, LPHEADCOMBO lphc, HWND hwndParent, LONG
                                            lphc->droppedRect.right - lphc->droppedRect.left,
                                            lphc->droppedRect.bottom - lphc->droppedRect.top,
                                            hwnd, (HMENU)ID_CB_LISTBOX,
-                                           (HINSTANCE)GetWindowLongA( hwnd, GWL_HINSTANCE ), lphc );
+                                           (HINSTANCE)GetWindowLongPtrW( hwnd, GWLP_HINSTANCE ), lphc );
       else
           lphc->hWndLBox = CreateWindowExA(lbeExStyle, "ComboLBox", NULL, lbeStyle,
                                            lphc->droppedRect.left,
@@ -591,7 +607,7 @@ static LRESULT COMBO_Create( HWND hwnd, LPHEADCOMBO lphc, HWND hwndParent, LONG
                                            lphc->droppedRect.right - lphc->droppedRect.left,
                                            lphc->droppedRect.bottom - lphc->droppedRect.top,
                                            hwnd, (HMENU)ID_CB_LISTBOX,
-                                           (HINSTANCE)GetWindowLongA( hwnd, GWL_HINSTANCE ), lphc );
+                                           (HINSTANCE)GetWindowLongPtrW( hwnd, GWLP_HINSTANCE ), lphc );
 
       if( lphc->hWndLBox )
       {
@@ -617,14 +633,14 @@ static LRESULT COMBO_Create( HWND hwnd, LPHEADCOMBO lphc, HWND hwndParent, LONG
                                                    lphc->textRect.right - lphc->textRect.left,
                                                    lphc->textRect.bottom - lphc->textRect.top,
                                                    hwnd, (HMENU)ID_CB_EDIT,
-                                                   (HINSTANCE)GetWindowLongA( hwnd, GWL_HINSTANCE ), NULL );
+                                                   (HINSTANCE)GetWindowLongPtrW( hwnd, GWLP_HINSTANCE ), NULL );
               else
                   lphc->hWndEdit = CreateWindowExA(0, "Edit", NULL, lbeStyle,
                                                    lphc->textRect.left, lphc->textRect.top,
                                                    lphc->textRect.right - lphc->textRect.left,
                                                    lphc->textRect.bottom - lphc->textRect.top,
                                                    hwnd, (HMENU)ID_CB_EDIT,
-                                                   (HINSTANCE)GetWindowLongA( hwnd, GWL_HINSTANCE ), NULL );
+                                                   (HINSTANCE)GetWindowLongPtrW( hwnd, GWLP_HINSTANCE ), NULL );
 
              if( !lphc->hWndEdit )
                bEdit = FALSE;
@@ -736,7 +752,7 @@ static void CBPaintText(
      {
        DRAWITEMSTRUCT dis;
        HRGN           clipRegion;
-       UINT ctlid = GetWindowLongA( lphc->self, GWL_ID );
+       UINT ctlid = (UINT)GetWindowLongPtrW( lphc->self, GWLP_ID );
 
        /* setup state for DRAWITEM message. Owner will highlight */
        if ( (lphc->wState & CBF_FOCUSED) &&
@@ -1047,8 +1063,7 @@ static void CBUpdateEdit( LPHEADCOMBO lphc , INT index )
    if( lphc->wState & CBF_FOCUSED )
       SendMessageW(lphc->hWndEdit, EM_SETSEL, 0, (LPARAM)(-1));
 
-   if( pText )
-       HeapFree( GetProcessHeap(), 0, pText );
+   HeapFree( GetProcessHeap(), 0, pText );
 }
 
 /***********************************************************************
@@ -1399,7 +1414,7 @@ static LRESULT COMBO_Command( LPHEADCOMBO lphc, WPARAM wParam, HWND hWnd )
 static LRESULT COMBO_ItemOp( LPHEADCOMBO lphc, UINT msg, LPARAM lParam )
 {
    HWND hWnd = lphc->self;
-   UINT id = GetWindowLongA( hWnd, GWL_ID );
+   UINT id = (UINT)GetWindowLongPtrW( hWnd, GWLP_ID );
 
    TRACE("[%p]: ownerdraw op %04x\n", lphc->self, msg );
 
@@ -1506,7 +1521,7 @@ static LRESULT COMBO_GetTextA( LPHEADCOMBO lphc, INT count, LPSTR buf )
     if (!count || !buf) return 0;
     if( lphc->hWndLBox )
     {
-        INT idx = SendMessageA(lphc->hWndLBox, LB_GETCURSEL, 0, 0);
+        INT idx = SendMessageW(lphc->hWndLBox, LB_GETCURSEL, 0, 0);
         if (idx == LB_ERR) goto error;
         length = SendMessageA(lphc->hWndLBox, LB_GETTEXTLEN, idx, 0 );
         if (length == LB_ERR) goto error;
@@ -1809,6 +1824,36 @@ static void COMBO_MouseMove( LPHEADCOMBO lphc, WPARAM wParam, LPARAM lParam )
    }
 }
 
+static LRESULT COMBO_GetComboBoxInfo(LPHEADCOMBO lphc, COMBOBOXINFO *pcbi)
+{
+    if (!pcbi || (pcbi->cbSize < sizeof(COMBOBOXINFO)))
+        return FALSE;
+
+    pcbi->rcItem = lphc->textRect;
+    pcbi->rcButton = lphc->buttonRect;
+    pcbi->stateButton = 0;
+    if (lphc->wState & CBF_BUTTONDOWN)
+        pcbi->stateButton |= STATE_SYSTEM_PRESSED;
+    if (IsRectEmpty(&lphc->buttonRect))
+        pcbi->stateButton |= STATE_SYSTEM_INVISIBLE;
+    pcbi->hwndCombo = lphc->self;
+    pcbi->hwndItem = lphc->hWndEdit;
+    pcbi->hwndList = lphc->hWndLBox;
+    return TRUE;
+}
+
+static char *strdupA(LPCSTR str)
+{
+    char *ret;
+    DWORD len;
+
+    if(!str) return NULL;
+
+    len = strlen(str);
+    ret = HeapAlloc(GetProcessHeap(), 0, len + 1);
+    memcpy(ret, str, len + 1);
+    return ret;
+}
 
 /***********************************************************************
  *           ComboWndProc_common
@@ -1818,7 +1863,7 @@ static void COMBO_MouseMove( LPHEADCOMBO lphc, WPARAM wParam, LPARAM lParam )
 static LRESULT ComboWndProc_common( HWND hwnd, UINT message,
                                     WPARAM wParam, LPARAM lParam, BOOL unicode )
 {
-      LPHEADCOMBO lphc = (LPHEADCOMBO)GetWindowLongA( hwnd, 0 );
+      LPHEADCOMBO lphc = (LPHEADCOMBO)GetWindowLongPtrW( hwnd, 0 );
 
       //TRACE("[%p]: msg %s wp %08x lp %08lx\n",
       //      hwnd, SPY_GetMsgName(message, hwnd), wParam, lParam );
@@ -2045,13 +2090,24 @@ static LRESULT ComboWndProc_common( HWND hwnd, UINT message,
                         struprW((LPWSTR)lParam);
                     return SendMessageW(lphc->hWndLBox, LB_ADDSTRING, 0, lParam);
                 }
-                else
+                else /* unlike the unicode version, the ansi version does not overwrite
+                        the string if converting case */
                 {
+                    char *string = NULL;
+                    LRESULT ret;
                     if( lphc->dwStyle & CBS_LOWERCASE )
-                        _strlwr((LPSTR)lParam);
+                    {
+                        string = strdupA((LPSTR)lParam);
+                        _strlwr(string);
+                    }
                     else if( lphc->dwStyle & CBS_UPPERCASE )
-                        _strupr((LPSTR)lParam);
-                    return SendMessageA(lphc->hWndLBox, LB_ADDSTRING, 0, lParam);
+                    {
+                        string = strdupA((LPSTR)lParam);
+                        _strupr(string);
+                    }
+                    ret = SendMessageA(lphc->hWndLBox, LB_ADDSTRING, 0, string ? (LPARAM)string : lParam);
+                    HeapFree(GetProcessHeap(), 0, string);
+                    return ret;
                 }
 #ifndef __REACTOS__
        case CB_INSERTSTRING16:
@@ -2291,6 +2347,8 @@ static LRESULT ComboWndProc_common( HWND hwnd, UINT message,
 #endif
        case CB_GETEXTENDEDUI:
                return  (lphc->wState & CBF_EUI) ? TRUE : FALSE;
+       case CB_GETCOMBOBOXINFO:
+               return COMBO_GetComboBoxInfo(lphc, (COMBOBOXINFO *)lParam);
 
        default:
                if (message >= WM_USER)
@@ -2329,7 +2387,5 @@ static LRESULT WINAPI ComboWndProcW( HWND hwnd, UINT message, WPARAM wParam, LPA
 BOOL WINAPI GetComboBoxInfo(HWND hwndCombo,      /* [in] handle to combo box */
                            PCOMBOBOXINFO pcbi   /* [in/out] combo box information */)
 {
-    FIXME("\n");
-    return FALSE;
-
+    return SendMessageW(hwndCombo, CB_GETCOMBOBOXINFO, 0, (LPARAM)pcbi);
 }