Nikolay Sivov : comctl32/monthcal: Process UpDown year control through subclass procedure.
Alexandre Julliard
julliard at winehq.org
Mon Oct 12 11:19:44 CDT 2009
Module: wine
Branch: master
Commit: 2906aaf605e432bdb7d46be33727fe53a525470a
URL: http://source.winehq.org/git/wine.git/?a=commit;h=2906aaf605e432bdb7d46be33727fe53a525470a
Author: Nikolay Sivov <bunglehead at gmail.com>
Date: Sat Oct 10 21:04:16 2009 +0400
comctl32/monthcal: Process UpDown year control through subclass procedure.
---
dlls/comctl32/monthcal.c | 126 ++++++++++++++++++++++++++++-----------
dlls/comctl32/tests/monthcal.c | 23 +++++++
2 files changed, 113 insertions(+), 36 deletions(-)
diff --git a/dlls/comctl32/monthcal.c b/dlls/comctl32/monthcal.c
index 7697187..fc73537 100644
--- a/dlls/comctl32/monthcal.c
+++ b/dlls/comctl32/monthcal.c
@@ -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);
diff --git a/dlls/comctl32/tests/monthcal.c b/dlls/comctl32/tests/monthcal.c
index 21c171e..d767066 100644
--- a/dlls/comctl32/tests/monthcal.c
+++ b/dlls/comctl32/tests/monthcal.c
@@ -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);
More information about the wine-cvs
mailing list