mirror of
https://github.com/reactos/reactos.git
synced 2024-08-19 09:59:44 +00:00
[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:
parent
84291d0d72
commit
8d084e9377
|
@ -1122,8 +1122,8 @@ static LRESULT COMBOEX_Command (COMBOEX_INFO *infoPtr, WPARAM wParam)
|
|||
case CBN_DROPDOWN:
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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];
|
||||
|
||||
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;
|
||||
infoPtr->charsEntered[infoPtr->nCharsEntered++] = vkCode;
|
||||
|
||||
fieldSpec = infoPtr->fieldspec[fieldNum];
|
||||
|
||||
if (fieldSpec == INVALIDFULLYEAR || fieldSpec == FULLYEAR)
|
||||
maxChars = 4;
|
||||
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;
|
||||
}
|
||||
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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,7 +4337,7 @@ 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 */
|
||||
|
@ -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,7 +8853,7 @@ 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;
|
||||
|
@ -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);
|
||||
|
||||
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);
|
||||
|
@ -10214,10 +10263,6 @@ static LRESULT LISTVIEW_Notify(LISTVIEW_INFO *infoPtr, const NMHDR *lpnmhdr)
|
|||
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:
|
||||
{
|
||||
|
@ -10225,10 +10270,6 @@ static LRESULT LISTVIEW_Notify(LISTVIEW_INFO *infoPtr, const NMHDR *lpnmhdr)
|
|||
HDITEMW hdi;
|
||||
INT dx, cxy;
|
||||
|
||||
notify_forward_header(infoPtr, lpnmh);
|
||||
if (!IsWindow(hwndSelf))
|
||||
break;
|
||||
|
||||
if (!lpnmh->pitem || !(lpnmh->pitem->mask & HDI_WIDTH))
|
||||
{
|
||||
hdi.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: */
|
||||
|
|
|
@ -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] 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 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;
|
||||
RECT text_rect, box_rect;
|
||||
HFONT old_font;
|
||||
INT col;
|
||||
|
||||
if(!(infoPtr->dwStyle & MCS_NOTODAYCIRCLE)) {
|
||||
SYSTEMTIME fake_st;
|
||||
if(infoPtr->dwStyle & MCS_NOTODAY) return;
|
||||
|
||||
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)))
|
||||
{
|
||||
static const WCHAR todayW[] = { 'T','o','d','a','y',':',0 };
|
||||
WARN("Can't load resource\n");
|
||||
strcpyW(buf_todayW, todayW);
|
||||
}
|
||||
MONTHCAL_CalcDayRect(infoPtr, &rtoday, 1, 6);
|
||||
|
||||
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));
|
||||
SelectObject(hdc, infoPtr->hBoldFont);
|
||||
old_font = SelectObject(hdc, infoPtr->hBoldFont);
|
||||
SetTextColor(hdc, infoPtr->colors[MCSC_TEXT]);
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
SelectObject(hdc, infoPtr->hFont);
|
||||
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,79 +962,31 @@ static void MONTHCAL_PaintFocusAndCircle(const MONTHCAL_INFO *infoPtr, HDC hdc,
|
|||
}
|
||||
}
|
||||
|
||||
/* paint a calendar area */
|
||||
static void MONTHCAL_PaintCalendar(const MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps, INT calIdx)
|
||||
/* months before first calendar month and after last calendar month */
|
||||
static void MONTHCAL_PaintLeadTrailMonths(const MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps)
|
||||
{
|
||||
const SYSTEMTIME *date = &infoPtr->calendars[calIdx].month;
|
||||
INT prev_month, i, j, length;
|
||||
RECT r, fill_bk_rect;
|
||||
SYSTEMTIME st;
|
||||
WCHAR buf[80];
|
||||
HBRUSH hbr;
|
||||
int mask;
|
||||
INT mask, length;
|
||||
SYSTEMTIME st_max, st;
|
||||
|
||||
/* fill whole days area - from week days area to today note rectangle */
|
||||
fill_bk_rect = infoPtr->calendars[calIdx].wdays;
|
||||
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);
|
||||
|
||||
/* draw line under day abbreviations */
|
||||
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;
|
||||
|
||||
infoPtr->calendars[calIdx].wdays.left = infoPtr->calendars[calIdx].days.left =
|
||||
infoPtr->calendars[calIdx].weeknums.right;
|
||||
|
||||
/* 1. draw day abbreviations */
|
||||
SelectObject(hdc, infoPtr->hFont);
|
||||
SetBkColor(hdc, infoPtr->colors[MCSC_MONTHBK]);
|
||||
SetTextColor(hdc, infoPtr->colors[MCSC_TRAILINGTEXT]);
|
||||
/* rectangle to draw a single day abbreviation within */
|
||||
r = infoPtr->calendars[calIdx].wdays;
|
||||
r.right = r.left + infoPtr->width_increment;
|
||||
|
||||
i = infoPtr->firstDay;
|
||||
for(j = 0; j < 7; j++) {
|
||||
GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SABBREVDAYNAME1 + (i+j+6)%7, buf, countof(buf));
|
||||
DrawTextW(hdc, buf, strlenW(buf), &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
|
||||
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;
|
||||
if (infoPtr->dwStyle & MCS_NOTRAILINGDATES) return;
|
||||
|
||||
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);
|
||||
|
||||
/* 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 */
|
||||
if (calIdx == infoPtr->cal_num - 1)
|
||||
{
|
||||
st = *date;
|
||||
st = infoPtr->calendars[infoPtr->cal_num-1].month;
|
||||
st.wDay = 1;
|
||||
MONTHCAL_GetNextMonth(&st);
|
||||
MONTHCAL_GetMaxDate(infoPtr, &st_max);
|
||||
|
@ -1032,9 +999,52 @@ static void MONTHCAL_PaintCalendar(const MONTHCAL_INFO *infoPtr, HDC hdc, const
|
|||
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 i, j, length;
|
||||
RECT r, fill_bk_rect;
|
||||
SYSTEMTIME st;
|
||||
WCHAR buf[80];
|
||||
HPEN old_pen;
|
||||
int mask;
|
||||
|
||||
/* fill whole days area - from week days area to today note rectangle */
|
||||
fill_bk_rect = infoPtr->calendars[calIdx].wdays;
|
||||
fill_bk_rect.bottom = infoPtr->calendars[calIdx].days.bottom +
|
||||
(infoPtr->todayrect.bottom - infoPtr->todayrect.top);
|
||||
|
||||
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);
|
||||
SelectObject(hdc, old_pen);
|
||||
|
||||
infoPtr->calendars[calIdx].wdays.left = infoPtr->calendars[calIdx].days.left =
|
||||
infoPtr->calendars[calIdx].weeknums.right;
|
||||
|
||||
/* draw day abbreviations */
|
||||
SelectObject(hdc, infoPtr->hFont);
|
||||
SetBkColor(hdc, infoPtr->colors[MCSC_MONTHBK]);
|
||||
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;
|
||||
|
||||
i = infoPtr->firstDay;
|
||||
for(j = 0; j < 7; j++) {
|
||||
GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SABBREVDAYNAME1 + (i+j+6)%7, buf, countof(buf));
|
||||
DrawTextW(hdc, buf, strlenW(buf), &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
|
||||
OffsetRect(&r, infoPtr->width_increment, 0);
|
||||
}
|
||||
|
||||
/* 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,6 +2608,8 @@ fail:
|
|||
static LRESULT
|
||||
MONTHCAL_Destroy(MONTHCAL_INFO *infoPtr)
|
||||
{
|
||||
INT i;
|
||||
|
||||
/* free month calendar info data */
|
||||
Free(infoPtr->monthdayState);
|
||||
Free(infoPtr->calendars);
|
||||
|
@ -2571,6 +2617,9 @@ MONTHCAL_Destroy(MONTHCAL_INFO *infoPtr)
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 (!(item = Alloc(TAB_ITEM_SIZE(infoPtr)))) return FALSE;
|
||||
if (DPA_InsertPtr(infoPtr->items, iItem, item) == -1)
|
||||
{
|
||||
Free(item);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (infoPtr->uNumItem == 0) {
|
||||
infoPtr->items = Alloc (TAB_ITEM_SIZE(infoPtr));
|
||||
infoPtr->uNumItem++;
|
||||
if (infoPtr->uNumItem == 0)
|
||||
infoPtr->iSelected = 0;
|
||||
}
|
||||
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)
|
||||
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))
|
||||
{
|
||||
TAB_ITEM *item = TAB_GetItem(infoPtr, iItem);
|
||||
LPBYTE oldItems = (LPBYTE)infoPtr->items;
|
||||
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);
|
||||
Free(item->pszText);
|
||||
infoPtr->uNumItem--;
|
||||
|
||||
if (!infoPtr->uNumItem)
|
||||
if (infoPtr->uNumItem == 0)
|
||||
{
|
||||
infoPtr->items = NULL;
|
||||
if (infoPtr->iHotTracked >= 0)
|
||||
{
|
||||
KillTimer(infoPtr->hwnd, TAB_HOTTRACK_TIMER);
|
||||
infoPtr->iHotTracked = -1;
|
||||
}
|
||||
|
||||
infoPtr->iSelected = -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 */
|
||||
/* adjust 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 */
|
||||
/* reposition and repaint tabs */
|
||||
TAB_SetItemBounds(infoPtr);
|
||||
|
||||
bResult = TRUE;
|
||||
}
|
||||
|
||||
return bResult;
|
||||
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);
|
||||
|
|
|
@ -246,20 +246,28 @@ 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)
|
||||
if(!paint)
|
||||
return FALSE;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return FALSE; /* Delegate drawing to the non-themed code. */
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* The button control subclass window proc.
|
||||
*/
|
||||
|
@ -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);
|
||||
|
|
|
@ -54,6 +54,8 @@ LRESULT CALLBACK THEMING_DialogSubclassProc (HWND hWnd, UINT msg,
|
|||
|
||||
case WM_DESTROY:
|
||||
CloseThemeData ( theme );
|
||||
SetWindowTheme( hWnd, NULL, NULL );
|
||||
OpenThemeData( hWnd, NULL );
|
||||
return THEMING_CallOriginalClass (hWnd, msg, wParam, lParam);
|
||||
|
||||
case WM_THEMECHANGED:
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue