comctl32/monthcal: Process UpDown year control through subclass procedure.

This commit is contained in:
Nikolay Sivov 2009-10-10 21:04:16 +04:00 committed by Alexandre Julliard
parent 48fcccd861
commit 2906aaf605
2 changed files with 113 additions and 36 deletions

View file

@ -128,6 +128,7 @@ typedef struct
HWND hwndNotify; /* Window to receive the notifications */
HWND hWndYearEdit; /* Window Handle of edit box to handle years */
HWND hWndYearUpDown;/* Window Handle of updown box to handle years */
WNDPROC EditWndProc; /* original Edit window procedure */
} MONTHCAL_INFO, *LPMONTHCAL_INFO;
@ -1355,7 +1356,7 @@ MONTHCAL_GetCurSel(const MONTHCAL_INFO *infoPtr, SYSTEMTIME *curSel)
/* FIXME: if the specified date is not visible, make it visible */
static LRESULT
MONTHCAL_SetCurSel(MONTHCAL_INFO *infoPtr, SYSTEMTIME *curSel)
MONTHCAL_SetCurSel(MONTHCAL_INFO *infoPtr, const SYSTEMTIME *curSel)
{
TRACE("%p\n", curSel);
if(!curSel) return FALSE;
@ -1725,6 +1726,53 @@ MONTHCAL_RButtonUp(MONTHCAL_INFO *infoPtr, LPARAM lParam)
return 0;
}
/***
* DESCRIPTION:
* Subclassed edit control windproc function
*
* PARAMETER(S):
* [I] hwnd : the edit window handle
* [I] uMsg : the message that is to be processed
* [I] wParam : first message parameter
* [I] lParam : second message parameter
*
*/
static LRESULT CALLBACK EditWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
MONTHCAL_INFO *infoPtr = (MONTHCAL_INFO *)GetWindowLongPtrW(GetParent(hwnd), 0);
TRACE("(hwnd=%p, uMsg=%x, wParam=%lx, lParam=%lx)\n",
hwnd, uMsg, wParam, lParam);
switch (uMsg)
{
case WM_GETDLGCODE:
return DLGC_WANTARROWS | DLGC_WANTALLKEYS;
case WM_DESTROY:
{
WNDPROC editProc = infoPtr->EditWndProc;
infoPtr->EditWndProc = NULL;
SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (DWORD_PTR)editProc);
return CallWindowProcW(editProc, hwnd, uMsg, wParam, lParam);
}
case WM_KILLFOCUS:
break;
case WM_KEYDOWN:
if ((VK_ESCAPE == (INT)wParam) || (VK_RETURN == (INT)wParam))
break;
default:
return CallWindowProcW(infoPtr->EditWndProc, hwnd, uMsg, wParam, lParam);
}
SendMessageW(infoPtr->hWndYearUpDown, WM_CLOSE, 0, 0);
SendMessageW(hwnd, WM_CLOSE, 0, 0);
return 0;
}
/* creates updown control and edit box */
static void MONTHCAL_EditYear(MONTHCAL_INFO *infoPtr)
{
@ -1749,6 +1797,12 @@ static void MONTHCAL_EditYear(MONTHCAL_INFO *infoPtr)
MAKELONG(max_allowed_date.wYear, min_allowed_date.wYear));
SendMessageW(infoPtr->hWndYearUpDown, UDM_SETBUDDY, (WPARAM)infoPtr->hWndYearEdit, 0);
SendMessageW(infoPtr->hWndYearUpDown, UDM_SETPOS, 0, infoPtr->curSel.wYear);
/* subclass edit box */
infoPtr->EditWndProc = (WNDPROC)SetWindowLongPtrW(infoPtr->hWndYearEdit,
GWLP_WNDPROC, (DWORD_PTR)EditWndProc);
SetFocus(infoPtr->hWndYearEdit);
}
static LRESULT
@ -1757,24 +1811,12 @@ MONTHCAL_LButtonDown(MONTHCAL_INFO *infoPtr, LPARAM lParam)
MCHITTESTINFO ht;
DWORD hit;
if (infoPtr->hWndYearUpDown)
/* Actually we don't need input focus for calendar, this is used to kill
year updown and its buddy edit box */
if (IsWindow(infoPtr->hWndYearUpDown))
{
infoPtr->curSel.wYear = SendMessageW(infoPtr->hWndYearUpDown, UDM_SETPOS, 0, 0);
if(!DestroyWindow(infoPtr->hWndYearUpDown))
{
FIXME("Can't destroy Updown Control\n");
}
else
infoPtr->hWndYearUpDown = 0;
if(!DestroyWindow(infoPtr->hWndYearEdit))
{
FIXME("Can't destroy Updown Control\n");
}
else
infoPtr->hWndYearEdit = 0;
InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
SetFocus(infoPtr->hwndSelf);
return 0;
}
SetCapture(infoPtr->hwndSelf);
@ -1899,6 +1941,8 @@ MONTHCAL_LButtonUp(MONTHCAL_INFO *infoPtr, LPARAM lParam)
SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, nmhdr.idFrom, (LPARAM)&nmhdr);
if(!(infoPtr->status & MC_SEL_LBUTDOWN)) return 0;
ht.cbSize = sizeof(MCHITTESTINFO);
ht.pt.x = (short)LOWORD(lParam);
ht.pt.y = (short)HIWORD(lParam);
@ -2049,21 +2093,6 @@ MONTHCAL_Paint(MONTHCAL_INFO *infoPtr, HDC hdc_paint)
return 0;
}
static LRESULT
MONTHCAL_KillFocus(const MONTHCAL_INFO *infoPtr, HWND hFocusWnd)
{
TRACE("\n");
if (infoPtr->hwndNotify != hFocusWnd)
ShowWindow(infoPtr->hwndSelf, SW_HIDE);
else
InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
return 0;
}
static LRESULT
MONTHCAL_SetFocus(const MONTHCAL_INFO *infoPtr)
{
@ -2360,6 +2389,31 @@ MONTHCAL_Destroy(MONTHCAL_INFO *infoPtr)
return 0;
}
/*
* Handler for WM_NOTIFY messages
*/
static LRESULT
MONTHCAL_Notify(MONTHCAL_INFO *infoPtr, NMHDR *hdr)
{
/* notification from year edit updown */
if (hdr->code == UDN_DELTAPOS)
{
NMUPDOWN *nmud = (NMUPDOWN*)hdr;
if (hdr->hwndFrom == infoPtr->hWndYearUpDown)
{
/* year value limits are set up explicitly after updown creation */
if ((nmud->iDelta + nmud->iPos) != infoPtr->curSel.wYear)
{
SYSTEMTIME new_date = infoPtr->curSel;
new_date.wYear = nmud->iDelta + nmud->iPos;
MONTHCAL_SetCurSel(infoPtr, &new_date);
}
}
}
return 0;
}
static LRESULT WINAPI
MONTHCAL_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
@ -2439,9 +2493,6 @@ MONTHCAL_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
case WM_GETDLGCODE:
return DLGC_WANTARROWS | DLGC_WANTCHARS;
case WM_KILLFOCUS:
return MONTHCAL_KillFocus(infoPtr, (HWND)wParam);
case WM_RBUTTONUP:
return MONTHCAL_RButtonUp(infoPtr, lParam);
@ -2464,6 +2515,9 @@ MONTHCAL_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
case WM_SIZE:
return MONTHCAL_Size(infoPtr, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam));
case WM_NOTIFY:
return MONTHCAL_Notify(infoPtr, (NMHDR*)lParam);
case WM_CREATE:
return MONTHCAL_Create(hwnd, (LPCREATESTRUCTW)lParam);

View file

@ -1647,6 +1647,28 @@ static void test_monthcal_selrange(void)
DestroyWindow(hwnd);
}
static void test_killfocus(void)
{
HWND hwnd;
DWORD style;
hwnd = create_monthcal_control(0);
/* make parent invisible */
style = GetWindowLong(parent_wnd, GWL_STYLE);
SetWindowLong(parent_wnd, GWL_STYLE, style &~ WS_VISIBLE);
SendMessage(hwnd, WM_KILLFOCUS, (WPARAM)GetDesktopWindow(), 0);
style = GetWindowLong(hwnd, GWL_STYLE);
ok(style & WS_VISIBLE, "Expected WS_VISIBLE to be set\n");
style = GetWindowLong(parent_wnd, GWL_STYLE);
SetWindowLong(parent_wnd, GWL_STYLE, style | WS_VISIBLE);
DestroyWindow(hwnd);
}
START_TEST(monthcal)
{
HMODULE hComctl32;
@ -1684,6 +1706,7 @@ START_TEST(monthcal)
test_monthcal_size();
test_monthcal_maxselday();
test_monthcal_selrange();
test_killfocus();
flush_sequences(sequences, NUM_MSG_SEQUENCES);
DestroyWindow(parent_wnd);