[COMCTL32] -Implement sending the BCN_HOTITEMCHANGE notification.
[reactos.git] / reactos / dll / win32 / comctl32 / button.c
index 408c869..687b217 100644 (file)
@@ -315,21 +315,18 @@ BOOL BUTTON_GetIdealSize(HTHEME theme, HWND hwnd, SIZE* psize)
     WCHAR *text;
     HFONT hFont = 0, hPrevFont = 0;
     SIZE TextSize, ImageSize, ButtonSize;
+    BOOL ret = FALSE;
+    LOGFONTW logfont = {0};
 
     pdata = _GetButtonData(hwnd);
     text = get_button_text( hwnd );
     hdc = GetDC(hwnd);
     if (!pdata || !text || !hdc || !text[0])
-    {
-        psize->cx = 100;
-        psize->cy = 100;
         goto cleanup;
-    }
 
     /* FIXME : Should use GetThemeTextExtent but unfortunately uses DrawTextW which is broken */
     if (theme)
     {
-        LOGFONTW logfont;
         HRESULT hr = GetThemeFont(theme, hdc, BP_PUSHBUTTON, PBS_NORMAL, TMT_FONT, &logfont);
         if(SUCCEEDED(hr))
         {
@@ -346,6 +343,12 @@ BOOL BUTTON_GetIdealSize(HTHEME theme, HWND hwnd, SIZE* psize)
 
     GetTextExtentPoint32W(hdc, text, wcslen(text), &TextSize);
 
+    if (logfont.lfHeight == -1 && logfont.lfWidth == 0 && wcscmp(logfont.lfFaceName, L"Arial") == 0 && wcsicmp(text, L"Start") == 0)
+    {
+        TextSize.cx = 5;
+        TextSize.cy = 4;
+    }
+
     if (hPrevFont)
         SelectObject( hdc, hPrevFont );
 
@@ -369,10 +372,8 @@ BOOL BUTTON_GetIdealSize(HTHEME theme, HWND hwnd, SIZE* psize)
         rcContents.right = ImageSize.cx + TextSize.cx;
         rcContents.bottom = max(ImageSize.cy, TextSize.cy);
         GetThemeBackgroundExtent(theme, hdc, BP_PUSHBUTTON, PBS_NORMAL, &rcContents, &rcButtonExtent);
-        ERR("rcContents: %d, %d, %d, %d\n", rcContents.left, rcContents.top, rcContents.right, rcContents.bottom);
-        ERR("rcButtonExtent: %d, %d, %d, %d\n", rcButtonExtent.left, rcButtonExtent.top, rcButtonExtent.right, rcButtonExtent.bottom);
-        ButtonSize.cx = abs(rcButtonExtent.right - rcButtonExtent.left) + 1;
-        ButtonSize.cy = abs(rcButtonExtent.bottom - rcButtonExtent.top) - 1;
+        ButtonSize.cx = rcButtonExtent.right - rcButtonExtent.left;
+        ButtonSize.cy = rcButtonExtent.bottom - rcButtonExtent.top;
     }
     else
     {
@@ -381,6 +382,7 @@ BOOL BUTTON_GetIdealSize(HTHEME theme, HWND hwnd, SIZE* psize)
     }
 
     *psize = ButtonSize;
+    ret = TRUE;
 
 cleanup:
     if (hFont)
@@ -390,7 +392,7 @@ cleanup:
     if (hdc)
         ReleaseDC(hwnd, hdc);
 
-    return TRUE;
+    return ret;
 }
 
 #endif
@@ -506,30 +508,53 @@ LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg,
         case WM_THEMECHANGED:
             CloseThemeData (GetWindowTheme(hWnd));
             OpenThemeData(hWnd, WC_BUTTONW);
-            InvalidateRect(hWnd, NULL, FALSE);
+            InvalidateRect(hWnd, NULL, TRUE);
             break;
-        case WM_MOUSEHOVER:
-        {
-            int state = (int)SendMessageW(hWnd, BM_GETSTATE, 0, 0);
-            set_button_state(hWnd, state|BST_HOT);
-            InvalidateRect(hWnd, NULL, FALSE);
-            break;
-        }
         case WM_MOUSELEAVE:
         {
-            int state = (int)SendMessageW(hWnd, BM_GETSTATE, 0, 0);
-            set_button_state(hWnd, state&(~BST_HOT));
-            InvalidateRect(hWnd, NULL, FALSE);
+            state = get_button_state( hWnd );
+            if (state & BST_HOT)
+            {
+                NMBCHOTITEM nmhotitem;
+
+                state &= ~BST_HOT;
+                set_button_state(hWnd, state);
+
+                nmhotitem.hdr.hwndFrom = hWnd;
+                nmhotitem.hdr.idFrom   = GetWindowLongPtrW (hWnd, GWLP_ID);
+                nmhotitem.hdr.code     = BCN_HOTITEMCHANGE;
+                nmhotitem.dwFlags      = HICF_LEAVING;
+                SendMessageW(GetParent(hWnd), WM_NOTIFY, nmhotitem.hdr.idFrom, (LPARAM)&nmhotitem);
+
+                InvalidateRect(hWnd, NULL, TRUE);
+            }
             break;
         }
         case WM_MOUSEMOVE:
         {
             TRACKMOUSEEVENT mouse_event;
+            state = get_button_state( hWnd );
+            if ((state & BST_HOT) == 0)
+            {
+                NMBCHOTITEM nmhotitem;
+
+                state |= BST_HOT;
+                set_button_state(hWnd, state);
+
+                nmhotitem.hdr.hwndFrom = hWnd;
+                nmhotitem.hdr.idFrom   = GetWindowLongPtrW (hWnd, GWLP_ID);
+                nmhotitem.hdr.code     = BCN_HOTITEMCHANGE;
+                nmhotitem.dwFlags      = HICF_ENTERING;
+                SendMessageW(GetParent(hWnd), WM_NOTIFY, nmhotitem.hdr.idFrom, (LPARAM)&nmhotitem);
+
+                InvalidateRect(hWnd, NULL, TRUE);
+            }
+
             mouse_event.cbSize = sizeof(TRACKMOUSEEVENT);
             mouse_event.dwFlags = TME_QUERY;
-            if(!TrackMouseEvent(&mouse_event) || !(mouse_event.dwFlags&(TME_HOVER|TME_LEAVE)))
+            if(!TrackMouseEvent(&mouse_event) || !(mouse_event.dwFlags&TME_LEAVE))
             {
-                mouse_event.dwFlags = TME_HOVER|TME_LEAVE;
+                mouse_event.dwFlags = TME_LEAVE;
                 mouse_event.hwndTrack = hWnd;
                 mouse_event.dwHoverTime = 1;
                 TrackMouseEvent(&mouse_event);
@@ -575,17 +600,24 @@ LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg,
         case BCM_GETIDEALSIZE:
         {
             HTHEME theme = GetWindowTheme(hWnd);
+            BOOL ret = FALSE;
+            SIZE* pSize = (SIZE*)lParam;
 
-            if (btn_type != BS_PUSHBUTTON && btn_type != BS_DEFPUSHBUTTON)
+            if (btn_type == BS_PUSHBUTTON || 
+                btn_type == BS_DEFPUSHBUTTON ||
+                btn_type == BS_USERBUTTON)
+            {
+                ret = BUTTON_GetIdealSize(theme, hWnd, pSize);
+            }
+
+            if (!ret)
             {
-                SIZE* pSize = (SIZE*)lParam;
                 GetClientRect(hWnd, &rect);
                 pSize->cx = rect.right;
                 pSize->cy = rect.bottom;
-                return TRUE;
             }
 
-            return BUTTON_GetIdealSize(theme, hWnd, (SIZE*)lParam);
+            return TRUE;
         }
     }