Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Popup Calendar
#1
Well here's a little Screen Zero Hero Productions goody from 25 years a ago.

I did a rewrite because my coding style back then was to use all caps, no remarks, non-descriptive variable names, and no indentation.

I uses the mapping technique, I described in the other thread, for mouse recognition.

Anyway, I have some bells and whistles I'd like to add going forward, but here is a working demo that shows how it can be applied in what I term as a flow-through routine. That means the calendar routine will keep flowing through the main routine, so what's going on there won't be disturbed.

I'll post back with some more info on keys and Mouse use. For now, just use arrow keys, page keys, Enter, Esc, F1, F12, or click / double click a day, x symbol, "<" or ">" symbols enclosing the month and year, or use the mouse wheel.

Code: (Select All)
ReDim Shared mRow$(0)
Palette 1, 8
Width 80, 28
_Font 16
Palette 7, 63
Color 0, 1
Cls
View Print 3 To _Height - 2
Color 0, 7: Cls 2
View Print
Color 14, 1
Locate 1, 1: Print String$(80, 196);
Locate _Height - 1, 1: Print String$(80, 196);
msg$ = "Chritmas Card and Calendar Demo"
Locate 2, _Width \ 2 + 1 - Len(msg$) \ 2: Print msg$;
Locate 3, 1: Print String$(80, 196);
msg$ = "Press [F12] for Calendar or [F1] for Help."
Locate _Height, _Width \ 2 + 1 - Len(msg$) \ 2: Print msg$;
train$ = Space$(_Width) + "[oo]-[oo]-[Oo>"
Color 2, 7
msg$ = " Merry Christmas "
Locate 8, _Width \ 2 - Len(msg$) \ 2 + 1
Color 4, 7: Print msg$: Color 2
Locate 14
a$ = "*"
For i = 1 To 13
    If i > 10 Then a$ = "*": Color 0
    Locate , _Width \ 2 - Len(a$) \ 2 + 1
    Print a$
    a$ = a$ + "**"
Next
y = CsrLin - 1
_Delay 2: x = 5: z = Timer
Do
    If gocal = 0 Then
        Locate 14: a$ = "*"
        For i = 1 To 10
            Locate , _Width \ 2 - Len(a$) \ 2 + 1
            Color 2, 7: Print a$;
            For j = 1 To Len(a$)
                If Rnd * 20 > 17 Then
                    Locate , _Width \ 2 - Len(a$) \ 2 + j
                    Color 12 + 16: Print "*";
                End If
            Next
            Print
            a$ = a$ + "**"
        Next
    End If
    If Abs(z - Timer) > x Then
        z = Timer
        If t = Len(train$) + 1 Then
            t = 1: x = 3
        Else
            Sound 300, .05
            t = t + 1: x = .05
            Locate y, 1: Color 0, 7: Print Mid$(train$, Len(train$) - t, _Width);
            If t >= _Width / 2 + Len(_Trim$(train$)) Then Color 0: Locate , _Width \ 2 + 1: Print "*";
        End If
    End If
    b$ = InKey$
    If b$ = Chr$(0) + Chr$(134) Then
        _KeyClear
        gocal = 1: Color 0, 7: Locate y, 1: Print Space$(_Width);
        Color 0, 7: Locate , _Width \ 2 + 1: Print "*";
    End If
    If b$ = Chr$(0) + Chr$(59) Then
        _MessageBox
    End If
    If gocal Then

        cal ds$

        If Len(ds$) Then
            If ds$ <> "esc" Then _Title ds$
            ds$ = "": gocal = 0: _KeyClear
        End If
    End If
Loop

Sub cal (Cal_DateSelected$)
    Static initiate ' Needed for this sub. Other static variables below are only required for flo-through.
    Static DaysInMonth$, EndDate, yr, mo, dy, month$, fullmonth$, oldmapy, oldday$, datex$, yy, xx
    Static BorderColorFg, BorderColorBg, ShadowFg, ShadowBg, DOWColor, DOWColorSunday, DOWHighlightBg
    Static w1, w2, w3, w4, xover, caly, calx, calfg, calbg, a1$, a2$, a3$, b1$, b2$, b3$
    Static mx, my, lb, mb, mw, clkcnt, hlclose
    Locate , , 0 ' Hide cursor.
    If initiate = 0 Then
        initiate = 1
        PCopy 0, 3
        Palette 5, 63
        BorderColorFg = 15
        BorderColorBg = 1
        ShadowFg = 8
        ShadowBg = 0
        DOWColor = 15
        DOWColorSunday = 3
        DOWHighlightBg = 4
        j = 4
        a1$ = Chr$(218) + String$(j, Chr$(196)) + Chr$(191)
        a2$ = Chr$(179) + String$(j, Chr$(32)) + Chr$(179)
        a3$ = Chr$(192) + String$(j, Chr$(196)) + Chr$(217)
        b1$ = a1$: b2$ = a2$: b3$ = a3$
        For i = 1 To 7 - 1
            a1$ = a1$ + " " + b1$
            a2$ = a2$ + " " + b2$
            a3$ = a3$ + " " + b3$
        Next i
        w1 = 7 ' Top
        w2 = Int(_Width \ 2 - Len(a1$) \ 2) - 2 ' Left margin
        w3 = 18 ' Height
        w4 = Len(a1$) + 4 ' Width
        yy = w1: xx = Int(_Width \ 2 - Len(a1$) \ 2) ' Left top corner.
        Color BorderColorFg, BorderColorBg: Locate w1 - 1, w2: Print Chr$(218) + String$(w4 - 2, 196) + Chr$(191);
        ' Create box-----------------------------------------------------------------------
        Locate w1, w2
        For i = 1 To w3 - 1
            Color BorderColorFg, BorderColorBg: Locate , w2: Print Chr$(179);: Color 7, 1: Print Space$(w4 - 2);: Color BorderColorFg, 1: Print Chr$(179);
            Color 8, 0: Print Chr$(Screen(CsrLin, Pos(0)));: Print Chr$(Screen(CsrLin, Pos(0)))
        Next i
        Color BorderColorFg, BorderColorBg: Locate , w2: Print Chr$(192) + String$(w4 - 2, 196) + Chr$(217);
        Color ShadowFg, ShadowBg: Print Chr$(Screen(CsrLin, Pos(0)));: Print Chr$(Screen(CsrLin, Pos(0)))
        ' ---------------------------------------------------------------------------------
        Color ShadowFg, ShadowBg: Locate , w2 + 1
        For i = 1 To w4 + 1
            Print Chr$(Screen(CsrLin, Pos(0)));
        Next
        Locate yy + 1, xx
        Color 11, 1
        Print " Sun.  Mon.  Tue.  Wed.  Thu.  Fri.  Sat. "
        DaysInMonth$ = "312831303130313130313031"
        GoSub update_calendar
    Else
        Locate caly, calx
        Color calfg, calbg
    End If
    Do
        _Limit 30

        MyMouse_and_Keyboard lb, mb, rb, my, mx, mw, shift%, alt%, clkcnt, drag, b$, autokey$

        If hlclose Then
            If Mid$(mRow$(my), mx, 1) <> "x" Then
                s1 = CsrLin: s2 = Pos(0)
                c1 = _DefaultColor: c2 = _BackgroundColor
                Color BorderColorBg, BorderColorFg
                Locate hlclose, InStr(mRow$(hlclose), "x") - 1
                Color BorderColorBg, BorderColorBg: Print Chr$(221);
                Color BorderColorFg, BorderColorBg: Print "x";
                Color BorderColorBg, BorderColorBg: Print Chr$(222);

                Color c1, c2
                Locate s1, s2
                hlclose = 0
            End If
        Else
            If Mid$(mRow$(my), mx, 1) = "x" Then ' Highlight "x" close popup symbol.
                hlclose = my
                s1 = CsrLin: s2 = Pos(0)
                c1 = _DefaultColor: c2 = _BackgroundColor
                Color BorderColorFg, DOWHighlightBg
                Locate my, mx - 1
                Color BorderColorBg, DOWHighlightBg: Print Chr$(221);
                Color BorderColorFg, DOWHighlightBg: Print "x";
                Color BorderColorBg, DOWHighlightBg: Print Chr$(222);
                Color c1, c2
                Locate s1, s2
            End If
        End If
        If lb = 2 Then
            If hlclose Then
                b$ = Chr$(27)
            Else
                x$ = Mid$(mRow$(my), mx, 1)
                If x$ = "<" Or x$ = ">" Then
                    If InStr(mx, mRow$(my), "ù") Then
                        If x$ = "<" Then i = -1 Else i = 1 ' Change month.
                        j = 0: GoSub change_mo_yr: If i = -999 Then Exit Do
                        b$ = "lb"
                    Else
                        If x$ = "<" Then j = -1 Else j = 1 ' Change year.
                        i = 0: GoSub change_mo_yr: If i = -999 Then Exit Do
                        If dy > Val(Mid$(DaysInMonth$, mo * 2 - 1, 2)) Then dy = 0 ' Note: Automatically adjusts for a leap year when dy=0 is evaluated in next cycle.
                        b$ = "lb"
                    End If
                End If
                If InStr(mRow$(my), Chr$(179)) Then
                    j = InStr(mx, mRow$(my), Chr$(179)) - 1
                    x$ = Mid$(mRow$(my), 1, j)
                    x$ = Mid$(x$, _InStrRev(x$, Chr$(179)) + 1)
                    If Val(x$) Then ' Click was on a calendar date.
                        Select Case x$ ' Block is [3210] for j - mx.
                            Case "2330": If j - mx > 1 Then x$ = "23" Else x$ = "30"
                            Case "2431": If j - mx > 1 Then x$ = "24" Else x$ = "31"
                        End Select
                        dy = Val(x$)
                        If clkcnt = 1 Then
                            b$ = Chr$(13) ' A double click on a calendar date triggers selection.
                        Else
                            b$ = "lb" ' Highlights date clicked.
                        End If
                    End If
                End If
            End If
        Else
            If mw > 0 Then b$ = Chr$(0) + "P" ' Page up.
            If mw < 0 Then b$ = Chr$(0) + "H" ' Page dn.
        End If
        If Len(b$) Then
            h = 0: v = 0
            Select Case b$
                Case "lb" ' Mouse event.
                Case Chr$(9), Chr$(8) ' Tab or Backspace.
                    datex$ = "" ' Triggers today's date.
                    GoSub update_calendar
                Case Chr$(0) + "H", Chr$(0) + "M", Chr$(0) + "P", Chr$(0) + "K" ' Arrow keys.
                    Select Case b$
                        Case Chr$(0) + "H": v = -1
                        Case Chr$(0) + "M": h = 1
                        Case Chr$(0) + "P": v = 1
                        Case Chr$(0) + "K": h = -1
                    End Select
                    If h Then
                        If dy + h > 0 And dy + h <= EndDate Then
                            dy = dy + h
                            day$ = LTrim$(Str$(dy))
                            If Len(day$) = 1 Then day$ = "0" + day$
                        Else
                            If h > 0 Then
                                i = 1: j = 0: GoSub change_mo_yr: If i = -999 Then Exit Do
                                dy = 1
                            ElseIf h < 0 Then
                                i = -1: j = 0: GoSub change_mo_yr: If i = -999 Then Exit Do
                                dy = 0
                            End If
                        End If
                    ElseIf v Then
                        If dy + v * 7 > 0 And dy + v * 7 <= EndDate Then
                            dy = dy + v * 7
                            day$ = LTrim$(Str$(dy))
                            If Len(day$) = 1 Then day$ = "0" + day$
                        Else ' Change month/year.
                            If v > 0 Then
                                i = 1: j = 0: GoSub change_mo_yr: If i = -999 Then Exit Do
                                dy = dy + 7 - EndDate
                            ElseIf v < 0 Then
                                i = -1: j = 0: GoSub change_mo_yr: If i = -999 Then Exit Do
                                j = Val(Mid$(DaysInMonth$, mo * 2 - 1, 2))
                                If mo = 2 Then ' Leap Year adjustment.
                                    If yr Mod 4 = 0 And yr Mod 100 Or yr Mod 4 = 0 And yr Mod 100 = 0 And yr Mod 400 = 0 Then j = j + 1
                                End If
                                dy = (dy - 7) + j
                            End If
                        End If
                    End If
                Case Chr$(0) + "I", Chr$(0) + "Q" ' Page keys.
                    If b$ = Chr$(0) + "I" Then i = -1 Else i = 1
                    j = 0: GoSub change_mo_yr: If i = -999 Then Exit Do
                    j = (xover + dy - 1) \ 7 + 1 ' Calendar row.
                    k = (xover + ((dy - 1) Mod 7)) Mod 7 + 1 ' Calendar column.

                    cal_calc nul$, nul$, mo, yr, i, nul

                    l = Val(Mid$(DaysInMonth$, mo * 2 - 1, 2))
                    dy = (j - 1) * 7 + k - i
                    If dy > l Then dy = dy - 7
                    If dy < 1 Then dy = dy + 7
                Case Chr$(0) + "G" ' Home key
                    dy = 1
                Case Chr$(0) + "O" ' End key.
                    dy = EndDate
                Case Chr$(13) ' Enter key.
                    temp$ = "Sunday    Monday    Tuesday  Wednesday Thursday  Friday    Saturday"
                    temp$ = Mid$(temp$, ((xover - 1 + dy) Mod 7) * 10 + 1, 10)
                    Cal_DateSelected$ = _Trim$(temp$) + " " + fullmonth$ + " " + LTrim$(Str$(dy)) + ", " + LTrim$(Str$(yr))
                    PCopy 3, 0
                    initiate = 0
                    Exit Do
                Case Chr$(27), Chr$(0) + Chr$(134) ' Esc key or F12 toggle.
                    PCopy 3, 0
                    Cal_DateSelected$ = "esc"
                    initiate = 0
                    Exit Do
                Case Else
                    Exit Do ' Bypass update_calendar routine, below.
            End Select
            If Len(b$) Then
                GoSub update_calendar
            End If
        End If
        Exit Do
    Loop
    caly = CsrLin: calx = Pos(0)
    calfg = _DefaultColor: calbg = _BackgroundColor
    Exit Sub

    change_mo_yr:
    k = mo + i ' Where k substitutes for month and l substitutes for year.
    l = yr + j
    If k = 0 Then l = l - 1: k = 12
    If k = 13 Then i = i + 1: k = 1
    If l <= 1582 Then Beep: dy = 1: i = -999 ' This value tell calling routine to exit the loop without changes.
    If l > 9999 Then Beep: dy = EndDate: i = -999
    If i <> -999 Then
        mo = k: yr = l
    End If
    Return

    update_calendar:
    oldmapy = 0: oldmapx = 0: oldday$ = ""
    If datex$ = "" Then
        datex$ = Date$
        mo = Val(Mid$(datex$, 1, 2))
        yr = Val(Mid$(datex$, 7, 4))
        dy = Val(Mid$(datex$, 4, 2))
    End If

    cal_calc month$, fullmonth$, mo, yr, xover, leapyear

    Color BorderColorFg, 1 ' Make the squares to display the days.
    Locate yy + 2, xx
    For i = 1 To 5
        a$ = a1$: cal_mapit a$
        Locate CsrLin + 1, xx
        a$ = a2$: cal_mapit a$
        Locate CsrLin + 1, xx
        a$ = a3$: cal_mapit a$
        Locate CsrLin + 1, xx
    Next i
    Locate yy - 1, w2 + w4 - 4 ' Display date at top of the calendar.
    y_close = CsrLin: x_close = Pos(0) + 1
    Color BorderColorBg, BorderColorBg: a$ = "Ý": cal_mapit a$
    Color BorderColorFg, BorderColorBg: a$ = "x": cal_mapit a$
    Color BorderColorBg, BorderColorBg: a$ = "Þ": cal_mapit a$
    Color BorderColorFg, BorderColorBg
    Locate yy - 1, _Width / 2 - (Len(month$) + Len(LTrim$(Str$(yr)))) \ 2 - 3
    a$ = "<": cal_mapit a$
    a$ = month$: cal_mapit a$
    a$ = ">": cal_mapit a$
    a$ = "ù": cal_mapit a$
    a$ = "<": cal_mapit a$
    a$ = LTrim$(Str$(yr)): cal_mapit a$
    a$ = ">": cal_mapit a$
    EndDate = Val(Mid$(DaysInMonth$, mo * 2 - 1, 2))
    k = EndDate
    If k = 28 And leapyear Then k = 29: EndDate = 29
    If k = 30 And xover = 6 Then k = k - 1 ' Overlap 1 date.
    If k = 31 And xover > 4 Then k = k - (xover - 4) ' Overlap 2 dates.
    If dy = 0 Then dy = EndDate ' Zero signals backtracking in months or years. Places highlighted date as the last day of the month.
    j = yy + 3
    Locate j, w2 - 1 + 7 * xover
    For i = 1 To k ' Display the days in the squares.
        Locate j, Pos(0) + 5
        If (i + xover - 1) Mod 7 = 0 Then
            Color DOWColorSunday, BorderColorBg ' Sunday.
            If i > 1 Then j = j + 3: Locate j, xx + 2 ' Start next column.
        Else
            Color DOWColor, BorderColorBg ' Weekday/Saturday.
        End If
        If i < 10 Then a$ = "0" + LTrim$(Str$(i)) Else a$ = LTrim$(Str$(i))
        If i = 23 Or i = 24 Then
            If mo <> 2 Then
                Select Case xover
                    Case 5
                        If EndDate = 31 And i = 24 Then a$ = "2431"
                    Case 6
                        Select Case EndDate
                            Case 30
                                If i = 23 Then a$ = "2330"
                            Case 31
                                If i = 23 Then a$ = "2330"
                                If i = 24 Then a$ = "2431"
                        End Select
                End Select
            End If
        End If
        If Len(a$) > 2 Then Locate , Pos(0) - 1
        cal_mapit a$
        If Len(a$) > 2 Then Locate , Pos(0) - 1
    Next i
    day$ = LTrim$(Str$(dy)): If Len(day$) = 1 Then day$ = "0" + day$
    GoSub highlight_date
    Return

    highlight_date:
    For i = 8 To _Height
        j = InStr(mRow$(i), day$)
        If j Then
            Color BorderColorFg, BorderColorBg
            If oldmapy Then Locate oldmapy, oldmapx: Print oldday$;
            k = 0
            p = Val(day$)
            If p <> dy Then Beep
            If mo <> 2 And xover > 4 Then
                If dy = 23 Or dy = 24 Or dy = 30 Or dy = 31 Then
                    Select Case xover
                        Case 5
                            If EndDate = 31 Then If dy = 24 Or dy = 31 Then k = 1
                        Case 6
                            Select Case EndDate
                                Case 30
                                    If dy = 23 Or dy = 30 Then k = 1
                                Case 31
                                    If dy = 23 Or dy = 24 Or dy = 30 Or dy = 31 Then k = 1
                            End Select
                    End Select
                End If
            End If
            Color BorderColorBg, DOWHighlightBg
            If k Then
                Locate i, j: Print "  ";
            Else
                Locate i, j - 1: Print Chr$(221) + "  " + Chr$(222);
            End If
            If (Val(day$) + xover - 1) Mod 7 = 0 Then
                Color DOWColorSunday, DOWHighlightBg
            Else
                Color DOWColor, DOWHighlightBg
            End If
            Locate i, j: Print day$;
            mapy = i: mapx = j
            oldday$ = day$: oldmapy = mapy: oldmapx = mapx
            Exit For
        End If
    Next
    Return
End Sub

Sub cal_mapit (a$)
    Static initiate As Integer
    If initiate = 0 Then
        initiate = 1
        ReDim mRow$(_Height)
    End If
    If mRow$(CsrLin) = "" Then mRow$(CsrLin) = Space$(_Width)
    Mid$(mRow$(CsrLin), Pos(0)) = a$
    Print a$;
End Sub

Sub cal_calc (month$, fullmonth$, mo, yr, xover, leapyear)
    Select Case mo
        Case 1: month$ = "Jan": fullmonth$ = "January": ordinal = 0
        Case 2: month$ = "Feb": fullmonth$ = "February": ordinal = 31
        Case 3: month$ = "Mar": fullmonth$ = "March": ordinal = 59
        Case 4: month$ = "Apr": fullmonth$ = "April": ordinal = 90
        Case 5: month$ = "May": fullmonth$ = "May": ordinal = 120
        Case 6: month$ = "Jun": fullmonth$ = "June": ordinal = 151
        Case 7: month$ = "Jul": fullmonth$ = "July": ordinal = 181
        Case 8: month$ = "Aug": fullmonth$ = "August": ordinal = 212
        Case 9: month$ = "Sep": fullmonth$ = "September": ordinal = 243
        Case 10: month$ = "Oct": fullmonth$ = "October": ordinal = 273
        Case 11: month$ = "Nov": fullmonth$ = "November": ordinal = 304
        Case 12: month$ = "Dec": fullmonth$ = "December": ordinal = 334
    End Select
    leapyear = 0
    xdays = (365 * yr) + yr \ 4 - yr \ 100 + yr \ 400 - 365
    If yr Mod 4 = 0 And yr Mod 100 Or yr Mod 4 = 0 And yr Mod 100 = 0 And yr Mod 400 = 0 Then leapyear = 1
    xdays = xdays + ordinal + 1
    If leapyear And mo < 3 Then xdays = xdays - 1
    xover = xdays Mod 7 ' First day of month and year.
End Sub

Sub MyMouse_and_Keyboard (lb, mb, rb, my, mx, mw, shift%, alt%, clkcnt, drag, b$, autokey$)
    Static oldmy, oldmx, z1, hover, mwy, oldmwy
    If Len(autokey$) Then
        b$ = Mid$(autokey$, 1, InStr(autokey$ + ",", ",") - 1)
        autokey$ = Mid$(autokey$, InStr(autokey$ + ",", ",") + 1)
        Exit Sub
    Else
        k& = _KeyHit
        If k& = 100307 Or k& = 100308 Then alt% = -1: Exit Sub Else If alt% Then alt% = 0
        If k& > 0 Then
            b$ = MKI$(k&)
            If Right$(b$, 1) = Chr$(0) Then b$ = Left$(b$, 1)
        Else
            b$ = ""
        End If
    End If
    If z1 Then If Abs(Timer - z1) > .3 Then z1 = 0: clkcnt = 0
    If lb > 0 Then
        If lb = 1 Then
            lb = -1
        Else
            lb = 0
        End If
    End If
    If rb > 0 Then If rb = 1 Then rb = -1 Else rb = 0
    If mb > 0 Then If mb = 1 Then mb = -1 Else mb = 0
    While _MouseInput
        mwy = mwy + _MouseWheel
    Wend
    my = _MouseY
    mx = _MouseX
    b_hover = 0
    For i = 1 To nob ' number of buttons.
        If my >= y_btl(i) And my <= y_bbr(i) And mx >= x_btl(i) And mx <= x_bbr(i) Then
            b_hover = i
            Exit For
        End If
    Next
    If lb = -1 Then
        If oldmy And oldmx <> mx Or oldmy And oldmy <> my Then
            If mx <> oldmx Then drag = Sgn(mx - oldmx) ' Prevent zero which can occur if mouse moves off row when being dragged horizontally.
        End If
    End If
    If drag = 0 Then
        If mwy <> oldmw Then
            mw = Sgn(mwy - oldmwy): mwy = 0
        Else
            mw = 0
        End If
        oldmwy = mwy
        If _KeyDown(100303) Or _KeyDown(100304) Then shift% = -1 Else If shift% Then shift% = 0
    End If
    If lb = -1 And _MouseButton(1) = 0 Then
        lb = 2: drag = 0: hover = 0
    ElseIf rb = -1 And _MouseButton(2) = 0 Then
        rb = 2
    ElseIf mb = -1 And _MouseButton(3) = 0 Then
        mb = 2
    End If
    If _MouseButton(1) Then
        If lb = 0 Then
            lb = 1
            If z1 = 0 Then
                z1 = Timer ' Let first click go through.
            Else
                clkcnt = clkcnt + 1
            End If
        End If
    ElseIf _MouseButton(2) And rb = 0 Then
        rb = 1
    ElseIf _MouseButton(3) And mb = 0 Then
        mb = 1
    End If
    oldmy = my: oldmx = mx
End Sub

The goal here again is to turn the calendar popup into a library.

Pete
Reply
#2
Love it! F1 doesn't work for me though. I see a pop-up, but no information.
*EDIT* I didn't see that this was in Works in Progress.
Reply




Users browsing this thread: 1 Guest(s)