[comctl32]

- Sync comctl32 with wine. Among it's improvements are reduced flicker in the listview and hot tracking support for themed buttons

svn path=/branches/GSoC_2011/ThemesSupport/; revision=52714
This commit is contained in:
Giannis Adamopoulos 2011-07-17 15:16:59 +00:00
parent 84291d0d72
commit 8d084e9377
15 changed files with 648 additions and 529 deletions

View file

@ -1120,10 +1120,10 @@ static LRESULT COMBOEX_Command (COMBOEX_INFO *infoPtr, WPARAM wParam)
switch (command)
{
case CBN_DROPDOWN:
SetFocus (infoPtr->hwndCombo);
ShowWindow (infoPtr->hwndEdit, SW_HIDE);
return SendMessageW (parent, WM_COMMAND, wParam, (LPARAM)infoPtr->hwndSelf);
SetFocus (infoPtr->hwndCombo);
ShowWindow (infoPtr->hwndEdit, SW_HIDE);
infoPtr->flags |= WCBE_ACTEDIT;
return SendMessageW (parent, WM_COMMAND, wParam, (LPARAM)infoPtr->hwndSelf);
case CBN_CLOSEUP:
SendMessageW (parent, WM_COMMAND, wParam, (LPARAM)infoPtr->hwndSelf);
/*
@ -1741,7 +1741,7 @@ COMBOEX_EditWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
return DefSubclassProc(hwnd, uMsg, wParam, lParam);
case WM_KEYDOWN: {
INT_PTR oldItem, selected, step = 1;
INT_PTR oldItem, selected;
CBE_ITEMDATA *item;
switch ((INT)wParam)
@ -1851,13 +1851,15 @@ COMBOEX_EditWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
break;
case VK_UP:
step = -1;
case VK_DOWN:
/* by default, step is 1 */
{
INT step = wParam == VK_DOWN ? 1 : -1;
oldItem = SendMessageW (infoPtr->hwndSelf, CB_GETCURSEL, 0, 0);
if (oldItem >= 0 && oldItem + step >= 0)
SendMessageW (infoPtr->hwndSelf, CB_SETCURSEL, oldItem + step, 0);
return 0;
}
default:
return DefSubclassProc(hwnd, uMsg, wParam, lParam);
}

View file

@ -168,23 +168,23 @@ DWORD WINAPI GetSize (LPVOID lpMem)
*|typedef INT (CALLBACK *MRUStringCmpFn)(LPCTSTR lhs, LPCTSTR rhs);
*|typedef INT (CALLBACK *MRUBinaryCmpFn)(LPCVOID lhs, LPCVOID rhs, DWORD length);
*|
*|typedef struct tagCREATEMRULIST
*|typedef struct tagMRUINFO
*|{
*| DWORD cbSize;
*| DWORD nMaxItems;
*| DWORD dwFlags;
*| UINT uMax;
*| UINT fFlags;
*| HKEY hKey;
*| LPTSTR lpszSubKey;
*| PROC lpfnCompare;
*|} CREATEMRULIST, *LPCREATEMRULIST;
*|} MRUINFO, *LPMRUINFO;
*
* MEMBERS
* cbSize [I] The size of the CREATEMRULIST structure. This must be set
* to sizeof(CREATEMRULIST) by the caller.
* nMaxItems [I] The maximum number of items allowed in the list. Because
* cbSize [I] The size of the MRUINFO structure. This must be set
* to sizeof(MRUINFO) by the caller.
* uMax [I] The maximum number of items allowed in the list. Because
* of the limited number of identifiers, this should be set to
* a value from 1 to 30 by the caller.
* dwFlags [I] If bit 0 is set, the list will be used to store binary
* fFlags [I] If bit 0 is set, the list will be used to store binary
* data, otherwise it is assumed to store strings. If bit 1
* is set, every change made to the list will be reflected in
* the registry immediately, otherwise changes will only be
@ -210,11 +210,11 @@ typedef INT (CALLBACK *MRUStringCmpFnA)(LPCSTR lhs, LPCSTR rhs);
typedef INT (CALLBACK *MRUStringCmpFnW)(LPCWSTR lhs, LPCWSTR rhs);
typedef INT (CALLBACK *MRUBinaryCmpFn)(LPCVOID lhs, LPCVOID rhs, DWORD length);
typedef struct tagCREATEMRULISTA
typedef struct tagMRUINFOA
{
DWORD cbSize;
DWORD nMaxItems;
DWORD dwFlags;
UINT uMax;
UINT fFlags;
HKEY hKey;
LPSTR lpszSubKey;
union
@ -222,13 +222,13 @@ typedef struct tagCREATEMRULISTA
MRUStringCmpFnA string_cmpfn;
MRUBinaryCmpFn binary_cmpfn;
} u;
} CREATEMRULISTA, *LPCREATEMRULISTA;
} MRUINFOA, *LPMRUINFOA;
typedef struct tagCREATEMRULISTW
typedef struct tagMRUINFOW
{
DWORD cbSize;
DWORD nMaxItems;
DWORD dwFlags;
UINT uMax;
UINT fFlags;
HKEY hKey;
LPWSTR lpszSubKey;
union
@ -236,12 +236,12 @@ typedef struct tagCREATEMRULISTW
MRUStringCmpFnW string_cmpfn;
MRUBinaryCmpFn binary_cmpfn;
} u;
} CREATEMRULISTW, *LPCREATEMRULISTW;
} MRUINFOW, *LPMRUINFOW;
/* dwFlags */
#define MRUF_STRING_LIST 0 /* list will contain strings */
#define MRUF_BINARY_LIST 1 /* list will contain binary data */
#define MRUF_DELAYED_SAVE 2 /* only save list order to reg. is FreeMRUList */
/* MRUINFO.fFlags */
#define MRU_STRING 0 /* list will contain strings */
#define MRU_BINARY 1 /* list will contain binary data */
#define MRU_CACHEWRITE 2 /* only save list order to reg. is FreeMRUList */
/* If list is a string list lpfnCompare has the following prototype
* int CALLBACK MRUCompareString(LPCSTR s1, LPCSTR s2)
@ -263,7 +263,7 @@ typedef struct tagWINEMRUITEM
typedef struct tagWINEMRULIST
{
CREATEMRULISTW extview; /* original create information */
MRUINFOW extview; /* original create information */
BOOL isUnicode; /* is compare fn Unicode */
DWORD wineFlags; /* internal flags */
DWORD cursize; /* current size of realMRU */
@ -325,7 +325,7 @@ static void MRU_SaveChanged ( LPWINEMRULIST mp )
witem->itemFlag &= ~WMRUIF_CHANGED;
realname[0] = 'a' + i;
err = RegSetValueExW(newkey, realname, 0,
(mp->extview.dwFlags & MRUF_BINARY_LIST) ?
(mp->extview.fFlags & MRU_BINARY) ?
REG_BINARY : REG_SZ,
&witem->datastart, witem->size);
if (err) {
@ -363,7 +363,7 @@ void WINAPI FreeMRUList (HANDLE hMRUList)
MRU_SaveChanged( mp );
}
for(i=0; i<mp->extview.nMaxItems; i++)
for(i=0; i<mp->extview.uMax; i++)
Free(mp->array[i]);
Free(mp->realMRU);
@ -400,7 +400,7 @@ INT WINAPI FindMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData,
if (!mp || !mp->extview.u.string_cmpfn)
return -1;
if(!(mp->extview.dwFlags & MRUF_BINARY_LIST) && !mp->isUnicode) {
if(!(mp->extview.fFlags & MRU_BINARY) && !mp->isUnicode) {
DWORD len = WideCharToMultiByte(CP_ACP, 0, lpData, -1,
NULL, 0, NULL, NULL);
dataA = Alloc(len);
@ -408,7 +408,7 @@ INT WINAPI FindMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData,
}
for(i=0; i<mp->cursize; i++) {
if (mp->extview.dwFlags & MRUF_BINARY_LIST) {
if (mp->extview.fFlags & MRU_BINARY) {
if (!mp->extview.u.binary_cmpfn(lpData, &mp->array[i]->datastart, cbData))
break;
}
@ -480,7 +480,7 @@ INT WINAPI AddMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData)
}
else {
/* either add a new entry or replace oldest */
if (mp->cursize < mp->extview.nMaxItems) {
if (mp->cursize < mp->extview.uMax) {
/* Add in a new item */
replace = mp->cursize;
mp->cursize++;
@ -509,7 +509,7 @@ INT WINAPI AddMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData)
TRACE("(%p, %p, %d) adding data, /%c/ now most current\n",
hList, lpData, cbData, replace+'a');
if (!(mp->extview.dwFlags & MRUF_DELAYED_SAVE)) {
if (!(mp->extview.fFlags & MRU_CACHEWRITE)) {
/* save changed stuff right now */
MRU_SaveChanged( mp );
}
@ -649,9 +649,9 @@ INT WINAPI FindMRUStringA (HANDLE hList, LPCSTR lpszString, LPINT lpRegNum)
}
/*************************************************************************
* CreateMRUListLazy_common (internal)
* create_mru_list (internal)
*/
static HANDLE CreateMRUListLazy_common(LPWINEMRULIST mp)
static HANDLE create_mru_list(LPWINEMRULIST mp)
{
UINT i, err;
HKEY newkey;
@ -663,12 +663,12 @@ static HANDLE CreateMRUListLazy_common(LPWINEMRULIST mp)
/* get space to save indices that will turn into names
* but in order of most to least recently used
*/
mp->realMRU = Alloc((mp->extview.nMaxItems + 2) * sizeof(WCHAR));
mp->realMRU = Alloc((mp->extview.uMax + 2) * sizeof(WCHAR));
/* get space to save pointers to actual data in order of
* 'a' to 'z' (0 to n).
*/
mp->array = Alloc(mp->extview.nMaxItems * sizeof(LPVOID));
mp->array = Alloc(mp->extview.uMax * sizeof(LPVOID));
/* open the sub key */
if ((err = RegCreateKeyExW( mp->extview.hKey, mp->extview.lpszSubKey,
@ -681,7 +681,7 @@ static HANDLE CreateMRUListLazy_common(LPWINEMRULIST mp)
&dwdisp))) {
/* error - what to do ??? */
ERR("(%u %u %x %p %s %p): Could not open key, error=%d\n",
mp->extview.cbSize, mp->extview.nMaxItems, mp->extview.dwFlags,
mp->extview.cbSize, mp->extview.uMax, mp->extview.fFlags,
mp->extview.hKey, debugstr_w(mp->extview.lpszSubKey),
mp->extview.u.string_cmpfn, err);
return 0;
@ -689,7 +689,7 @@ static HANDLE CreateMRUListLazy_common(LPWINEMRULIST mp)
/* get values from key 'MRUList' */
if (newkey) {
datasize = (mp->extview.nMaxItems + 1) * sizeof(WCHAR);
datasize = (mp->extview.uMax + 1) * sizeof(WCHAR);
if((err=RegQueryValueExW( newkey, strMRUList, 0, &type,
(LPBYTE)mp->realMRU, &datasize))) {
/* not present - set size to 1 (will become 0 later) */
@ -726,7 +726,7 @@ static HANDLE CreateMRUListLazy_common(LPWINEMRULIST mp)
mp->cursize = 0;
TRACE("(%u %u %x %p %s %p): Current Size = %d\n",
mp->extview.cbSize, mp->extview.nMaxItems, mp->extview.dwFlags,
mp->extview.cbSize, mp->extview.uMax, mp->extview.fFlags,
mp->extview.hKey, debugstr_w(mp->extview.lpszSubKey),
mp->extview.u.string_cmpfn, mp->cursize);
return mp;
@ -737,24 +737,22 @@ static HANDLE CreateMRUListLazy_common(LPWINEMRULIST mp)
*
* See CreateMRUListLazyA.
*/
HANDLE WINAPI CreateMRUListLazyW (const CREATEMRULISTW *lpcml, DWORD dwParam2,
HANDLE WINAPI CreateMRUListLazyW (const MRUINFOW *infoW, DWORD dwParam2,
DWORD dwParam3, DWORD dwParam4)
{
LPWINEMRULIST mp;
/* Native does not check for a NULL lpcml */
if (lpcml->cbSize != sizeof(CREATEMRULISTW) || !lpcml->hKey ||
IsBadStringPtrW(lpcml->lpszSubKey, -1))
if (!infoW->hKey || IsBadStringPtrW(infoW->lpszSubKey, -1))
return NULL;
mp = Alloc(sizeof(WINEMRULIST));
memcpy(&mp->extview, lpcml, sizeof(CREATEMRULISTW));
mp->extview.lpszSubKey = Alloc((strlenW(lpcml->lpszSubKey) + 1) * sizeof(WCHAR));
strcpyW(mp->extview.lpszSubKey, lpcml->lpszSubKey);
memcpy(&mp->extview, infoW, sizeof(MRUINFOW));
mp->extview.lpszSubKey = Alloc((strlenW(infoW->lpszSubKey) + 1) * sizeof(WCHAR));
strcpyW(mp->extview.lpszSubKey, infoW->lpszSubKey);
mp->isUnicode = TRUE;
return CreateMRUListLazy_common(mp);
return create_mru_list(mp);
}
/**************************************************************************
@ -771,7 +769,7 @@ HANDLE WINAPI CreateMRUListLazyW (const CREATEMRULISTW *lpcml, DWORD dwParam2,
* RETURNS
* Handle to MRU list.
*/
HANDLE WINAPI CreateMRUListLazyA (const CREATEMRULISTA *lpcml, DWORD dwParam2,
HANDLE WINAPI CreateMRUListLazyA (const MRUINFOA *lpcml, DWORD dwParam2,
DWORD dwParam3, DWORD dwParam4)
{
LPWINEMRULIST mp;
@ -779,18 +777,18 @@ HANDLE WINAPI CreateMRUListLazyA (const CREATEMRULISTA *lpcml, DWORD dwParam2,
/* Native does not check for a NULL lpcml */
if (lpcml->cbSize != sizeof(CREATEMRULISTA) || !lpcml->hKey ||
if (lpcml->cbSize != sizeof(MRUINFOA) || !lpcml->hKey ||
IsBadStringPtrA(lpcml->lpszSubKey, -1))
return 0;
mp = Alloc(sizeof(WINEMRULIST));
memcpy(&mp->extview, lpcml, sizeof(CREATEMRULISTW));
memcpy(&mp->extview, lpcml, sizeof(MRUINFOA));
len = MultiByteToWideChar(CP_ACP, 0, lpcml->lpszSubKey, -1, NULL, 0);
mp->extview.lpszSubKey = Alloc(len * sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, 0, lpcml->lpszSubKey, -1,
mp->extview.lpszSubKey, len);
mp->isUnicode = FALSE;
return CreateMRUListLazy_common(mp);
return create_mru_list(mp);
}
/**************************************************************************
@ -798,9 +796,9 @@ HANDLE WINAPI CreateMRUListLazyA (const CREATEMRULISTA *lpcml, DWORD dwParam2,
*
* See CreateMRUListA.
*/
HANDLE WINAPI CreateMRUListW (const CREATEMRULISTW *lpcml)
HANDLE WINAPI CreateMRUListW (const MRUINFOW *infoW)
{
return CreateMRUListLazyW(lpcml, 0, 0, 0);
return CreateMRUListLazyW(infoW, 0, 0, 0);
}
/**************************************************************************
@ -814,7 +812,7 @@ HANDLE WINAPI CreateMRUListW (const CREATEMRULISTW *lpcml)
* RETURNS
* Handle to MRU list.
*/
HANDLE WINAPI CreateMRUListA (const CREATEMRULISTA *lpcml)
HANDLE WINAPI CreateMRUListA (const MRUINFOA *lpcml)
{
return CreateMRUListLazyA (lpcml, 0, 0, 0);
}
@ -879,7 +877,7 @@ INT WINAPI EnumMRUListA (HANDLE hList, INT nItemPos, LPVOID lpBuffer,
desired -= 'a';
TRACE("nItemPos=%d, desired=%d\n", nItemPos, desired);
witem = mp->array[desired];
if(mp->extview.dwFlags & MRUF_BINARY_LIST) {
if(mp->extview.fFlags & MRU_BINARY) {
datasize = min( witem->size, nBufferSize );
memcpy( lpBuffer, &witem->datastart, datasize);
} else {

View file

@ -73,6 +73,8 @@ typedef struct
BOOL bCalDepressed; /* TRUE = cal button is depressed */
int bDropdownEnabled;
int select;
WCHAR charsEntered[4];
int nCharsEntered;
HFONT hFont;
int nrFieldsAllocated;
int nrFields;
@ -165,7 +167,8 @@ DATETIME_SetSystemTime (DATETIME_INFO *infoPtr, DWORD flag, const SYSTEMTIME *sy
if (flag == GDT_VALID) {
if (systime->wYear < 1601 || systime->wYear > 30827 ||
systime->wMonth < 1 || systime->wMonth > 12 ||
systime->wDay < 1 || systime->wDay > 31 ||
systime->wDay < 1 ||
systime->wDay > MONTHCAL_MonthLength(systime->wMonth, systime->wYear) ||
systime->wHour > 23 ||
systime->wMinute > 59 ||
systime->wSecond > 59 ||
@ -277,10 +280,11 @@ DATETIME_UseFormat (DATETIME_INFO *infoPtr, LPCWSTR formattxt)
static BOOL
DATETIME_SetFormatW (DATETIME_INFO *infoPtr, LPCWSTR lpszFormat)
DATETIME_SetFormatW (DATETIME_INFO *infoPtr, LPCWSTR format)
{
if (!lpszFormat) {
WCHAR format_buf[80];
WCHAR format_buf[80];
if (!format) {
DWORD format_item;
if (infoPtr->dwStyle & DTS_LONGDATEFORMAT)
@ -290,13 +294,13 @@ DATETIME_SetFormatW (DATETIME_INFO *infoPtr, LPCWSTR lpszFormat)
else /* DTS_SHORTDATEFORMAT */
format_item = LOCALE_SSHORTDATE;
GetLocaleInfoW(LOCALE_USER_DEFAULT, format_item, format_buf, sizeof(format_buf)/sizeof(format_buf[0]));
lpszFormat = format_buf;
format = format_buf;
}
DATETIME_UseFormat (infoPtr, lpszFormat);
DATETIME_UseFormat (infoPtr, format);
InvalidateRect (infoPtr->hwndSelf, NULL, TRUE);
return 1;
return TRUE;
}
@ -470,6 +474,9 @@ DATETIME_IncreaseField (DATETIME_INFO *infoPtr, int number, int delta)
case TWODIGITYEAR:
case FULLYEAR:
date->wYear = wrap(date->wYear, delta, 1752, 9999);
if (date->wDay > MONTHCAL_MonthLength(date->wMonth, date->wYear))
/* This can happen when moving away from a leap year. */
date->wDay = MONTHCAL_MonthLength(date->wMonth, date->wYear);
MONTHCAL_CalculateDayOfWeek(date, TRUE);
break;
case ONEDIGITMONTH:
@ -696,6 +703,13 @@ DATETIME_Refresh (DATETIME_INFO *infoPtr, HDC hdc)
/* fill if focused */
HBRUSH hbr = CreateSolidBrush (comctl32_color.clrActiveCaption);
if (infoPtr->nCharsEntered)
{
memcpy(txt, infoPtr->charsEntered, infoPtr->nCharsEntered * sizeof(WCHAR));
txt[infoPtr->nCharsEntered] = 0;
GetTextExtentPoint32W (hdc, txt, strlenW(txt), &size);
}
selection.left = 0;
selection.top = 0;
selection.right = size.cx;
@ -755,6 +769,74 @@ static int DATETIME_GetPrevDateField(const DATETIME_INFO *infoPtr, int i)
return -1;
}
static void
DATETIME_ApplySelectedField (DATETIME_INFO *infoPtr)
{
int fieldNum = infoPtr->select & DTHT_DATEFIELD;
int i, val=0, clamp_day=0;
SYSTEMTIME date = infoPtr->date;
if (infoPtr->select == -1 || infoPtr->nCharsEntered == 0)
return;
for (i=0; i<infoPtr->nCharsEntered; i++)
val = val * 10 + infoPtr->charsEntered[i] - '0';
infoPtr->nCharsEntered = 0;
switch (infoPtr->fieldspec[fieldNum]) {
case ONEDIGITYEAR:
case TWODIGITYEAR:
date.wYear = date.wYear - (date.wYear%100) + val;
clamp_day = 1;
break;
case INVALIDFULLYEAR:
case FULLYEAR:
date.wYear = val;
clamp_day = 1;
break;
case ONEDIGITMONTH:
case TWODIGITMONTH:
date.wMonth = val;
clamp_day = 1;
break;
case ONEDIGITDAY:
case TWODIGITDAY:
date.wDay = val;
break;
case ONEDIGIT12HOUR:
case TWODIGIT12HOUR:
case ONEDIGIT24HOUR:
case TWODIGIT24HOUR:
/* FIXME: Preserve AM/PM for 12HOUR? */
date.wHour = val;
break;
case ONEDIGITMINUTE:
case TWODIGITMINUTE:
date.wMinute = val;
break;
case ONEDIGITSECOND:
case TWODIGITSECOND:
date.wSecond = val;
break;
}
if (clamp_day && date.wDay > MONTHCAL_MonthLength(date.wMonth, date.wYear))
date.wDay = MONTHCAL_MonthLength(date.wMonth, date.wYear);
if (DATETIME_SetSystemTime(infoPtr, GDT_VALID, &date))
DATETIME_SendDateTimeChangeNotify (infoPtr);
}
static void
DATETIME_SetSelectedField (DATETIME_INFO *infoPtr, int select)
{
DATETIME_ApplySelectedField(infoPtr);
infoPtr->select = select;
infoPtr->nCharsEntered = 0;
}
static LRESULT
DATETIME_LButtonDown (DATETIME_INFO *infoPtr, INT x, INT y)
{
@ -783,7 +865,8 @@ DATETIME_LButtonDown (DATETIME_INFO *infoPtr, INT x, INT y)
if (infoPtr->fieldspec[new] == FULLDAY) return 0;
}
}
infoPtr->select = new;
DATETIME_SetSelectedField(infoPtr, new);
if (infoPtr->select == DTHT_MCPOPUP) {
RECT rcMonthCal;
@ -961,6 +1044,7 @@ DATETIME_KeyDown (DATETIME_INFO *infoPtr, DWORD vkCode)
{
int fieldNum = infoPtr->select & DTHT_DATEFIELD;
int wrap = 0;
int new;
if (!(infoPtr->haveFocus)) return 0;
if ((fieldNum==0) && (infoPtr->select)) return 0;
@ -972,40 +1056,50 @@ DATETIME_KeyDown (DATETIME_INFO *infoPtr, DWORD vkCode)
switch (vkCode) {
case VK_ADD:
case VK_UP:
infoPtr->nCharsEntered = 0;
DATETIME_IncreaseField (infoPtr, fieldNum, 1);
DATETIME_SendDateTimeChangeNotify (infoPtr);
break;
case VK_SUBTRACT:
case VK_DOWN:
infoPtr->nCharsEntered = 0;
DATETIME_IncreaseField (infoPtr, fieldNum, -1);
DATETIME_SendDateTimeChangeNotify (infoPtr);
break;
case VK_HOME:
infoPtr->nCharsEntered = 0;
DATETIME_IncreaseField (infoPtr, fieldNum, INT_MIN);
DATETIME_SendDateTimeChangeNotify (infoPtr);
break;
case VK_END:
infoPtr->nCharsEntered = 0;
DATETIME_IncreaseField (infoPtr, fieldNum, INT_MAX);
DATETIME_SendDateTimeChangeNotify (infoPtr);
break;
case VK_LEFT:
new = infoPtr->select;
do {
if (infoPtr->select == 0) {
infoPtr->select = infoPtr->nrFields - 1;
if (new == 0) {
new = new - 1;
wrap++;
} else {
infoPtr->select--;
new--;
}
} while ((infoPtr->fieldspec[infoPtr->select] & DT_STRING) && (wrap<2));
} while ((infoPtr->fieldspec[new] & DT_STRING) && (wrap<2));
if (new != infoPtr->select)
DATETIME_SetSelectedField(infoPtr, new);
break;
case VK_RIGHT:
new = infoPtr->select;
do {
infoPtr->select++;
if (infoPtr->select==infoPtr->nrFields) {
infoPtr->select = 0;
new++;
if (new==infoPtr->nrFields) {
new = 0;
wrap++;
}
} while ((infoPtr->fieldspec[infoPtr->select] & DT_STRING) && (wrap<2));
} while ((infoPtr->fieldspec[new] & DT_STRING) && (wrap<2));
if (new != infoPtr->select)
DATETIME_SetSelectedField(infoPtr, new);
break;
}
@ -1021,80 +1115,20 @@ DATETIME_Char (DATETIME_INFO *infoPtr, WPARAM vkCode)
int fieldNum = infoPtr->select & DTHT_DATEFIELD;
if (vkCode >= '0' && vkCode <= '9') {
int num = vkCode-'0';
int newDays;
int maxChars;
int fieldSpec;
/* this is a somewhat simplified version of what Windows does */
SYSTEMTIME *date = &infoPtr->date;
switch (infoPtr->fieldspec[fieldNum]) {
case ONEDIGITYEAR:
case TWODIGITYEAR:
date->wYear = date->wYear - (date->wYear%100) +
(date->wYear%10)*10 + num;
MONTHCAL_CalculateDayOfWeek(date, TRUE);
DATETIME_SendDateTimeChangeNotify (infoPtr);
break;
case INVALIDFULLYEAR:
case FULLYEAR:
/* reset current year initialy */
date->wYear = ((date->wYear/1000) ? 0 : 1)*(date->wYear%1000)*10 + num;
MONTHCAL_CalculateDayOfWeek(date, TRUE);
DATETIME_SendDateTimeChangeNotify (infoPtr);
break;
case ONEDIGITMONTH:
case TWODIGITMONTH:
if ((date->wMonth%10) > 1 || num > 2)
date->wMonth = num;
else
date->wMonth = (date->wMonth%10)*10+num;
MONTHCAL_CalculateDayOfWeek(date, TRUE);
DATETIME_SendDateTimeChangeNotify (infoPtr);
break;
case ONEDIGITDAY:
case TWODIGITDAY:
newDays = (date->wDay%10)*10+num;
if (newDays > MONTHCAL_MonthLength(date->wMonth, date->wYear))
date->wDay = num;
else
date->wDay = newDays;
MONTHCAL_CalculateDayOfWeek(date, TRUE);
DATETIME_SendDateTimeChangeNotify (infoPtr);
break;
case ONEDIGIT12HOUR:
case TWODIGIT12HOUR:
if ((date->wHour%10) > 1 || num > 2)
date->wHour = num;
else
date->wHour = (date->wHour%10)*10+num;
DATETIME_SendDateTimeChangeNotify (infoPtr);
break;
case ONEDIGIT24HOUR:
case TWODIGIT24HOUR:
if ((date->wHour%10) > 2)
date->wHour = num;
else if ((date->wHour%10) == 2 && num > 3)
date->wHour = num;
else
date->wHour = (date->wHour%10)*10+num;
DATETIME_SendDateTimeChangeNotify (infoPtr);
break;
case ONEDIGITMINUTE:
case TWODIGITMINUTE:
if ((date->wMinute%10) > 5)
date->wMinute = num;
else
date->wMinute = (date->wMinute%10)*10+num;
DATETIME_SendDateTimeChangeNotify (infoPtr);
break;
case ONEDIGITSECOND:
case TWODIGITSECOND:
if ((date->wSecond%10) > 5)
date->wSecond = num;
else
date->wSecond = (date->wSecond%10)*10+num;
DATETIME_SendDateTimeChangeNotify (infoPtr);
break;
}
infoPtr->charsEntered[infoPtr->nCharsEntered++] = vkCode;
fieldSpec = infoPtr->fieldspec[fieldNum];
if (fieldSpec == INVALIDFULLYEAR || fieldSpec == FULLYEAR)
maxChars = 4;
else
maxChars = 2;
if (maxChars == infoPtr->nCharsEntered)
DATETIME_ApplySelectedField(infoPtr);
}
return 0;
}
@ -1132,6 +1166,7 @@ DATETIME_KillFocus (DATETIME_INFO *infoPtr, HWND lostFocus)
if (infoPtr->haveFocus) {
DATETIME_SendSimpleNotify (infoPtr, NM_KILLFOCUS);
infoPtr->haveFocus = 0;
DATETIME_SetSelectedField (infoPtr, -1);
}
InvalidateRect (infoPtr->hwndSelf, NULL, TRUE);

View file

@ -384,15 +384,16 @@ static void IPADDRESS_SetFocusToField (const IPADDRESS_INFO *infoPtr, INT index)
static BOOL IPADDRESS_ConstrainField (const IPADDRESS_INFO *infoPtr, int currentfield)
{
const IPPART_INFO *part = &infoPtr->Part[currentfield];
WCHAR field[10];
static const WCHAR fmt[] = { '%', 'd', 0 };
const IPPART_INFO *part;
int curValue, newValue;
WCHAR field[10];
TRACE("(currentfield=%d)\n", currentfield);
if (currentfield < 0 || currentfield > 3) return FALSE;
part = &infoPtr->Part[currentfield];
if (!GetWindowTextW (part->EditHwnd, field, 4)) return FALSE;
curValue = atoiW(field);

View file

@ -315,7 +315,6 @@ typedef struct tagLISTVIEW_INFO
COLORREF clrBk;
COLORREF clrText;
COLORREF clrTextBk;
BOOL bDefaultBkColor;
/* font */
HFONT hDefaultFont;
@ -1498,6 +1497,70 @@ static BOOL iterator_visibleitems(ITERATOR *i, const LISTVIEW_INFO *infoPtr, HDC
return TRUE;
}
/* Remove common elements from two iterators */
/* Passed iterators have to point on the first elements */
static BOOL iterator_remove_common_items(ITERATOR *iter1, ITERATOR *iter2)
{
if(!iter1->ranges || !iter2->ranges) {
int lower, upper;
if(iter1->ranges || iter2->ranges ||
(iter1->range.lower<iter2->range.lower && iter1->range.upper>iter2->range.upper) ||
(iter1->range.lower>iter2->range.lower && iter1->range.upper<iter2->range.upper)) {
ERR("result is not a one range iterator\n");
return FALSE;
}
if(iter1->range.lower==-1 || iter2->range.lower==-1)
return TRUE;
lower = iter1->range.lower;
upper = iter1->range.upper;
if(lower < iter2->range.lower)
iter1->range.upper = iter2->range.lower;
else if(upper > iter2->range.upper)
iter1->range.lower = iter2->range.upper;
else
iter1->range.lower = iter1->range.upper = -1;
if(iter2->range.lower < lower)
iter2->range.upper = lower;
else if(iter2->range.upper > upper)
iter2->range.lower = upper;
else
iter2->range.lower = iter2->range.upper = -1;
return TRUE;
}
iterator_next(iter1);
iterator_next(iter2);
while(1) {
if(iter1->nItem==-1 || iter2->nItem==-1)
break;
if(iter1->nItem == iter2->nItem) {
int delete = iter1->nItem;
iterator_prev(iter1);
iterator_prev(iter2);
ranges_delitem(iter1->ranges, delete);
ranges_delitem(iter2->ranges, delete);
iterator_next(iter1);
iterator_next(iter2);
} else if(iter1->nItem > iter2->nItem)
iterator_next(iter2);
else
iterator_next(iter1);
}
iter1->nItem = iter1->range.lower = iter1->range.upper = -1;
iter2->nItem = iter2->range.lower = iter2->range.upper = -1;
return TRUE;
}
/******** Misc helper functions ************************************/
static inline LRESULT CallWindowProcT(WNDPROC proc, HWND hwnd, UINT uMsg,
@ -1636,19 +1699,8 @@ static inline BOOL LISTVIEW_GetItemW(const LISTVIEW_INFO *infoPtr, LPLVITEMW lpL
/* used to handle collapse main item column case */
static inline BOOL LISTVIEW_DrawFocusRect(const LISTVIEW_INFO *infoPtr, HDC hdc)
{
BOOL Ret = FALSE;
if (infoPtr->rcFocus.left < infoPtr->rcFocus.right)
{
DWORD dwOldBkColor, dwOldTextColor;
dwOldBkColor = SetBkColor(hdc, RGB(255, 255, 255));
dwOldTextColor = SetBkColor(hdc, RGB(0, 0, 0));
Ret = DrawFocusRect(hdc, &infoPtr->rcFocus);
SetBkColor(hdc, dwOldBkColor);
SetBkColor(hdc, dwOldTextColor);
}
return Ret;
return (infoPtr->rcFocus.left < infoPtr->rcFocus.right) ?
DrawFocusRect(hdc, &infoPtr->rcFocus) : FALSE;
}
/* Listview invalidation functions: use _only_ these functions to invalidate */
@ -3745,7 +3797,7 @@ static void LISTVIEW_MarqueeHighlight(LISTVIEW_INFO *infoPtr, const POINT *coord
{
BOOL controlDown = FALSE;
LVITEMW item;
ITERATOR i;
ITERATOR old_elems, new_elems;
RECT rect;
if (coords_offs->x > infoPtr->marqueeOrigin.x)
@ -3788,54 +3840,55 @@ static void LISTVIEW_MarqueeHighlight(LISTVIEW_INFO *infoPtr, const POINT *coord
if ((scroll & SCROLL_DOWN) && (coords_orig->y >= infoPtr->rcList.bottom))
LISTVIEW_Scroll(infoPtr, 0, (coords_orig->y - infoPtr->rcList.bottom));
/* Invert the items in the old marquee rectangle */
iterator_frameditems_absolute(&i, infoPtr, &infoPtr->marqueeRect);
while (iterator_next(&i))
{
if (i.nItem > -1)
{
if (LISTVIEW_GetItemState(infoPtr, i.nItem, LVIS_SELECTED) == LVIS_SELECTED)
item.state = 0;
else
item.state = LVIS_SELECTED;
item.stateMask = LVIS_SELECTED;
LISTVIEW_SetItemState(infoPtr, i.nItem, &item);
}
}
iterator_destroy(&i);
iterator_frameditems_absolute(&old_elems, infoPtr, &infoPtr->marqueeRect);
CopyRect(&infoPtr->marqueeRect, &rect);
CopyRect(&infoPtr->marqueeDrawRect, &rect);
OffsetRect(&infoPtr->marqueeDrawRect, offset->x, offset->y);
/* Iterate over the items within our marquee rectangle */
iterator_frameditems_absolute(&i, infoPtr, &infoPtr->marqueeRect);
iterator_frameditems_absolute(&new_elems, infoPtr, &infoPtr->marqueeRect);
iterator_remove_common_items(&old_elems, &new_elems);
if (GetKeyState(VK_CONTROL) & 0x8000)
controlDown = TRUE;
while (iterator_next(&i))
/* Iterate over no longer selected items */
while (iterator_next(&old_elems))
{
if (i.nItem > -1)
if (old_elems.nItem > -1)
{
/* If CTRL is pressed, invert. If not, always select the item. */
if ((controlDown) && (LISTVIEW_GetItemState(infoPtr, i.nItem, LVIS_SELECTED)))
if (LISTVIEW_GetItemState(infoPtr, old_elems.nItem, LVIS_SELECTED) == LVIS_SELECTED)
item.state = 0;
else
item.state = LVIS_SELECTED;
item.stateMask = LVIS_SELECTED;
LISTVIEW_SetItemState(infoPtr, i.nItem, &item);
LISTVIEW_SetItemState(infoPtr, old_elems.nItem, &item);
}
}
iterator_destroy(&old_elems);
/* Iterate over newly selected items */
if (GetKeyState(VK_CONTROL) & 0x8000)
controlDown = TRUE;
while (iterator_next(&new_elems))
{
if (new_elems.nItem > -1)
{
/* If CTRL is pressed, invert. If not, always select the item. */
if ((controlDown) && (LISTVIEW_GetItemState(infoPtr, new_elems.nItem, LVIS_SELECTED)))
item.state = 0;
else
item.state = LVIS_SELECTED;
item.stateMask = LVIS_SELECTED;
LISTVIEW_SetItemState(infoPtr, new_elems.nItem, &item);
}
}
iterator_destroy(&new_elems);
iterator_destroy(&i);
LISTVIEW_InvalidateRect(infoPtr, &rect);
}
@ -4284,9 +4337,9 @@ static BOOL set_sub_item(const LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVItem,
particularly useful. We currently do not actually do anything with
the flag on subitems.
*/
if (lpLVItem->mask & ~(LVIF_TEXT | LVIF_IMAGE | LVIF_STATE)) return FALSE;
if (lpLVItem->mask & ~(LVIF_TEXT | LVIF_IMAGE | LVIF_STATE | LVIF_DI_SETITEM)) return FALSE;
if (!(lpLVItem->mask & (LVIF_TEXT | LVIF_IMAGE | LVIF_STATE))) return TRUE;
/* get the subitem structure, and create it if not there */
hdpaSubItems = DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem);
assert (hdpaSubItems);
@ -4354,6 +4407,9 @@ static BOOL LISTVIEW_SetItemT(LISTVIEW_INFO *infoPtr, LVITEMW *lpLVItem, BOOL is
if (!lpLVItem || lpLVItem->iItem < 0 || lpLVItem->iItem >= infoPtr->nItemCount)
return FALSE;
/* Invalidate old item area */
LISTVIEW_InvalidateItem(infoPtr, lpLVItem->iItem);
/* For efficiency, we transform the lpLVItem->pszText to Unicode here */
if ((lpLVItem->mask & LVIF_TEXT) && is_text(lpLVItem->pszText))
{
@ -4973,6 +5029,9 @@ static void LISTVIEW_Refresh(LISTVIEW_INFO *infoPtr, HDC hdc, const RECT *prcEra
SelectObject(hdc, hbmp);
SelectObject(hdc, infoPtr->hFont);
if(GetClipBox(hdcOrig, &rcClient))
IntersectClipRect(hdc, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
} else {
/* Save dc values we're gonna trash while drawing
* FIXME: Should be done in LISTVIEW_DrawItem() */
@ -5054,11 +5113,7 @@ enddraw:
/* Draw marquee rectangle if appropriate */
if (infoPtr->bMarqueeSelect)
{
SetBkColor(hdc, RGB(255, 255, 255));
SetTextColor(hdc, RGB(0, 0, 0));
DrawFocusRect(hdc, &infoPtr->marqueeDrawRect);
}
if (cdmode & CDRF_NOTIFYPOSTPAINT)
notify_postpaint(infoPtr, &nmlvcd);
@ -5678,7 +5733,7 @@ static BOOL LISTVIEW_EndEditLabelT(LISTVIEW_INFO *infoPtr, BOOL storeText, BOOL
WCHAR szDispText[DISP_TEXT_SIZE] = { 0 };
NMLVDISPINFOW dispInfo;
INT editedItem = infoPtr->nEditLabelItem;
BOOL bSame;
BOOL same;
WCHAR *pszText = NULL;
BOOL res;
@ -5698,9 +5753,6 @@ static BOOL LISTVIEW_EndEditLabelT(LISTVIEW_INFO *infoPtr, BOOL storeText, BOOL
TRACE("(pszText=%s, isW=%d)\n", debugtext_t(pszText, isW), isW);
infoPtr->nEditLabelItem = -1;
infoPtr->hwndEdit = 0;
ZeroMemory(&dispInfo, sizeof(dispInfo));
dispInfo.item.mask = LVIF_PARAM | LVIF_STATE | LVIF_TEXT;
dispInfo.item.iItem = editedItem;
@ -5715,32 +5767,34 @@ static BOOL LISTVIEW_EndEditLabelT(LISTVIEW_INFO *infoPtr, BOOL storeText, BOOL
}
if (isW)
bSame = (lstrcmpW(dispInfo.item.pszText, pszText) == 0);
same = (lstrcmpW(dispInfo.item.pszText, pszText) == 0);
else
{
LPWSTR tmp = textdupTtoW(pszText, FALSE);
bSame = (lstrcmpW(dispInfo.item.pszText, tmp) == 0);
same = (lstrcmpW(dispInfo.item.pszText, tmp) == 0);
textfreeT(tmp, FALSE);
}
/* add the text from the edit in */
dispInfo.item.mask |= LVIF_TEXT;
dispInfo.item.pszText = bSame ? NULL : pszText;
dispInfo.item.cchTextMax = bSame ? 0 : textlenT(pszText, isW);
dispInfo.item.pszText = same ? NULL : pszText;
dispInfo.item.cchTextMax = textlenT(dispInfo.item.pszText, isW);
/* Do we need to update the Item Text */
if (!notify_dispinfoT(infoPtr, LVN_ENDLABELEDITW, &dispInfo, isW))
{
res = FALSE;
goto cleanup;
}
res = notify_dispinfoT(infoPtr, LVN_ENDLABELEDITW, &dispInfo, isW);
infoPtr->nEditLabelItem = -1;
infoPtr->hwndEdit = 0;
if (!res) goto cleanup;
if (!IsWindow(hwndSelf))
{
res = FALSE;
goto cleanup;
}
if (!pszText) return TRUE;
if (bSame)
if (same)
{
res = TRUE;
goto cleanup;
@ -7823,10 +7877,8 @@ static BOOL LISTVIEW_RedrawItems(const LISTVIEW_INFO *infoPtr, INT nFirst, INT n
* is passed, then the scroll will be 0. (per MSDN 7/2002)
*
* For: (per experimentation with native control and CSpy ListView)
* LV_VIEW_ICON dy=1 = 1 pixel (vertical only)
* dx ignored
* LV_VIEW_SMALLICON dy=1 = 1 pixel (vertical only)
* dx ignored
* LV_VIEW_ICON scrolling in any direction is allowed
* LV_VIEW_SMALLICON scrolling in any direction is allowed
* LV_VIEW_LIST dx=1 = 1 column (horizontal only)
* but will only scroll 1 column per message
* no matter what the value.
@ -7846,7 +7898,6 @@ static BOOL LISTVIEW_Scroll(LISTVIEW_INFO *infoPtr, INT dx, INT dy)
if (dy != 0) return FALSE;
break;
default: /* icon */
dx = 0;
break;
}
@ -7872,7 +7923,6 @@ static BOOL LISTVIEW_SetBkColor(LISTVIEW_INFO *infoPtr, COLORREF clrBk)
{
TRACE("(clrBk=%x)\n", clrBk);
infoPtr->bDefaultBkColor = FALSE;
if(infoPtr->clrBk != clrBk) {
if (infoPtr->clrBk != CLR_NONE) DeleteObject(infoPtr->hBkBrush);
infoPtr->clrBk = clrBk;
@ -8803,8 +8853,8 @@ static BOOL LISTVIEW_SetItemTextT(LISTVIEW_INFO *infoPtr, INT nItem, const LVITE
{
LVITEMW lvItem;
if (nItem < 0 && nItem >= infoPtr->nItemCount) return FALSE;
if (!lpLVItem || nItem < 0 || nItem >= infoPtr->nItemCount) return FALSE;
lvItem.iItem = nItem;
lvItem.iSubItem = lpLVItem->iSubItem;
lvItem.mask = LVIF_TEXT;
@ -9116,9 +9166,7 @@ static BOOL LISTVIEW_SortItems(LISTVIEW_INFO *infoPtr, PFNLVCOMPARE pfnCompare,
/* I believe nHotItem should be left alone, see LISTVIEW_ShiftIndices */
/* refresh the display */
if (infoPtr->uView != LV_VIEW_ICON && infoPtr->uView != LV_VIEW_SMALLICON)
LISTVIEW_InvalidateList(infoPtr);
LISTVIEW_InvalidateList(infoPtr);
return TRUE;
}
@ -9265,7 +9313,6 @@ static LRESULT LISTVIEW_NCCreate(HWND hwnd, const CREATESTRUCTW *lpcs)
infoPtr->clrText = CLR_DEFAULT;
infoPtr->clrTextBk = CLR_DEFAULT;
LISTVIEW_SetBkColor(infoPtr, comctl32_color.clrWindow);
infoPtr->bDefaultBkColor = TRUE;
/* set default values */
infoPtr->nFocusedItem = -1;
@ -9595,6 +9642,7 @@ static LRESULT LISTVIEW_HScroll(LISTVIEW_INFO *infoPtr, INT nScrollCode,
{
INT nOldScrollPos, nNewScrollPos;
SCROLLINFO scrollInfo;
BOOL is_an_icon;
TRACE("(nScrollCode=%d(%s), nScrollDiff=%d)\n", nScrollCode,
debugscrollcode(nScrollCode), nScrollDiff);
@ -9604,6 +9652,8 @@ static LRESULT LISTVIEW_HScroll(LISTVIEW_INFO *infoPtr, INT nScrollCode,
scrollInfo.cbSize = sizeof(SCROLLINFO);
scrollInfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_TRACKPOS;
is_an_icon = ((infoPtr->uView == LV_VIEW_ICON) || (infoPtr->uView == LV_VIEW_SMALLICON));
if (!GetScrollInfo(infoPtr->hwndSelf, SB_HORZ, &scrollInfo)) return 1;
nOldScrollPos = scrollInfo.nPos;
@ -9614,11 +9664,11 @@ static LRESULT LISTVIEW_HScroll(LISTVIEW_INFO *infoPtr, INT nScrollCode,
break;
case SB_LINELEFT:
nScrollDiff = -1;
nScrollDiff = (is_an_icon) ? -LISTVIEW_SCROLL_ICON_LINE_SIZE : -1;
break;
case SB_LINERIGHT:
nScrollDiff = 1;
nScrollDiff = (is_an_icon) ? LISTVIEW_SCROLL_ICON_LINE_SIZE : 1;
break;
case SB_PAGELEFT:
@ -10160,7 +10210,6 @@ static LRESULT LISTVIEW_NCDestroy(LISTVIEW_INFO *infoPtr)
*/
static LRESULT LISTVIEW_Notify(LISTVIEW_INFO *infoPtr, const NMHDR *lpnmhdr)
{
HWND hwndSelf = infoPtr->hwndSelf;
const NMHEADERW *lpnmh;
TRACE("(lpnmhdr=%p)\n", lpnmhdr);
@ -10213,10 +10262,6 @@ static LRESULT LISTVIEW_Notify(LISTVIEW_INFO *infoPtr, const NMHDR *lpnmhdr)
LISTVIEW_InvalidateList(infoPtr);
notify_forward_header(infoPtr, lpnmh);
return FALSE;
case HDN_ITEMCHANGINGW:
case HDN_ITEMCHANGINGA:
return notify_forward_header(infoPtr, lpnmh);
case HDN_ITEMCHANGEDW:
case HDN_ITEMCHANGEDA:
@ -10224,10 +10269,6 @@ static LRESULT LISTVIEW_Notify(LISTVIEW_INFO *infoPtr, const NMHDR *lpnmhdr)
COLUMN_INFO *lpColumnInfo;
HDITEMW hdi;
INT dx, cxy;
notify_forward_header(infoPtr, lpnmh);
if (!IsWindow(hwndSelf))
break;
if (!lpnmh->pitem || !(lpnmh->pitem->mask & HDI_WIDTH))
{
@ -11528,11 +11569,6 @@ LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
case WM_SYSCOLORCHANGE:
COMCTL32_RefreshSysColors();
if (infoPtr->bDefaultBkColor)
{
LISTVIEW_SetBkColor(infoPtr, comctl32_color.clrWindow);
infoPtr->bDefaultBkColor = TRUE;
}
return 0;
/* case WM_TIMER: */

View file

@ -6,7 +6,7 @@
* Copyright 1999 Chris Morgan <cmorgan@wpi.edu> and
* James Abbatiello <abbeyj@wpi.edu>
* Copyright 2000 Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de>
* Copyright 2009, 2010 Nikolay Sivov
* Copyright 2009-2011 Nikolay Sivov
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -33,7 +33,6 @@
*
* TODO:
* -- MCM_[GS]ETUNICODEFORMAT
* -- MONTHCAL_GetMonthRange
* -- handle resources better (doesn't work now);
* -- take care of internationalization.
* -- keyboard handling.
@ -77,6 +76,21 @@ WINE_DEFAULT_DEBUG_CHANNEL(monthcal);
/* convert from days to 100 nanoseconds unit - used as FILETIME unit */
#define DAYSTO100NSECS(days) (((ULONGLONG)(days))*24*60*60*10000000)
enum CachedPen
{
PenRed = 0,
PenText,
PenLast
};
enum CachedBrush
{
BrushTitle = 0,
BrushMonth,
BrushBackground,
BrushLast
};
/* single calendar data */
typedef struct _CALENDAR_INFO
{
@ -96,6 +110,8 @@ typedef struct
DWORD dwStyle; /* cached GWL_STYLE */
COLORREF colors[MCSC_TRAILINGTEXT+1];
HBRUSH brushes[BrushLast];
HPEN pens[PenLast];
HFONT hFont;
HFONT hBoldFont;
@ -143,8 +159,8 @@ static const WCHAR themeClass[] = { 'S','c','r','o','l','l','b','a','r',0 };
/* empty SYSTEMTIME const */
static const SYSTEMTIME st_null;
/* valid date limits */
static const SYSTEMTIME max_allowed_date = { 9999, 12, 0, 31, 0, 0, 0, 0 };
static const SYSTEMTIME min_allowed_date = { 1752, 9, 0, 14, 0, 0, 0, 0 };
static const SYSTEMTIME max_allowed_date = { .wYear = 9999, .wMonth = 12, .wDay = 31 };
static const SYSTEMTIME min_allowed_date = { .wYear = 1752, .wMonth = 9, .wDay = 14 };
/* Prev/Next buttons */
enum nav_direction
@ -449,7 +465,7 @@ int MONTHCAL_CalculateDayOfWeek(SYSTEMTIME *date, BOOL inplace)
return st.wDayOfWeek;
}
/* add/substract 'months' from date */
/* add/subtract 'months' from date */
static inline void MONTHCAL_GetMonth(SYSTEMTIME *date, INT months)
{
INT length, m = date->wMonth + months;
@ -636,28 +652,31 @@ static BOOL MONTHCAL_SetDayFocus(MONTHCAL_INFO *infoPtr, const SYSTEMTIME *st)
return TRUE;
}
/* draw today boundary box for specified rectangle */
static void MONTHCAL_Circle(const MONTHCAL_INFO *infoPtr, HDC hdc, const RECT *r)
{
HPEN old_pen = SelectObject(hdc, infoPtr->pens[PenRed]);
HBRUSH old_brush;
old_brush = SelectObject(hdc, GetStockObject(NULL_BRUSH));
Rectangle(hdc, r->left, r->top, r->right, r->bottom);
SelectObject(hdc, old_brush);
SelectObject(hdc, old_pen);
}
/* Draw today day mark rectangle
*
* [I] hdc : context to draw in
* [I] day : day to mark with rectangle
* [I] hdc : context to draw in
* [I] date : day to mark with rectangle
*
*/
static void MONTHCAL_CircleDay(const MONTHCAL_INFO *infoPtr, HDC hdc,
const SYSTEMTIME *date)
{
HPEN hRedPen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
HPEN hOldPen2 = SelectObject(hdc, hRedPen);
HBRUSH hOldBrush;
RECT day_rect;
MONTHCAL_CalcPosFromDay(infoPtr, date, &day_rect);
hOldBrush = SelectObject(hdc, GetStockObject(NULL_BRUSH));
Rectangle(hdc, day_rect.left, day_rect.top, day_rect.right, day_rect.bottom);
SelectObject(hdc, hOldBrush);
DeleteObject(hRedPen);
SelectObject(hdc, hOldPen2);
MONTHCAL_Circle(infoPtr, hdc, &day_rect);
}
static void MONTHCAL_DrawDay(const MONTHCAL_INFO *infoPtr, HDC hdc, const SYSTEMTIME *st,
@ -666,46 +685,39 @@ static void MONTHCAL_DrawDay(const MONTHCAL_INFO *infoPtr, HDC hdc, const SYSTEM
static const WCHAR fmtW[] = { '%','d',0 };
WCHAR buf[10];
RECT r, r_temp;
static BOOL bold_selected;
BOOL selected_day = FALSE;
HBRUSH hbr;
COLORREF oldCol = 0;
COLORREF oldBk = 0;
INT old_bkmode, selection;
/* No need to check styles: when selection is not valid, it is set to zero.
* 1<day<31, so everything is OK.
*/
/* no need to check styles: when selection is not valid, it is set to zero.
1 < day < 31, so everything is OK */
MONTHCAL_CalcPosFromDay(infoPtr, st, &r);
if(!IntersectRect(&r_temp, &(ps->rcPaint), &r)) return;
if ((MONTHCAL_CompareDate(st, &infoPtr->minSel) >= 0) &&
(MONTHCAL_CompareDate(st, &infoPtr->maxSel) <= 0)) {
(MONTHCAL_CompareDate(st, &infoPtr->maxSel) <= 0))
{
TRACE("%d %d %d\n", st->wDay, infoPtr->minSel.wDay, infoPtr->maxSel.wDay);
TRACE("%s\n", wine_dbgstr_rect(&r));
oldCol = SetTextColor(hdc, infoPtr->colors[MCSC_MONTHBK]);
oldBk = SetBkColor(hdc, infoPtr->colors[MCSC_TRAILINGTEXT]);
hbr = GetSysColorBrush(COLOR_HIGHLIGHT);
FillRect(hdc, &r, hbr);
FillRect(hdc, &r, infoPtr->brushes[BrushTitle]);
selected_day = TRUE;
selection = 1;
}
else
selection = 0;
if(bold && !bold_selected) {
SelectObject(hdc, infoPtr->hBoldFont);
bold_selected = TRUE;
}
if(!bold && bold_selected) {
SelectObject(hdc, infoPtr->hFont);
bold_selected = FALSE;
}
SelectObject(hdc, bold ? infoPtr->hBoldFont : infoPtr->hFont);
SetBkMode(hdc,TRANSPARENT);
old_bkmode = SetBkMode(hdc, TRANSPARENT);
wsprintfW(buf, fmtW, st->wDay);
DrawTextW(hdc, buf, -1, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE );
SetBkMode(hdc, old_bkmode);
if(selected_day) {
if (selection)
{
SetTextColor(hdc, oldCol);
SetBkColor(hdc, oldBk);
}
@ -755,13 +767,10 @@ static void MONTHCAL_PaintTitle(MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRU
RECT *title = &infoPtr->calendars[calIdx].title;
const SYSTEMTIME *st = &infoPtr->calendars[calIdx].month;
WCHAR buf_month[80], buf_fmt[80];
HBRUSH hbr;
SIZE sz;
/* fill header box */
hbr = CreateSolidBrush(infoPtr->colors[MCSC_TITLEBK]);
FillRect(hdc, title, hbr);
DeleteObject(hbr);
FillRect(hdc, title, infoPtr->brushes[BrushTitle]);
/* month/year string */
SetBkColor(hdc, infoPtr->colors[MCSC_TITLEBK]);
@ -793,7 +802,7 @@ static void MONTHCAL_PaintWeeknumbers(const MONTHCAL_INFO *infoPtr, HDC hdc, con
INT i, prev_month;
SYSTEMTIME st;
WCHAR buf[80];
HBRUSH hbr;
HPEN old_pen;
RECT r;
if (!(infoPtr->dwStyle & MCS_WEEKNUMBERS)) return;
@ -865,9 +874,8 @@ static void MONTHCAL_PaintWeeknumbers(const MONTHCAL_INFO *infoPtr, HDC hdc, con
r = infoPtr->calendars[calIdx].weeknums;
/* erase whole week numbers area */
hbr = CreateSolidBrush(infoPtr->colors[MCSC_MONTHBK]);
FillRect(hdc, &r, hbr);
DeleteObject(hbr);
FillRect(hdc, &r, infoPtr->brushes[BrushTitle]);
SetTextColor(hdc, infoPtr->colors[MCSC_TITLEBK]);
/* reduce rectangle to one week number */
r.bottom = r.top + infoPtr->height_increment;
@ -890,43 +898,50 @@ static void MONTHCAL_PaintWeeknumbers(const MONTHCAL_INFO *infoPtr, HDC hdc, con
}
/* line separator for week numbers column */
old_pen = SelectObject(hdc, infoPtr->pens[PenText]);
MoveToEx(hdc, infoPtr->calendars[calIdx].weeknums.right, infoPtr->calendars[calIdx].weeknums.top + 3 , NULL);
LineTo(hdc, infoPtr->calendars[calIdx].weeknums.right, infoPtr->calendars[calIdx].weeknums.bottom);
SelectObject(hdc, old_pen);
}
/* bottom today date */
static void MONTHCAL_PaintTodayTitle(const MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps)
{
if(!(infoPtr->dwStyle & MCS_NOTODAY)) {
static const WCHAR fmt_todayW[] = { '%','s',' ','%','s',0 };
WCHAR buf_todayW[30], buf_dateW[20], buf[80];
RECT text_rect, box_rect;
HFONT old_font;
INT col;
if(infoPtr->dwStyle & MCS_NOTODAY) return;
if (!LoadStringW(COMCTL32_hModule, IDM_TODAY, buf_todayW, countof(buf_todayW)))
{
static const WCHAR todayW[] = { 'T','o','d','a','y',':',0 };
static const WCHAR fmt_todayW[] = { '%','s',' ','%','s',0 };
WCHAR buf_todayW[30], buf_dateW[20], buf[80];
RECT rtoday;
if(!(infoPtr->dwStyle & MCS_NOTODAYCIRCLE)) {
SYSTEMTIME fake_st;
MONTHCAL_GetMaxDate(infoPtr, &fake_st);
/* this is always safe cause next month will never fully fit calendar */
fake_st.wDay += 1;
MONTHCAL_CircleDay(infoPtr, hdc, &fake_st);
}
if (!LoadStringW(COMCTL32_hModule, IDM_TODAY, buf_todayW, countof(buf_todayW)))
{
WARN("Can't load resource\n");
strcpyW(buf_todayW, todayW);
}
MONTHCAL_CalcDayRect(infoPtr, &rtoday, 1, 6);
GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &infoPtr->todaysDate, NULL,
buf_dateW, countof(buf_dateW));
SelectObject(hdc, infoPtr->hBoldFont);
wsprintfW(buf, fmt_todayW, buf_todayW, buf_dateW);
DrawTextW(hdc, buf, -1, &rtoday, DT_CALCRECT | DT_LEFT | DT_VCENTER | DT_SINGLELINE);
DrawTextW(hdc, buf, -1, &rtoday, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
SelectObject(hdc, infoPtr->hFont);
WARN("Can't load resource\n");
strcpyW(buf_todayW, todayW);
}
col = infoPtr->dwStyle & MCS_NOTODAYCIRCLE ? 0 : 1;
if (infoPtr->dwStyle & MCS_WEEKNUMBERS) col--;
MONTHCAL_CalcDayRect(infoPtr, &text_rect, col, 6);
box_rect = text_rect;
GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &infoPtr->todaysDate, NULL,
buf_dateW, countof(buf_dateW));
old_font = SelectObject(hdc, infoPtr->hBoldFont);
SetTextColor(hdc, infoPtr->colors[MCSC_TEXT]);
wsprintfW(buf, fmt_todayW, buf_todayW, buf_dateW);
DrawTextW(hdc, buf, -1, &text_rect, DT_CALCRECT | DT_LEFT | DT_VCENTER | DT_SINGLELINE);
DrawTextW(hdc, buf, -1, &text_rect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
if(!(infoPtr->dwStyle & MCS_NOTODAYCIRCLE)) {
OffsetRect(&box_rect, -infoPtr->width_increment, 0);
MONTHCAL_Circle(infoPtr, hdc, &box_rect);
}
SelectObject(hdc, old_font);
}
/* today mark + focus */
@ -947,15 +962,53 @@ static void MONTHCAL_PaintFocusAndCircle(const MONTHCAL_INFO *infoPtr, HDC hdc,
}
}
/* months before first calendar month and after last calendar month */
static void MONTHCAL_PaintLeadTrailMonths(const MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps)
{
INT mask, length;
SYSTEMTIME st_max, st;
if (infoPtr->dwStyle & MCS_NOTRAILINGDATES) return;
SetTextColor(hdc, infoPtr->colors[MCSC_TRAILINGTEXT]);
/* draw prev month */
MONTHCAL_GetMinDate(infoPtr, &st);
mask = 1 << (st.wDay-1);
/* December and January both 31 days long, so no worries if wrapped */
length = MONTHCAL_MonthLength(infoPtr->calendars[0].month.wMonth - 1,
infoPtr->calendars[0].month.wYear);
while(st.wDay <= length)
{
MONTHCAL_DrawDay(infoPtr, hdc, &st, infoPtr->monthdayState[0] & mask, ps);
mask <<= 1;
st.wDay++;
}
/* draw next month */
st = infoPtr->calendars[infoPtr->cal_num-1].month;
st.wDay = 1;
MONTHCAL_GetNextMonth(&st);
MONTHCAL_GetMaxDate(infoPtr, &st_max);
mask = 1;
while(st.wDay <= st_max.wDay)
{
MONTHCAL_DrawDay(infoPtr, hdc, &st, infoPtr->monthdayState[2] & mask, ps);
mask <<= 1;
st.wDay++;
}
}
/* paint a calendar area */
static void MONTHCAL_PaintCalendar(const MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps, INT calIdx)
{
const SYSTEMTIME *date = &infoPtr->calendars[calIdx].month;
INT prev_month, i, j, length;
INT i, j, length;
RECT r, fill_bk_rect;
SYSTEMTIME st;
WCHAR buf[80];
HBRUSH hbr;
HPEN old_pen;
int mask;
/* fill whole days area - from week days area to today note rectangle */
@ -963,26 +1016,23 @@ static void MONTHCAL_PaintCalendar(const MONTHCAL_INFO *infoPtr, HDC hdc, const
fill_bk_rect.bottom = infoPtr->calendars[calIdx].days.bottom +
(infoPtr->todayrect.bottom - infoPtr->todayrect.top);
hbr = CreateSolidBrush(infoPtr->colors[MCSC_MONTHBK]);
FillRect(hdc, &fill_bk_rect, hbr);
DeleteObject(hbr);
FillRect(hdc, &fill_bk_rect, infoPtr->brushes[BrushMonth]);
/* draw line under day abbreviations */
old_pen = SelectObject(hdc, infoPtr->pens[PenText]);
MoveToEx(hdc, infoPtr->calendars[calIdx].days.left + 3,
infoPtr->calendars[calIdx].title.bottom + infoPtr->textHeight + 1, NULL);
LineTo(hdc, infoPtr->calendars[calIdx].days.right - 3,
infoPtr->calendars[calIdx].title.bottom + infoPtr->textHeight + 1);
prev_month = date->wMonth - 1;
if (prev_month == 0) prev_month = 12;
SelectObject(hdc, old_pen);
infoPtr->calendars[calIdx].wdays.left = infoPtr->calendars[calIdx].days.left =
infoPtr->calendars[calIdx].weeknums.right;
/* 1. draw day abbreviations */
/* draw day abbreviations */
SelectObject(hdc, infoPtr->hFont);
SetBkColor(hdc, infoPtr->colors[MCSC_MONTHBK]);
SetTextColor(hdc, infoPtr->colors[MCSC_TRAILINGTEXT]);
SetTextColor(hdc, infoPtr->colors[MCSC_TITLEBK]);
/* rectangle to draw a single day abbreviation within */
r = infoPtr->calendars[calIdx].wdays;
r.right = r.left + infoPtr->width_increment;
@ -994,47 +1044,7 @@ static void MONTHCAL_PaintCalendar(const MONTHCAL_INFO *infoPtr, HDC hdc, const
OffsetRect(&r, infoPtr->width_increment, 0);
}
/* 2. previous and next months */
if (!(infoPtr->dwStyle & MCS_NOTRAILINGDATES) && (calIdx == 0 || calIdx == infoPtr->cal_num - 1))
{
SYSTEMTIME st_max;
SetTextColor(hdc, infoPtr->colors[MCSC_TRAILINGTEXT]);
/* draw prev month */
if (calIdx == 0)
{
MONTHCAL_GetMinDate(infoPtr, &st);
mask = 1 << (st.wDay-1);
length = MONTHCAL_MonthLength(prev_month, date->wYear);
while(st.wDay <= length)
{
MONTHCAL_DrawDay(infoPtr, hdc, &st, infoPtr->monthdayState[0] & mask, ps);
mask <<= 1;
st.wDay++;
}
}
/* draw next month */
if (calIdx == infoPtr->cal_num - 1)
{
st = *date;
st.wDay = 1;
MONTHCAL_GetNextMonth(&st);
MONTHCAL_GetMaxDate(infoPtr, &st_max);
mask = 1;
while(st.wDay <= st_max.wDay)
{
MONTHCAL_DrawDay(infoPtr, hdc, &st, infoPtr->monthdayState[2] & mask, ps);
mask <<= 1;
st.wDay++;
}
}
}
/* 3. current month */
/* draw current month */
SetTextColor(hdc, infoPtr->colors[MCSC_TEXT]);
st = *date;
st.wDay = 1;
@ -1076,6 +1086,9 @@ static void MONTHCAL_Refresh(MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT
MONTHCAL_PaintWeeknumbers(infoPtr, hdc, ps, i);
}
/* partially visible months */
MONTHCAL_PaintLeadTrailMonths(infoPtr, hdc, ps);
/* focus and today rectangle */
MONTHCAL_PaintFocusAndCircle(infoPtr, hdc, ps);
@ -1125,6 +1138,7 @@ MONTHCAL_GetColor(const MONTHCAL_INFO *infoPtr, UINT index)
static LRESULT
MONTHCAL_SetColor(MONTHCAL_INFO *infoPtr, UINT index, COLORREF color)
{
enum CachedBrush type;
COLORREF prev;
TRACE("%p, %d: color %08x\n", infoPtr, index, color);
@ -1134,6 +1148,35 @@ MONTHCAL_SetColor(MONTHCAL_INFO *infoPtr, UINT index, COLORREF color)
prev = infoPtr->colors[index];
infoPtr->colors[index] = color;
/* update cached brush */
switch (index)
{
case MCSC_BACKGROUND:
type = BrushBackground;
break;
case MCSC_TITLEBK:
type = BrushTitle;
break;
case MCSC_MONTHBK:
type = BrushMonth;
break;
default:
type = BrushLast;
}
if (type != BrushLast)
{
DeleteObject(infoPtr->brushes[type]);
infoPtr->brushes[type] = CreateSolidBrush(color);
}
/* update cached pen */
if (index == MCSC_TEXT)
{
DeleteObject(infoPtr->pens[PenText]);
infoPtr->pens[PenText] = CreatePen(PS_SOLID, 1, infoPtr->colors[index]);
}
InvalidateRect(infoPtr->hwndSelf, NULL, index == MCSC_BACKGROUND ? TRUE : FALSE);
return prev;
}
@ -1265,8 +1308,6 @@ MONTHCAL_GetMonthRange(const MONTHCAL_INFO *infoPtr, DWORD flag, SYSTEMTIME *st)
}
case GMR_DAYSTATE:
{
/*FIXME: currently multicalendar feature isn't implemented,
min date from previous month and max date from next one returned */
MONTHCAL_GetMinDate(infoPtr, &st[0]);
MONTHCAL_GetMaxDate(infoPtr, &st[1]);
break;
@ -1727,7 +1768,7 @@ MONTHCAL_HitTest(const MONTHCAL_INFO *infoPtr, MCHITTESTINFO *lpht)
{
htinfo.uHit = MCHT_CALENDARDATEPREV;
MONTHCAL_GetPrevMonth(&htinfo.st);
htinfo.st.wDay = MONTHCAL_MonthLength(lpht->st.wMonth, lpht->st.wYear) + day;
htinfo.st.wDay = MONTHCAL_MonthLength(htinfo.st.wMonth, htinfo.st.wYear) + day;
}
else if (day > MONTHCAL_MonthLength(ht_month.wMonth, ht_month.wYear))
{
@ -2237,15 +2278,11 @@ MONTHCAL_Paint(MONTHCAL_INFO *infoPtr, HDC hdc_paint)
static LRESULT
MONTHCAL_EraseBkgnd(const MONTHCAL_INFO *infoPtr, HDC hdc)
{
HBRUSH hbr;
RECT rc;
if (!GetClipBox(hdc, &rc)) return FALSE;
/* fill background */
hbr = CreateSolidBrush (infoPtr->colors[MCSC_BACKGROUND]);
FillRect(hdc, &rc, hbr);
DeleteObject(hbr);
FillRect(hdc, &rc, infoPtr->brushes[BrushBackground]);
return TRUE;
}
@ -2520,7 +2557,7 @@ MONTHCAL_Create(HWND hwnd, LPCREATESTRUCTW lpcs)
MONTHCAL_SetFont(infoPtr, GetStockObject(DEFAULT_GUI_FONT), FALSE);
/* initialize info structure */
/* FIXME: calculate systemtime ->> localtime(substract timezoneinfo) */
/* FIXME: calculate systemtime ->> localtime(subtract timezoneinfo) */
GetLocalTime(&infoPtr->todaysDate);
MONTHCAL_SetFirstDayOfWeek(infoPtr, -1);
@ -2538,6 +2575,13 @@ MONTHCAL_Create(HWND hwnd, LPCREATESTRUCTW lpcs)
infoPtr->colors[MCSC_MONTHBK] = comctl32_color.clrWindow;
infoPtr->colors[MCSC_TRAILINGTEXT] = comctl32_color.clrGrayText;
infoPtr->brushes[BrushBackground] = CreateSolidBrush(infoPtr->colors[MCSC_BACKGROUND]);
infoPtr->brushes[BrushTitle] = CreateSolidBrush(infoPtr->colors[MCSC_TITLEBK]);
infoPtr->brushes[BrushMonth] = CreateSolidBrush(infoPtr->colors[MCSC_MONTHBK]);
infoPtr->pens[PenRed] = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
infoPtr->pens[PenText] = CreatePen(PS_SOLID, 1, infoPtr->colors[MCSC_TEXT]);
infoPtr->minSel = infoPtr->todaysDate;
infoPtr->maxSel = infoPtr->todaysDate;
infoPtr->calendars[0].month = infoPtr->todaysDate;
@ -2564,13 +2608,18 @@ fail:
static LRESULT
MONTHCAL_Destroy(MONTHCAL_INFO *infoPtr)
{
INT i;
/* free month calendar info data */
Free(infoPtr->monthdayState);
Free(infoPtr->calendars);
SetWindowLongPtrW(infoPtr->hwndSelf, 0, 0);
CloseThemeData (GetWindowTheme (infoPtr->hwndSelf));
for (i = 0; i < BrushLast; i++) DeleteObject(infoPtr->brushes[i]);
for (i = 0; i < PenLast; i++) DeleteObject(infoPtr->pens[i]);
Free(infoPtr);
return 0;
}

View file

@ -2490,7 +2490,7 @@ static void PROPSHEET_SetWizButtons(HWND hwndDlg, DWORD dwFlags)
{
SendMessageW(hwndDlg, DM_SETDEFID, IDC_FINISH_BUTTON, 0);
SetFocus(hwndFinish);
}
}
else if (dwFlags & PSWIZB_NEXT)
{
SendMessageW(hwndDlg, DM_SETDEFID, IDC_NEXT_BUTTON, 0);

View file

@ -661,10 +661,12 @@ static BOOL
STATUSBAR_SetParts (STATUS_INFO *infoPtr, INT count, LPINT parts)
{
STATUSWINDOWPART *tmp;
UINT i, oldNumParts;
INT i, oldNumParts;
TRACE("(%d,%p)\n", count, parts);
if(!count) return FALSE;
oldNumParts = infoPtr->numParts;
infoPtr->numParts = count;
if (oldNumParts > infoPtr->numParts) {
@ -693,7 +695,7 @@ STATUSBAR_SetParts (STATUS_INFO *infoPtr, INT count, LPINT parts)
infoPtr->parts[i].x = parts[i];
if (infoPtr->hwndToolTip) {
UINT nTipCount;
INT nTipCount;
TTTOOLINFOW ti;
ZeroMemory (&ti, sizeof(TTTOOLINFOW));

View file

@ -529,7 +529,7 @@ static PDOC_ITEM SYSLINK_GetFocusLink (const SYSLINK_INFO *infoPtr, int *LinkId)
while(Current != NULL)
{
if((Current->Type == slLink))
if(Current->Type == slLink)
{
if(Current->u.Link.state & LIS_FOCUSED)
{
@ -1564,7 +1564,7 @@ static LRESULT WINAPI SysLinkWindowProc(HWND hwnd, UINT message,
infoPtr = (SYSLINK_INFO *)GetWindowLongPtrW(hwnd, 0);
if (!infoPtr && message != WM_CREATE)
goto HandleDefaultMessage;
return DefWindowProcW(hwnd, message, wParam, lParam);
switch(message) {
case WM_PRINTCLIENT:
@ -1588,8 +1588,8 @@ static LRESULT WINAPI SysLinkWindowProc(HWND hwnd, UINT message,
SetCursor(LoadCursorW(0, (LPCWSTR)IDC_HAND));
return TRUE;
}
/* let the default window proc handle this message */
goto HandleDefaultMessage;
return DefWindowProcW(hwnd, message, wParam, lParam);
}
case WM_SIZE:
@ -1615,7 +1615,7 @@ static LRESULT WINAPI SysLinkWindowProc(HWND hwnd, UINT message,
case WM_SETTEXT:
SYSLINK_SetText(infoPtr, (LPWSTR)lParam);
goto HandleDefaultMessage;
return DefWindowProcW(hwnd, message, wParam, lParam);
case WM_LBUTTONDOWN:
{
@ -1645,8 +1645,9 @@ static LRESULT WINAPI SysLinkWindowProc(HWND hwnd, UINT message,
SYSKEY_SelectNextPrevLink(infoPtr, shift);
return 0;
}
default:
return DefWindowProcW(hwnd, message, wParam, lParam);
}
goto HandleDefaultMessage;
}
case WM_GETDLGCODE:
@ -1777,7 +1778,6 @@ static LRESULT WINAPI SysLinkWindowProc(HWND hwnd, UINT message,
return 0;
default:
HandleDefaultMessage:
if ((message >= WM_USER) && (message < WM_APP) && !COMCTL32_IsReflectedMessage(message))
{
ERR("unknown msg %04x wp=%04lx lp=%08lx\n", message, wParam, lParam );

View file

@ -52,6 +52,7 @@
*
*/
#include <assert.h>
#include <stdarg.h>
#include <string.h>
@ -110,7 +111,6 @@ typedef struct
INT iSelected; /* the currently selected item */
INT iHotTracked; /* the highlighted item under the mouse */
INT uFocus; /* item which has the focus */
TAB_ITEM* items; /* pointer to an array of TAB_ITEM's */
BOOL DoRedraw; /* flag for redrawing when tab contents is changed*/
BOOL needsScrolling; /* TRUE if the size of the tabs is greater than
* the size of the control */
@ -122,6 +122,8 @@ typedef struct
DWORD exStyle; /* Extended style used, currently:
TCS_EX_FLATSEPARATORS, TCS_EX_REGISTERDROP */
DWORD dwStyle; /* the cached window GWL_STYLE */
HDPA items; /* dynamic array of TAB_ITEM* pointers */
} TAB_INFO;
/******************************************************************************
@ -141,9 +143,6 @@ typedef struct
#define EXTRA_ICON_PADDING 3
#define TAB_GetInfoPtr(hwnd) ((TAB_INFO *)GetWindowLongPtrW(hwnd,0))
/* Since items are variable sized, cannot directly access them */
#define TAB_GetItem(info,i) \
((TAB_ITEM*)((LPBYTE)info->items + (i) * TAB_ITEM_SIZE(info)))
#define GET_DEFAULT_MIN_TAB_WIDTH(infoPtr) (DEFAULT_MIN_TAB_WIDTH - (DEFAULT_PADDING_X - (infoPtr)->uHItemPadding) * 2)
@ -155,6 +154,12 @@ typedef struct
static const WCHAR themeClass[] = { 'T','a','b',0 };
static inline TAB_ITEM* TAB_GetItem(const TAB_INFO *infoPtr, INT i)
{
assert(i >= 0 && i < infoPtr->uNumItem);
return DPA_GetPtr(infoPtr->items, i);
}
/******************************************************************************
* Prototypes
*/
@ -209,9 +214,8 @@ static void
TAB_DumpItemInternal(const TAB_INFO *infoPtr, UINT iItem)
{
if (TRACE_ON(tab)) {
TAB_ITEM *ti;
TAB_ITEM *ti = TAB_GetItem(infoPtr, iItem);
ti = TAB_GetItem(infoPtr, iItem);
TRACE("tab %d, dwState=0x%08x, pszText=%s, iImage=%d\n",
iItem, ti->dwState, debugstr_w(ti->pszText), ti->iImage);
TRACE("tab %d, rect.left=%d, rect.top(row)=%d\n",
@ -702,11 +706,10 @@ TAB_LButtonUp (const TAB_INFO *infoPtr)
return 0;
}
static inline LRESULT
TAB_RButtonDown (const TAB_INFO *infoPtr)
static inline void
TAB_RButtonUp (const TAB_INFO *infoPtr)
{
TAB_SendSimpleNotify(infoPtr, NM_RCLICK);
return 0;
}
/******************************************************************************
@ -1766,6 +1769,7 @@ TAB_DrawItemInterior(const TAB_INFO *infoPtr, HDC hdc, INT iItem, RECT *drawRect
{
/* this could be considered broken on 64 bit, but that's how it works -
only first 4 bytes are copied */
dis.itemData = 0;
memcpy(&dis.itemData, (ULONG_PTR*)TAB_GetItem(infoPtr, iItem)->extra, 4);
}
@ -2113,9 +2117,10 @@ static void TAB_DrawItem(const TAB_INFO *infoPtr, HDC hdc, INT iItem)
partIndex += 4;
/* The part also differs on the position of a tab on a line.
* "Visually" determining the position works well enough. */
GetClientRect(infoPtr->hwnd, &r1);
if(selectedRect.left == 0)
partIndex += 1;
if(selectedRect.right == clRight)
if(selectedRect.right == r1.right)
partIndex += 2;
if (iItem == infoPtr->iSelected)
@ -2436,6 +2441,9 @@ static void TAB_EnsureSelectionVisible(
INT iSelected = infoPtr->iSelected;
INT iOrigLeftmostVisible = infoPtr->leftmostVisible;
if (iSelected < 0)
return;
/* set the items row to the bottommost row or topmost row depending on
* style */
if ((infoPtr->uNumRows > 1) && !(infoPtr->dwStyle & TCS_BUTTONS))
@ -2640,42 +2648,21 @@ TAB_InsertItemT (TAB_INFO *infoPtr, INT iItem, const TCITEMW *pti, BOOL bUnicode
TAB_DumpItemExternalT(pti, iItem, bUnicode);
if (infoPtr->uNumItem == 0) {
infoPtr->items = Alloc (TAB_ITEM_SIZE(infoPtr));
infoPtr->uNumItem++;
infoPtr->iSelected = 0;
if (!(item = Alloc(TAB_ITEM_SIZE(infoPtr)))) return FALSE;
if (DPA_InsertPtr(infoPtr->items, iItem, item) == -1)
{
Free(item);
return FALSE;
}
else {
LPBYTE oldItems = (LPBYTE)infoPtr->items;
infoPtr->uNumItem++;
infoPtr->items = Alloc (TAB_ITEM_SIZE(infoPtr) * infoPtr->uNumItem);
/* pre insert copy */
if (iItem > 0) {
memcpy (infoPtr->items, oldItems,
iItem * TAB_ITEM_SIZE(infoPtr));
}
/* post insert copy */
if (iItem < infoPtr->uNumItem - 1) {
memcpy (TAB_GetItem(infoPtr, iItem + 1),
oldItems + iItem * TAB_ITEM_SIZE(infoPtr),
(infoPtr->uNumItem - iItem - 1) * TAB_ITEM_SIZE(infoPtr));
}
if (iItem <= infoPtr->iSelected)
if (infoPtr->uNumItem == 0)
infoPtr->iSelected = 0;
else if (iItem <= infoPtr->iSelected)
infoPtr->iSelected++;
Free (oldItems);
}
item = TAB_GetItem(infoPtr, iItem);
infoPtr->uNumItem++;
item->pszText = NULL;
if (pti->mask & TCIF_TEXT)
{
if (bUnicode)
@ -2885,64 +2872,49 @@ TAB_GetItemT (TAB_INFO *infoPtr, INT iItem, LPTCITEMW tabItem, BOOL bUnicode)
static LRESULT TAB_DeleteItem (TAB_INFO *infoPtr, INT iItem)
{
BOOL bResult = FALSE;
TAB_ITEM *item;
TRACE("(%p, %d)\n", infoPtr, iItem);
if ((iItem >= 0) && (iItem < infoPtr->uNumItem))
if (iItem < 0 || iItem >= infoPtr->uNumItem) return FALSE;
item = TAB_GetItem(infoPtr, iItem);
Free(item->pszText);
Free(item);
infoPtr->uNumItem--;
DPA_DeletePtr(infoPtr->items, iItem);
TAB_InvalidateTabArea(infoPtr);
if (infoPtr->uNumItem == 0)
{
TAB_ITEM *item = TAB_GetItem(infoPtr, iItem);
LPBYTE oldItems = (LPBYTE)infoPtr->items;
TAB_InvalidateTabArea(infoPtr);
Free(item->pszText);
infoPtr->uNumItem--;
if (!infoPtr->uNumItem)
if (infoPtr->iHotTracked >= 0)
{
infoPtr->items = NULL;
if (infoPtr->iHotTracked >= 0)
{
KillTimer(infoPtr->hwnd, TAB_HOTTRACK_TIMER);
infoPtr->iHotTracked = -1;
}
KillTimer(infoPtr->hwnd, TAB_HOTTRACK_TIMER);
infoPtr->iHotTracked = -1;
}
else
{
infoPtr->items = Alloc(TAB_ITEM_SIZE(infoPtr) * infoPtr->uNumItem);
if (iItem > 0)
memcpy(infoPtr->items, oldItems, iItem * TAB_ITEM_SIZE(infoPtr));
if (iItem < infoPtr->uNumItem)
memcpy(TAB_GetItem(infoPtr, iItem),
oldItems + (iItem + 1) * TAB_ITEM_SIZE(infoPtr),
(infoPtr->uNumItem - iItem) * TAB_ITEM_SIZE(infoPtr));
if (iItem <= infoPtr->iHotTracked)
{
/* When tabs move left/up, the hot track item may change */
FIXME("Recalc hot track\n");
}
}
Free(oldItems);
/* Readjust the selected index */
if (iItem == infoPtr->iSelected)
infoPtr->iSelected = -1;
else if (iItem < infoPtr->iSelected)
infoPtr->iSelected--;
if (infoPtr->uNumItem == 0)
infoPtr->iSelected = -1;
/* Reposition and repaint tabs */
TAB_SetItemBounds(infoPtr);
bResult = TRUE;
infoPtr->iSelected = -1;
}
else
{
if (iItem <= infoPtr->iHotTracked)
{
/* When tabs move left/up, the hot track item may change */
FIXME("Recalc hot track\n");
}
}
return bResult;
/* adjust the selected index */
if (iItem == infoPtr->iSelected)
infoPtr->iSelected = -1;
else if (iItem < infoPtr->iSelected)
infoPtr->iSelected--;
/* reposition and repaint tabs */
TAB_SetItemBounds(infoPtr);
return TRUE;
}
static inline LRESULT TAB_DeleteAllItems (TAB_INFO *infoPtr)
@ -3063,7 +3035,7 @@ static LRESULT TAB_Create (HWND hwnd, LPARAM lParam)
infoPtr->uHItemPadding_s = 6;
infoPtr->uVItemPadding_s = 3;
infoPtr->hFont = 0;
infoPtr->items = 0;
infoPtr->items = DPA_Create(8);
infoPtr->hcurArrow = LoadCursorW (0, (LPWSTR)IDC_ARROW);
infoPtr->iSelected = -1;
infoPtr->iHotTracked = -1;
@ -3147,16 +3119,22 @@ static LRESULT TAB_Create (HWND hwnd, LPARAM lParam)
static LRESULT
TAB_Destroy (TAB_INFO *infoPtr)
{
UINT iItem;
INT iItem;
SetWindowLongPtrW(infoPtr->hwnd, 0, 0);
if (infoPtr->items) {
for (iItem = 0; iItem < infoPtr->uNumItem; iItem++) {
Free (TAB_GetItem(infoPtr, iItem)->pszText);
}
Free (infoPtr->items);
for (iItem = infoPtr->uNumItem - 1; iItem >= 0; iItem--)
{
TAB_ITEM *tab = TAB_GetItem(infoPtr, iItem);
DPA_DeletePtr(infoPtr->items, iItem);
infoPtr->uNumItem--;
Free(tab->pszText);
Free(tab);
}
DPA_Destroy(infoPtr->items);
infoPtr->items = NULL;
if (infoPtr->hwndToolTip)
DestroyWindow (infoPtr->hwndToolTip);
@ -3450,8 +3428,9 @@ TAB_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
case WM_NOTIFY:
return SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, wParam, lParam);
case WM_RBUTTONDOWN:
return TAB_RButtonDown (infoPtr);
case WM_RBUTTONUP:
TAB_RButtonUp (infoPtr);
return DefWindowProcW (hwnd, uMsg, wParam, lParam);
case WM_MOUSEMOVE:
return TAB_MouseMove (infoPtr, wParam, lParam);

View file

@ -246,18 +246,26 @@ static BOOL BUTTON_Paint(HTHEME theme, HWND hwnd, HDC hParamDC)
DWORD dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
DWORD dwStyleEx = GetWindowLongW(hwnd, GWL_EXSTYLE);
UINT dtFlags = get_drawtext_flags(dwStyle, dwStyleEx);
ButtonState drawState = IsWindowEnabled(hwnd) ? STATE_NORMAL : STATE_DISABLED;
int state = (int)SendMessageW(hwnd, BM_GETSTATE, 0, 0);
ButtonState drawState;
pfThemedPaint paint = btnThemedPaintFunc[ dwStyle & BUTTON_TYPE ];
if (paint)
{
hDC = hParamDC ? hParamDC : BeginPaint(hwnd, &ps);
paint(theme, hwnd, hDC, drawState, dtFlags);
if (!hParamDC) EndPaint(hwnd, &ps);
return TRUE;
}
if(!paint)
return FALSE;
return FALSE; /* Delegate drawing to the non-themed code. */
if(IsWindowEnabled(hwnd))
{
if(state & BST_PUSHED) drawState = STATE_PRESSED;
else if(state & BST_HOT) drawState = STATE_HOT;
else if(state & BST_FOCUS) drawState = STATE_DEFAULTED;
else drawState = STATE_NORMAL;
}
else drawState = STATE_DISABLED;
hDC = hParamDC ? hParamDC : BeginPaint(hwnd, &ps);
paint(theme, hwnd, hDC, drawState, dtFlags);
if (!hParamDC) EndPaint(hwnd, &ps);
return TRUE;
}
/**********************************************************************
@ -309,6 +317,37 @@ LRESULT CALLBACK THEMING_ButtonSubclassProc(HWND hwnd, UINT msg,
RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW);
return THEMING_CallOriginalClass(hwnd, msg, wParam, lParam);
case WM_MOUSEMOVE:
{
TRACKMOUSEEVENT mouse_event;
mouse_event.cbSize = sizeof(TRACKMOUSEEVENT);
mouse_event.dwFlags = TME_QUERY;
if(!TrackMouseEvent(&mouse_event) || !(mouse_event.dwFlags&(TME_HOVER|TME_LEAVE)))
{
mouse_event.dwFlags = TME_HOVER|TME_LEAVE;
mouse_event.hwndTrack = hwnd;
mouse_event.dwHoverTime = 1;
TrackMouseEvent(&mouse_event);
}
break;
}
case WM_MOUSEHOVER:
{
int state = (int)SendMessageW(hwnd, BM_GETSTATE, 0, 0);
SetWindowLongW(hwnd, 0, state|BST_HOT);
InvalidateRect(hwnd, NULL, FALSE);
break;
}
case WM_MOUSELEAVE:
{
int state = (int)SendMessageW(hwnd, BM_GETSTATE, 0, 0);
SetWindowLongW(hwnd, 0, state&(~BST_HOT));
InvalidateRect(hwnd, NULL, FALSE);
break;
}
default:
/* Call old proc */
return THEMING_CallOriginalClass(hwnd, msg, wParam, lParam);

View file

@ -54,7 +54,9 @@ LRESULT CALLBACK THEMING_DialogSubclassProc (HWND hWnd, UINT msg,
case WM_DESTROY:
CloseThemeData ( theme );
return THEMING_CallOriginalClass (hWnd, msg, wParam, lParam);
SetWindowTheme( hWnd, NULL, NULL );
OpenThemeData( hWnd, NULL );
return THEMING_CallOriginalClass (hWnd, msg, wParam, lParam);
case WM_THEMECHANGED:
CloseThemeData ( theme );

View file

@ -35,15 +35,15 @@ typedef LRESULT (CALLBACK* THEMING_SUBCLASSPROC)(HWND, UINT, WPARAM, LPARAM,
ULONG_PTR);
extern LRESULT CALLBACK THEMING_ButtonSubclassProc (HWND, UINT, WPARAM, LPARAM,
ULONG_PTR);
ULONG_PTR) DECLSPEC_HIDDEN;
extern LRESULT CALLBACK THEMING_ComboSubclassProc (HWND, UINT, WPARAM, LPARAM,
ULONG_PTR);
ULONG_PTR) DECLSPEC_HIDDEN;
extern LRESULT CALLBACK THEMING_DialogSubclassProc (HWND, UINT, WPARAM, LPARAM,
ULONG_PTR);
ULONG_PTR) DECLSPEC_HIDDEN;
extern LRESULT CALLBACK THEMING_EditSubclassProc (HWND, UINT, WPARAM, LPARAM,
ULONG_PTR);
ULONG_PTR) DECLSPEC_HIDDEN;
extern LRESULT CALLBACK THEMING_ListBoxSubclassProc (HWND, UINT, WPARAM, LPARAM,
ULONG_PTR);
ULONG_PTR) DECLSPEC_HIDDEN;
static const WCHAR dialogClass[] = {'#','3','2','7','7','0',0};
static const WCHAR comboLboxClass[] = {'C','o','m','b','o','L','b','o','x',0};

View file

@ -574,7 +574,7 @@ TOOLBAR_DrawString (const TOOLBAR_INFO *infoPtr, RECT *rcText, LPCWSTR lpText,
UINT state = tbcd->nmcd.uItemState;
/* draw text */
if (lpText) {
if (lpText && infoPtr->nMaxTextRows > 0) {
TRACE("string=%s rect=(%s)\n", debugstr_w(lpText),
wine_dbgstr_rect(rcText));
@ -2305,7 +2305,7 @@ static LRESULT TOOLBAR_Cust_AvailDragListNotification(const CUSTDLG_INFO *custIn
return 0;
}
extern UINT uDragListMessage;
extern UINT uDragListMessage DECLSPEC_HIDDEN;
/***********************************************************************
* TOOLBAR_CustomizeDialogProc

View file

@ -1979,37 +1979,13 @@ TOOLTIPS_NCHitTest (const TOOLTIPS_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
static LRESULT
TOOLTIPS_NotifyFormat (TOOLTIPS_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
{
TTTOOL_INFO *toolPtr = infoPtr->tools;
LRESULT nResult;
TRACE("infoPtr=%p wParam=%lx lParam=%p\n", infoPtr, wParam, (PVOID)lParam);
if (lParam == NF_QUERY) {
if (toolPtr->bNotifyUnicode) {
return NFR_UNICODE;
} else {
return NFR_ANSI;
}
}
else if (lParam == NF_REQUERY) {
nResult = SendMessageW (toolPtr->hwnd, WM_NOTIFYFORMAT,
(WPARAM)infoPtr->hwndSelf, (LPARAM)NF_QUERY);
if (nResult == NFR_ANSI) {
toolPtr->bNotifyUnicode = FALSE;
TRACE(" -- WM_NOTIFYFORMAT returns: NFR_ANSI\n");
} else if (nResult == NFR_UNICODE) {
toolPtr->bNotifyUnicode = TRUE;
TRACE(" -- WM_NOTIFYFORMAT returns: NFR_UNICODE\n");
} else {
TRACE (" -- WM_NOTIFYFORMAT returns: error!\n");
}
return nResult;
}
FIXME ("hwnd=%p wParam=%lx lParam=%lx\n", infoPtr->hwndSelf, wParam, lParam);
return 0;
}
static LRESULT
TOOLTIPS_Paint (const TOOLTIPS_INFO *infoPtr, HDC hDC)
{
@ -2076,7 +2052,7 @@ TOOLTIPS_OnWMGetText (const TOOLTIPS_INFO *infoPtr, WPARAM size, LPWSTR pszText)
{
LRESULT res;
if(!infoPtr->szTipText || !size)
if(!size)
return 0;
res = min(strlenW(infoPtr->szTipText)+1, size);