home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / Basic / Visual Basic.60 / COMMON / TOOLS / VB / OLEMSG / CAL.FRM (.txt) < prev    next >
Encoding:
Visual Basic Form  |  1996-06-15  |  31.3 KB  |  751 lines

  1. VERSION 5.00
  2. Begin VB.Form frmCalender 
  3.    BackColor       =   &H00C0C0C0&
  4.    Caption         =   "Calendar"
  5.    ClientHeight    =   4830
  6.    ClientLeft      =   885
  7.    ClientTop       =   1245
  8.    ClientWidth     =   4230
  9.    ClipControls    =   0   'False
  10.    FillColor       =   &H00FFFFFF&
  11.    ForeColor       =   &H00000000&
  12.    Height          =   5235
  13.    KeyPreview      =   -1  'True
  14.    Left            =   825
  15.    LinkTopic       =   "Form1"
  16.    ScaleHeight     =   3.354
  17.    ScaleMode       =   5  'Inch
  18.    ScaleWidth      =   2.937
  19.    Top             =   900
  20.    Width           =   4350
  21.    Begin VB.Frame fraCalender 
  22.       BackColor       =   &H00C0C0C0&
  23.       Caption         =   "Dates:"
  24.       Height          =   4335
  25.       Left            =   360
  26.       TabIndex        =   0
  27.       Top             =   360
  28.       Width           =   3615
  29.       Begin VB.PictureBox picWeekdays 
  30.          Appearance      =   0  'Flat
  31.          AutoRedraw      =   -1  'True
  32.          BackColor       =   &H00C0C0C0&
  33.          BorderStyle     =   0  'None
  34.          ForeColor       =   &H80000008&
  35.          Height          =   225
  36.          Left            =   120
  37.          ScaleHeight     =   225
  38.          ScaleWidth      =   2415
  39.          TabIndex        =   4
  40.          Top             =   600
  41.          Width           =   2415
  42.       End
  43.       Begin VB.PictureBox picCal 
  44.          Appearance      =   0  'Flat
  45.          AutoRedraw      =   -1  'True
  46.          BackColor       =   &H00C0C0C0&
  47.          BorderStyle     =   0  'None
  48.          ForeColor       =   &H80000008&
  49.          Height          =   1452
  50.          Left            =   120
  51.          ScaleHeight     =   1455
  52.          ScaleWidth      =   2415
  53.          TabIndex        =   3
  54.          Top             =   872
  55.          Width           =   2412
  56.       End
  57.       Begin VB.CommandButton cmdOK 
  58.          Caption         =   "&OK"
  59.          Default         =   -1  'True
  60.          Height          =   372
  61.          Left            =   120
  62.          TabIndex        =   2
  63.          Top             =   2760
  64.          Width           =   1092
  65.       End
  66.       Begin VB.CommandButton cmdCancel 
  67.          Cancel          =   -1  'True
  68.          Caption         =   "&Cancel"
  69.          Height          =   372
  70.          Left            =   1320
  71.          TabIndex        =   1
  72.          Top             =   2760
  73.          Width           =   1092
  74.       End
  75.       Begin VB.Line linDivider 
  76.          BorderColor     =   &H00FFFFFF&
  77.          Index           =   3
  78.          X1              =   120
  79.          X2              =   2640
  80.          Y1              =   2416
  81.          Y2              =   2416
  82.       End
  83.       Begin VB.Line linDivider 
  84.          BorderColor     =   &H00808080&
  85.          Index           =   2
  86.          X1              =   120
  87.          X2              =   2640
  88.          Y1              =   2400
  89.          Y2              =   2400
  90.       End
  91.       Begin VB.Line linDivider 
  92.          BorderColor     =   &H00FFFFFF&
  93.          Index           =   1
  94.          X1              =   120
  95.          X2              =   2640
  96.          Y1              =   856
  97.          Y2              =   856
  98.       End
  99.       Begin VB.Line linDivider 
  100.          BorderColor     =   &H00808080&
  101.          Index           =   0
  102.          X1              =   120
  103.          X2              =   2640
  104.          Y1              =   840
  105.          Y2              =   840
  106.       End
  107.       Begin VB.Label lblMonth 
  108.          Alignment       =   2  'Center
  109.          BackColor       =   &H00C0C0C0&
  110.          Caption         =   "Deciembre  1943"
  111.          BeginProperty Font 
  112.             Name            =   "MS Sans Serif"
  113.             Size            =   9.75
  114.             Charset         =   0
  115.             Weight          =   400
  116.             Underline       =   0   'False
  117.             Italic          =   0   'False
  118.             Strikethrough   =   0   'False
  119.          EndProperty
  120.          Height          =   240
  121.          Left            =   960
  122.          TabIndex        =   5
  123.          Top             =   240
  124.          Width           =   1812
  125.       End
  126.       Begin VB.Image picGoMonth 
  127.          Height          =   180
  128.          Index           =   1
  129.          Left            =   2880
  130.          Picture         =   "CAL.frx":0000
  131.          Top             =   300
  132.          Width           =   180
  133.       End
  134.       Begin VB.Image picGoMonth 
  135.          Height          =   180
  136.          Index           =   0
  137.          Left            =   600
  138.          Picture         =   "CAL.frx":04D2
  139.          Top             =   300
  140.          Width           =   180
  141.       End
  142.    End
  143. Attribute VB_Name = "frmCalender"
  144. Attribute VB_Base = "0{CFF16A29-C697-11CF-A520-00A0D1003923}"
  145. Attribute VB_GlobalNameSpace = False
  146. Attribute VB_Creatable = False
  147. Attribute VB_TemplateDerived = False
  148. Attribute VB_PredeclaredId = True
  149. Attribute VB_Exposed = False
  150. Attribute VB_Customizable = False
  151. Option Explicit
  152. Dim fDirty%
  153. Dim fRet As Boolean
  154. Const kfMultiselectDates = False  '** can multiple dates be selected at a time?
  155. Const kiDayIndexMax = 41    '** picCal displays 41 visible dates
  156. Private Type SingleDay       '** each visible date has info in a SingleDate rec
  157.     iTop As Integer
  158.     iLeft As Integer
  159.     lForeColor As Long      '** kBlack = current month; kDkGray = prev/next month
  160.     sCaption As String      '** date text ("1"-"31")
  161. End Type
  162. Dim gfrmCal As Form         '** form containing cal frame
  163. '** cal graphic-related vars
  164. Dim giCurYear%, giCurMonth%         '** current month/year visible
  165. Dim giDayWidth%, giDayHeight%       '** dimensions of the 41 visible dates
  166. Dim gsMonthes$(1 To 12)             '** stores month names
  167. Dim gaDays(0 To 41) As SingleDay    '** array of info on visible dates
  168. Dim giTodayIndex%           '** if current month visible then giTodayIndex is graphical inset
  169. Dim gfCreateNewCal%
  170. Dim fFirstClick%
  171. Dim gsUsername$
  172. '** cal date selection vars
  173. '** cal has two kinds of selections
  174. '**     main selection: made by click, shift-click, or drag
  175. '**     ctrl selections: made by ctrl-click
  176. Dim gdSelStart As Date   '** start of main selection block
  177. Dim gdSelEnd As Date     '** end of main selection block
  178. Dim gadCtrlSelect(0 To 100) As Date  '** array of current ctrl-clicked dates; erased on non-ctrl-mousedown
  179.                                         '** if date in main sel then non-selected, else then selected
  180. Dim giMaxCtrlSelectIndex As Integer  '** highest index of gadCtrlSelect in use; init to -1
  181. '** cal mouse vars
  182. Dim giLastSelIndex As Integer    '** last index selected by drag; used to validate MouseOver calls during drags
  183. Dim gdLastDateClicked As Date       '** last index clicked; used as next start for selection block
  184. Dim gfExitedGray%           '** after dragging over gray date to switch month, has mouse left gray dates on new month yet?
  185. '** colors used cal
  186. Const kLtGray = &HC0C0C0
  187. Const kDkGray = &H808080
  188. Const kBlack = &H0&
  189. Const kWhite = &HFFFFFF
  190. Const kBlue = &HFF0000
  191. Private Sub ClearOldSelection(ByVal dStartNew As Date, ByVal dEndNew As Date, ByVal dStartOld As Date, ByVal dEndOld As Date)
  192.     '** redraws all dates between dStartOld & dStartNew but not between dStartNew & dEndNew
  193.     '**     as unselected.
  194.     '** CalMousedown uses ClearOldSelection to deselect dates in the previous selection
  195.     '**     block that are not in the new selection block
  196.     Dim dTmp As Date        '** used as utility date
  197.     Dim dFirstDate As Date  '** first date vis in picCal; may be gray from previous month
  198.     Dim iIndex%             '** gaDay index to deselect
  199.     If dEndOld = 0 Or dStartOld = 0 Then Exit Sub
  200.     '** switch dStartNew with dEndNew if dStartNew is higher
  201.     If dStartNew > dEndNew Then
  202.         dTmp = dStartNew
  203.         dStartNew = dEndNew
  204.         dEndNew = dTmp
  205.     End If
  206.     '** switch dStartOld with dEndOld if dStartOld is higher
  207.     If dStartOld > dEndOld Then
  208.         dTmp = dStartOld
  209.         dStartOld = dEndOld
  210.         dEndOld = dTmp
  211.     End If
  212.     '** if dStartOld comes before the dates visible,
  213.     '** then set dStartOld to first date visible
  214.     If gaDays(0).lForeColor = kDkGray Then
  215.         dFirstDate = DateSerial(giCurYear, giCurMonth - 1, CInt(gaDays(0).sCaption))
  216.     Else
  217.         dFirstDate = DateSerial(giCurYear, giCurMonth, CInt(gaDays(0).sCaption))
  218.     End If
  219.     If dFirstDate > dStartOld Then dStartOld = dFirstDate
  220.     '** if dEndOld comes after the dates visible,
  221.     '** then set dEndOld to last date visible
  222.     If gaDays(kiDayIndexMax).lForeColor = kDkGray Then
  223.         dTmp = DateSerial(giCurYear, giCurMonth + 1, CInt(gaDays(kiDayIndexMax).sCaption))
  224.     Else
  225.         dTmp = DateSerial(giCurYear, giCurMonth, CInt(gaDays(kiDayIndexMax).sCaption))
  226.     End If
  227.     If dTmp < dEndOld Then dEndOld = dTmp
  228.     '** deselect all dates necessary
  229.     For dTmp = dStartOld To dEndOld
  230.         If dTmp < dStartNew Or dTmp > dEndNew Then
  231.             iIndex = dTmp - dFirstDate
  232.             DrawDay iIndex, kLtGray
  233.         End If
  234.     Next dTmp
  235. End Sub
  236. Private Sub DrawDay(ByVal iIndex%, ByVal lColor&)
  237.     Dim picCal As PictureBox '** vb4 workaround
  238.     Set picCal = gfrmCal!picCal
  239.     '** draws an individual day
  240.     '** draw background of day
  241.     '** lColor = kBlue if selected, ltGray if unselected
  242.     picCal.Line (gaDays(iIndex).iLeft, gaDays(iIndex).iTop)-(gaDays(iIndex).iLeft + giDayWidth - Screen.TwipsPerPixelX, gaDays(iIndex).iTop + giDayHeight - Screen.TwipsPerPixelY), lColor&, BF
  243.     '** if this day is today, inset in 3d
  244.     If iIndex = giTodayIndex Then
  245.         ThreeDRect picCal, gaDays(iIndex).iLeft + Screen.TwipsPerPixelX * 1, gaDays(iIndex).iTop + Screen.TwipsPerPixelY * 1, gaDays(iIndex).iLeft + giDayWidth - Screen.TwipsPerPixelX * 1, gaDays(iIndex).iTop + giDayHeight - Screen.TwipsPerPixelX * 1, True
  246.     End If
  247.     '** print the number of the day
  248.     picCal.CurrentX = (giDayWidth - picCal.TextWidth(gaDays(iIndex).sCaption)) / 2 + gaDays(iIndex).iLeft
  249.     picCal.CurrentY = (giDayHeight - picCal.TextHeight(gaDays(iIndex).sCaption)) / 2 + gaDays(iIndex).iTop
  250.     If lColor = kBlue And gaDays(iIndex).lForeColor <> kDkGray Then
  251.         picCal.ForeColor = kWhite '** if selected, kWhite
  252.     Else
  253.         picCal.ForeColor = gaDays(iIndex).lForeColor
  254.     End If
  255.     picCal.Print gaDays(iIndex).sCaption
  256. End Sub
  257. Private Sub fMoreGrayDates()
  258. End Sub
  259. Private Function fIsDateSelected%(ByVal iYear%, ByVal iMonth%, ByVal iDay%)
  260.     Dim dSrc As Date, i%
  261.     dSrc = DateSerial(iYear, iMonth, iDay)
  262.     If (dSrc <= gdSelEnd And dSrc >= gdSelStart) Or (dSrc >= gdSelEnd And dSrc <= gdSelStart) Then
  263.         fIsDateSelected = True
  264.     End If
  265.     For i = 0 To giMaxCtrlSelectIndex
  266.         If gadCtrlSelect(i) = dSrc Then
  267.             If fDateInBetween(gadCtrlSelect(i), gdSelStart, gdSelEnd) Then
  268.                 fIsDateSelected = False
  269.             Else
  270.                 fIsDateSelected = True
  271.             End If
  272.         End If
  273.     Next i
  274. End Function
  275. Private Sub InitCalControls()
  276.     Dim i%, sWeekdays$
  277.     Dim iOldScaleMode%, iOnePixelX%, iOnePixelY%
  278.     Dim iRow%, iColumn%
  279.     Dim picWeekdays As PictureBox '** vb4 workaround
  280.     Set picWeekdays = gfrmCal!picWeekdays
  281.     iOldScaleMode = gfrmCal.ScaleMode
  282.     gfrmCal.ScaleMode = 1
  283.     iOnePixelX = Screen.TwipsPerPixelX
  284.     iOnePixelY = Screen.TwipsPerPixelY
  285.     gfrmCal!lblMonth.Left = (gfrmCal!fraCalender.Width - gfrmCal!lblMonth.Width) / 2
  286.     gfrmCal!picGoMonth(0).Left = gfrmCal!lblMonth.Left - (gfrmCal!picGoMonth(0).Width + 3 * iOnePixelX)
  287.     gfrmCal!picGoMonth(1).Left = gfrmCal!lblMonth.Left + gfrmCal!lblMonth.Width + 3 * iOnePixelX
  288.     gfrmCal!cmdOK.Top = gfrmCal!fraCalender.Height - (8 * iOnePixelY + gfrmCal!cmdOK.Height)
  289.     gfrmCal!cmdCancel.Top = gfrmCal!fraCalender.Height - (8 * iOnePixelY + gfrmCal!cmdCancel.Height)
  290.     gfrmCal!picCal.Width = gfrmCal!fraCalender.Width - 16 * iOnePixelX
  291.     gfrmCal!picCal.Height = gfrmCal!cmdOK.Top - (gfrmCal!picCal.Top) - 10 * iOnePixelY
  292.     giDayHeight = gfrmCal!picCal.Height / 6
  293.     giDayWidth = gfrmCal!picCal.Width / 7
  294.     picWeekdays.Width = gfrmCal!picCal.Width
  295.     picWeekdays.Left = gfrmCal!picCal.Left
  296.     gfrmCal!linDivider(0).X1 = gfrmCal!picCal.Left
  297.     gfrmCal!linDivider(0).X2 = gfrmCal!picCal.Left + gfrmCal!picCal.Width
  298.     gfrmCal!linDivider(2).Y1 = gfrmCal!picCal.Top + gfrmCal!picCal.Height + iOnePixelY
  299.     gfrmCal!linDivider(2).Y2 = gfrmCal!linDivider(2).Y1
  300.     gfrmCal!linDivider(3).Y1 = gfrmCal!linDivider(2).Y1 + iOnePixelY
  301.     gfrmCal!linDivider(3).Y2 = gfrmCal!linDivider(2).Y1 + iOnePixelY
  302.     For i = 1 To 3
  303.         gfrmCal!linDivider(i).X1 = gfrmCal!linDivider(0).X1
  304.         gfrmCal!linDivider(i).X2 = gfrmCal!linDivider(0).X2
  305.     Next i
  306.     sWeekdays = "SMTWTFS"
  307.     For i = 0 To 6
  308.         picWeekdays.CurrentX = i * giDayWidth + giDayWidth / 2
  309.         picWeekdays.Print Mid(sWeekdays, i + 1, 1);
  310.     Next i
  311.     For i = 0 To kiDayIndexMax '41 number of days
  312.         gaDays(i).iLeft = iColumn * giDayWidth
  313.         gaDays(i).iTop = iRow * giDayHeight
  314.         iColumn = iColumn + 1
  315.         If iColumn = 7 Then
  316.             iColumn = 0
  317.             iRow = iRow + 1
  318.         End If
  319.     Next i
  320.     gfrmCal.ScaleMode = iOldScaleMode
  321. End Sub
  322. Function iDayIndex%(iYear%, iMonth%, iDay%)
  323.    iDayIndex = WeekDay(DateSerial(iYear, iMonth, 1)) + iDay - 2
  324. End Function
  325. Private Sub MakeSelection(ByVal dStartNew As Date, ByVal dEndNew As Date, ByVal dStartOld As Date, ByVal dEndOld As Date)
  326.     Dim dTmp
  327.     Dim dFirstDate As Date
  328.     Dim iDayDiff%
  329.     If dEndOld = 0 Or dStartOld = 0 Then Exit Sub
  330.     If dStartNew > dEndNew Then
  331.         dTmp = dStartNew
  332.         dStartNew = dEndNew
  333.         dEndNew = dTmp
  334.     End If
  335.     If dStartOld > dEndOld Then
  336.         dTmp = dStartOld
  337.         dStartOld = dEndOld
  338.         dEndOld = dTmp
  339.     End If
  340.     'reset dStartOld to first of cal if efficient
  341.     If gaDays(0).lForeColor = kDkGray Then
  342.         dFirstDate = DateSerial(giCurYear, giCurMonth - 1, CInt(gaDays(0).sCaption))
  343.     Else
  344.         dFirstDate = DateSerial(giCurYear, giCurMonth, CInt(gaDays(0).sCaption))
  345.     End If
  346.     If dFirstDate > dStartNew Then dStartNew = dFirstDate
  347.     'reset dEndOld to first of cal if efficient
  348.      If gaDays(kiDayIndexMax).lForeColor = kDkGray Then
  349.         dTmp = DateSerial(giCurYear, giCurMonth + 1, CInt(gaDays(kiDayIndexMax).sCaption))
  350.     Else
  351.         dTmp = DateSerial(giCurYear, giCurMonth, CInt(gaDays(kiDayIndexMax).sCaption))
  352.     End If
  353.     If dTmp < dEndNew Then dEndNew = dTmp
  354.     For dTmp = dStartNew To dEndNew '** ALERT: THIS DOES NOT INCLUDE OLD NOT SELOTHERS!!!
  355.         If dTmp >= dEndOld Or dTmp <= dStartOld Then
  356.             iDayDiff = dTmp - dFirstDate
  357.             DrawDay iDayDiff, kBlue
  358.         End If
  359.     Next dTmp
  360. End Sub
  361. Private Sub DrawCalender()
  362.     '** draws the current dates and selection
  363.     Dim dStartDate As Date '** first date of month
  364.     Dim iDayOfWeek%
  365.     Dim iDaysInMonth%
  366.     Dim i%
  367.     Dim iDayInPrevMonth%
  368.     Dim iCurDay%
  369.     gfrmCal!lblMonth = gsMonthes(giCurMonth) & " " & CStr(giCurYear) '** set month label
  370.     dStartDate = DateSerial(giCurYear, giCurMonth, 1)
  371.     '** if this is current month, find which index is today
  372.     If (giCurYear = Year(Now)) And (Month(Now) = giCurMonth) Then
  373.         giTodayIndex = iDayIndex(Year(Now), Month(Now), day(Now))
  374.     Else
  375.         giTodayIndex = -1
  376.     End If
  377.     '** find how many days are in current month
  378.     '** to get: subtract first day of next month by first day of this month
  379.     If giCurMonth = 12 Then
  380.         iDaysInMonth = DateSerial(giCurYear + 1, 1, 1) - dStartDate
  381.     Else
  382.         iDaysInMonth = DateSerial(giCurYear, giCurMonth + 1, 1) - dStartDate
  383.     End If
  384.     iDayOfWeek = WeekDay(dStartDate)    '** set day of week which the first day of the month falls on
  385.     '** draw all the days of this month
  386.     For i = iDayOfWeek - 1 To (iDayOfWeek - 1) + iDaysInMonth - 1
  387.         iCurDay% = iCurDay% + 1
  388.         gaDays(i).sCaption = Str(iCurDay%)
  389.         If fIsDateSelected(giCurYear, giCurMonth, iCurDay%) Then
  390.             gaDays(i).lForeColor = kBlack
  391.             DrawDay i, kBlue
  392.         Else
  393.             gaDays(i).lForeColor = kBlack
  394.             DrawDay i, kLtGray
  395.         End If
  396.     Next i
  397.     '** calculate the number of days in previous month
  398.     If giCurMonth = 1 Then
  399.         iDayInPrevMonth = dStartDate - DateSerial(giCurYear - 1, 12, 1)
  400.     Else
  401.         iDayInPrevMonth = dStartDate - DateSerial(giCurYear, giCurMonth - 1, 1)
  402.     End If
  403.     '** draw in the last gray days of previous month
  404.     For i = 0 To iDayOfWeek - 2
  405.         iCurDay% = iDayInPrevMonth - (iDayOfWeek - i) + 2
  406.         gaDays(i).sCaption = iCurDay%
  407.         gaDays(i).lForeColor = kDkGray
  408.         If fIsDateSelected(giCurYear, giCurMonth - 1, iCurDay%) Then
  409.             DrawDay i, kBlue
  410.         Else
  411.             DrawDay i, kLtGray
  412.         End If
  413.     Next i
  414.     '** draw in the first gray days of next month
  415.     iCurDay% = 0
  416.     For i = (iDayOfWeek - 1) + iDaysInMonth To 41
  417.         iCurDay% = iCurDay% + 1
  418.         gaDays(i).lForeColor = kDkGray
  419.         gaDays(i).sCaption = iCurDay%
  420.         If fIsDateSelected(giCurYear, giCurMonth + 1, iCurDay%) Then
  421.             DrawDay i, kBlue
  422.         Else
  423.             DrawDay i, kLtGray
  424.         End If
  425.     Next i
  426. End Sub
  427. Private Sub CalInitialize(frmCal As Form)
  428.      '** initializes cal vars and controls
  429.     '** frmCal = the form with cal frame control
  430.     fRet = False
  431.     Dim i%
  432.     Set gfrmCal = frmCal
  433.     InitCalControls     '** place and initialize controls in cal frame control
  434.     '** init global cal variables
  435.     giCurYear = Year(Now)
  436.     giCurMonth = Month(Now)
  437.     For i = LBound(gadCtrlSelect) To UBound(gadCtrlSelect)
  438.         gadCtrlSelect(i) = 0
  439.     Next i
  440.     gdSelStart = DateSerial(Year(Now), Month(Now), day(Now)) '** init main selection to today
  441.     gdSelEnd = gdSelStart
  442.     giMaxCtrlSelectIndex = -1
  443.     giLastSelIndex = -1
  444.     gfExitedGray = True
  445.     For i = 1 To 12 '** fill gsMonthes array with month names
  446.         gsMonthes(i) = Format$(DateSerial(giCurYear, i, 1), "mmmm")
  447.     Next
  448.     DrawCalender    '** draw the current month
  449.     fFirstClick = True
  450. End Sub
  451. Private Sub ThreeDRect(picCanvas As PictureBox, iLeft%, iTop%, iRight%, iBottom%, fOut%)
  452.     Dim lColor1&, lColor2&
  453.     If fOut Then
  454.         lColor1 = kDkGray
  455.         lColor2 = kWhite
  456.     Else
  457.         lColor1 = kWhite
  458.         lColor2 = kDkGray
  459.     End If
  460.     picCanvas.ForeColor = lColor1
  461.     picCanvas.Line (iLeft - 1, iTop - 2)-(iLeft - 1, iBottom + 2)
  462.     picCanvas.Line (iLeft - 2, iTop - 2)-(iLeft - 2, iBottom + 2)
  463.     picCanvas.Line (iLeft - 2, iTop - 1)-(iRight + 2, iTop - 1)
  464.     picCanvas.Line (iLeft - 2, iTop - 2)-(iRight + 2, iTop - 2)
  465.     picCanvas.ForeColor = lColor2
  466.     picCanvas.Line (iRight + 1, iTop - 1)-(iRight + 1, iBottom + 2)
  467.     picCanvas.Line (iRight + 2, iTop - 2)-(iRight + 2, iBottom + 2)
  468.     picCanvas.Line (iLeft - 1, iBottom + 1)-(iRight + 2, iBottom + 1)
  469.     picCanvas.Line (iLeft - 2, iBottom + 2)-(iRight + 2, iBottom + 2)
  470. End Sub
  471. Private Sub CalMouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
  472.     '** select or de-select a date
  473.     '** handles click, shift-click and ctrl-click
  474.     '** MouseOver calls CalMousedown with shift for dragging
  475.     Dim dNewDate As Date    '** date selected
  476.     Dim iIndex%             '** gaDay index of date clicked
  477.     Dim iDay%               '** current day (1-31)
  478.     '** if not left mouse button then exit
  479.     If (Button And vbLeftButton) <= 0 Then Exit Sub
  480.     If fFirstClick = True Then Shift = 0
  481.     fFirstClick = False
  482.     '** find the gaDay index of date clicked on
  483.     iIndex = (Int(Y / giDayHeight) * 7) + Int(X / giDayWidth)
  484.     If iIndex < 0 Or iIndex > kiDayIndexMax Then Exit Sub
  485.     iDay = CInt(gaDays(iIndex).sCaption)
  486.     '** if the click is on a grayed out date then make new month visible
  487.     If gaDays(iIndex).lForeColor = kDkGray Then
  488.         If iDay < 15 Then
  489.             CalGoMonth 1 '** switch to prev month
  490.         Else
  491.             CalGoMonth 0 '** switch to next month
  492.         End If
  493.         iIndex = iDayIndex(giCurYear, giCurMonth, iDay) '** adjust iIndex to new month
  494.         If (Shift And vbShiftMask) > 0 Then gfExitedGray = False '** set flag to prevent another month switch if new month
  495.     End If                                                       '** has grayed out date under mouse
  496.     dNewDate = DateSerial(giCurYear, giCurMonth, iDay)
  497.     If kfMultiselectDates And (Shift And vbShiftMask) > 0 Then '** shift-key down
  498.         ClearCtrlSelects '** clear all ctrl-key selected dates
  499.         ClearOldSelection gdLastDateClicked, dNewDate, gdSelStart, gdSelEnd
  500.         MakeSelection gdLastDateClicked, dNewDate, gdSelStart, gdSelEnd
  501.         gdSelEnd = dNewDate
  502.         gdSelStart = gdLastDateClicked
  503.     ElseIf kfMultiselectDates And (Shift And vbCtrlMask) > 0 Then '** ctrl-key down
  504.         CtrlSelectDate iIndex, dNewDate
  505.     Else '**simple mouse click, no keys down
  506.         ClearCtrlSelects  '** clear all ctrl-key selected dates
  507.         ClearOldSelection dNewDate, dNewDate, gdSelStart, gdSelEnd
  508.         gdSelStart = dNewDate
  509.         gdSelEnd = dNewDate
  510.         DrawDay iIndex, kBlue
  511.         gdLastDateClicked = dNewDate
  512.     End If
  513. End Sub
  514. Private Sub CalGoMonth(iIndex%)
  515.     '** if index = 0, make previous month visible
  516.     '** else, make next month visible
  517.     If iIndex% = 0 Then
  518.         giCurMonth = giCurMonth - 1
  519.         If giCurMonth = 0 Then
  520.             giCurMonth = 12
  521.             giCurYear = giCurYear - 1
  522.         End If
  523.     Else
  524.         giCurMonth = giCurMonth + 1
  525.         If giCurMonth = 13 Then
  526.             giCurMonth = 1
  527.             giCurYear = giCurYear + 1
  528.         End If
  529.     End If
  530.     DrawCalender    '** draw new month
  531. End Sub
  532. Private Sub CalMouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
  533.     Dim iIndex% '** index of gaDay that mouse is over
  534.     '** set gfExitedGray to true if mouse is not over gray date
  535.     iIndex = (Int(Y / giDayHeight) * 7) + Int(X / giDayWidth) '** calculate index
  536.     If iIndex >= 0 And iIndex <= kiDayIndexMax Then
  537.         If gaDays(iIndex).lForeColor = kBlack Then
  538.             gfExitedGray = True
  539.         End If
  540.     End If
  541.     '** if the mouse is not on the same index as last mousemove
  542.     '** and the left mouse button is down
  543.     If kfMultiselectDates And ((Button And vbLeftButton) > 0) And (Shift And vbShiftMask) = 0 And (Shift And vbCtrlMask) = 0 And iIndex <> giLastSelIndex And gfExitedGray = True Then
  544.         giLastSelIndex = iIndex
  545.         CalMouseDown Button, vbShiftMask, X, Y '** simulate mousedown with shiftkey
  546.     End If
  547.         
  548. End Sub
  549. Private Function fDateInBetween(dSrc As Date, dStart As Date, dEnd As Date)
  550.     If (dSrc <= dEnd And dSrc >= dStart) Or (dSrc >= dEnd And dSrc <= dStart) Then
  551.         fDateInBetween = True
  552.     End If
  553. End Function
  554. Private Sub ClearCtrlSelects()
  555.     '** clear gadCtrlSelect array; no ctrl-key selection blocks
  556.     '** redraw the ex-ctrl-selected dates
  557.     Dim i%, dFirstDate As Date, iIndex%
  558.     If gaDays(0).lForeColor = kDkGray Then
  559.         dFirstDate = DateSerial(giCurYear, giCurMonth - 1, CInt(gaDays(0).sCaption))
  560.     Else
  561.         dFirstDate = DateSerial(giCurYear, giCurMonth, CInt(gaDays(0).sCaption))
  562.     End If
  563.     For i = 0 To giMaxCtrlSelectIndex '** loop through gadCtrlSelect array
  564.         If gadCtrlSelect(i) <> 0 Then '** if valid ctrl-selection
  565.             If fDateInBetween(gadCtrlSelect(i), gdSelStart, gdSelEnd) Then '** redraw as selected day
  566.                 iIndex = gadCtrlSelect(i) - dFirstDate
  567.                 If iIndex > -1 And iIndex <= kiDayIndexMax Then
  568.                     DrawDay iIndex, kBlue
  569.                 End If
  570.             Else    '** redraw as unselected day (not in selection)
  571.                 iIndex = gadCtrlSelect(i) - dFirstDate
  572.                 If iIndex > -1 And iIndex <= kiDayIndexMax Then
  573.                     DrawDay iIndex, kLtGray
  574.                 End If
  575.             End If
  576.         End If
  577.         gadCtrlSelect(i) = 0 '** clear to 0 (turn off)
  578.     Next i
  579.     giMaxCtrlSelectIndex = -1
  580. End Sub
  581. Private Sub CtrlSelectDate(iIndex%, dNewDate As Date)
  582.     '** perform a ctrl-click on a dNewDate
  583.     '** if this date was selected then deselect; if this date was unselected then select
  584.     '** at least one date MUST be selected at any time
  585.     Dim fValid% '** is this ctrl-click valid?
  586.     Dim i%, dTmp As Date '** utility variables
  587.     Dim iExists% '** does this date exist in gadCtrlSelect array? if yes, holds index
  588.     Dim iStep% '** which way do we loop?
  589.     Dim iNumSelMain%, iNumSelCtrl% '** number of dates highlighted in main sel block/ctrl-click array
  590.     '** first, check if this is a valid ctrl-click
  591.     '** if this causes no dates to be selected than it is INVALID
  592.     '** how many dates are selected within the main selection block?
  593.     If gdSelStart > gdSelEnd Then '** do we have to loop through selection backwards?
  594.         iStep = -1  '** yes, gdSelEnd comes first
  595.     Else
  596.         iStep = 1   '** no, gsSelStart comes first
  597.     End If
  598.     '** loop through main selection block keeping tally of selected dates within
  599.     For dTmp = gdSelStart To gdSelEnd Step iStep
  600.         If fIsDateSelected(Year(dTmp), Month(dTmp), day(dTmp)) = True Then
  601.             iNumSelMain = iNumSelMain + 1
  602.             If iNumSelMain > 1 Then Exit For
  603.         End If
  604.     Next dTmp
  605.     dTmp = 0    '** clear loop variable
  606.     If iNumSelMain > 1 Then  '** multiple dates selected, ok to ctrl-click
  607.         fValid = True
  608.     Else '** if 0 or 1 dates are selected, ctrl-click may not be valid
  609.         '** how many ctrl-click dates are selected? keep tally in iNumSelCtrl
  610.         For i = 0 To giMaxCtrlSelectIndex
  611.             If gadCtrlSelect(i) > 0 And Not fDateInBetween(gadCtrlSelect(i), gdSelStart, gdSelEnd) Then
  612.                 iNumSelCtrl = iNumSelCtrl + 1
  613.                 If iNumSelCtrl > 1 Then Exit For
  614.             End If
  615.         Next i
  616.         
  617.         If iNumSelMain = 0 And iNumSelCtrl = 1 Then '** if we only have one selected date
  618.                                                     '** and it is a ctrl-click
  619.             '** find that date; store in dTmp
  620.             For i = 0 To giMaxCtrlSelectIndex
  621.                 If gadCtrlSelect(i) > 0 And Not fDateInBetween(gadCtrlSelect(i), gdSelStart, gdSelEnd) Then
  622.                     dTmp = gadCtrlSelect(i)
  623.                     Exit For
  624.                 End If
  625.             Next i
  626.             If dTmp <> dNewDate Then '** ctrl-click valid if selected date does
  627.                 fValid = True        '**    not equal the clicked
  628.             End If
  629.         ElseIf iNumSelMain = 1 And iNumSelCtrl = 0 Then '** if we have one selected date
  630.                                                         '** and it is in the main sel block
  631.             '** if the date just ctrl-clicked isn't the sole selected date than valid
  632.             If Not fIsDateSelected(Year(dNewDate), Month(dNewDate), day(dNewDate)) Then
  633.                 fValid = True
  634.             End If
  635.         Else
  636.             fValid = True '** valid; multiple ctrl-click selections
  637.         End If
  638.     End If
  639.     If fValid = True Then '** this is a valid ctrl click
  640.         '** does this ctrl-click already exist in the gadCtrlSelect array? if so, find it
  641.         iExists = -1
  642.         For i = 0 To giMaxCtrlSelectIndex
  643.             If gadCtrlSelect(i) = dNewDate Then
  644.                 iExists = i
  645.                 Exit For
  646.             End If
  647.         Next i
  648.         
  649.         If iExists > -1 Then '** yes, this ctrl-click already exists
  650.             '** since the user is reclicking an already selected ctrl-click,
  651.             '**     this is essentially identical to clearing it
  652.             '** first, draw the selection/deselection
  653.             If fDateInBetween(gadCtrlSelect(iExists), gdSelStart, gdSelEnd) Then
  654.                 DrawDay iIndex, kBlue
  655.             Else
  656.                 DrawDay iIndex, kLtGray
  657.             End If
  658.             
  659.             gadCtrlSelect(iExists) = 0 '** clear this ctrl-click from array
  660.             '** adjust giMaxCtrlSelectIndex to point to last valid ctrl-click
  661.             '**     in the gadCtrlSelect array
  662.             If iExists = giMaxCtrlSelectIndex Then
  663.                 giMaxCtrlSelectIndex = giMaxCtrlSelectIndex - 1
  664.                 If giMaxCtrlSelectIndex > -1 Then
  665.                     While giMaxCtrlSelectIndex > 0 And gadCtrlSelect(giMaxCtrlSelectIndex) = 0
  666.                         giMaxCtrlSelectIndex = giMaxCtrlSelectIndex - 1
  667.                     Wend
  668.                     If giMaxCtrlSelectIndex = 0 And gadCtrlSelect(0) = 0 Then giMaxCtrlSelectIndex = -1
  669.                 End If
  670.             End If
  671.         Else '** this ctrl-click does not exist already
  672.             '** find the first available (empty) gadCtrlSelect date
  673.             i = 0
  674.             While gadCtrlSelect(i) <> 0
  675.                 i = i + 1
  676.             Wend
  677.             
  678.             gadCtrlSelect(i) = dNewDate '** set to new date
  679.             '** draw this ctrl-click
  680.             If fDateInBetween(gadCtrlSelect(i), gdSelStart, gdSelEnd) Then
  681.                 DrawDay iIndex, kLtGray
  682.             Else
  683.                 DrawDay iIndex, kBlue
  684.             End If
  685.             If i > giMaxCtrlSelectIndex Then giMaxCtrlSelectIndex = i '** reset giMax if necessary
  686.         End If
  687.         gdLastDateClicked = dNewDate
  688.     End If
  689. End Sub
  690. Private Function ValidatePayPeriod(dateToValidate As Date) As Boolean
  691. 'in this sample we require that date identifying a pay period be a Friday
  692. If WeekDay(dateToValidate, vbSunday) = vbFriday Then
  693.     ValidatePayPeriod = True
  694.     MsgBox "The date has to be a Friday"
  695.     ValidatePayPeriod = False
  696. End If
  697. End Function
  698. Private Sub JumpToFirstSelected()
  699.     '** set the month/year to the month/year with first selected date
  700.     Dim i%
  701.     Dim dFirstDate As Date
  702.     If gdSelStart < gdSelEnd Then
  703.         dFirstDate = gdSelStart
  704.     Else
  705.         dFirstDate = gdSelEnd
  706.     End If
  707.          
  708.     For i = 0 To giMaxCtrlSelectIndex
  709.         If gadCtrlSelect(i) < dFirstDate And Not fDateInBetween(gadCtrlSelect(i), gdSelStart, gdSelEnd) Then
  710.             dFirstDate = gadCtrlSelect(i)
  711.         End If
  712.     Next i
  713.     giCurMonth = Month(dFirstDate)
  714.     giCurYear = Year(dFirstDate)
  715.     DrawCalender
  716. End Sub
  717. Public Function GetDate(DateToSet As Date) As Boolean
  718. frmCalender.Show 1
  719. If fRet Then
  720.     DateToSet = gdSelStart
  721.     GetDate = True
  722.     GetDate = False
  723. End If
  724. End Function
  725. Private Sub cmdCancel_Click()
  726. fRet = False
  727. Unload Me
  728. End Sub
  729. Private Sub cmdOK_Click()
  730. If ValidatePayPeriod(gdSelStart) Then
  731.     fRet = True
  732.     Unload Me
  733. End If
  734. End Sub
  735. Private Sub Form_Load()
  736.     CalInitialize Me
  737. End Sub
  738. Private Sub picCal_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
  739.      fDirty = True
  740.      CalMouseDown Button, Shift, X, Y
  741. End Sub
  742. Private Sub picCal_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
  743.     CalMouseMove Button, Shift, X, Y
  744. End Sub
  745. Private Sub picCal_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
  746.     giLastSelIndex = -1
  747. End Sub
  748. Private Sub picGoMonth_Click(Index As Integer)
  749.     CalGoMonth Index
  750. End Sub
  751.