[PATCH 03/10] Handle mouse pointer followed focus rectangle more accurately

Nikolay Sivov bunglehead at gmail.com
Sun Oct 4 14:16:41 CDT 2009


---
 dlls/comctl32/monthcal.c |   73 +++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 62 insertions(+), 11 deletions(-)

diff --git a/dlls/comctl32/monthcal.c b/dlls/comctl32/monthcal.c
index b5cb65a..a54cba7 100644
--- a/dlls/comctl32/monthcal.c
+++ b/dlls/comctl32/monthcal.c
@@ -102,6 +102,7 @@ typedef struct
     SYSTEMTIME	minSel;
     SYSTEMTIME	maxSel;
     SYSTEMTIME  curSel;         /* contains currently selected year, month and day */
+    SYSTEMTIME  focusedSel;     /* date currently focused with mouse movement */
     DWORD	rangeValid;
     SYSTEMTIME	minDate;
     SYSTEMTIME	maxDate;
@@ -312,6 +313,43 @@ static inline void MONTHCAL_CalcPosFromDay(const MONTHCAL_INFO *infoPtr,
   MONTHCAL_CalcDayRect(infoPtr, r, x, y);
 }
 
+/* Focused day helper:
+
+   - set focused date to given value;
+   - reset to zero value if NULL passed;
+   - invalidate previous and new day rectangle only if needed.
+*/
+static void MONTHCAL_SetDayFocus(MONTHCAL_INFO *infoPtr, const SYSTEMTIME *st)
+{
+  RECT r;
+
+  if(st)
+  {
+    /* there's nothing to do if it's the same date,
+       mouse move within same date rectangle case */
+    if(MONTHCAL_IsDateEqual(&infoPtr->focusedSel, st)) return;
+
+    /* invalidate old focused day */
+    MONTHCAL_CalcPosFromDay(infoPtr, infoPtr->focusedSel.wDay,
+                                     infoPtr->focusedSel.wMonth, &r);
+    InvalidateRect(infoPtr->hwndSelf, &r, FALSE);
+
+    infoPtr->focusedSel = *st;
+  }
+
+  MONTHCAL_CalcPosFromDay(infoPtr, infoPtr->focusedSel.wDay,
+                                   infoPtr->focusedSel.wMonth, &r);
+
+  if(!st & MONTHCAL_ValidateDate(&infoPtr->focusedSel))
+  {
+    static const SYSTEMTIME st_null;
+
+    infoPtr->focusedSel = st_null;
+  }
+
+  /* on set invalidates new day, on reset clears previous focused day */
+  InvalidateRect(infoPtr->hwndSelf, &r, FALSE);
+}
 
 /* day is the day in the month(1 == 1st of the month) */
 /* month is the month value(1 == january, 12 == december) */
@@ -393,8 +431,8 @@ static void MONTHCAL_DrawDay(const MONTHCAL_INFO *infoPtr, HDC hdc, int day, int
     SetBkColor(hdc, oldBk);
   }
 
-  /* draw a rectangle around the currently selected days text */
-  if((day == infoPtr->curSel.wDay) && (month == infoPtr->curSel.wMonth))
+  /* draw focus rectangle */
+  if((day == infoPtr->focusedSel.wDay) && (month == infoPtr->focusedSel.wMonth))
     DrawFocusRect(hdc, &r);
 }
 
@@ -1470,13 +1508,16 @@ MONTHCAL_LButtonDown(MONTHCAL_INFO *infoPtr, LPARAM lParam)
       InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
   }
 
+  SetCapture(infoPtr->hwndSelf);
+
   ht.cbSize = sizeof(MCHITTESTINFO);
   ht.pt.x = (short)LOWORD(lParam);
   ht.pt.y = (short)HIWORD(lParam);
-  TRACE("(%d, %d)\n", ht.pt.x, ht.pt.y);
 
   hit = MONTHCAL_HitTest(infoPtr, &ht);
 
+  TRACE("%x at (%d, %d)\n", hit, ht.pt.x, ht.pt.y);
+
   switch(hit)
   {
   case MCHT_TITLEBTNNEXT:
@@ -1535,12 +1576,13 @@ MONTHCAL_LButtonDown(MONTHCAL_INFO *infoPtr, LPARAM lParam)
     MONTHCAL_NotifySelect(infoPtr);
     return 0;
   }
+  case MCHT_CALENDARDATENEXT:
+  case MCHT_CALENDARDATEPREV:
   case MCHT_CALENDARDATE:
   {
-    TRACE("MCHT_CALENDARDATE\n");
-
     infoPtr->firstSelDay = ht.st.wDay;
     infoPtr->status = MC_SEL_LBUTDOWN;
+    MONTHCAL_SetDayFocus(infoPtr, &ht.st);
     return 0;
   }
   }
@@ -1570,6 +1612,8 @@ MONTHCAL_LButtonUp(MONTHCAL_INFO *infoPtr, LPARAM lParam)
     redraw = TRUE;
   }
 
+  ReleaseCapture();
+
   /* always send NM_RELEASEDCAPTURE notification */
   nmhdr.hwndFrom = infoPtr->hwndSelf;
   nmhdr.idFrom   = GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_ID);
@@ -1584,6 +1628,7 @@ MONTHCAL_LButtonUp(MONTHCAL_INFO *infoPtr, LPARAM lParam)
   hit = MONTHCAL_HitTest(infoPtr, &ht);
 
   infoPtr->status = MC_SEL_LBUTUP;
+  MONTHCAL_SetDayFocus(infoPtr, NULL);
 
   if((hit == MCHT_CALENDARDATENEXT) ||
      (hit == MCHT_CALENDARDATEPREV) ||
@@ -1646,7 +1691,8 @@ static LRESULT
 MONTHCAL_MouseMove(MONTHCAL_INFO *infoPtr, LPARAM lParam)
 {
   MCHITTESTINFO ht;
-  int oldselday, selday, hit;
+  SYSTEMTIME old_focused;
+  int selday, hit;
   RECT r;
 
   if(!(infoPtr->status & MC_SEL_LBUTDOWN)) return 0;
@@ -1659,12 +1705,17 @@ MONTHCAL_MouseMove(MONTHCAL_INFO *infoPtr, LPARAM lParam)
 
   /* not on the calendar date numbers? bail out */
   TRACE("hit:%x\n",hit);
-  if((hit & MCHT_CALENDARDATE) != MCHT_CALENDARDATE) return 0;
+  if((hit & MCHT_CALENDARDATE) != MCHT_CALENDARDATE)
+  {
+    MONTHCAL_SetDayFocus(infoPtr, NULL);
+    return 0;
+  }
 
   selday = ht.st.wDay;
-  oldselday = infoPtr->curSel.wDay;
-  infoPtr->curSel.wDay = selday;
-  MONTHCAL_CalcPosFromDay(infoPtr, selday, ht.st. wMonth, &r);
+  old_focused = infoPtr->focusedSel;
+  MONTHCAL_SetDayFocus(infoPtr, &ht.st);
+
+  MONTHCAL_CalcPosFromDay(infoPtr, ht.st.wDay, ht.st.wMonth, &r);
 
   if(infoPtr->dwStyle & MCS_MULTISELECT)  {
     SYSTEMTIME selArray[2];
@@ -1709,7 +1760,7 @@ done:
   /* only redraw if the currently selected day changed */
   /* FIXME: this should specify a rectangle containing only the days that changed */
   /* using InvalidateRect */
-  if(oldselday != infoPtr->curSel.wDay)
+  if(!MONTHCAL_IsDateEqual(&old_focused, &infoPtr->focusedSel))
     InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
 
   return 0;
-- 
1.5.6.5


--=-qucft4puV4axkxAC51K1--




More information about the wine-patches mailing list