DateTime and MonthCal control fixes

Krzysztof Foltman kfoltman at portal.onet.pl
Mon Apr 19 16:10:58 CDT 2004


This is my first Wine patch. It's supposed to fix a few bugs in Date 
Time and Month Calendar controls. Most of changes are related to 
interaction between date picker and the embedded (dropdown) calendar, 
which is why I sent one patch and not two.

Changes in datetime:
- make monthcal a child of datetime (it was a sibling before, causing 
completely incorrect message flow)
- update monthcal after date change in datetime
- choose different coordinates when DTS_SHOWNONE is not used
- embedded monthcal is now 200 pixels wide (about same width as on my 
Windows machine, looks definitely better; I'm not sure if it should be a 
fixed constant or it should be calculated from font size)
- selecting a day in embedded monthcal updates the datetime and hides 
the monthcal
- changing months/years by clicking month name/year in title bar works
- embedded month calendar is correctly destroyed (it used to stick on 
the screen long after the datetime's container was closed)

Changes in monthcal:
- next/prev month don't stick anymore
- min/max ranges initialized to some reasonable values
- fixed some bugs caused by reversed order of arguments of MONTHCAL_CopyTime
- update current month/year after setting current date
- changing months etc doesn't send MCN_SELECT (which could be sent only 
after a particular day was click)
- changed (hit && MCHT_CALENDARDATE) to (hit == MCHT_CALENDARDATE) - the 
former looks too much like a bug in this context (testing bit flags with 
&& ? can't be right) - and behaves like a bug too

Known bugs made/left:
- Implementation still incomplete (there's at least one unhandled MCN_ 
value), however, it's complete enough for some Polish accounting program 
I need to have running ;-)
- I didn't check correctness of min/max range behaviour yet (don't even 
know if they're implemented)
- default min/max date ranges don't have proper month&day set (OK, I'm 
lazy and don't care about 'em as long as they're half-decent)

I hope you'll like 'em :-)

Krzysztof

-------------- next part --------------
Index: datetime.c
===================================================================
RCS file: /home/wine/wine/dlls/comctl32/datetime.c,v
retrieving revision 1.42
diff -u -r1.42 datetime.c
--- datetime.c	20 Nov 2003 22:04:14 -0000	1.42
+++ datetime.c	19 Apr 2004 20:52:20 -0000
@@ -148,13 +148,14 @@
   TRACE("%p %04x %08lx\n",hwnd, wParam, lParam);
   if (!lParam) return 0;
 
-  TRACE("%04d/%02d/%02d %02d:%02d:%02d)\n",
+  TRACE("%04d/%02d/%02d %02d:%02d:%02d\n",
         lprgSysTimeArray->wYear, lprgSysTimeArray->wMonth, lprgSysTimeArray->wDay,
         lprgSysTimeArray->wHour, lprgSysTimeArray->wMinute, lprgSysTimeArray->wSecond);
 
   if (wParam==GDT_VALID) {
       infoPtr->dateValid = TRUE;
       MONTHCAL_CopyTime (lprgSysTimeArray, &infoPtr->date);
+	SendMessageA(infoPtr->hMonthCal, MCM_SETCURSEL, 0, (LPARAM)(&infoPtr->date));
       SendMessageA (infoPtr->hwndCheckbut, BM_SETCHECK, BST_CHECKED, 0);
   } else if (wParam==GDT_NONE) {
       infoPtr->dateValid = FALSE;
@@ -784,8 +785,10 @@
     GetTextExtentPoint32A (hdc, txt, strlen (txt), &size);
     rcDraw->bottom = size.cy+2;
 
-    if (dwStyle & DTS_SHOWNONE) checkbox->right = 18;
-
+    if (dwStyle & DTS_SHOWNONE)
+      checkbox->right = 18;
+    else
+      checkbox->right = 2;	 
     prevright = checkbox->right;
 
     for (i=0; i<infoPtr->nrFields; i++) {
@@ -882,19 +885,25 @@
     /* recalculate the position of the monthcal popup */
     if(dwStyle & DTS_RIGHTALIGN)
       infoPtr->monthcal_pos.x = infoPtr->rcClient.right - ((infoPtr->calbutton.right -
-                                infoPtr->calbutton.left) + 145);
+                                infoPtr->calbutton.left) + 200);
     else
       infoPtr->monthcal_pos.x = 8;
 
     infoPtr->monthcal_pos.y = infoPtr->rcClient.bottom;
     ClientToScreen (hwnd, &(infoPtr->monthcal_pos));
+    /* FIXME My Windoze has cx=about 200, but it probably depends on font size etc */
     SetWindowPos(infoPtr->hMonthCal, 0, infoPtr->monthcal_pos.x,
-        infoPtr->monthcal_pos.y, 145, 150, 0);
+        infoPtr->monthcal_pos.y, 200, 150, 0);
 
     if(IsWindowVisible(infoPtr->hMonthCal))
         ShowWindow(infoPtr->hMonthCal, SW_HIDE);
-    else
-        ShowWindow(infoPtr->hMonthCal, SW_SHOW);
+    else {
+      SYSTEMTIME *lprgSysTimeArray = &infoPtr->date;
+      TRACE("update calendar %04d/%02d/%02d\n", 
+        lprgSysTimeArray->wYear, lprgSysTimeArray->wMonth, lprgSysTimeArray->wDay);
+      SendMessageA(infoPtr->hMonthCal, MCM_SETCURSEL, 0, (LPARAM)(&infoPtr->date));
+      ShowWindow(infoPtr->hMonthCal, SW_SHOW);
+    }
 
     TRACE ("dt:%p mc:%p mc parent:%p, desktop:%p\n",
            hwnd, infoPtr->hMonthCal, infoPtr->hwndNotify, GetDesktopWindow ());
@@ -995,6 +1004,18 @@
  TRACE ("%x,%lx\n",wParam, lParam);
  TRACE ("Got notification %x from %p\n", lpnmh->code, lpnmh->hwndFrom);
  TRACE ("info: %p %p %p\n",hwnd,infoPtr->hMonthCal,infoPtr->hUpdown);
+
+ if (lpnmh->code==MCN_SELECT) {
+   NMSELCHANGE *psc = (NMSELCHANGE *)lpnmh;
+   ShowWindow(infoPtr->hMonthCal, SW_HIDE);
+   infoPtr->dateValid = TRUE;
+   SendMessageA (infoPtr->hMonthCal, MCM_GETCURSEL, 0, (LPARAM)&infoPtr->date);
+   TRACE("got from calendar %04d/%02d/%02d\n", 
+      infoPtr->date.wYear, infoPtr->date.wMonth, infoPtr->date.wDay);
+   SendMessageA (infoPtr->hwndCheckbut, BM_SETCHECK, BST_CHECKED, 0);
+   InvalidateRect(hwnd, NULL, TRUE);
+   DATETIME_SendDateTimeChangeNotify (hwnd);
+ }
  return 0;
 }
 
@@ -1232,7 +1253,7 @@
     infoPtr->hMonthCal = CreateWindowExA (0,"SysMonthCal32", 0,
 	WS_BORDER | WS_POPUP | WS_CLIPSIBLINGS,
 	0, 0, 0, 0,
-	infoPtr->hwndNotify,
+	hwnd,
 	0, 0, 0);
 
   /* initialize info structure */
@@ -1249,8 +1270,14 @@
     DATETIME_INFO *infoPtr = DATETIME_GetInfoPtr (hwnd);
 
     TRACE("\n");
+    if (infoPtr->hMonthCal) {
+	/* FIXME I don't completely understand why doesn't it
+	 *   happen automatically, WS_POPUP maybe? */
+        DestroyWindow(infoPtr->hMonthCal);
+	infoPtr->hMonthCal = NULL;
+    }
     Free (infoPtr);
-    SetWindowLongA( hwnd, 0, 0 );
+    SetWindowLongA( hwnd, 0, 0 ); /* clear infoPtr */
     return 0;
 }
 
Index: monthcal.c
===================================================================
RCS file: /home/wine/wine/dlls/comctl32/monthcal.c,v
retrieving revision 1.43
diff -u -r1.43 monthcal.c
--- monthcal.c	20 Nov 2003 22:04:14 -0000	1.43
+++ monthcal.c	19 Apr 2004 20:52:21 -0000
@@ -948,7 +948,7 @@
 MONTHCAL_SetRange(HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
   MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd);
-  SYSTEMTIME lprgSysTimeArray[1];
+  SYSTEMTIME *lprgSysTimeArray=(SYSTEMTIME *)lParam;
   int prev;
 
   TRACE("%x %lx\n", wParam, lParam);
@@ -1033,6 +1033,7 @@
   if(GetWindowLongA(hwnd, GWL_STYLE) & MCS_MULTISELECT) return FALSE;
 
   MONTHCAL_CopyTime(&infoPtr->minSel, lpSel);
+  TRACE("%d/%d/%d\n", lpSel->wYear, lpSel->wMonth, lpSel->wDay);
   return TRUE;
 }
 
@@ -1048,7 +1049,8 @@
   if((infoPtr==NULL) ||(lpSel==NULL)) return FALSE;
   if(GetWindowLongA(hwnd, GWL_STYLE) & MCS_MULTISELECT) return FALSE;
 
-  TRACE("%d %d\n", lpSel->wMonth, lpSel->wDay);
+  infoPtr->currentMonth=lpSel->wMonth;
+  infoPtr->currentYear=lpSel->wYear;
 
   MONTHCAL_CopyTime(lpSel, &infoPtr->minSel);
   MONTHCAL_CopyTime(lpSel, &infoPtr->maxSel);
@@ -1479,23 +1481,24 @@
     InvalidateRect(hwnd, NULL, FALSE);
     return TRUE;
   }
-  if(hit && MCHT_CALENDARDATE) {
+  if(hit == MCHT_CALENDARDATE) {
     SYSTEMTIME selArray[2];
     NMSELCHANGE nmsc;
 
+    MONTHCAL_CopyTime(&ht.st, &selArray[0]);
+    MONTHCAL_CopyTime(&ht.st, &selArray[1]);
+    MONTHCAL_SetSelRange(hwnd,0,(LPARAM) &selArray);
+    MONTHCAL_SetCurSel(hwnd,0,(LPARAM) &selArray);
     TRACE("MCHT_CALENDARDATE\n");
     nmsc.nmhdr.hwndFrom = hwnd;
     nmsc.nmhdr.idFrom   = GetWindowLongA(hwnd, GWL_ID);
     nmsc.nmhdr.code     = MCN_SELCHANGE;
-    MONTHCAL_CopyTime(&nmsc.stSelStart, &infoPtr->minSel);
-    MONTHCAL_CopyTime(&nmsc.stSelEnd, &infoPtr->maxSel);
+    MONTHCAL_CopyTime(&infoPtr->minSel,&nmsc.stSelStart);
+    MONTHCAL_CopyTime(&infoPtr->maxSel,&nmsc.stSelEnd);
 
     SendMessageA(infoPtr->hwndNotify, WM_NOTIFY,
            (WPARAM)nmsc.nmhdr.idFrom,(LPARAM)&nmsc);
 
-    MONTHCAL_CopyTime(&ht.st, &selArray[0]);
-    MONTHCAL_CopyTime(&ht.st, &selArray[1]);
-    MONTHCAL_SetSelRange(hwnd,0,(LPARAM) &selArray);
 
     /* redraw both old and new days if the selected day changed */
     if(infoPtr->curSelDay != ht.st.wDay) {
@@ -1530,10 +1533,12 @@
 
   if(infoPtr->status & MC_NEXTPRESSED) {
     KillTimer(hwnd, MC_NEXTMONTHTIMER);
+    infoPtr->status &= ~MC_NEXTPRESSED;
     redraw = TRUE;
   }
   if(infoPtr->status & MC_PREVPRESSED) {
     KillTimer(hwnd, MC_PREVMONTHTIMER);
+    infoPtr->status &= ~MC_PREVPRESSED;
     redraw = TRUE;
   }
 
@@ -1560,20 +1565,21 @@
 
   SendMessageA(infoPtr->hwndNotify, WM_NOTIFY,
                                 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
-
-  nmsc.nmhdr.hwndFrom = hwnd;
-  nmsc.nmhdr.idFrom   = GetWindowLongA(hwnd, GWL_ID);
-  nmsc.nmhdr.code     = MCN_SELECT;
-  MONTHCAL_CopyTime(&nmsc.stSelStart, &infoPtr->minSel);
-  MONTHCAL_CopyTime(&nmsc.stSelEnd, &infoPtr->maxSel);
-
-  SendMessageA(infoPtr->hwndNotify, WM_NOTIFY,
-           (WPARAM)nmsc.nmhdr.idFrom, (LPARAM)&nmsc);
-
   /* redraw if necessary */
   if(redraw)
     InvalidateRect(hwnd, NULL, FALSE);
+  /* only send MCN_SELECT if currently displayed month's day was selected */
+  if(hit == MCHT_CALENDARDATE) {
+    nmsc.nmhdr.hwndFrom = hwnd;
+    nmsc.nmhdr.idFrom   = GetWindowLongA(hwnd, GWL_ID);
+    nmsc.nmhdr.code     = MCN_SELECT;
+    MONTHCAL_CopyTime(&infoPtr->minSel, &nmsc.stSelStart);
+    MONTHCAL_CopyTime(&infoPtr->maxSel, &nmsc.stSelEnd);
 
+    SendMessageA(infoPtr->hwndNotify, WM_NOTIFY,
+             (WPARAM)nmsc.nmhdr.idFrom, (LPARAM)&nmsc);
+
+  }
   return 0;
 }
 
@@ -1898,6 +1904,8 @@
   infoPtr->currentYear = infoPtr->todaysDate.wYear;
   MONTHCAL_CopyTime(&infoPtr->todaysDate, &infoPtr->minDate);
   MONTHCAL_CopyTime(&infoPtr->todaysDate, &infoPtr->maxDate);
+  infoPtr->maxDate.wYear=2050;
+  infoPtr->minDate.wYear=1950;
   infoPtr->maxSelCount  = 7;
   infoPtr->monthRange = 3;
   infoPtr->monthdayState = Alloc


More information about the wine-patches mailing list