Sync to Wine-20050628:
authorGé van Geldorp <ge@gse.nl>
Wed, 6 Jul 2005 22:33:11 +0000 (22:33 +0000)
committerGé van Geldorp <ge@gse.nl>
Wed, 6 Jul 2005 22:33:11 +0000 (22:33 +0000)
Robert Shearman <rob@codeweavers.com>
- Document how the native lays out the internal components of
  buttons.
- Fix control to follow these rules.
- Don't redraw disabled buttons.
- Padding is never less that GetSystemMetrics(SM_{CX,CY}EDGE).
- Change default iListGap value to 4 to match native.
- Fix a regression in IE where the Favourites menu didn't appear
  correctly because the height and width were swapped in the pager
  control.
Stefan Huehner <stefan@huehner.org>
- Fix more -Wstrict-prototypes warnings.
Mike McCormack <mike@codeweavers.com>
- Warning fixes for -Wmissing-declarations and -Wwrite-strings.
Felix Nawothnig <felix.nawothnig@t-online.de>
- Fix some missed invalidations after column resize.
- Pass the right hwnd to ReleaseDC().
Kouji Sasaki <taro-x@justsystem.co.jp>
- Added the feature to change row height in owner draw controls.
- Added the callback item processing for LISTVIEW_EndEditLabelT
  function.
- Corrected the priority of operators for LISTVIEW_GetNextItem
  function.
Huw Davies <huw@codeweavers.com>
- For modal propsheets we should run our own message loop rather than
  use a modal dialogbox just like Windows does.  This helps apps that
  subclass the propsheet's wndproc.
Francois Gouget <fgouget@free.fr>
- Assorted spelling fixes.
James Hawkins <truiken@gmail.com>
- Audit the Tab control.
- Factor out common text shifting logic.
- Shift selected tab text up instead of down.
Alex Zorach <info@suscomputing.com>
- Fixed SetFocus behavior.
Krzysztof Foltman <wdev@foltman.com>
- Don't send TVN_SELCHANGING nor TVN_SELCHANGED if the same item is
  selected again.

svn path=/trunk/; revision=16472

12 files changed:
reactos/lib/comctl32/comctl32.h
reactos/lib/comctl32/commctrl.c
reactos/lib/comctl32/flatsb.c
reactos/lib/comctl32/ipaddress.c
reactos/lib/comctl32/listview.c
reactos/lib/comctl32/monthcal.c
reactos/lib/comctl32/pager.c
reactos/lib/comctl32/propsheet.c
reactos/lib/comctl32/tab.c
reactos/lib/comctl32/toolbar.c
reactos/lib/comctl32/treeview.c
reactos/lib/comctl32/updown.c

index 6b5a84d..a73911f 100644 (file)
@@ -191,4 +191,62 @@ BOOL WINAPI DPA_Merge (const HDPA, const HDPA, DWORD, PFNDPACOMPARE, PFNDPAMERGE
 LRESULT WINAPI SetPathWordBreakProc(HWND hwnd, BOOL bSet);\r
 BOOL WINAPI MirrorIcon(HICON *phicon1, HICON *phicon2);\r
 \r
+extern void ANIMATE_Register(void);\r
+extern void ANIMATE_Unregister(void);\r
+extern void COMBOEX_Register(void);\r
+extern void COMBOEX_Unregister(void);\r
+extern void DATETIME_Register(void);\r
+extern void DATETIME_Unregister(void);\r
+extern void FLATSB_Register(void);\r
+extern void FLATSB_Unregister(void);\r
+extern void HEADER_Register(void);\r
+extern void HEADER_Unregister(void);\r
+extern void HOTKEY_Register(void);\r
+extern void HOTKEY_Unregister(void);\r
+extern void IPADDRESS_Register(void);\r
+extern void IPADDRESS_Unregister(void);\r
+extern void LISTVIEW_Register(void);\r
+extern void LISTVIEW_Unregister(void);\r
+extern void MONTHCAL_Register(void);\r
+extern void MONTHCAL_Unregister(void);\r
+extern void NATIVEFONT_Register(void);\r
+extern void NATIVEFONT_Unregister(void);\r
+extern void PAGER_Register(void);\r
+extern void PAGER_Unregister(void);\r
+extern void PROGRESS_Register(void);\r
+extern void PROGRESS_Unregister(void);\r
+extern void REBAR_Register(void);\r
+extern void REBAR_Unregister(void);\r
+extern void STATUS_Register(void);\r
+extern void STATUS_Unregister(void);\r
+extern void SYSLINK_Register(void);\r
+extern void SYSLINK_Unregister(void);\r
+extern void TAB_Register(void);\r
+extern void TAB_Unregister(void);\r
+extern void TOOLBAR_Register(void);\r
+extern void TOOLBAR_Unregister(void);\r
+extern void TOOLTIPS_Register(void);\r
+extern void TOOLTIPS_Unregister(void);\r
+extern void TRACKBAR_Register(void);\r
+extern void TRACKBAR_Unregister(void);\r
+extern void TREEVIEW_Register(void);\r
+extern void TREEVIEW_Unregister(void);\r
+extern void UPDOWN_Register(void);\r
+extern void UPDOWN_Unregister(void);\r
+\r
+\r
+int MONTHCAL_MonthLength(int month, int year);\r
+\r
+static inline void MONTHCAL_CopyTime(const SYSTEMTIME *from, SYSTEMTIME *to)\r
+{\r
+  to->wYear = from->wYear;\r
+  to->wMonth = from->wMonth;\r
+  to->wDayOfWeek = from->wDayOfWeek;\r
+  to->wDay = from->wDay;\r
+  to->wHour = from->wHour;\r
+  to->wMinute = from->wMinute;\r
+  to->wSecond = from->wSecond;\r
+  to->wMilliseconds = from->wMilliseconds;\r
+}\r
+\r
 #endif  /* __WINE_COMCTL32_H */\r
index c10aded..0d315e9 100644 (file)
 \r
 WINE_DEFAULT_DEBUG_CHANNEL(commctrl);\r
 \r
-extern void ANIMATE_Register(void);\r
-extern void ANIMATE_Unregister(void);\r
-extern void COMBOEX_Register(void);\r
-extern void COMBOEX_Unregister(void);\r
-extern void DATETIME_Register(void);\r
-extern void DATETIME_Unregister(void);\r
-extern void FLATSB_Register(void);\r
-extern void FLATSB_Unregister(void);\r
-extern void HEADER_Register(void);\r
-extern void HEADER_Unregister(void);\r
-extern void HOTKEY_Register(void);\r
-extern void HOTKEY_Unregister(void);\r
-extern void IPADDRESS_Register(void);\r
-extern void IPADDRESS_Unregister(void);\r
-extern void LISTVIEW_Register(void);\r
-extern void LISTVIEW_Unregister(void);\r
-extern void MONTHCAL_Register(void);\r
-extern void MONTHCAL_Unregister(void);\r
-extern void NATIVEFONT_Register(void);\r
-extern void NATIVEFONT_Unregister(void);\r
-extern void PAGER_Register(void);\r
-extern void PAGER_Unregister(void);\r
-extern void PROGRESS_Register(void);\r
-extern void PROGRESS_Unregister(void);\r
-extern void REBAR_Register(void);\r
-extern void REBAR_Unregister(void);\r
-extern void STATUS_Register(void);\r
-extern void STATUS_Unregister(void);\r
-extern void SYSLINK_Register(void);\r
-extern void SYSLINK_Unregister(void);\r
-extern void TAB_Register(void);\r
-extern void TAB_Unregister(void);\r
-extern void TOOLBAR_Register(void);\r
-extern void TOOLBAR_Unregister(void);\r
-extern void TOOLTIPS_Register(void);\r
-extern void TOOLTIPS_Unregister(void);\r
-extern void TRACKBAR_Register(void);\r
-extern void TRACKBAR_Unregister(void);\r
-extern void TREEVIEW_Register(void);\r
-extern void TREEVIEW_Unregister(void);\r
-extern void UPDOWN_Register(void);\r
-extern void UPDOWN_Unregister(void);\r
-\r
 LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);\r
 \r
 LPWSTR  COMCTL32_wSubclass = NULL;\r
index baebbe6..6d16c3c 100644 (file)
@@ -36,6 +36,7 @@
 #include "winerror.h"\r
 #include "winuser.h"\r
 #include "commctrl.h"\r
+#include "comctl32.h"\r
 #include "wine/debug.h"\r
 \r
 WINE_DEFAULT_DEBUG_CHANNEL(commctrl);\r
index 1e0f50c..5dd0cc1 100644 (file)
@@ -346,11 +346,7 @@ static void IPADDRESS_SetFocusToField (IPADDRESS_INFO *infoPtr, INT index)
 {\r
     TRACE("(index=%d)\n", index);\r
 \r
-    if (index > 3) {\r
-       for (index = 0; index < 4; index++)\r
-           if (!GetWindowTextLengthW(infoPtr->Part[index].EditHwnd)) break;\r
-    }\r
-    if (index < 9 || index > 3) index = 0;\r
+    if (index > 3 || index < 0) index=0;\r
 \r
     SetFocus (infoPtr->Part[index].EditHwnd);\r
 }\r
index 8bd2d9f..c9f9e9d 100644 (file)
@@ -277,7 +277,8 @@ typedef struct tagLISTVIEW_INFO
   HFONT hDefaultFont;\r
   HFONT hFont;\r
   INT ntmHeight;               /* Some cached metrics of the font used */\r
-  INT ntmAveCharWidth;         /* by the listview to draw items */\r
+  INT ntmMaxCharWidth;         /* by the listview to draw items */\r
+  INT nEllipsisWidth;\r
   BOOL bRedraw;                /* Turns on/off repaints & invalidations */\r
   BOOL bAutoarrange;           /* Autoarrange flag when NOT in LVS_AUTOARRANGE */\r
   BOOL bFocus;\r
@@ -307,6 +308,7 @@ typedef struct tagLISTVIEW_INFO
   INT nSearchParamLength;\r
   WCHAR szSearchParam[ MAX_PATH ];\r
   BOOL bIsDrawing;\r
+  INT nMeasureItemHeight;\r
 } LISTVIEW_INFO;\r
 \r
 /*\r
@@ -548,7 +550,7 @@ static inline LPCSTR debugtext_tn(LPCWSTR text, BOOL isW, INT n)
     return isW ? debugstr_wn(text, n) : debugstr_an((LPCSTR)text, n);\r
 }\r
 \r
-static char* debug_getbuf()\r
+static char* debug_getbuf(void)\r
 {\r
     static int index = 0;\r
     static char buffers[DEBUG_BUFFERS][DEBUG_BUFFER_SIZE];\r
@@ -2454,6 +2456,8 @@ static INT LISTVIEW_CalculateItemHeight(LISTVIEW_INFO *infoPtr)
            nItemHeight = max(nItemHeight, infoPtr->iconSize.cy);\r
        if (infoPtr->himlState || infoPtr->himlSmall)\r
            nItemHeight += HEIGHT_PADDING;\r
+    if (infoPtr->nMeasureItemHeight > 0)\r
+        nItemHeight = infoPtr->nMeasureItemHeight;\r
     }\r
 \r
     return max(nItemHeight, 1);\r
@@ -2491,12 +2495,17 @@ static void LISTVIEW_SaveTextMetrics(LISTVIEW_INFO *infoPtr)
     HFONT hFont = infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont;\r
     HFONT hOldFont = SelectObject(hdc, hFont);\r
     TEXTMETRICW tm;\r
+    SIZE sz;\r
 \r
     if (GetTextMetricsW(hdc, &tm))\r
     {\r
        infoPtr->ntmHeight = tm.tmHeight;\r
-       infoPtr->ntmAveCharWidth = tm.tmAveCharWidth;\r
+       infoPtr->ntmMaxCharWidth = tm.tmMaxCharWidth;\r
     }\r
+\r
+    if (GetTextExtentPoint32A(hdc, "...", 3, &sz))\r
+       infoPtr->nEllipsisWidth = sz.cx;\r
+       \r
     SelectObject(hdc, hOldFont);\r
     ReleaseDC(infoPtr->hwndSelf, hdc);\r
     \r
@@ -4268,6 +4277,7 @@ static void LISTVIEW_ScrollColumns(LISTVIEW_INFO *infoPtr, INT nColumn, INT dx)
 {\r
     COLUMN_INFO *lpColumnInfo;\r
     RECT rcOld, rcCol;\r
+    POINT ptOrigin;\r
     INT nCol;\r
    \r
     if (nColumn < 0 || DPA_GetPtrCount(infoPtr->hdpaColumns) < 1) return;\r
@@ -4294,10 +4304,11 @@ static void LISTVIEW_ScrollColumns(LISTVIEW_INFO *infoPtr, INT nColumn, INT dx)
     infoPtr->nItemWidth += dx;\r
 \r
     LISTVIEW_UpdateScroll(infoPtr);\r
+    LISTVIEW_GetOrigin(infoPtr, &ptOrigin);\r
 \r
     /* scroll to cover the deleted column, and invalidate for redraw */\r
     rcOld = infoPtr->rcList;\r
-    rcOld.left = rcCol.left;\r
+    rcOld.left = ptOrigin.x + rcCol.left + dx;\r
     ScrollWindowEx(infoPtr->hwndSelf, dx, 0, &rcOld, &rcOld, 0, 0, SW_ERASE | SW_INVALIDATE);\r
     \r
     /* we can restore focus now */\r
@@ -4562,6 +4573,17 @@ static BOOL LISTVIEW_EndEditLabelT(LISTVIEW_INFO *infoPtr, LPWSTR pszText, BOOL
     if (!notify_dispinfoT(infoPtr, LVN_ENDLABELEDITW, &dispInfo, isW)) return FALSE;\r
     if (!pszText) return TRUE;\r
 \r
+    if (!(infoPtr->dwStyle & LVS_OWNERDATA))\r
+    {\r
+        HDPA hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, infoPtr->nEditLabelItem);\r
+        ITEM_INFO* lpItem = (ITEM_INFO *)DPA_GetPtr(hdpaSubItems, 0);\r
+        if (lpItem && lpItem->hdr.pszText == LPSTR_TEXTCALLBACKW)\r
+        {\r
+            LISTVIEW_InvalidateItem(infoPtr, infoPtr->nEditLabelItem);\r
+            return TRUE;\r
+        }\r
+    }\r
+\r
     ZeroMemory(&dispInfo, sizeof(dispInfo));\r
     dispInfo.item.mask = LVIF_TEXT;\r
     dispInfo.item.iItem = infoPtr->nEditLabelItem;\r
@@ -5738,7 +5760,7 @@ static INT LISTVIEW_GetNextItem(LISTVIEW_INFO *infoPtr, INT nItem, UINT uFlags)
      * so it's worth optimizing */\r
     if (uFlags & LVNI_FOCUSED)\r
     {\r
-       if (!(LISTVIEW_GetItemState(infoPtr, infoPtr->nFocusedItem, uMask) & uMask) == uMask) return -1;\r
+       if ((LISTVIEW_GetItemState(infoPtr, infoPtr->nFocusedItem, uMask) & uMask) != uMask) return -1;\r
        return (infoPtr->nFocusedItem == nItem) ? -1 : infoPtr->nFocusedItem;\r
     }\r
     \r
@@ -6906,7 +6928,7 @@ static DWORD LISTVIEW_SetIconSpacing(LISTVIEW_INFO *infoPtr, INT cx, INT cy)
     return oldspacing;\r
 }\r
 \r
-inline void set_icon_size(SIZE *size, HIMAGELIST himl, BOOL small)\r
+static inline void set_icon_size(SIZE *size, HIMAGELIST himl, BOOL small)\r
 {\r
     INT cx, cy;\r
     \r
@@ -7500,6 +7522,7 @@ static LRESULT LISTVIEW_Create(HWND hwnd, const CREATESTRUCTW *lpcs)
   infoPtr->iconSpacing.cy = GetSystemMetrics(SM_CYICONSPACING);\r
   infoPtr->nEditLabelItem = -1;\r
   infoPtr->dwHoverTime = -1; /* default system hover time */\r
+  infoPtr->nMeasureItemHeight = 0;\r
 \r
   /* get default font (icon title) */\r
   SystemParametersInfoW(SPI_GETICONTITLELOGFONT, 0, &logFont, 0);\r
@@ -8275,21 +8298,27 @@ static LRESULT LISTVIEW_HeaderNotification(LISTVIEW_INFO *infoPtr, const NMHEADE
            dx = cxy - (lpColumnInfo->rcHeader.right - lpColumnInfo->rcHeader.left);\r
            if (dx != 0)\r
            {\r
-               RECT rcCol = lpColumnInfo->rcHeader;\r
-\r
                lpColumnInfo->rcHeader.right += dx;\r
                LISTVIEW_ScrollColumns(infoPtr, lpnmh->iItem + 1, dx);\r
                LISTVIEW_UpdateItemSize(infoPtr);\r
                if (uView == LVS_REPORT && is_redrawing(infoPtr))\r
                {\r
-                   /* this trick works for left aligned columns only */\r
+                   POINT ptOrigin;\r
+                   RECT rcCol = lpColumnInfo->rcHeader;\r
+                   \r
+                   LISTVIEW_GetOrigin(infoPtr, &ptOrigin);\r
+                   OffsetRect(&rcCol, ptOrigin.x, 0);\r
+                   \r
+                   rcCol.top = infoPtr->rcList.top;\r
+                   rcCol.bottom = infoPtr->rcList.bottom;\r
+\r
+                   /* resizing left-aligned columns leaves most of the left side untouched */\r
                    if ((lpColumnInfo->fmt & LVCFMT_JUSTIFYMASK) == LVCFMT_LEFT)\r
                    {\r
-                       rcCol.right = min (rcCol.right, lpColumnInfo->rcHeader.right);\r
-                       rcCol.left = max (rcCol.left, rcCol.right - 3 * infoPtr->ntmAveCharWidth);\r
+                       INT nMaxDirty = infoPtr->nEllipsisWidth + infoPtr->ntmMaxCharWidth + dx;\r
+                       rcCol.left = max (rcCol.left, rcCol.right - nMaxDirty);\r
                    }\r
-                   rcCol.top = infoPtr->rcList.top;\r
-                   rcCol.bottom = infoPtr->rcList.bottom;\r
+                   \r
                    LISTVIEW_InvalidateRect(infoPtr, &rcCol);\r
                }\r
            }\r
@@ -9314,8 +9343,24 @@ LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
   case WM_WINDOWPOSCHANGED:\r
       if (!(((WINDOWPOS *)lParam)->flags & SWP_NOSIZE)) \r
       {\r
+      UINT uView = infoPtr->dwStyle & LVS_TYPEMASK;\r
          SetWindowPos(infoPtr->hwndSelf, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOACTIVATE |\r
                       SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE);\r
+\r
+      if ((infoPtr->dwStyle & LVS_OWNERDRAWFIXED) && (uView == LVS_REPORT))\r
+      {\r
+          MEASUREITEMSTRUCT mis;\r
+          mis.CtlType = ODT_LISTVIEW;\r
+          mis.CtlID = GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_ID);\r
+          mis.itemID = -1;\r
+          mis.itemWidth = 0;\r
+          mis.itemData = 0;\r
+          mis.itemHeight= infoPtr->nItemHeight;\r
+          SendMessageW(infoPtr->hwndNotify, WM_MEASUREITEM, mis.CtlID, (LPARAM)&mis);\r
+          if (infoPtr->nItemHeight != max(mis.itemHeight, 1))\r
+              infoPtr->nMeasureItemHeight = infoPtr->nItemHeight = max(mis.itemHeight, 1);\r
+      }\r
+\r
          LISTVIEW_UpdateSize(infoPtr);\r
          LISTVIEW_UpdateScroll(infoPtr);\r
       }\r
@@ -9433,7 +9478,7 @@ static LRESULT LISTVIEW_Command(LISTVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lP
             if(hFont != 0)\r
                 SelectObject(hdc, hOldFont);\r
 \r
-           ReleaseDC(infoPtr->hwndSelf, hdc);\r
+           ReleaseDC(infoPtr->hwndEdit, hdc);\r
 \r
            break;\r
        }\r
index 75fa4e4..2504758 100644 (file)
@@ -134,7 +134,7 @@ static const int DayOfWeekTable[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
 /* january is 1, december is 12 */\r
 int MONTHCAL_MonthLength(int month, int year)\r
 {\r
-const int mdays[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0};\r
+  const int mdays[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0};\r
   /*Wrap around, this eases handling*/\r
   if(month == 0)\r
     month = 12;\r
@@ -170,19 +170,6 @@ static int MONTHCAL_ValidateTime(SYSTEMTIME time)
 }\r
 \r
 \r
-void MONTHCAL_CopyTime(const SYSTEMTIME *from, SYSTEMTIME *to)\r
-{\r
-  to->wYear = from->wYear;\r
-  to->wMonth = from->wMonth;\r
-  to->wDayOfWeek = from->wDayOfWeek;\r
-  to->wDay = from->wDay;\r
-  to->wHour = from->wHour;\r
-  to->wMinute = from->wMinute;\r
-  to->wSecond = from->wSecond;\r
-  to->wMilliseconds = from->wMilliseconds;\r
-}\r
-\r
-\r
 /* Note:Depending on DST, this may be offset by a day.\r
    Need to find out if we're on a DST place & adjust the clock accordingly.\r
    Above function assumes we have a valid data.\r
@@ -212,7 +199,7 @@ static int MONTHCAL_CalcDayFromPos(MONTHCAL_INFO *infoPtr, int x, int y,
   GetClientRect(infoPtr->hwndSelf, &rcClient);\r
 \r
   /* if the point is outside the x bounds of the window put\r
-  it at the boundry */\r
+  it at the boundary */\r
   if (x > rcClient.right)\r
     x = rcClient.right;\r
 \r
index 021489e..b426a63 100644 (file)
@@ -1227,9 +1227,9 @@ PAGER_Size (PAGER_INFO* infoPtr, INT type, INT x, INT y)
     TRACE("[%p] %d,%d\n", infoPtr->hwndSelf, x, y);\r
 \r
     if (infoPtr->dwStyle & PGS_HORZ)\r
-        infoPtr->nHeight = x;\r
+        infoPtr->nHeight = y;\r
     else\r
-        infoPtr->nWidth = y;\r
+        infoPtr->nWidth = x;\r
 \r
     return PAGER_RecalcSize(infoPtr);\r
 }\r
index f61463a..200c429 100644 (file)
@@ -131,6 +131,7 @@ typedef struct tagPropSheetInfo
   int width;\r
   int height;\r
   HIMAGELIST hImageList;\r
+  BOOL ended;\r
 } PropSheetInfo;\r
 \r
 typedef struct\r
@@ -296,7 +297,7 @@ static void PROPSHEET_GetPageRect(const PropSheetInfo * psInfo, HWND hwndDlg,
  *\r
  * Find page index corresponding to page resource id.\r
  */\r
-INT PROPSHEET_FindPageByResId(PropSheetInfo * psInfo, LRESULT resId)\r
+static INT PROPSHEET_FindPageByResId(PropSheetInfo * psInfo, LRESULT resId)\r
 {\r
    INT i;\r
 \r
@@ -707,39 +708,21 @@ int PROPSHEET_CreateDialog(PropSheetInfo* psInfo)
    * -1 (error). */\r
   if( psInfo->unicode )\r
   {\r
-    if (!(psInfo->ppshheader.dwFlags & PSH_MODELESS))\r
-      ret = DialogBoxIndirectParamW(psInfo->ppshheader.hInstance,\r
-                                    (LPDLGTEMPLATEW) temp,\r
-                                    psInfo->ppshheader.hwndParent,\r
-                                    PROPSHEET_DialogProc,\r
-                                    (LPARAM)psInfo);\r
-    else\r
-    {\r
-      ret = (int)CreateDialogIndirectParamW(psInfo->ppshheader.hInstance,\r
-                                            (LPDLGTEMPLATEW) temp,\r
-                                            psInfo->ppshheader.hwndParent,\r
-                                            PROPSHEET_DialogProc,\r
-                                            (LPARAM)psInfo);\r
-      if ( !ret ) ret = -1;\r
-    }\r
+    ret = (int)CreateDialogIndirectParamW(psInfo->ppshheader.hInstance,\r
+                                          (LPDLGTEMPLATEW) temp,\r
+                                          psInfo->ppshheader.hwndParent,\r
+                                          PROPSHEET_DialogProc,\r
+                                          (LPARAM)psInfo);\r
+    if ( !ret ) ret = -1;\r
   }\r
   else\r
   {\r
-    if (!(psInfo->ppshheader.dwFlags & PSH_MODELESS))\r
-      ret = DialogBoxIndirectParamA(psInfo->ppshheader.hInstance,\r
-                                    (LPDLGTEMPLATEA) temp,\r
-                                    psInfo->ppshheader.hwndParent,\r
-                                    PROPSHEET_DialogProc,\r
-                                    (LPARAM)psInfo);\r
-    else\r
-    {\r
-      ret = (int)CreateDialogIndirectParamA(psInfo->ppshheader.hInstance,\r
-                                            (LPDLGTEMPLATEA) temp,\r
-                                            psInfo->ppshheader.hwndParent,\r
-                                            PROPSHEET_DialogProc,\r
-                                            (LPARAM)psInfo);\r
-      if ( !ret ) ret = -1;\r
-    }\r
+    ret = (int)CreateDialogIndirectParamA(psInfo->ppshheader.hInstance,\r
+                                          (LPDLGTEMPLATEA) temp,\r
+                                          psInfo->ppshheader.hwndParent,\r
+                                          PROPSHEET_DialogProc,\r
+                                          (LPARAM)psInfo);\r
+    if ( !ret ) ret = -1;\r
   }\r
 \r
   Free(temp);\r
@@ -1265,7 +1248,7 @@ static BOOL PROPSHEET_CreateTabControl(HWND hwndParent,
  * Subclassing window procedure for wizard extrior pages to prevent drawing\r
  * background and so drawing above the watermark.\r
  */\r
-LRESULT CALLBACK\r
+static LRESULT CALLBACK\r
 PROPSHEET_WizardSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uID, DWORD_PTR dwRef)\r
 {\r
   switch (uMsg)\r
@@ -1757,7 +1740,7 @@ static BOOL PROPSHEET_Finish(HWND hwndDlg)
   if (psInfo->isModeless)\r
     psInfo->activeValid = FALSE;\r
   else\r
-    EndDialog(hwndDlg, TRUE);\r
+    psInfo->ended = TRUE;\r
 \r
   return TRUE;\r
 }\r
@@ -1870,7 +1853,7 @@ static void PROPSHEET_Cancel(HWND hwndDlg, LPARAM lParam)
      psInfo->activeValid = FALSE;\r
   }\r
   else\r
-    EndDialog(hwndDlg, FALSE);\r
+    psInfo->ended = TRUE;\r
 }\r
 \r
 /******************************************************************************\r
@@ -2396,7 +2379,7 @@ static BOOL PROPSHEET_RemovePage(HWND hwndDlg,
       psInfo->active_page = -1;\r
       if (!psInfo->isModeless)\r
       {\r
-         EndDialog(hwndDlg, FALSE);\r
+         psInfo->ended = TRUE;\r
          return TRUE;\r
       }\r
     }\r
@@ -2737,6 +2720,34 @@ static void PROPSHEET_CleanUp(HWND hwndDlg)
   GlobalFree((HGLOBAL)psInfo);\r
 }\r
 \r
+static INT do_loop(PropSheetInfo *psInfo)\r
+{\r
+    MSG msg;\r
+    INT ret = -1;\r
+    HWND hwnd = psInfo->hwnd;\r
+\r
+    while(IsWindow(hwnd) && !psInfo->ended && (ret = GetMessageW(&msg, NULL, 0, 0)))\r
+    {\r
+        if(ret == -1)\r
+            break;\r
+\r
+        if(!IsDialogMessageW(hwnd, &msg))\r
+        {\r
+            TranslateMessage(&msg);\r
+            DispatchMessageW(&msg);\r
+        }\r
+    }\r
+\r
+    if(ret == 0)\r
+    {\r
+        PostQuitMessage(msg.wParam);\r
+        ret = -1;\r
+    }\r
+\r
+    DestroyWindow(hwnd);\r
+    return ret;\r
+}\r
+\r
 /******************************************************************************\r
  *            PropertySheet    (COMCTL32.@)\r
  *            PropertySheetA   (COMCTL32.@)\r
@@ -2787,7 +2798,11 @@ INT WINAPI PropertySheetA(LPCPROPSHEETHEADERA lppsh)
   }\r
 \r
   psInfo->unicode = FALSE;\r
+  psInfo->ended = FALSE;\r
+\r
   bRet = PROPSHEET_CreateDialog(psInfo);\r
+  if(!psInfo->isModeless)\r
+      bRet = do_loop(psInfo);\r
 \r
   return bRet;\r
 }\r
@@ -2834,7 +2849,11 @@ INT WINAPI PropertySheetW(LPCPROPSHEETHEADERW lppsh)
   }\r
 \r
   psInfo->unicode = TRUE;\r
+  psInfo->ended = FALSE;\r
+\r
   bRet = PROPSHEET_CreateDialog(psInfo);\r
+  if(!psInfo->isModeless)\r
+      bRet = do_loop(psInfo);\r
 \r
   return bRet;\r
 }\r
@@ -3039,7 +3058,7 @@ static BOOL PROPSHEET_DoCommand(HWND hwnd, WORD wID)
                    if (psInfo->isModeless)\r
                        psInfo->activeValid = FALSE;\r
                    else\r
-                       EndDialog(hwnd, result);\r
+                        psInfo->ended = TRUE;\r
                }\r
            else\r
                EnableWindow(hwndApplyBtn, FALSE);\r
@@ -3424,6 +3443,17 @@ PROPSHEET_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
       }\r
       return TRUE;\r
 \r
+    case WM_SYSCOMMAND:\r
+      switch(wParam & 0xfff0)\r
+      {\r
+        case SC_CLOSE:\r
+          PROPSHEET_Cancel(hwnd, 1);\r
+          return TRUE;\r
+\r
+        default:\r
+          return FALSE;\r
+      }\r
+\r
     case WM_NOTIFY:\r
     {\r
       NMHDR* pnmh = (LPNMHDR) lParam;\r
index 9f4f280..927046c 100644 (file)
  * License along with this library; if not, write to the Free Software\r
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
  *\r
+ * NOTES\r
+ *\r
+ * This code was audited for completeness against the documented features\r
+ * of Comctl32.dll version 6.0 on May. 20, 2005, by James Hawkins.\r
+ *\r
+ * Unless otherwise noted, we believe this code to be complete, as per\r
+ * the specification mentioned above.\r
+ * If you discover missing features, or bugs, please note them below.\r
+ *\r
  * TODO:\r
  *\r
  *  Styles:\r
+ *   TCS_MULTISELECT\r
+ *   TCS_RIGHT\r
+ *   TCS_RIGHTJUSTIFY\r
+ *   TCS_SCROLLOPPOSITE\r
+ *   TCS_SINGLELINE\r
  *   TCIF_RTLREADING\r
  *\r
+ *  Extended Styles:\r
+ *   TCS_EX_FLATSEPARATORS\r
+ *   TCS_EX_REGISTERDROP\r
+ *\r
+ *  States:\r
+ *   TCIS_BUTTONPRESSED\r
+ *\r
+ *  Notifications:\r
+ *   NM_RELEASEDCAPTURE\r
+ *   TCN_FOCUSCHANGE\r
+ *   TCN_GETOBJECT\r
+ *   TCN_KEYDOWN\r
+ *\r
  *  Messages:\r
  *   TCM_REMOVEIMAGE\r
  *   TCM_DESELECTALL\r
  *   TCM_GETEXTENDEDSTYLE\r
  *   TCM_SETEXTENDEDSTYLE\r
  *\r
+ *  Macros:\r
+ *   TabCtrl_AdjustRect\r
+ *\r
  */\r
 \r
 #include <stdarg.h>\r
@@ -1727,14 +1757,20 @@ TAB_DrawItemInterior
       else\r
         drawRect->bottom-=center_offset_h;\r
 \r
-      center_offset_v = ((drawRect->right - drawRect->left) - (rcText.bottom - rcText.top) + infoPtr->uVItemPadding) / 2;\r
+      center_offset_v = ((drawRect->right - drawRect->left) - (rcText.bottom - rcText.top)) / 2;\r
     }\r
     else\r
     {\r
       drawRect->left += center_offset_h;\r
-      center_offset_v = ((drawRect->bottom - drawRect->top) - (rcText.bottom - rcText.top) + infoPtr->uVItemPadding) / 2;\r
+      center_offset_v = ((drawRect->bottom - drawRect->top) - (rcText.bottom - rcText.top)) / 2;\r
     }\r
 \r
+    /* if an item is selected, the text is shifted up instead of down */\r
+    if (iItem == infoPtr->iSelected)\r
+        center_offset_v -= infoPtr->uVItemPadding / 2;\r
+    else\r
+        center_offset_v += infoPtr->uVItemPadding / 2;\r
+\r
     if (center_offset_v < 0)\r
       center_offset_v = 0;\r
 \r
index b740673..53f1884 100644 (file)
@@ -211,12 +211,13 @@ typedef enum
 \r
 #define DEFPAD_CX 7\r
 #define DEFPAD_CY 6\r
+#define DEFLISTGAP 4\r
+\r
+/* vertical padding used in list mode when image is present */\r
+#define LISTPAD_CY 9\r
 \r
-/* gap between border of button and text/image */\r
-#define OFFSET_X 1\r
-#define OFFSET_Y 1\r
 /* how wide to treat the bitmap if it isn't present */\r
-#define LIST_IMAGE_ABSENT_WIDTH 2\r
+#define NONLIST_NOTEXT_OFFSET 2\r
 \r
 #define TOOLBAR_NOWHERE (-1)\r
 \r
@@ -224,11 +225,6 @@ typedef enum
 #define TOOLBAR_HasText(x, y) (TOOLBAR_GetText(x, y) ? TRUE : FALSE)\r
 #define TOOLBAR_HasDropDownArrows(exStyle) ((exStyle & TBSTYLE_EX_DRAWDDARROWS) ? TRUE : FALSE)\r
 \r
-static inline int TOOLBAR_GetListTextOffset(TOOLBAR_INFO *infoPtr, INT iListGap)\r
-{\r
-    return GetSystemMetrics(SM_CXEDGE) + iListGap - infoPtr->szPadding.cx/2;\r
-}\r
-\r
 /* Used to find undocumented extended styles */\r
 #define TBSTYLE_EX_ALL (TBSTYLE_EX_DRAWDDARROWS | \\r
                         TBSTYLE_EX_UNDOC1 | \\r
@@ -396,6 +392,14 @@ TOOLBAR_IsValidBitmapIndex(TOOLBAR_INFO *infoPtr, INT index)
 }\r
 \r
 \r
+static inline BOOL\r
+TOOLBAR_IsValidImageList(TOOLBAR_INFO *infoPtr, INT index)\r
+{\r
+    HIMAGELIST himl = GETDEFIMAGELIST(infoPtr, GETHIMLID(infoPtr, index));\r
+    return (himl != NULL) && (ImageList_GetImageCount(himl) > 0);\r
+}\r
+\r
+\r
 /***********************************************************************\r
 *              TOOLBAR_GetImageListForDrawing\r
 *\r
@@ -445,37 +449,6 @@ TOOLBAR_GetImageListForDrawing (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, IMA
 }\r
 \r
 \r
-/***********************************************************************\r
-*              TOOLBAR_TestImageExist\r
-*\r
-* This function is similar to TOOLBAR_GetImageListForDrawing, except it does not\r
-* return the image list. The I_IMAGECALLBACK functionality is implemented.\r
-*/\r
-static BOOL\r
-TOOLBAR_TestImageExist (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, HIMAGELIST himl)\r
-{\r
-    INT index;\r
-\r
-    if (!himl) return FALSE;\r
-\r
-    if (!TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap)) {\r
-       if (btnPtr->iBitmap == I_IMAGENONE) return FALSE;\r
-       ERR("index %d is not valid, max %d\n",\r
-           btnPtr->iBitmap, infoPtr->nNumBitmaps);\r
-       return FALSE;\r
-    }\r
-\r
-    if ((index = TOOLBAR_GetBitmapIndex(infoPtr, btnPtr)) < 0) {\r
-       if ((index == I_IMAGECALLBACK) ||\r
-           (index == I_IMAGENONE)) return FALSE;\r
-       ERR("TBN_GETDISPINFO returned invalid index %d\n",\r
-           index);\r
-       return FALSE;\r
-    }\r
-    return TRUE;\r
-}\r
-\r
-\r
 static void\r
 TOOLBAR_DrawFlatSeparator (LPRECT lpRect, HDC hdc, TOOLBAR_INFO *infoPtr)\r
 {\r
@@ -755,7 +728,7 @@ TOOLBAR_DrawImage(TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, INT left, INT top
 \r
 /* draws a blank frame for a toolbar button */\r
 static void\r
-TOOLBAR_DrawFrame(const TOOLBAR_INFO *infoPtr, BOOL flat, const NMTBCUSTOMDRAW *tbcd)\r
+TOOLBAR_DrawFrame(const TOOLBAR_INFO *infoPtr, const NMTBCUSTOMDRAW *tbcd)\r
 {\r
     HDC hdc = tbcd->nmcd.hdc;\r
     RECT rc = tbcd->nmcd.rc;\r
@@ -771,7 +744,7 @@ TOOLBAR_DrawFrame(const TOOLBAR_INFO *infoPtr, BOOL flat, const NMTBCUSTOMDRAW *
     if (infoPtr->dwItemCDFlag & TBCDRF_NOEDGES)\r
         return;\r
 \r
-    if (flat)\r
+    if (infoPtr->dwStyle & TBSTYLE_FLAT)\r
     {\r
         if (pressed_look)\r
             DrawEdge (hdc, &rc, BDR_SUNKENOUTER, BF_RECT);\r
@@ -845,7 +818,6 @@ TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc)
 \r
     rc = btnPtr->rect;\r
     CopyRect (&rcArrow, &rc);\r
-    CopyRect(&rcBitmap, &rc);\r
 \r
     /* get a pointer to the text */\r
     lpText = TOOLBAR_GetText(infoPtr, btnPtr);\r
@@ -865,47 +837,51 @@ TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc)
         rcArrow.left = right;\r
     }\r
 \r
-    /* copy text rect after adjusting for drop-down arrow\r
-     * so that text is centred in the rectangle not containing\r
+    /* copy text & bitmap rects after adjusting for drop-down arrow\r
+     * so that text & bitmap is centred in the rectangle not containing\r
      * the arrow */\r
     CopyRect(&rcText, &rc);\r
+    CopyRect(&rcBitmap, &rc);\r
 \r
     /* Center the bitmap horizontally and vertically */\r
     if (dwStyle & TBSTYLE_LIST)\r
-        rcBitmap.left += GetSystemMetrics(SM_CXEDGE);\r
+    {\r
+        if (lpText &&\r
+            infoPtr->nMaxTextRows > 0 &&\r
+            (!(infoPtr->dwExStyle & TBSTYLE_EX_MIXEDBUTTONS) ||\r
+            (btnPtr->fsStyle & BTNS_SHOWTEXT)) )\r
+            rcBitmap.left += GetSystemMetrics(SM_CXEDGE) + infoPtr->szPadding.cx / 2;\r
+        else\r
+            rcBitmap.left += GetSystemMetrics(SM_CXEDGE) + infoPtr->iListGap / 2;\r
+    }\r
     else\r
-        rcBitmap.left+=(infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2;\r
+        rcBitmap.left += (infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2;\r
 \r
-    if(lpText)\r
-        rcBitmap.top+= GetSystemMetrics(SM_CYEDGE);\r
-    else\r
-        rcBitmap.top+=(infoPtr->nButtonHeight - infoPtr->nBitmapHeight) / 2;\r
+    rcBitmap.top += infoPtr->szPadding.cy / 2;\r
 \r
-    TRACE("iBitmap%d, start=(%ld,%ld) w=%d, h=%d\n",\r
+    TRACE("iBitmap=%d, start=(%ld,%ld) w=%d, h=%d\n",\r
       btnPtr->iBitmap, rcBitmap.left, rcBitmap.top,\r
       infoPtr->nBitmapWidth, infoPtr->nBitmapHeight);\r
-    TRACE ("iString: %x\n", btnPtr->iString);\r
-    TRACE ("Stringtext: %s\n", debugstr_w(lpText));\r
+    TRACE("Text=%s\n", debugstr_w(lpText));\r
+    TRACE("iListGap=%d, padding = { %ld, %ld }\n", infoPtr->iListGap, infoPtr->szPadding.cx, infoPtr->szPadding.cy);\r
 \r
-    /* draw text */\r
-    if (lpText) {\r
-        rcText.left += GetSystemMetrics(SM_CXEDGE) + OFFSET_X;\r
-        rcText.right -= GetSystemMetrics(SM_CXEDGE) + OFFSET_X;\r
-        if (GETDEFIMAGELIST(infoPtr, GETHIMLID(infoPtr,btnPtr->iBitmap)) &&\r
-            TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))\r
+    /* calculate text position */\r
+    if (lpText)\r
+    {\r
+        rcText.left += GetSystemMetrics(SM_CXEDGE);\r
+        rcText.right -= GetSystemMetrics(SM_CXEDGE);\r
+        if (dwStyle & TBSTYLE_LIST)\r
         {\r
-            if (dwStyle & TBSTYLE_LIST)\r
-                rcText.left += infoPtr->nBitmapWidth + TOOLBAR_GetListTextOffset(infoPtr, infoPtr->iListGap);\r
-            else\r
-                rcText.top += GetSystemMetrics(SM_CYEDGE) + OFFSET_Y + infoPtr->nBitmapHeight + infoPtr->szPadding.cy/2;\r
+            if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))\r
+                rcText.left += infoPtr->nBitmapWidth + infoPtr->iListGap + 2;\r
         }\r
         else\r
-            if (dwStyle & TBSTYLE_LIST)\r
-                rcText.left += LIST_IMAGE_ABSENT_WIDTH + TOOLBAR_GetListTextOffset(infoPtr, infoPtr->iListGap);\r
-\r
-        if (!(infoPtr->dwItemCDFlag & TBCDRF_NOOFFSET) &&\r
-          (btnPtr->fsState & (TBSTATE_PRESSED | TBSTATE_CHECKED)))\r
-            OffsetRect(&rcText, 1, 1);\r
+        {\r
+            if (ImageList_GetImageCount(GETDEFIMAGELIST(infoPtr, 0)) > 0)\r
+                rcText.top += infoPtr->szPadding.cy/2 + infoPtr->nBitmapHeight + 1;\r
+            else\r
+                rcText.top += infoPtr->szPadding.cy/2 + 2;\r
+        }\r
     }\r
 \r
     /* Initialize fields in all cases, because we use these later\r
@@ -980,6 +956,10 @@ TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc)
        goto FINALNOTIFY;\r
     }\r
 \r
+    if (!(infoPtr->dwItemCDFlag & TBCDRF_NOOFFSET) &&\r
+        (btnPtr->fsState & (TBSTATE_PRESSED | TBSTATE_CHECKED)))\r
+        OffsetRect(&rcText, 1, 1);\r
+\r
     if (!(tbcd.nmcd.uItemState & CDIS_HOT) && \r
         ((tbcd.nmcd.uItemState & CDIS_CHECKED) || (tbcd.nmcd.uItemState & CDIS_INDETERMINATE)))\r
         TOOLBAR_DrawPattern (&rc, &tbcd);\r
@@ -998,7 +978,7 @@ TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc)
         }\r
     }\r
 \r
-    TOOLBAR_DrawFrame(infoPtr, dwStyle & TBSTYLE_FLAT, &tbcd);\r
+    TOOLBAR_DrawFrame(infoPtr, &tbcd);\r
 \r
     if (drawSepDropDownArrow)\r
         TOOLBAR_DrawSepDDArrow(infoPtr, &tbcd, &rcArrow, btnPtr->bDropDownPressed);\r
@@ -1397,6 +1377,166 @@ TOOLBAR_WrapToolbar( HWND hwnd, DWORD dwStyle )
 }\r
 \r
 \r
+/***********************************************************************\r
+*              TOOLBAR_MeasureButton\r
+*\r
+* Calculates the width and height required for a button. Used in\r
+* TOOLBAR_CalcToolbar to set the all-button width and height and also for\r
+* the width of buttons that are autosized.\r
+*\r
+* Note that it would have been rather elegant to use one piece of code for\r
+* both the laying out of the toolbar and for controlling where button parts\r
+* are drawn, but the native control has inconsistencies between the two that\r
+* prevent this from being effectively. These inconsistencies can be seen as\r
+* artefacts where parts of the button appear outside of the bounding button\r
+* rectangle.\r
+*\r
+* There are several cases for the calculation of the button dimensions and\r
+* button part positioning:\r
+*\r
+* List\r
+* ====\r
+*\r
+* With Bitmap:\r
+*\r
+* +--------------------------------------------------------+ ^\r
+* |                    ^                     ^             | |\r
+* |                    | pad.cy / 2          | centred     | |\r
+* | pad.cx/2 + cxedge +--------------+     +------------+  | | DEFPAD_CY +\r
+* |<----------------->| nBitmapWidth |     | Text       |  | | max(nBitmapHeight, szText.cy)\r
+* |                   |<------------>|     |            |  | |\r
+* |                   +--------------+     +------------+  | |\r
+* |<-------------------------------------->|               | |\r
+* |  cxedge + iListGap + nBitmapWidth + 2  |<----------->  | |\r
+* |                                           szText.cx    | |\r
+* +--------------------------------------------------------+ -\r
+* <-------------------------------------------------------->\r
+*  2*cxedge + nBitmapWidth + iListGap + szText.cx + pad.cx\r
+*\r
+* Without Bitmap (I_IMAGENONE):\r
+*\r
+* +-----------------------------------+ ^\r
+* |                     ^             | |\r
+* |                     | centred     | | LISTPAD_CY +\r
+* |                   +------------+  | | szText.cy\r
+* |                   | Text       |  | |\r
+* |                   |            |  | |\r
+* |                   +------------+  | |\r
+* |<----------------->|               | |\r
+* |      cxedge       |<----------->  | |\r
+* |                      szText.cx    | |\r
+* +-----------------------------------+ -\r
+* <----------------------------------->\r
+*          szText.cx + pad.cx\r
+*\r
+* Without text:\r
+*\r
+* +--------------------------------------+ ^\r
+* |                       ^              | |\r
+* |                       | padding.cy/2 | | DEFPAD_CY +\r
+* |                     +------------+   | | nBitmapHeight\r
+* |                     | Bitmap     |   | |\r
+* |                     |            |   | |\r
+* |                     +------------+   | |\r
+* |<------------------->|                | |\r
+* | cxedge + iListGap/2 |<----------->   | |\r
+* |                       nBitmapWidth   | |\r
+* +--------------------------------------+ -\r
+* <-------------------------------------->\r
+*     2*cxedge + nBitmapWidth + iListGap\r
+*\r
+* Non-List\r
+* ========\r
+*\r
+* With bitmap:\r
+*\r
+* +-----------------------------------+ ^\r
+* |                     ^             | |\r
+* |                     | pad.cy / 2  | | nBitmapHeight +\r
+* |                     -             | | szText.cy +\r
+* |                   +------------+  | | DEFPAD_CY + 1\r
+* |    centred        |   Bitmap   |  | |\r
+* |<----------------->|            |  | |\r
+* |                   +------------+  | |\r
+* |                         ^         | |\r
+* |                       1 |         | |\r
+* |                         -         | |\r
+* |     centred     +---------------+ | |\r
+* |<--------------->|      Text     | | |\r
+* |                 +---------------+ | |\r
+* +-----------------------------------+ -\r
+* <----------------------------------->\r
+* pad.cx + max(nBitmapWidth, szText.cx)\r
+*\r
+* Without bitmaps (NULL imagelist or ImageList_GetImageCount() = 0):\r
+*\r
+* +---------------------------------------+ ^\r
+* |                     ^                 | |\r
+* |                     | 2 + pad.cy / 2  | |\r
+* |                     -                 | | szText.cy +\r
+* |    centred      +-----------------+   | | pad.cy + 2\r
+* |<--------------->|   Text          |   | |\r
+* |                 +-----------------+   | |\r
+* |                                       | |\r
+* +---------------------------------------+ -\r
+* <--------------------------------------->\r
+*          2*cxedge + pad.cx + szText.cx\r
+*\r
+* Without text:\r
+*   As for with bitmaps, but with szText.cx zero.\r
+*/\r
+static inline SIZE TOOLBAR_MeasureButton(TOOLBAR_INFO *infoPtr, SIZE sizeString, BOOL bHasBitmap, BOOL bValidImageList)\r
+{\r
+    SIZE sizeButton;\r
+    if (infoPtr->dwStyle & TBSTYLE_LIST)\r
+    {\r
+        /* set button height from bitmap / text height... */\r
+        sizeButton.cy = max((bHasBitmap ? infoPtr->nBitmapHeight : 0),\r
+            sizeString.cy);\r
+\r
+        /* ... add on the necessary padding */\r
+        if (bValidImageList)\r
+        {\r
+            if (bHasBitmap)\r
+                sizeButton.cy += DEFPAD_CY;\r
+            else\r
+                sizeButton.cy += LISTPAD_CY;\r
+        }\r
+        else\r
+            sizeButton.cy += infoPtr->szPadding.cy;\r
+\r
+        /* calculate button width */\r
+        if (bHasBitmap)\r
+        {\r
+            sizeButton.cx = 2*GetSystemMetrics(SM_CXEDGE) +\r
+                infoPtr->nBitmapWidth + infoPtr->iListGap;\r
+            if (sizeString.cx > 0)\r
+                sizeButton.cx += sizeString.cx + infoPtr->szPadding.cx;\r
+        }\r
+        else\r
+            sizeButton.cx = sizeString.cx + infoPtr->szPadding.cx;\r
+    }\r
+    else\r
+    {\r
+        if (bHasBitmap)\r
+        {\r
+            sizeButton.cy = infoPtr->nBitmapHeight + 1 +\r
+                sizeString.cy + DEFPAD_CY;\r
+            sizeButton.cx = infoPtr->szPadding.cx +\r
+                max(sizeString.cx, infoPtr->nBitmapWidth);\r
+        }\r
+        else\r
+        {\r
+            sizeButton.cy = sizeString.cy + infoPtr->szPadding.cy +\r
+                NONLIST_NOTEXT_OFFSET;\r
+            sizeButton.cx = 2*GetSystemMetrics(SM_CXEDGE) +\r
+                infoPtr->szPadding.cx + sizeString.cx;\r
+        }\r
+    }\r
+    return sizeButton;\r
+}\r
+\r
+\r
 /***********************************************************************\r
 *              TOOLBAR_CalcToolbar\r
 *\r
@@ -1407,7 +1547,6 @@ TOOLBAR_WrapToolbar( HWND hwnd, DWORD dwStyle )
 * the tooltip window if appropriate. Finally, it updates the rcBound\r
 * rect and calculates the new required toolbar window height.\r
 */\r
-\r
 static void\r
 TOOLBAR_CalcToolbar (HWND hwnd)\r
 {\r
@@ -1416,9 +1555,10 @@ TOOLBAR_CalcToolbar (HWND hwnd)
     TBUTTON_INFO *btnPtr;\r
     INT i, nRows, nSepRows;\r
     INT x, y, cx, cy;\r
-    SIZE  sizeString;\r
+    SIZE  sizeString, sizeButton;\r
     BOOL bWrap;\r
     BOOL usesBitmaps = FALSE;\r
+    BOOL validImageList = FALSE;\r
     BOOL hasDropDownArrows = TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle);\r
 \r
     TOOLBAR_CalcStrings (hwnd, &sizeString);\r
@@ -1430,36 +1570,11 @@ TOOLBAR_CalcToolbar (HWND hwnd)
        if (TOOLBAR_IsValidBitmapIndex(infoPtr,infoPtr->buttons[i].iBitmap))\r
            usesBitmaps = TRUE;\r
     }\r
-    if (dwStyle & TBSTYLE_LIST)\r
-    {\r
-       infoPtr->nButtonHeight = max((usesBitmaps) ? infoPtr->nBitmapHeight :\r
-                                    0, sizeString.cy) + infoPtr->szPadding.cy;\r
-       infoPtr->nButtonWidth = ((usesBitmaps) ? infoPtr->nBitmapWidth :\r
-                                LIST_IMAGE_ABSENT_WIDTH) + sizeString.cx + infoPtr->szPadding.cx;\r
-        if (sizeString.cx > 0)\r
-            infoPtr->nButtonWidth += TOOLBAR_GetListTextOffset(infoPtr, infoPtr->iListGap) + infoPtr->szPadding.cx/2;\r
-       TRACE("LIST style, But w=%d h=%d, useBitmaps=%d, Bit w=%d h=%d\n",\r
-             infoPtr->nButtonWidth, infoPtr->nButtonHeight, usesBitmaps,\r
-             infoPtr->nBitmapWidth, infoPtr->nBitmapHeight);\r
-    }\r
-    else {\r
-        if (sizeString.cy > 0)\r
-        {\r
-            if (usesBitmaps)\r
-               infoPtr->nButtonHeight = sizeString.cy +\r
-                   infoPtr->szPadding.cy/2 + /* this is the space to separate text from bitmap */\r
-                  infoPtr->nBitmapHeight + infoPtr->szPadding.cy;\r
-            else\r
-                infoPtr->nButtonHeight = sizeString.cy + infoPtr->szPadding.cy;\r
-        }\r
-        else\r
-           infoPtr->nButtonHeight = infoPtr->nBitmapHeight + infoPtr->szPadding.cy;\r
-\r
-        if (sizeString.cx > infoPtr->nBitmapWidth)\r
-           infoPtr->nButtonWidth = sizeString.cx + infoPtr->szPadding.cx;\r
-        else\r
-            infoPtr->nButtonWidth = infoPtr->nBitmapWidth + infoPtr->szPadding.cx;\r
-    }\r
+    if (TOOLBAR_IsValidImageList(infoPtr, 0))\r
+        validImageList = TRUE;\r
+    sizeButton = TOOLBAR_MeasureButton(infoPtr, sizeString, usesBitmaps, validImageList);\r
+    infoPtr->nButtonWidth = sizeButton.cx;\r
+    infoPtr->nButtonHeight = sizeButton.cy;\r
 \r
     if ( infoPtr->cxMin >= 0 && infoPtr->nButtonWidth < infoPtr->cxMin )\r
         infoPtr->nButtonWidth = infoPtr->cxMin;\r
@@ -1474,9 +1589,7 @@ TOOLBAR_CalcToolbar (HWND hwnd)
     /* from above, minimum is a button, and possible text */\r
     cx = infoPtr->nButtonWidth;\r
 \r
-    /* cannot use just ButtonHeight, we may have no buttons! */\r
-    if (infoPtr->nNumButtons > 0)\r
-        infoPtr->nHeight = infoPtr->nButtonHeight;\r
+    infoPtr->nHeight = infoPtr->nButtonHeight;\r
 \r
     cy = infoPtr->nHeight;\r
 \r
@@ -1534,22 +1647,10 @@ TOOLBAR_CalcToolbar (HWND hwnd)
              SelectObject (hdc, hOldFont);\r
              ReleaseDC (hwnd, hdc);\r
 \r
-              /* add space on for button frame, etc */\r
-              cx = sz.cx + infoPtr->szPadding.cx;\r
-              \r
-              /* add list padding */\r
-              if ((dwStyle & TBSTYLE_LIST) && sz.cx > 0)\r
-                  cx += TOOLBAR_GetListTextOffset(infoPtr, infoPtr->iListGap) + infoPtr->szPadding.cx/2;\r
-\r
-              if (TOOLBAR_TestImageExist (infoPtr, btnPtr, GETDEFIMAGELIST(infoPtr,0)))\r
-              {\r
-                if (dwStyle & TBSTYLE_LIST)\r
-                  cx += infoPtr->nBitmapWidth;\r
-                else if (cx < (infoPtr->nBitmapWidth+infoPtr->szPadding.cx))\r
-                  cx = infoPtr->nBitmapWidth+infoPtr->szPadding.cx;\r
-              }\r
-              else if (dwStyle & TBSTYLE_LIST)\r
-                  cx += LIST_IMAGE_ABSENT_WIDTH;\r
+              sizeButton = TOOLBAR_MeasureButton(infoPtr, sz,\r
+                  TOOLBAR_IsValidBitmapIndex(infoPtr, infoPtr->buttons[i].iBitmap),\r
+                  validImageList);\r
+              cx = sizeButton.cx;\r
             }\r
             else\r
              cx = infoPtr->nButtonWidth;\r
@@ -4934,10 +5035,11 @@ TOOLBAR_SetHotItemEx (TOOLBAR_INFO *infoPtr, INT nHit, DWORD dwReason)
 \r
        no_highlight = TOOLBAR_SendNotify(&nmhotitem.hdr, infoPtr, TBN_HOTITEMCHANGE);\r
 \r
-       /* now invalidate the old and new buttons so they will be painted */\r
-       if (oldBtnPtr)\r
+       /* now invalidate the old and new buttons so they will be painted,\r
+        * but only if they are enabled - disabled buttons cannot become hot */\r
+       if (oldBtnPtr && (oldBtnPtr->fsState & TBSTATE_ENABLED))\r
            InvalidateRect(infoPtr->hwndSelf, &oldBtnPtr->rect, TRUE);\r
-       if (btnPtr && !no_highlight)\r
+       if (btnPtr && !no_highlight && (btnPtr->fsState & TBSTATE_ENABLED))\r
        {\r
             btnPtr->bHot = TRUE;\r
            InvalidateRect(infoPtr->hwndSelf, &btnPtr->rect, TRUE);\r
@@ -4990,8 +5092,8 @@ TOOLBAR_SetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
     if (!ImageList_GetIconSize(himl, &infoPtr->nBitmapWidth,\r
             &infoPtr->nBitmapHeight))\r
     {\r
-        infoPtr->nBitmapWidth = 0;\r
-        infoPtr->nBitmapHeight = 0;\r
+        infoPtr->nBitmapWidth = 1;\r
+        infoPtr->nBitmapHeight = 1;\r
     }\r
 \r
     TRACE("hwnd %p, new himl=%p, id = %d, count=%d, bitmap w=%d, h=%d\n",\r
@@ -5089,6 +5191,7 @@ TOOLBAR_SetMaxTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
  *    to control the bottom and right borders [with the border being\r
  *    szPadding.cx - (GetSystemMetrics(SM_CXEDGE)+1)], otherwise the padding\r
  *    is shared evenly on both sides of the button.\r
+ * See blueprints in comments above TOOLBAR_MeasureButton for more info.\r
  */\r
 static LRESULT\r
 TOOLBAR_SetPadding (HWND hwnd, WPARAM wParam, LPARAM lParam)\r
@@ -5097,8 +5200,8 @@ TOOLBAR_SetPadding (HWND hwnd, WPARAM wParam, LPARAM lParam)
     DWORD  oldPad;\r
 \r
     oldPad = MAKELONG(infoPtr->szPadding.cx, infoPtr->szPadding.cy);\r
-    infoPtr->szPadding.cx = LOWORD((DWORD)lParam);\r
-    infoPtr->szPadding.cy = HIWORD((DWORD)lParam);\r
+    infoPtr->szPadding.cx = min(LOWORD((DWORD)lParam), GetSystemMetrics(SM_CXEDGE));\r
+    infoPtr->szPadding.cy = min(HIWORD((DWORD)lParam), GetSystemMetrics(SM_CYEDGE));\r
     TRACE("cx=%ld, cy=%ld\n",\r
          infoPtr->szPadding.cx, infoPtr->szPadding.cy);\r
     return (LRESULT) oldPad;\r
@@ -5487,7 +5590,7 @@ TOOLBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
     infoPtr->clrBtnShadow = CLR_DEFAULT;\r
     infoPtr->szPadding.cx = DEFPAD_CX;\r
     infoPtr->szPadding.cy = DEFPAD_CY;\r
-    infoPtr->iListGap = infoPtr->szPadding.cx / 2;\r
+    infoPtr->iListGap = DEFLISTGAP;\r
     infoPtr->dwStyle = dwStyle;\r
     infoPtr->tbim.iButton = -1;\r
     GetClientRect(hwnd, &infoPtr->client_rect);\r
index 0bf386c..7ed7304 100644 (file)
@@ -4221,6 +4221,11 @@ TREEVIEW_DoSelectItem(TREEVIEW_INFO *infoPtr, INT action, HTREEITEM newSelect,
     case TVGN_CARET:\r
        prevSelect = infoPtr->selectedItem;\r
 \r
+       if (prevSelect == newSelect) {\r
+           TREEVIEW_EnsureVisible(infoPtr, infoPtr->selectedItem, FALSE);\r
+           break;\r
+       }\r
+\r
        if (TREEVIEW_SendTreeviewNotify(infoPtr,\r
                                        TVN_SELCHANGINGW,\r
                                        cause,\r
index da2dcc1..bec0fd0 100644 (file)
@@ -238,7 +238,7 @@ static BOOL UPDOWN_GetArrowFromPoint (UPDOWN_INFO* infoPtr, RECT *rect, POINT pt
  *           UPDOWN_GetThousandSep\r
  * Returns the thousand sep. If an error occurs, it returns ','.\r
  */\r
-static WCHAR UPDOWN_GetThousandSep()\r
+static WCHAR UPDOWN_GetThousandSep(void)\r
 {\r
     WCHAR sep[2];\r
 \r