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
\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
#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
{\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
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
INT nSearchParamLength;\r
WCHAR szSearchParam[ MAX_PATH ];\r
BOOL bIsDrawing;\r
+ INT nMeasureItemHeight;\r
} LISTVIEW_INFO;\r
\r
/*\r
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
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
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
{\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
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
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
* 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
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
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
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
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
if(hFont != 0)\r
SelectObject(hdc, hOldFont);\r
\r
- ReleaseDC(infoPtr->hwndSelf, hdc);\r
+ ReleaseDC(infoPtr->hwndEdit, hdc);\r
\r
break;\r
}\r
/* 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
}\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
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
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
int width;\r
int height;\r
HIMAGELIST hImageList;\r
+ BOOL ended;\r
} PropSheetInfo;\r
\r
typedef struct\r
*\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
* -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
* 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
if (psInfo->isModeless)\r
psInfo->activeValid = FALSE;\r
else\r
- EndDialog(hwndDlg, TRUE);\r
+ psInfo->ended = TRUE;\r
\r
return TRUE;\r
}\r
psInfo->activeValid = FALSE;\r
}\r
else\r
- EndDialog(hwndDlg, FALSE);\r
+ psInfo->ended = TRUE;\r
}\r
\r
/******************************************************************************\r
psInfo->active_page = -1;\r
if (!psInfo->isModeless)\r
{\r
- EndDialog(hwndDlg, FALSE);\r
+ psInfo->ended = TRUE;\r
return TRUE;\r
}\r
}\r
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
}\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
}\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
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
}\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
* 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
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
\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
#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
}\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
}\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
\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
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
\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
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
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
}\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
}\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
* 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
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
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
/* 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
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
\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
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
* 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
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
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
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
* 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