Changeset 496 for trunk/src/comctl32/monthcal.c
- Timestamp:
- Aug 14, 1999, 6:13:16 PM (26 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/comctl32/monthcal.c
r94 r496 1 /* $Id: monthcal.c,v 1.3 1999-06-10 16:22:01 achimha Exp $ */ 2 /* 3 * Month calendar control 1 2 /* Month calendar control 3 4 4 5 * 5 * Copyright 1998, 1999 Eric Kohl 6 * Copyright 1999 Achim Hasenmueller 7 * 8 * NOTES 9 * This is just a dummy control. An author is needed! Any volunteers? 10 * I will only improve this control once in a while. 11 * Eric <ekohl@abo.rhein-zeitung.de> 6 * Copyright 1998, 1999 Eric Kohl (ekohl@abo.rhein-zeitung.de) 7 * Copyright 1999 Alex Priem (alexp@sci.kun.nl) 8 * Copyright 1999 Christoph Bratschi 12 9 * 13 10 * TODO: 14 * - All messages. 15 * - All notifications. 11 * - Notifications. 16 12 * 13 * 14 * FIXME: refresh should ask for rect of required length. (?) 15 * FIXME: we refresh to often; especially in LButtonDown/MouseMove. 16 * FIXME: handle resources better (doesn't work now); also take care 17 of internationalization. 18 * FIXME: keyboard handling. 17 19 */ 18 20 19 21 #include "winbase.h" 22 #include "win.h" 20 23 #include "commctrl.h" 24 #include "comctl32.h" 21 25 #include "monthcal.h" 22 26 #include "winnls.h" 27 #include <stdio.h> 28 #include <string.h> 29 #include <stdlib.h> 30 31 //DEFAULT_DEBUG_CHANNEL(monthcal) 32 33 /* take #days/month from ole/parsedt.c; 34 * we want full month-names, and abbreviated weekdays, so these are 35 * defined here */ 23 36 24 37 #define MONTHCAL_GetInfoPtr(hwnd) ((MONTHCAL_INFO *)GetWindowLongA (hwnd, 0)) 25 38 26 27 28 39 /* helper functions 40 * MONTHCAL_ValidateTime: is time a valid date/time combo? 41 */ 42 43 int mdays[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0}; 44 45 int DayOfWeekTable[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; 46 47 static char *daytxt[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" }; 48 49 static char *monthtxt[] = {"January", "February", "March", "April", "May", 50 "June", "July", "August", "September", "October", 51 "November", "December"}; 52 53 /* CHECKME: all these validations OK? */ 54 55 static int MONTHCAL_ValidateTime (SYSTEMTIME time) 56 57 { 58 if (time.wMonth > 12) return FALSE; 59 if (time.wDayOfWeek > 6) return FALSE; 60 if (time.wDay > mdays[time.wMonth]) return FALSE; 61 if (time.wMonth > 23) return FALSE; 62 if (time.wMinute > 60) return FALSE; 63 if (time.wSecond > 60) return FALSE; 64 if (time.wMilliseconds > 100) return FALSE; 65 return TRUE; 66 } 67 68 void MONTHCAL_CopyTime (const SYSTEMTIME *from, SYSTEMTIME *to) 69 70 { 71 to->wYear=from->wYear; 72 to->wMonth=from->wMonth; 73 to->wDayOfWeek=from->wDayOfWeek; 74 to->wDay=from->wDay; 75 to->wHour=from->wHour; 76 to->wMinute=from->wMinute; 77 to->wSecond=from->wSecond; 78 to->wMilliseconds=from->wMilliseconds; 79 } 80 81 82 /* Note:Depending on DST, this may be offset by a day. 83 Need to find out if we're on a DST place & adjust the clock accordingly. 84 Above function assumes we have a valid data. 85 Valid for year>1752; d <= 1 <= 31, 1 <= m <= 12. 86 0=Monday. 87 */ 88 89 90 int MONTHCAL_CalculateDayOfWeek (DWORD day, DWORD month, DWORD year) 91 92 { 93 year -= month < 3; 94 return (year + year/4 - year/100 + year/400 + 95 DayOfWeekTable[month-1] + day - 1 ) % 7; 96 } 97 98 99 static int MONTHCAL_CalcDayFromPos (MONTHCAL_INFO *infoPtr, int x, int y) 100 101 { 102 int daypos,weekpos,retval,firstDay; 103 104 daypos=(x - infoPtr->prevmonth.left) / infoPtr->textWidth ; 105 weekpos=(y - infoPtr->days.bottom - infoPtr->rcClient.top) / 106 (infoPtr->textHeight*1.25); 107 firstDay=MONTHCAL_CalculateDayOfWeek (1,infoPtr->currentMonth,infoPtr->currentYear); 108 retval=daypos + 7*weekpos - firstDay; 109 //TRACE ("%d %d %d\n",daypos,weekpos,retval); 110 return retval; 111 } 112 113 114 static void MONTHCAL_CalcDayXY (MONTHCAL_INFO *infoPtr, int day, int month, 115 int *x, int *y) 116 117 { 118 int firstDay,prevMonth; 119 120 firstDay=MONTHCAL_CalculateDayOfWeek (1,infoPtr->currentMonth,infoPtr->currentYear); 121 122 if (month==infoPtr->currentMonth) { 123 *x=(day+firstDay) & 7; 124 *y=(day+firstDay-*x) / 7; 125 return; 126 } 127 if (month < infoPtr->currentMonth) { 128 prevMonth=month - 1; 129 if (prevMonth==0) prevMonth=11; 130 *x=(mdays[prevMonth]-firstDay) & 7; 131 *y=0; 132 } 133 134 *y=mdays[month] / 7; 135 *x=(day+firstDay+mdays[month]) & 7; 136 } 137 138 139 static void MONTHCAL_CalcDayRect (MONTHCAL_INFO *infoPtr, RECT *r, int x, int y) 140 { 141 r->left = infoPtr->prevmonth.left + x * infoPtr->textWidth; 142 r->right = r->left + infoPtr->textWidth; 143 r->top = infoPtr->rcClient.top + y * 1.25 * infoPtr->textHeight 144 + infoPtr->days.bottom; 145 r->bottom = r->top + infoPtr->textHeight; 146 147 } 148 149 static void MONTHCAL_CalcPosFromDay (MONTHCAL_INFO *infoPtr, 150 int day, int month, RECT *r) 151 152 { 153 int x,y; 154 155 MONTHCAL_CalcDayXY (infoPtr, day, month, &x, &y); 156 MONTHCAL_CalcDayRect (infoPtr, r, x, y); 157 } 158 159 160 161 162 static void MONTHCAL_CircleDay (HDC hdc, MONTHCAL_INFO *infoPtr, int i, int j) 163 164 { 165 HPEN hRedPen = CreatePen(PS_SOLID, 2, RGB (255,0,0) ); 166 HPEN hOldPen2 = SelectObject( hdc, hRedPen ); 167 POINT points[7]; 168 int x,y; 169 170 /* use prevmonth to calculate position because it contains the extra width 171 * from MCS_WEEKNUMBERS 172 */ 173 174 x=infoPtr->prevmonth.left + (i+0.5)*infoPtr->textWidth; 175 y=infoPtr->rcClient.top + 1.25*(j+0.5)*infoPtr->textHeight + infoPtr->days.bottom; 176 points[0].x = x; 177 points[0].y = y-0.25*infoPtr->textHeight; 178 points[1].x = x-1.0*infoPtr->textWidth; 179 points[1].y = y; 180 points[2].x = x; 181 points[2].y = y+0.6*infoPtr->textHeight; 182 points[3].x = x+0.5*infoPtr->textWidth; 183 points[3].y = y; 184 points[4].x = x+0.3*infoPtr->textWidth; 185 points[4].y = y-0.5*infoPtr->textHeight; 186 points[5].x = x-0.25*infoPtr->textWidth; 187 points[5].y = y-0.5*infoPtr->textHeight; 188 points[6].x = x-0.5*infoPtr->textWidth; 189 points[6].y = y-0.45*infoPtr->textHeight; 190 191 PolyBezier (hdc,points,4); 192 PolyBezier (hdc,points+3,4); 193 DeleteObject (hRedPen); 194 SelectObject (hdc, hOldPen2); 195 } 196 197 198 199 200 201 static void MONTHCAL_DrawDay (HDC hdc, MONTHCAL_INFO *infoPtr, 202 int day, int month, int x, int y, int bold) 203 204 { 205 char buf[10]; 206 RECT r; 207 static int haveBoldFont,haveSelectedDay=FALSE; 208 HBRUSH hbr; 209 COLORREF oldCol,oldBk; 210 211 sprintf (buf,"%d",day); 212 213 214 215 /* No need to check styles: when selection is not valid, it is set to zero. 216 * 1<day<31, so evertyhing's OK. 217 */ 218 219 MONTHCAL_CalcDayRect (infoPtr, &r, x, y); 220 221 if ((day>=infoPtr->minSel.wDay) && (day<=infoPtr->maxSel.wDay) 222 && (month==infoPtr->currentMonth)) { 223 HRGN hrgn; 224 RECT r2; 225 226 //TRACE ("%d %d %d\n",day,infoPtr->minSel.wDay,infoPtr->maxSel.wDay); 227 //TRACE ("%d %d %d %d\n", r.left, r.top, r.right, r.bottom); 228 oldCol=SetTextColor (hdc, infoPtr->monthbk); 229 oldBk=SetBkColor (hdc,infoPtr->trailingtxt); 230 hbr= GetSysColorBrush (COLOR_GRAYTEXT); 231 hrgn=CreateEllipticRgn (r.left,r.top, r.right,r.bottom); 232 FillRgn (hdc,hrgn,hbr); 233 234 r2.left = r.left-0.25*infoPtr->textWidth; 235 r2.top = r.top; 236 r2.right = r.left+0.5*infoPtr->textWidth; 237 r2.bottom = r.bottom; 238 if (haveSelectedDay) FillRect (hdc,&r2,hbr); 239 haveSelectedDay=TRUE; 240 } else { 241 haveSelectedDay=FALSE; 242 } 243 244 245 246 /* need to add some code for multiple selections */ 247 248 if ((bold) && (!haveBoldFont)) { 249 SelectObject (hdc, infoPtr->hBoldFont); 250 haveBoldFont=TRUE; 251 } 252 if ((!bold) && (haveBoldFont)) { 253 SelectObject (hdc, infoPtr->hFont); 254 haveBoldFont=FALSE; 255 } 256 257 258 259 DrawTextA ( hdc, buf, lstrlenA(buf), &r, 260 DT_CENTER | DT_VCENTER | DT_SINGLELINE ); 261 if (haveSelectedDay) { 262 SetTextColor(hdc, oldCol); 263 SetBkColor (hdc, oldBk); 264 } 265 266 if ((day==infoPtr->curSelDay) && (month==infoPtr->currentMonth)) { 267 HPEN hNewPen, hOldPen; 268 269 hNewPen = CreatePen(PS_DOT, 0, GetSysColor(COLOR_WINDOWTEXT) ); 270 hbr= GetSysColorBrush (COLOR_WINDOWTEXT); 271 hOldPen = SelectObject( hdc, hNewPen ); 272 r.left+=2; 273 r.right-=2; 274 r.top-=1; 275 r.bottom+=1; 276 FrameRect (hdc, &r, hbr); 277 SelectObject( hdc, hOldPen ); 278 } 279 } 280 281 282 /* CHECKME: For `todays date', do we need to check the locale?*/ 283 /* CHECKME: For `todays date', how do is Y2K handled?*/ 284 /* FIXME: todays date circle */ 285 286 static void MONTHCAL_Refresh (HWND hwnd, HDC hdc) 287 288 { 289 MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd); 290 RECT *rcClient=&infoPtr->rcClient; 291 RECT *title=&infoPtr->title; 292 RECT *prev=&infoPtr->titlebtnprev; 293 RECT *next=&infoPtr->titlebtnnext; 294 RECT *titlemonth=&infoPtr->titlemonth; 295 RECT *titleyear=&infoPtr->titleyear; 296 RECT *prevmonth=&infoPtr->prevmonth; 297 RECT *nextmonth=&infoPtr->nextmonth; 298 RECT *days=&infoPtr->days; 299 RECT *weeknums=&infoPtr->weeknums; 300 RECT *rtoday=&infoPtr->today; 301 int i,j,m,mask,day,firstDay, weeknum,prevMonth; 302 int textHeight,textWidth; 303 SIZE size; 304 HBRUSH hbr; 305 HFONT currentFont; 306 TEXTMETRICA tm; 307 /* LOGFONTA logFont; */ 308 char buf[20],*thisMonthtxt; 309 COLORREF oldTextColor,oldBkColor; 310 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE); 311 BOOL prssed; 312 313 314 oldTextColor = SetTextColor(hdc, GetSysColor( COLOR_WINDOWTEXT)); 315 316 currentFont = SelectObject (hdc, infoPtr->hFont); 317 318 /* FIXME: need a way to determine current font, without setting it */ 319 /* 320 if (infoPtr->hFont!=currentFont) { 321 SelectObject (hdc, currentFont); 322 infoPtr->hFont=currentFont; 323 GetObjectA (currentFont, sizeof (LOGFONTA), &logFont); 324 logFont.lfWeight=FW_BOLD; 325 infoPtr->hBoldFont = CreateFontIndirectA (&logFont); 326 } 327 */ 328 329 GetTextMetricsA (hdc, &tm); 330 infoPtr->textHeight=textHeight=tm.tmHeight + tm.tmExternalLeading; 331 GetTextExtentPoint32A (hdc, "Sun",3, &size); 332 infoPtr->textWidth=textWidth=size.cx+2; 333 334 GetClientRect (hwnd, rcClient); 335 hbr = CreateSolidBrush (RGB(255,255,255)); 336 DrawEdge (hdc, rcClient, EDGE_SUNKEN, BF_RECT | BF_ADJUST); 337 FillRect (hdc, rcClient, hbr); 338 DeleteObject (hbr); 339 340 /* calculate whole client area & title area */ 341 342 infoPtr->rcClient.right=7*infoPtr->textWidth; 343 if (dwStyle & MCS_WEEKNUMBERS) 344 infoPtr->rcClient.right+=infoPtr->textWidth; 345 346 title->top = rcClient->top + 1; 347 title->bottom = title->top + 2*textHeight + 4; 348 title->left = rcClient->left + 1; 349 title->right = rcClient->right - 1; 350 infoPtr->rcClient.bottom=title->bottom + 6*textHeight; 351 352 353 /* draw header */ 354 355 hbr = CreateSolidBrush (infoPtr->titlebk); 356 FillRect (hdc, title, hbr); 357 358 prev->top = next->top = title->top + 6; 359 prev->bottom = next->bottom = title->top + 2*textHeight - 3; 360 prev->right = title->left + 28; 361 prev->left = title->left + 4; 362 next->left = title->right - 28; 363 next->right = title->right - 4; 364 titlemonth->bottom= titleyear->bottom = prev->top + 2*textHeight - 3; 365 titlemonth->top = titleyear->top = title->top + 6; 366 titlemonth->left = title->left; 367 titlemonth->right = title->right; 368 prssed=FALSE; 369 370 if (!(infoPtr->status & MC_PREVPRESSED)) 371 DrawFrameControl(hdc, prev, DFC_SCROLL, 372 DFCS_SCROLLLEFT | (dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0) ); 373 374 if (!(infoPtr->status & MC_NEXTPRESSED)) 375 DrawFrameControl(hdc, next, DFC_SCROLL, 376 DFCS_SCROLLRIGHT | (dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0) ); 377 378 oldBkColor=SetBkColor (hdc,infoPtr->titlebk); 379 SetTextColor(hdc, infoPtr->titletxt); 380 SelectObject (hdc, infoPtr->hBoldFont); 381 382 thisMonthtxt=monthtxt[infoPtr->currentMonth - 1]; 383 sprintf (buf,"%s %ld",thisMonthtxt,infoPtr->currentYear); 384 DrawTextA ( hdc, buf, strlen(buf), titlemonth, 385 DT_CENTER | DT_VCENTER | DT_SINGLELINE ); 386 SelectObject (hdc, infoPtr->hFont); 387 388 /* titlemonth left/right contained rect for whole titletxt ('June 1999') 389 * MCM_HitTestInfo wants month & year rects, so prepare these now. 390 * (no, we can't draw them separately; the whole text is centered) 391 */ 392 393 GetTextExtentPoint32A (hdc, buf,lstrlenA (buf), &size); 394 titlemonth->left = title->right/2 - size.cx/2; 395 titleyear->right = title->right/2 + size.cx/2; 396 GetTextExtentPoint32A (hdc, thisMonthtxt,lstrlenA (thisMonthtxt), &size); 397 titlemonth->right= titlemonth->left+size.cx; 398 titleyear->right = titlemonth->right; 399 400 /* draw line under day abbreviatons */ 401 402 if (dwStyle & MCS_WEEKNUMBERS) 403 MoveToEx (hdc, rcClient->left+textWidth+3, 404 title->bottom + textHeight + 2, NULL); 405 else 406 MoveToEx (hdc, rcClient->left+3, title->bottom + textHeight + 2, NULL); 407 LineTo (hdc, rcClient->right-3, title->bottom + textHeight + 2); 408 409 /* draw day abbreviations */ 410 411 SetBkColor (hdc, infoPtr->monthbk); 412 SetTextColor(hdc, infoPtr->trailingtxt); 413 414 days->left = rcClient->left; 415 if (dwStyle & MCS_WEEKNUMBERS) days->left+=textWidth; 416 days->right = days->left + textWidth; 417 days->top = title->bottom + 2; 418 days->bottom = title->bottom + textHeight + 2; 419 i=infoPtr->firstDay; 420 421 for (j=0; j<7; j++) { 422 DrawTextA ( hdc, daytxt[i], strlen(daytxt[i]), days, 423 DT_CENTER | DT_VCENTER | DT_SINGLELINE ); 424 i++; 425 if (i>7) i-=7; 426 days->left+=textWidth; 427 days->right+=textWidth; 428 } 429 430 days->left = rcClient->left + j; 431 if (dwStyle & MCS_WEEKNUMBERS) days->left+=textWidth; 432 days->right = rcClient->left + (j+1)*textWidth-2; 433 434 /* draw day numbers; first, the previous month */ 435 436 prevmonth->left=0; 437 if (dwStyle & MCS_WEEKNUMBERS) prevmonth->left=textWidth; 438 439 firstDay=MONTHCAL_CalculateDayOfWeek (1,infoPtr->currentMonth,infoPtr->currentYear); 440 prevMonth=infoPtr->currentMonth-1; 441 if (prevMonth==0) prevMonth=11; 442 day=mdays[prevMonth]-firstDay; 443 mask=1<<(day-1); 444 445 i=0; 446 m=0; 447 while (day<=mdays[prevMonth]) { 448 MONTHCAL_DrawDay (hdc, infoPtr, day, prevMonth, i, 0, 449 infoPtr->monthdayState[m] & mask); 450 mask<<=1; 451 day++; 452 i++; 453 } 454 455 prevmonth->right = prevmonth->left+i*textWidth; 456 prevmonth->top = days->bottom; 457 prevmonth->bottom= prevmonth->top + textHeight; 458 459 /* draw `current' month */ 460 461 day=1; 462 infoPtr->firstDayplace=i; 463 SetTextColor(hdc, infoPtr->txt); 464 m++; 465 mask=1; 466 while (i<7) { 467 MONTHCAL_DrawDay (hdc, infoPtr, day, infoPtr->currentMonth, i, 0, 468 infoPtr->monthdayState[m] & mask); 469 if ((infoPtr->currentMonth==infoPtr->todaysDate.wMonth) && 470 (day==infoPtr->todaysDate.wDay)) 471 MONTHCAL_CircleDay (hdc, infoPtr, i,j); 472 mask<<=1; 473 day++; 474 i++; 475 } 476 477 j=1; 478 i=0; 479 while (day<=mdays[infoPtr->currentMonth]) { 480 MONTHCAL_DrawDay (hdc, infoPtr, day, infoPtr->currentMonth, i, j, 481 infoPtr->monthdayState[m] & mask); 482 if ((infoPtr->currentMonth==infoPtr->todaysDate.wMonth) && 483 (day==infoPtr->todaysDate.wDay)) 484 MONTHCAL_CircleDay (hdc, infoPtr, i,j); 485 mask<<=1; 486 day++; 487 i++; 488 if (i>6) { 489 i=0; 490 j++; 491 } 492 } 493 494 /* draw `next' month */ 495 496 /* note: the nextmonth rect only hints for the `half-week' that needs to be 497 * drawn to complete the current week. An eventual next week that needs to 498 * be drawn to complete the month calendar is not taken into account in 499 * this rect -- HitTest knows about this.*/ 500 501 502 503 nextmonth->left = prevmonth->left+i*textWidth; 504 nextmonth->right = rcClient->right; 505 nextmonth->top = days->bottom+(j+1)*textHeight; 506 nextmonth->bottom = nextmonth->top + textHeight; 507 508 day=1; 509 m++; 510 mask=1; 511 SetTextColor(hdc, infoPtr->trailingtxt); 512 while ((i<7) && (j<6)) { 513 MONTHCAL_DrawDay (hdc, infoPtr, day, infoPtr->currentMonth+1, i, j, 514 infoPtr->monthdayState[m] & mask); 515 mask<<=1; 516 day++; 517 i++; 518 if (i==7) { 519 i=0; 520 j++; 521 } 522 } 523 SetTextColor(hdc, infoPtr->txt); 524 525 526 527 /* draw `today' date if style allows it, and draw a circle before today's 528 * date if necessairy */ 529 530 if (!( dwStyle & MCS_NOTODAY)) { 531 int offset=0; 532 if (!( dwStyle & MCS_NOTODAYCIRCLE)) { 533 MONTHCAL_CircleDay (hdc, infoPtr, 0, 6); 534 offset+=textWidth; 535 } 536 537 MONTHCAL_CalcDayRect (infoPtr, rtoday, offset==textWidth, 6); 538 sprintf (buf,"Today: %d/%d/%d",infoPtr->todaysDate.wMonth, 539 infoPtr->todaysDate.wDay, infoPtr->todaysDate.wYear-1900); 540 rtoday->right = rcClient->right; 541 SelectObject (hdc, infoPtr->hBoldFont); 542 DrawTextA ( hdc, buf, lstrlenA(buf), rtoday, 543 DT_LEFT | DT_VCENTER | DT_SINGLELINE ); 544 SelectObject (hdc, infoPtr->hFont); 545 } 546 547 if (dwStyle & MCS_WEEKNUMBERS) { 548 /* display weeknumbers*/ 549 550 weeknums->left = 0; 551 weeknums->right = textWidth; 552 weeknums->top = days->bottom + 2; 553 weeknums->bottom = days->bottom + 2 + textHeight; 554 555 weeknum=0; 556 for (i=0; i<infoPtr->currentMonth-1; i++) 557 weeknum+=mdays[i]; 558 559 weeknum/=7; 560 for (i=0; i<6; i++) { 561 sprintf (buf,"%d",weeknum+i); 562 DrawTextA ( hdc, buf, lstrlenA(buf), weeknums, 563 DT_CENTER | DT_BOTTOM | DT_SINGLELINE ); 564 weeknums->top+=textHeight*1.25; 565 weeknums->bottom+=textHeight*1.25; 566 } 567 568 MoveToEx (hdc, weeknums->right, days->bottom+5 , NULL); 569 LineTo (hdc, weeknums->right, weeknums->bottom-1.25*textHeight-5); 570 571 } 572 573 /* currentFont was font at entering Refresh */ 574 575 SetBkColor (hdc, oldBkColor); 576 SelectObject (hdc, currentFont); 577 SetTextColor (hdc, oldTextColor); 578 } 579 580 581 static LRESULT 582 MONTHCAL_GetMinReqRect (HWND hwnd, WPARAM wParam, LPARAM lParam) 583 584 { 585 MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd); 586 LPRECT lpRect=(LPRECT) lParam; 587 //TRACE ("%x %lx\n",wParam,lParam); 588 589 /* validate parameters */ 590 591 if ( (infoPtr==NULL) || (lpRect == NULL) ) return FALSE; 592 593 lpRect->left=infoPtr->rcClient.left; 594 lpRect->right=infoPtr->rcClient.right; 595 lpRect->top=infoPtr->rcClient.top; 596 lpRect->bottom=infoPtr->rcClient.bottom; 597 return TRUE; 598 } 599 600 static LRESULT 601 MONTHCAL_GetColor (HWND hwnd, WPARAM wParam, LPARAM lParam) 602 603 { 604 MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd); 605 606 //TRACE ("%x %lx\n",wParam,lParam); 607 608 switch ((int)wParam) { 609 case MCSC_BACKGROUND: 610 return infoPtr->bk; 611 case MCSC_TEXT: 612 return infoPtr->txt; 613 case MCSC_TITLEBK: 614 return infoPtr->titlebk; 615 case MCSC_TITLETEXT: 616 return infoPtr->titletxt; 617 case MCSC_MONTHBK: 618 return infoPtr->monthbk; 619 case MCSC_TRAILINGTEXT: 620 return infoPtr->trailingtxt; 621 } 622 623 return -1; 624 } 625 626 static LRESULT 627 MONTHCAL_SetColor (HWND hwnd, WPARAM wParam, LPARAM lParam) 628 629 { 630 MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd); 631 int prev=-1; 632 633 //TRACE ("%x %lx\n",wParam,lParam); 634 635 switch ((int)wParam) { 636 case MCSC_BACKGROUND: 637 prev=infoPtr->bk; 638 infoPtr->bk=(COLORREF) lParam; 639 break; 640 case MCSC_TEXT: 641 prev=infoPtr->txt; 642 infoPtr->txt=(COLORREF) lParam; 643 break; 644 case MCSC_TITLEBK: 645 prev=infoPtr->titlebk; 646 infoPtr->titlebk=(COLORREF) lParam; 647 break; 648 case MCSC_TITLETEXT: 649 prev=infoPtr->titletxt; 650 infoPtr->titletxt=(COLORREF) lParam; 651 break; 652 case MCSC_MONTHBK: 653 prev=infoPtr->monthbk; 654 infoPtr->monthbk=(COLORREF) lParam; 655 break; 656 case MCSC_TRAILINGTEXT: 657 prev=infoPtr->trailingtxt; 658 infoPtr->trailingtxt=(COLORREF) lParam; 659 break; 660 } 661 662 return prev; 663 } 664 665 static LRESULT 666 MONTHCAL_GetMonthDelta (HWND hwnd, WPARAM wParam, LPARAM lParam) 667 668 { 669 MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd); 670 671 //TRACE ("%x %lx\n",wParam,lParam); 672 673 if (infoPtr->delta) return infoPtr->delta; 674 else return infoPtr->visible; 675 } 676 677 static LRESULT 678 MONTHCAL_SetMonthDelta (HWND hwnd, WPARAM wParam, LPARAM lParam) 679 680 { 681 MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd); 682 int prev=infoPtr->delta; 683 684 //TRACE ("%x %lx\n",wParam,lParam); 685 686 infoPtr->delta=(int) wParam; 687 return prev; 688 } 689 690 691 692 static LRESULT 693 MONTHCAL_GetFirstDayOfWeek (HWND hwnd, WPARAM wParam, LPARAM lParam) 694 { 695 MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd); 696 697 return infoPtr->firstDay; 698 } 699 700 /* FIXME: we need more error checking here */ 701 702 static LRESULT 703 MONTHCAL_SetFirstDayOfWeek (HWND hwnd, WPARAM wParam, LPARAM lParam) 704 705 { 706 MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd); 707 int prev=infoPtr->firstDay; 708 char buf[40]; 709 int day; 710 711 //TRACE ("%x %lx\n",wParam,lParam); 712 713 if ((lParam>=0) && (lParam<7)) { 714 infoPtr->firstDay=(int) lParam; 715 GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_IFIRSTDAYOFWEEK, 716 buf, sizeof(buf)); 717 //TRACE ("%s %d\n",buf,strlen(buf)); 718 if ((sscanf(buf,"%d",&day)==1) && (infoPtr->firstDay!=day)) 719 infoPtr->firstDay|=HIWORD(TRUE); 720 721 } 722 return prev; 723 } 724 725 726 727 /* FIXME: fill this in */ 728 729 static LRESULT 730 MONTHCAL_GetMonthRange (HWND hwnd, WPARAM wParam, LPARAM lParam) 731 { 732 MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd); 733 734 //TRACE ("%x %lx\n",wParam,lParam); 735 736 return infoPtr->monthRange; 737 } 738 739 static LRESULT 740 MONTHCAL_GetMaxTodayWidth (HWND hwnd) 741 742 { 743 MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd); 744 745 return (infoPtr->today.right-infoPtr->today.left); 746 } 747 748 /* FIXME: are validated times taken from current date/time or simply 749 * copied? 750 * FIXME: check whether MCM_GETMONTHRANGE shows correct result after 751 * adjusting range with MCM_SETRANGE 752 */ 753 754 static LRESULT 755 MONTHCAL_SetRange (HWND hwnd, WPARAM wParam, LPARAM lParam) 756 { 757 MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd); 758 SYSTEMTIME lprgSysTimeArray[1]; 759 int prev; 760 761 //TRACE ("%x %lx\n",wParam,lParam); 762 763 if (wParam & GDTR_MAX) { 764 if (MONTHCAL_ValidateTime(lprgSysTimeArray[1])){ 765 MONTHCAL_CopyTime (&lprgSysTimeArray[1],&infoPtr->maxDate); 766 infoPtr->rangeValid|=GDTR_MAX; 767 } else { 768 GetSystemTime (&infoPtr->todaysDate); 769 MONTHCAL_CopyTime (&infoPtr->todaysDate,&infoPtr->maxDate); 770 } 771 } 772 if (wParam & GDTR_MIN) { 773 if (MONTHCAL_ValidateTime(lprgSysTimeArray[0])) { 774 MONTHCAL_CopyTime (&lprgSysTimeArray[0],&infoPtr->maxDate); 775 infoPtr->rangeValid|=GDTR_MIN; 776 } else { 777 GetSystemTime (&infoPtr->todaysDate); 778 MONTHCAL_CopyTime (&infoPtr->todaysDate,&infoPtr->maxDate); 779 } 780 } 781 782 prev=infoPtr->monthRange; 783 infoPtr->monthRange=infoPtr->maxDate.wMonth-infoPtr->minDate.wMonth; 784 if (infoPtr->monthRange!=prev) 785 COMCTL32_ReAlloc (infoPtr->monthdayState, 786 infoPtr->monthRange*sizeof(MONTHDAYSTATE)); 787 788 return 1; 789 } 790 791 792 /* CHECKME: At the moment, we copy ranges anyway,regardless of 793 * infoPtr->rangeValid; a invalid range is simply filled with zeros in 794 * SetRange. Is this the right behavior? 795 */ 796 797 static LRESULT 798 MONTHCAL_GetRange (HWND hwnd, WPARAM wParam, LPARAM lParam) 799 { 800 MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd); 801 SYSTEMTIME *lprgSysTimeArray=(SYSTEMTIME *) lParam; 802 803 /* validate parameters */ 804 805 if ( (infoPtr==NULL) || (lprgSysTimeArray==NULL) ) return FALSE; 806 807 MONTHCAL_CopyTime (&infoPtr->maxDate,&lprgSysTimeArray[1]); 808 MONTHCAL_CopyTime (&infoPtr->minDate,&lprgSysTimeArray[0]); 809 810 return infoPtr->rangeValid; 811 } 812 813 static LRESULT 814 MONTHCAL_SetDayState (HWND hwnd, WPARAM wParam, LPARAM lParam) 815 816 { 817 MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd); 818 int i,iMonths=(int) wParam; 819 MONTHDAYSTATE *dayStates=(LPMONTHDAYSTATE) lParam; 820 821 //TRACE ("%x %lx\n",wParam,lParam); 822 if (iMonths!=infoPtr->monthRange) return 0; 823 824 for (i=0; i<iMonths; i++) 825 infoPtr->monthdayState[i]=dayStates[i]; 826 return 1; 827 } 828 829 static LRESULT 830 MONTHCAL_GetCurSel (HWND hwnd, WPARAM wParam, LPARAM lParam) 831 { 832 MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd); 833 SYSTEMTIME *lpSel=(SYSTEMTIME *) lParam; 834 835 //TRACE ("%x %lx\n",wParam,lParam); 836 if ( (infoPtr==NULL) || (lpSel==NULL) ) return FALSE; 837 if ( GetWindowLongA( hwnd, GWL_STYLE) & MCS_MULTISELECT) return FALSE; 838 839 MONTHCAL_CopyTime (&infoPtr->minSel,lpSel); 840 return TRUE; 841 } 842 843 844 /* FIXME: if the specified date is not visible, make it visible */ 845 /* FIXME: redraw? */ 846 847 static LRESULT 848 MONTHCAL_SetCurSel (HWND hwnd, WPARAM wParam, LPARAM lParam) 849 { 850 MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd); 851 SYSTEMTIME *lpSel=(SYSTEMTIME *) lParam; 852 853 //TRACE ("%x %lx\n",wParam,lParam); 854 if ( (infoPtr==NULL) || (lpSel==NULL) ) return FALSE; 855 if ( GetWindowLongA( hwnd, GWL_STYLE) & MCS_MULTISELECT) return FALSE; 856 857 //TRACE ("%d %d\n",lpSel->wMonth,lpSel->wDay); 858 859 MONTHCAL_CopyTime (lpSel,&infoPtr->minSel); 860 MONTHCAL_CopyTime (lpSel,&infoPtr->maxSel); 861 862 return TRUE; 863 } 864 865 static LRESULT 866 MONTHCAL_GetMaxSelCount (HWND hwnd, WPARAM wParam, LPARAM lParam) 867 { 868 MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd); 869 870 //TRACE ("%x %lx\n",wParam,lParam); 871 return infoPtr->maxSelCount; 872 } 873 874 static LRESULT 875 MONTHCAL_SetMaxSelCount (HWND hwnd, WPARAM wParam, LPARAM lParam) 876 { 877 MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd); 878 879 //TRACE ("%x %lx\n",wParam,lParam); 880 if ( GetWindowLongA( hwnd, GWL_STYLE) & MCS_MULTISELECT) { 881 infoPtr->maxSelCount=wParam; 882 } 883 884 return TRUE; 885 } 886 887 888 static LRESULT 889 MONTHCAL_GetSelRange (HWND hwnd, WPARAM wParam, LPARAM lParam) 890 { 891 MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd); 892 SYSTEMTIME *lprgSysTimeArray=(SYSTEMTIME *) lParam; 893 894 //TRACE ("%x %lx\n",wParam,lParam); 895 896 /* validate parameters */ 897 898 if ( (infoPtr==NULL) || (lprgSysTimeArray==NULL) ) return FALSE; 899 900 if ( GetWindowLongA( hwnd, GWL_STYLE) & MCS_MULTISELECT) { 901 MONTHCAL_CopyTime (&infoPtr->maxSel,&lprgSysTimeArray[1]); 902 MONTHCAL_CopyTime (&infoPtr->minSel,&lprgSysTimeArray[0]); 903 //TRACE ("[min,max]=[%d %d]\n",infoPtr->minSel.wDay,infoPtr->maxSel.wDay); 904 return TRUE; 905 } 906 907 return FALSE; 908 } 909 910 static LRESULT 911 MONTHCAL_SetSelRange (HWND hwnd, WPARAM wParam, LPARAM lParam) 912 { 913 MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd); 914 SYSTEMTIME *lprgSysTimeArray=(SYSTEMTIME *) lParam; 915 916 //TRACE ("%x %lx\n",wParam,lParam); 917 918 /* validate parameters */ 919 920 if ( (infoPtr==NULL) || (lprgSysTimeArray==NULL) ) return FALSE; 921 922 if ( GetWindowLongA( hwnd, GWL_STYLE) & MCS_MULTISELECT) { 923 MONTHCAL_CopyTime (&lprgSysTimeArray[1],&infoPtr->maxSel); 924 MONTHCAL_CopyTime (&lprgSysTimeArray[0],&infoPtr->minSel); 925 //TRACE ("[min,max]=[%d %d]\n",infoPtr->minSel.wDay,infoPtr->maxSel.wDay); 926 return TRUE; 927 } 928 929 return FALSE; 930 } 931 932 933 934 935 static LRESULT 936 MONTHCAL_GetToday (HWND hwnd, WPARAM wParam, LPARAM lParam) 937 { 938 MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd); 939 SYSTEMTIME *lpToday=(SYSTEMTIME *) lParam; 940 941 //TRACE ("%x %lx\n",wParam,lParam); 942 943 /* validate parameters */ 944 945 if ( (infoPtr==NULL) || (lpToday==NULL) ) return FALSE; 946 MONTHCAL_CopyTime (&infoPtr->todaysDate,lpToday); 947 return TRUE; 948 } 949 950 951 static LRESULT 952 MONTHCAL_SetToday (HWND hwnd, WPARAM wParam, LPARAM lParam) 953 { 954 MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd); 955 SYSTEMTIME *lpToday=(SYSTEMTIME *) lParam; 956 957 //TRACE ("%x %lx\n",wParam,lParam); 958 959 /* validate parameters */ 960 961 if ( (infoPtr==NULL) || (lpToday==NULL) ) return FALSE; 962 MONTHCAL_CopyTime (lpToday, &infoPtr->todaysDate); 963 return TRUE; 964 } 965 966 967 968 969 static LRESULT 970 MONTHCAL_HitTest (HWND hwnd, LPARAM lParam) 971 { 972 MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd); 973 PMCHITTESTINFO lpht=(PMCHITTESTINFO) lParam; 974 UINT x,y; 975 DWORD retval; 976 977 x=lpht->pt.x; 978 y=lpht->pt.y; 979 retval=MCHT_NOWHERE; 980 981 982 /* are we in the header? */ 983 984 if (PtInRect (&infoPtr->title, lpht->pt)) { 985 986 if (PtInRect (&infoPtr->titlebtnprev, lpht->pt)) { 987 retval=MCHT_TITLEBTNPREV; 988 goto done; 989 } 990 if (PtInRect (&infoPtr->titlebtnnext, lpht->pt)) { 991 retval=MCHT_TITLEBTNNEXT; 992 goto done; 993 } 994 if (PtInRect (&infoPtr->titlemonth, lpht->pt)) { 995 retval=MCHT_TITLEMONTH; 996 goto done; 997 } 998 if (PtInRect (&infoPtr->titleyear, lpht->pt)) { 999 retval=MCHT_TITLEYEAR; 1000 goto done; 1001 } 1002 retval=MCHT_TITLE; 1003 goto done; 1004 } 1005 1006 if (PtInRect (&infoPtr->days, lpht->pt)) { 1007 retval=MCHT_CALENDARDAY; /* FIXME: find out which day we're on */ 1008 goto done; 1009 } 1010 if (PtInRect (&infoPtr->weeknums, lpht->pt)) { 1011 retval=MCHT_CALENDARWEEKNUM;/* FIXME: find out which day we're on */ 1012 goto done; 1013 } 1014 if (PtInRect (&infoPtr->prevmonth, lpht->pt)) { 1015 retval=MCHT_CALENDARDATEPREV; 1016 goto done; 1017 } 1018 if (PtInRect (&infoPtr->nextmonth, lpht->pt) || 1019 ((x>infoPtr->nextmonth.left) && (x<infoPtr->nextmonth.right) && 1020 (y>infoPtr->nextmonth.bottom) && (y<infoPtr->today.top ))) { 1021 retval=MCHT_CALENDARDATENEXT; 1022 goto done; 1023 } 1024 1025 1026 if (PtInRect (&infoPtr->today, lpht->pt)) { 1027 retval=MCHT_TODAYLINK; 1028 goto done; 1029 } 1030 1031 /* MCHT_CALENDARDATE determination: since the next & previous month have 1032 * been handled already (MCHT_CALENDARDATEPREV/NEXT), we only have to check 1033 * whether we're in the calendar area. infoPtr->prevMonth.left handles the 1034 * MCS_WEEKNUMBERS style nicely. 1035 */ 1036 1037 1038 //TRACE ("%d %d [%d %d %d %d] [%d %d %d %d]\n",x,y, 1039 // infoPtr->prevmonth.left, infoPtr->prevmonth.right, 1040 // infoPtr->prevmonth.top, infoPtr->prevmonth.bottom, 1041 // infoPtr->nextmonth.left, infoPtr->nextmonth.right, 1042 // infoPtr->nextmonth.top, infoPtr->nextmonth.bottom); 1043 1044 if ((x>infoPtr->prevmonth.left) && (x<infoPtr->nextmonth.right) && 1045 (y>infoPtr->prevmonth.top) && (y<infoPtr->nextmonth.bottom)) { 1046 lpht->st.wYear=infoPtr->currentYear; 1047 lpht->st.wMonth=infoPtr->currentMonth; 1048 1049 lpht->st.wDay=MONTHCAL_CalcDayFromPos (infoPtr,x,y); 1050 1051 //TRACE ("day hit: %d\n",lpht->st.wDay); 1052 retval=MCHT_CALENDARDATE; 1053 goto done; 1054 1055 } 1056 1057 /* Hit nothing special? What's left must be background :-) */ 1058 1059 retval=MCHT_CALENDARBK; 1060 done: 1061 lpht->uHit=retval; 1062 return retval; 1063 } 1064 1065 1066 1067 static void MONTHCAL_GoToNextMonth (HWND hwnd, MONTHCAL_INFO *infoPtr) 1068 { 1069 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE); 1070 1071 //TRACE ("\n"); 1072 1073 infoPtr->currentMonth++; 1074 if (infoPtr->currentMonth>12) { 1075 infoPtr->currentYear++; 1076 infoPtr->currentMonth=1; 1077 } 1078 1079 if (dwStyle & MCS_DAYSTATE) { 1080 NMDAYSTATE nmds; 1081 int i; 1082 1083 nmds.nmhdr.hwndFrom = hwnd; 1084 nmds.nmhdr.idFrom = GetWindowLongA( hwnd, GWL_ID); 1085 nmds.nmhdr.code = MCN_GETDAYSTATE; 1086 nmds.cDayState = infoPtr->monthRange; 1087 nmds.prgDayState = COMCTL32_Alloc 1088 (infoPtr->monthRange*sizeof(MONTHDAYSTATE)); 1089 1090 SendMessageA (GetParent (hwnd), WM_NOTIFY, 1091 (WPARAM)nmds.nmhdr.idFrom, (LPARAM)&nmds); 1092 for (i=0; i<infoPtr->monthRange; i++) 1093 infoPtr->monthdayState[i]=nmds.prgDayState[i]; 1094 } 1095 1096 } 1097 1098 1099 static void MONTHCAL_GoToPrevMonth (HWND hwnd, MONTHCAL_INFO *infoPtr) 1100 { 1101 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE); 1102 1103 //TRACE ("\n"); 1104 1105 infoPtr->currentMonth--; 1106 if (infoPtr->currentMonth<1) { 1107 infoPtr->currentYear--; 1108 infoPtr->currentMonth=12; 1109 } 1110 1111 if (dwStyle & MCS_DAYSTATE) { 1112 NMDAYSTATE nmds; 1113 int i; 1114 1115 nmds.nmhdr.hwndFrom = hwnd; 1116 nmds.nmhdr.idFrom = GetWindowLongA( hwnd, GWL_ID); 1117 nmds.nmhdr.code = MCN_GETDAYSTATE; 1118 nmds.cDayState = infoPtr->monthRange; 1119 nmds.prgDayState = COMCTL32_Alloc 1120 (infoPtr->monthRange*sizeof(MONTHDAYSTATE)); 1121 1122 SendMessageA (GetParent (hwnd), WM_NOTIFY, 1123 (WPARAM)nmds.nmhdr.idFrom, (LPARAM)&nmds); 1124 for (i=0; i<infoPtr->monthRange; i++) 1125 infoPtr->monthdayState[i]=nmds.prgDayState[i]; 1126 } 1127 } 1128 1129 1130 static LRESULT 1131 MONTHCAL_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam) 1132 1133 { 1134 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr (hwnd); 1135 MCHITTESTINFO ht; 1136 HDC hdc; 1137 DWORD hit; 1138 HMENU hMenu; 1139 HWND retval; 1140 1141 1142 //TRACE ("%x %lx\n",wParam,lParam); 1143 1144 ht.pt.x = (INT)LOWORD(lParam); 1145 ht.pt.y = (INT)HIWORD(lParam); 1146 hit=MONTHCAL_HitTest (hwnd, (LPARAM) &ht); 1147 1148 hdc=GetDC (hwnd); 1149 1150 if (hit & MCHT_NEXT){ 1151 MONTHCAL_GoToNextMonth (hwnd, infoPtr); 1152 infoPtr->status=MC_NEXTPRESSED; 1153 SetTimer (hwnd, MC_NEXTMONTHTIMER, MC_NEXTMONTHDELAY,0); 1154 } 1155 if (hit & MCHT_PREV) { 1156 MONTHCAL_GoToPrevMonth (hwnd, infoPtr); 1157 infoPtr->status=MC_PREVPRESSED; 1158 SetTimer (hwnd, MC_PREVMONTHTIMER, MC_NEXTMONTHDELAY,0); 1159 } 1160 1161 if (hit == MCHT_TITLEMONTH) { 1162 /* 1163 HRSRC hrsrc = FindResourceA( COMCTL32_hModule, MAKEINTRESOURCEA(IDD_MCMONTHMENU), RT_MENUA ); 1164 if (!hrsrc) { 1165 TRACE ("returning zero\n"); 1166 return 0; 1167 } 1168 TRACE ("resource is:%x\n",hrsrc); 1169 hMenu=LoadMenuIndirectA( (LPCVOID)LoadResource( COMCTL32_hModule, hrsrc )); 1170 1171 TRACE ("menu is:%x\n",hMenu); 1172 */ 1173 1174 hMenu=CreateMenu (); 1175 AppendMenuA (hMenu,MF_STRING,IDM_JAN,"January"); 1176 AppendMenuA (hMenu,MF_STRING,IDM_FEB,"February"); 1177 AppendMenuA (hMenu,MF_STRING,IDM_MAR,"March"); 1178 1179 retval=CreateWindowA (POPUPMENU_CLASS_ATOM, NULL, 1180 WS_CHILD | WS_VISIBLE, 1181 0,0,100,220, 1182 hwnd, hMenu, GetWindowLongA (hwnd, GWL_HINSTANCE), NULL); 1183 //TRACE ("hwnd returned:%x\n",retval); 1184 1185 } 1186 if (hit == MCHT_TITLEYEAR) { 1187 //FIXME ("create updown for yearselection\n"); 1188 } 1189 if (hit == MCHT_TODAYLINK) { 1190 //FIXME ("set currentday\n"); 1191 } 1192 if (hit == MCHT_CALENDARDATE) { 1193 SYSTEMTIME selArray[2]; 1194 NMSELCHANGE nmsc; 1195 1196 //TRACE ("\n"); 1197 nmsc.nmhdr.hwndFrom = hwnd; 1198 nmsc.nmhdr.idFrom = GetWindowLongA( hwnd, GWL_ID); 1199 nmsc.nmhdr.code = MCN_SELCHANGE; 1200 MONTHCAL_CopyTime (&nmsc.stSelStart, &infoPtr->minSel); 1201 MONTHCAL_CopyTime (&nmsc.stSelEnd, &infoPtr->maxSel); 1202 1203 SendMessageA (GetParent (hwnd), WM_NOTIFY, 1204 (WPARAM)nmsc.nmhdr.idFrom, (LPARAM)&nmsc); 1205 1206 MONTHCAL_CopyTime (&ht.st, &selArray[0]); 1207 MONTHCAL_CopyTime (&ht.st, &selArray[1]); 1208 MONTHCAL_SetSelRange (hwnd,0,(LPARAM) &selArray); 1209 1210 infoPtr->firstSelDay=ht.st.wDay; 1211 infoPtr->curSelDay=ht.st.wDay; 1212 infoPtr->status=MC_SEL_LBUTDOWN; 1213 } 1214 1215 MONTHCAL_Refresh (hwnd,hdc); 1216 ReleaseDC (hwnd,hdc); 1217 return 0; 1218 } 1219 1220 static LRESULT 1221 MONTHCAL_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam) 1222 1223 { 1224 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr (hwnd); 1225 NMSELCHANGE nmsc; 1226 NMHDR nmhdr; 1227 HDC hdc; 1228 1229 //TRACE ("\n"); 1230 1231 if (infoPtr->status & MC_NEXTPRESSED) 1232 KillTimer (hwnd, MC_NEXTMONTHTIMER); 1233 if (infoPtr->status & MC_PREVPRESSED) 1234 KillTimer (hwnd, MC_PREVMONTHTIMER); 1235 infoPtr->status=MC_SEL_LBUTUP; 1236 infoPtr->curSelDay=0; 1237 1238 nmhdr.hwndFrom = hwnd; 1239 nmhdr.idFrom = GetWindowLongA( hwnd, GWL_ID); 1240 nmhdr.code = NM_RELEASEDCAPTURE; 1241 //TRACE ("Sent notification from %x to %x\n", hwnd, GetParent (hwnd)); 1242 1243 SendMessageA (GetParent (hwnd), WM_NOTIFY, 1244 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr); 1245 1246 nmsc.nmhdr.hwndFrom = hwnd; 1247 nmsc.nmhdr.idFrom = GetWindowLongA( hwnd, GWL_ID); 1248 nmsc.nmhdr.code = MCN_SELECT; 1249 MONTHCAL_CopyTime (&nmsc.stSelStart, &infoPtr->minSel); 1250 MONTHCAL_CopyTime (&nmsc.stSelEnd, &infoPtr->maxSel); 1251 1252 SendMessageA (GetParent (hwnd), WM_NOTIFY, 1253 (WPARAM)nmsc.nmhdr.idFrom, (LPARAM)&nmsc); 1254 1255 hdc=GetDC (hwnd); 1256 MONTHCAL_Refresh (hwnd,hdc); 1257 ReleaseDC (hwnd,hdc); 1258 1259 return 0; 1260 } 1261 1262 static LRESULT 1263 MONTHCAL_Timer (HWND hwnd, WPARAM wParam, LPARAM lParam) 1264 1265 { 1266 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr (hwnd); 1267 HDC hdc; 1268 1269 //TRACE(" %d\n",wParam); 1270 if (!infoPtr) return FALSE; 1271 1272 hdc=GetDC (hwnd); 1273 switch (wParam) { 1274 case MC_NEXTMONTHTIMER: 1275 MONTHCAL_GoToNextMonth (hwnd, infoPtr); 1276 break; 1277 case MC_PREVMONTHTIMER: 1278 MONTHCAL_GoToPrevMonth (hwnd, infoPtr); 1279 break; 1280 //default: 1281 //ERR("got unknown timer\n"); 1282 } 1283 1284 MONTHCAL_Refresh (hwnd,hdc); 1285 ReleaseDC (hwnd,hdc); 1286 return 0; 1287 } 1288 1289 1290 1291 static LRESULT 1292 MONTHCAL_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam) 1293 { 1294 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr (hwnd); 1295 MCHITTESTINFO ht; 1296 HDC hdc; 1297 int selday,hit; 1298 RECT r; 1299 1300 if (!(infoPtr->status & MC_SEL_LBUTDOWN)) return 0; 1301 1302 ht.pt.x=LOWORD(lParam); 1303 ht.pt.y=HIWORD(lParam); 1304 1305 hit=MONTHCAL_HitTest (hwnd, (LPARAM) &ht); 1306 1307 /* not on the calendar date numbers? bail out */ 1308 //TRACE ("hit:%x\n",hit); 1309 if ((hit & MCHT_CALENDARDATE) !=MCHT_CALENDARDATE) return 0; 1310 1311 selday=ht.st.wDay; 1312 infoPtr->curSelDay=selday; 1313 MONTHCAL_CalcPosFromDay (infoPtr,selday,ht.st.wMonth,&r); 1314 1315 if ( GetWindowLongA( hwnd, GWL_STYLE) & MCS_MULTISELECT) { 1316 SYSTEMTIME selArray[2]; 1317 int i; 1318 1319 MONTHCAL_GetSelRange (hwnd,0,(LPARAM) &selArray); 1320 i=0; 1321 if (infoPtr->firstSelDay==selArray[0].wDay) i=1; 1322 //TRACE ("oldRange:%d %d %d %d\n",infoPtr->firstSelDay,selArray[0].wDay,selArray[1].wDay,i); 1323 if (infoPtr->firstSelDay==selArray[1].wDay) { 1324 /* 1st time we get here: selArray[0]=selArray[1]) */ 1325 /* if we're still at the first selected date, return */ 1326 if (infoPtr->firstSelDay==selday) goto done; 1327 1328 if (selday<infoPtr->firstSelDay) i=0; 1329 } 1330 1331 if (abs(infoPtr->firstSelDay - selday) >= infoPtr->maxSelCount) { 1332 if (selday>infoPtr->firstSelDay) 1333 selday=infoPtr->firstSelDay+infoPtr->maxSelCount; 1334 else 1335 selday=infoPtr->firstSelDay-infoPtr->maxSelCount; 1336 } 1337 1338 if (selArray[i].wDay!=selday) { 1339 1340 //TRACE ("newRange:%d %d %d %d\n",infoPtr->firstSelDay,selArray[0].wDay,selArray[1].wDay,i); 1341 1342 selArray[i].wDay=selday; 1343 1344 1345 if (selArray[0].wDay>selArray[1].wDay) { 1346 DWORD tempday; 1347 tempday=selArray[1].wDay; 1348 selArray[1].wDay=selArray[0].wDay; 1349 selArray[0].wDay=tempday; 1350 } 1351 1352 MONTHCAL_SetSelRange (hwnd,0,(LPARAM) &selArray); 1353 } 1354 } 1355 1356 done: 1357 1358 hdc=GetDC (hwnd); 1359 MONTHCAL_Refresh (hwnd, hdc); 1360 ReleaseDC (hwnd, hdc); 1361 1362 return 0; 1363 } 1364 1365 static LRESULT 1366 MONTHCAL_Paint (HWND hwnd, WPARAM wParam) 1367 { 1368 HDC hdc; 1369 PAINTSTRUCT ps; 1370 1371 hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam; 1372 MONTHCAL_Refresh (hwnd, hdc); 1373 if(!wParam) 1374 EndPaint (hwnd, &ps); 1375 return 0; 1376 } 1377 1378 static LRESULT 1379 MONTHCAL_KillFocus (HWND hwnd, WPARAM wParam, LPARAM lParam) 1380 { 1381 HDC hdc; 1382 1383 //TRACE ("\n"); 1384 1385 hdc = GetDC (hwnd); 1386 MONTHCAL_Refresh (hwnd, hdc); 1387 ReleaseDC (hwnd, hdc); 1388 InvalidateRect (hwnd, NULL, TRUE); 1389 1390 return 0; 1391 } 1392 1393 1394 static LRESULT 1395 MONTHCAL_SetFocus (HWND hwnd, WPARAM wParam, LPARAM lParam) 1396 { 1397 HDC hdc; 1398 1399 //TRACE ("\n"); 1400 1401 hdc = GetDC (hwnd); 1402 MONTHCAL_Refresh (hwnd, hdc); 1403 ReleaseDC (hwnd, hdc); 1404 1405 return 0; 1406 } 1407 1408 1409 /* FIXME: check whether dateMin/dateMax need to be adjusted. */ 29 1410 30 1411 … … 33 1414 { 34 1415 MONTHCAL_INFO *infoPtr; 1416 LOGFONTA logFont; 35 1417 36 1418 /* allocate memory for info structure */ … … 38 1420 SetWindowLongA (hwnd, 0, (DWORD)infoPtr); 39 1421 1422 if (infoPtr == NULL) { 1423 //ERR ( "could not allocate info memory!\n"); 1424 return 0; 1425 } 1426 if ((MONTHCAL_INFO*) GetWindowLongA( hwnd, 0) != infoPtr) { 1427 //ERR ( "pointer assignment error!\n"); 1428 return 0; 1429 } 1430 1431 1432 infoPtr->hFont=GetStockObject(DEFAULT_GUI_FONT); 1433 GetObjectA (infoPtr->hFont, sizeof (LOGFONTA), &logFont); 1434 logFont.lfWeight=FW_BOLD; 1435 infoPtr->hBoldFont = CreateFontIndirectA (&logFont); 40 1436 41 1437 /* initialize info structure */ 42 43 1438 /* FIXME: calculate systemtime ->> localtime (substract timezoneinfo) */ 1439 1440 GetSystemTime (&infoPtr->todaysDate); 1441 infoPtr->firstDay = 0; 1442 infoPtr->currentMonth = infoPtr->todaysDate.wMonth; 1443 infoPtr->currentYear= infoPtr->todaysDate.wYear; 1444 MONTHCAL_CopyTime (&infoPtr->todaysDate,&infoPtr->minDate); 1445 MONTHCAL_CopyTime (&infoPtr->todaysDate,&infoPtr->maxDate); 1446 infoPtr->maxSelCount=6; 1447 infoPtr->monthRange=3; 1448 infoPtr->monthdayState=COMCTL32_Alloc 1449 (infoPtr->monthRange*sizeof(MONTHDAYSTATE)); 1450 infoPtr->titlebk = GetSysColor (COLOR_GRAYTEXT); 1451 infoPtr->titletxt = GetSysColor (COLOR_WINDOW); 1452 infoPtr->monthbk = GetSysColor (COLOR_WINDOW); 1453 infoPtr->trailingtxt = GetSysColor (COLOR_GRAYTEXT); 1454 infoPtr->bk = GetSysColor (COLOR_WINDOW); 1455 infoPtr->txt = GetSysColor (COLOR_WINDOWTEXT); 44 1456 45 1457 return 0; … … 52 1464 MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr (hwnd); 53 1465 54 55 56 57 58 59 /* free ipaddress info data */ 1466 /* free month calendar info data */ 60 1467 COMCTL32_Free (infoPtr); 61 1468 … … 65 1472 66 1473 67 68 LRESULT WINAPI 1474 static LRESULT WINAPI 69 1475 MONTHCAL_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 70 1476 { 1477 71 1478 switch (uMsg) 72 1479 { 73 1480 74 75 case WM_CREATE: 76 return MONTHCAL_Create (hwnd, wParam, lParam); 77 78 case WM_DESTROY: 79 return MONTHCAL_Destroy (hwnd, wParam, lParam); 80 81 default: 82 // if (uMsg >= WM_USER) 83 // ERR (monthcal, "unknown msg %04x wp=%08x lp=%08lx\n", 84 // uMsg, wParam, lParam); 85 return DefWindowProcA (hwnd, uMsg, wParam, lParam); 1481 case MCM_GETCURSEL: 1482 return MONTHCAL_GetCurSel (hwnd, wParam, lParam); 1483 1484 case MCM_SETCURSEL: 1485 return MONTHCAL_SetCurSel (hwnd, wParam, lParam); 1486 1487 case MCM_GETMAXSELCOUNT: 1488 return MONTHCAL_GetMaxSelCount (hwnd, wParam, lParam); 1489 1490 case MCM_SETMAXSELCOUNT: 1491 return MONTHCAL_SetMaxSelCount (hwnd, wParam, lParam); 1492 1493 case MCM_GETSELRANGE: 1494 return MONTHCAL_GetSelRange (hwnd, wParam, lParam); 1495 1496 case MCM_SETSELRANGE: 1497 return MONTHCAL_SetSelRange (hwnd, wParam, lParam); 1498 1499 case MCM_GETMONTHRANGE: 1500 return MONTHCAL_GetMonthRange (hwnd, wParam, lParam); 1501 1502 case MCM_SETDAYSTATE: 1503 return MONTHCAL_SetDayState (hwnd, wParam, lParam); 1504 1505 case MCM_GETMINREQRECT: 1506 return MONTHCAL_GetMinReqRect (hwnd, wParam, lParam); 1507 1508 case MCM_GETCOLOR: 1509 return MONTHCAL_GetColor (hwnd, wParam, lParam); 1510 1511 case MCM_SETCOLOR: 1512 return MONTHCAL_SetColor (hwnd, wParam, lParam); 1513 1514 case MCM_GETTODAY: 1515 return MONTHCAL_GetToday (hwnd, wParam, lParam); 1516 1517 case MCM_SETTODAY: 1518 return MONTHCAL_SetToday (hwnd, wParam, lParam); 1519 1520 case MCM_HITTEST: 1521 return MONTHCAL_HitTest (hwnd,lParam); 1522 1523 case MCM_GETFIRSTDAYOFWEEK: 1524 return MONTHCAL_GetFirstDayOfWeek (hwnd, wParam, lParam); 1525 1526 case MCM_SETFIRSTDAYOFWEEK: 1527 return MONTHCAL_SetFirstDayOfWeek (hwnd, wParam, lParam); 1528 1529 case MCM_GETRANGE: 1530 return MONTHCAL_GetRange (hwnd, wParam, lParam); 1531 1532 case MCM_SETRANGE: 1533 return MONTHCAL_SetRange (hwnd, wParam, lParam); 1534 1535 case MCM_GETMONTHDELTA: 1536 return MONTHCAL_GetMonthDelta (hwnd, wParam, lParam); 1537 1538 case MCM_SETMONTHDELTA: 1539 return MONTHCAL_SetMonthDelta (hwnd, wParam, lParam); 1540 1541 case MCM_GETMAXTODAYWIDTH: 1542 return MONTHCAL_GetMaxTodayWidth (hwnd); 1543 1544 case WM_GETDLGCODE: 1545 return DLGC_WANTARROWS | DLGC_WANTCHARS; 1546 1547 case WM_KILLFOCUS: 1548 return MONTHCAL_KillFocus (hwnd, wParam, lParam); 1549 1550 case WM_LBUTTONDOWN: 1551 return MONTHCAL_LButtonDown (hwnd, wParam, lParam); 1552 1553 case WM_MOUSEMOVE: 1554 return MONTHCAL_MouseMove (hwnd, wParam, lParam); 1555 1556 case WM_LBUTTONUP: 1557 return MONTHCAL_LButtonUp (hwnd, wParam, lParam); 1558 1559 case WM_PAINT: 1560 return MONTHCAL_Paint (hwnd, wParam); 1561 1562 case WM_SETFOCUS: 1563 return MONTHCAL_SetFocus (hwnd, wParam, lParam); 1564 1565 case WM_CREATE: 1566 return MONTHCAL_Create (hwnd, wParam, lParam); 1567 1568 case WM_TIMER: 1569 return MONTHCAL_Timer (hwnd, wParam, lParam); 1570 1571 case WM_DESTROY: 1572 return MONTHCAL_Destroy (hwnd, wParam, lParam); 1573 1574 default: 1575 //if (uMsg >= WM_USER) 1576 // ERR ( "unknown msg %04x wp=%08x lp=%08lx\n", 1577 // uMsg, wParam, lParam); 1578 return DefWindowProcA (hwnd, uMsg, wParam, lParam); 86 1579 } 87 1580 return 0; … … 89 1582 90 1583 91 VOID 92 MONTHCAL_Register ( VOID)1584 void 1585 MONTHCAL_Register (void) 93 1586 { 94 1587 WNDCLASSA wndClass; … … 104 1597 wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 105 1598 wndClass.lpszClassName = MONTHCAL_CLASSA; 106 1599 107 1600 RegisterClassA (&wndClass); 108 1601 } 109 1602 110 1603 111 VOID 112 MONTHCAL_Unregister ( VOID)1604 void 1605 MONTHCAL_Unregister (void) 113 1606 { 114 1607 if (GlobalFindAtomA (MONTHCAL_CLASSA)) 115 116 } 117 1608 UnregisterClassA (MONTHCAL_CLASSA, (HINSTANCE)NULL); 1609 } 1610
Note:
See TracChangeset
for help on using the changeset viewer.