A Personal *Event Coundown Reminder* (Feedback Welcome)

Developed or developing a new product in PureBasic? Tell the world about it.
Randy Walker
Addict
Addict
Posts: 991
Joined: Sun Jul 25, 2004 4:21 pm
Location: USoA

A Personal *Event Coundown Reminder* (Feedback Welcome)

Post by Randy Walker »

Thanks to the many here who have helped me in the past and continue to do so. Here is a little 'something back' and hope some of you will find it useful. Please feel free to comment on results. In particular, I would be interested to know how it performs in various Windows flavors. Specific modifications required to adapt to other flavors, etc.

:evil: BTW: My intent here was to produce a plain and simple, cut and dry event reminder. Nothing glorious, nothing fancy to distract from the items in the list ... just a basic list. Going for the *Less is More* effect so I'm not really interested in how I could enhance it or how it may fall short of some feature packed utility. Only thing I'm really interested in is cross-platform performance on various flavors of Windows, and if you happen to like it, then that's just icing on the cake :)

Originally written and tested on Windows XP Pro using jaPBe v3.12 and PureBasic v4.60

[EDIT] 11/09/34 -- 2 modifications as noted in comments below:
[EDIT] 11/11/34 -- added patch to force listing to bottom when event count exceeds display area
[Updated] 11/27/24 -- Details inside code.
[EDIT] 11/30/24 -- added code at top of file to prevent more than one instance <<VERY CRITICAL

Code: Select all

; Snipppet from 'Fluid byte' over there in the German forum
; used here as base starting point for 'Event Coundown Reminder':
; http://www.purebasic.fr/german/viewtopic.php?t=17692&start=4

; With special thanks to members of this thread:
; http://www.purebasic.fr/english/viewtopic.php?f=13&t=38387

;11/09/24 -- Further modified to run cleanly on v5.40 and look nice on v6.12 so I could read it without a magnifier, although on v6.12 it will crash on first line following the CallDebugger command line if you double click an existing event or click [add event] and NO idea why.
;11/09/34 -- Modified [Discard all changes] to truly discard all changes from point of launch.
;11/10/24 -- fix a bug with ESC on existing calendar event.
;11/26/24 -- Modified color for events on target date snd day before.
;11/26/24 -- Disabled ListIconGadget on close window click so it's obvious you clicked close.
;BIG Thanks to the RSBasic Moderator for showing me how to enlarge CalenderGadget
;https://www.purebasic.fr/english/viewtopic.php?p=509399&hilit=change+font+CalendarGadget#p509399

SetClipboardText("92122") ; PCH search string
Global active.W, targetWindow$, hWin.i
Procedure ReallySetForegroundWindow(m_hWnd.i)
  ; http://www.drdobbs.com/184405755
  hOtherWnd.i = GetForegroundWindow_()
  ;
  ; get thread handles on our window and foreground window
  hMyThread.i = GetWindowThreadProcessId_(m_hWnd, 0)
  hOtherThread.i = GetWindowThreadProcessId_(hOtherWnd,0)
  ;
  ; attach our thread to foreground thread, take foreground, and detach threads
  AttachThreadInput_(hMyThread,hOtherThread, #True)
  SetForegroundWindow_(m_hWnd)
  AttachThreadInput_(hMyThread,hOtherThread, #False)
  ; AttachThreadInput_(hOtherThread,hMyThread, #True); backward set
  ; SetForegroundWindow_(m_hWnd)
  ; AttachThreadInput_(hOtherThread,hMyThread, #False)
  ;
  ; Now that our window "thread" has fisrt place in the queue...
  ; make sure our "window" is visible
  If IsIconic_(m_hWnd)
    ShowWindow_(m_hWnd,#SW_RESTORE)
  Else
    ShowWindow_(m_hWnd,#SW_SHOW)
  EndIf
  SetActiveWindow(GetDlgCtrlID_(m_hWnd))
  WaitWindowEvent()
  SetForegroundWindow_(m_hWnd)
EndProcedure
Procedure.i ListWindows(Window, Parameter) ; used inside Gt_Prog()
  WindowTitle.s = Space(255) 
  GetWindowText_(Window, WindowTitle, 255)
  WindowTitle = LCase(WindowTitle)
  If LCase(WindowTitle) = targetWindow$
    active.W = 1
    hWin.i = Window
  ElseIf Left(WindowTitle,9) = targetWindow$
    active.W = 1
    hWin.i = Window
  EndIf
  ProcedureReturn #True
EndProcedure
Procedure Gt_Prog(dmy$)   ;   input : 11 char PROCESS name  ,  active.w = true if running : hWin.i holds Window handle
  targetWindow$ = LCase(dmy$)
  active.W = 0
  hWin.i = 0
  EnumWindows_(@ListWindows(), 0) ; Windows CallBack operation.
  ProcedureReturn active.W
EndProcedure
If Gt_Prog(" reminder")   ; Prevent 2nd instance if already running
  SetForegroundWindow_(hWin.i) ; and bring current instance into foreground.
  ShowWindow_(hWin.i, #SW_RESTORE)
  Delay(250)
  End ; Quit from this duplicate instance.
EndIf
; <dpiAware>True/PM</dpiAware>
; <dpiAwareness>PerMonitorV2, PerMonitor</dpiAwareness>
#MainWindow = 1
#DateWindow = 0
Global timeNow.l, AnimateReminder.l, _x, _y, fontVerd9B.i
_x = GetSystemMetrics_(#SM_CXSCREEN)
_y = GetSystemMetrics_(#SM_CYSCREEN)
Debug Str(_x) +"  "+Str(_y)
Global lippi.LASTINPUTINFO ; Wow! Who understands this stuff??!
lippi\cbSize = SizeOf(LASTINPUTINFO) ; Compensating for "dumb" API I guess?? 

#MCM_HITTEST = #MCM_FIRST + 14
#MCHT_CALENDAR = $20000
#MCHT_CALENDARDATE = #MCHT_CALENDAR | $0001
lvc.LV_COLUMN  ; set up structure for global use to format ListIconGadget columns
lvc\mask = #LVCF_FMT
lvc\fmt  = #LVCFMT_RIGHT
Global lpPrevFunc, WnHdl.l, now.l, selected.l, eventFile$
TAG_CR$ = Chr(13)+Chr(10)
eventFile$=GetEnvironmentVariable("USERPROFILE") + "\MyEvents.txt"
eventBack$=GetEnvironmentVariable("USERPROFILE") + "\MyEvents.bak"
CopyFile(eventFile$,eventBack$) ; make backup so we can discard all changes
Debug eventFile$
If FileSize(eventFile$)= -1
  CreateFile(0,eventFile$)
  CloseFile(0)
EndIf

Structure Cells
  chronos.l
  Descript$
EndStructure

Global NewList Ocassion.Cells()

Procedure FixTitle()
  s$ = " Reminder" + FormatDate("%mm/%dd/%yyyy",Date())
  SetWindowTitle(1,s$)
EndProcedure

Procedure TopOfToday()
  Protected TODAY$
  TODAY$ = Str(Month(Date()))
  TODAY$ + "/" + Str(Day(Date()))
  TODAY$ + "/" + Str(Year(Date()))
  Debug TODAY$
  now=ParseDate("%mm/%dd/%yyyy", TODAY$)
  ProcedureReturn now
EndProcedure

Procedure reList()
  Protected place
  ;FixTitle()
  TopOfToday()
  SortStructuredList(Ocassion(), 0, OffsetOf(Cells\chronos), #PB_Long)
  place = 0
  ForEach Ocassion()
    date1 = Ocassion()\chronos
    days = (date1 - now) /86400
    If days = 0
      dayZero.l = #True
      GetLastInputInfo_(@lippi) ; no recent user activity so let show and animate 'reminder'
      timeNow.l = ElapsedMilliseconds() ; get current timestamp value for comparison calculations
      If timeNow.l - lippi\dwTime > 100
        AnimateReminder.l = #True
      EndIf
      event$ = "TODAY is"
      If IsWindowVisible_(WindowID(0))
        ResizeWindow(0, WindowX(1)+112, WindowY(1), #PB_Ignore, #PB_Ignore)
        HideWindow(1,0)
        ShowWindow_(WindowID(1),#SW_RESTORE)
        HideWindow(0,0)
      Else
        HideWindow(1,0)
        ShowWindow_(WindowID(1),#SW_RESTORE)
      EndIf ;                                               BBGGRR
      SetGadgetItemColor(2,  place, #PB_Gadget_BackColor,  $0F48FF, -1)
    ElseIf days = 1
      event$ = Str(days) + " day until"
      SetGadgetItemColor(2,  place, #PB_Gadget_BackColor,  $10F8F8, -1)
    ElseIf days < 2
      event$ = Str(days) + " day until"
      SetGadgetItemColor(2,  place, #PB_Gadget_BackColor,  $0AE0F0, -1)
    ElseIf days < 35
      event$ = Str(days) + " days until"
      SetGadgetItemColor(2,  place, #PB_Gadget_BackColor,  -1, -1)
    Else
      event$ = Str(days/7) + " weeks until"
      SetGadgetItemColor(2,  place, #PB_Gadget_BackColor,  -1, -1)
    EndIf
    SetGadgetItemText(2,place,event$,0)
    SetGadgetItemText(2,place,Ocassion()\Descript$,1)
    place + 1
  Next
EndProcedure

Procedure ModEntry()
  date1 = ParseDate("%mm/%dd/%yyyy",FormatDate("%mm/%dd/%yyyy",GetGadgetState(0)))
  SelectElement(Ocassion(), selected)
  Ocassion()\chronos = date1
  s$ = GetGadgetText(1)
  If s$ = ""
    s$ = "undefined event"
  EndIf
  Ocassion()\Descript$ = s$
  reList()
  DisableGadget(3,0)
  SetGadgetState(2,-1) ; deselect all items
EndProcedure

Procedure LoadEvents()
  Protected F1.l, F2$
  If ReadFile(0,eventFile$)
    If Lof(0) > 10
      Repeat
        F2$ = ReadString(0,#PB_Ascii)
        F1.l = Val(F2$)
        F2$ = ReadString(0,#PB_Ascii)
        AddElement(Ocassion())
        Ocassion()\chronos = F1
        Ocassion()\Descript$ = F2$
        AddGadgetItem(2,-1,"Loading...")
      Until Eof(0)
      reList()
      n = CountGadgetItems(2)-1
      SetGadgetState(2, n)
      SetGadgetItemState(2, n,0)
    EndIf
    CloseFile(0)
  EndIf
EndProcedure

Procedure SaveEvents()
  If CreateFile(0,eventFile$)
    ForEach Ocassion()
      F1 = Ocassion()\chronos
      F2$ = Str(F1)
      WriteStringN(0,F2$,#PB_Ascii)
      F2$ = Ocassion()\Descript$
      WriteStringN(0,F2$,#PB_Ascii)
    Next
    CloseFile(0)
  EndIf
EndProcedure
  
Procedure OLDJogReminder()
  Protected x, y
  Repeat
    x = Random(_x - 317)
  Until Abs(WindowX(1) - Abs(x)) > 100
  Repeat
    y = Random(_y - 199)
  Until Abs(WindowY(1) - Abs(y)) > 100
  ResizeWindow(1, Abs(x),Abs(y), #PB_Ignore,#PB_Ignore)
EndProcedure
Procedure JogReminder()
  Protected x, y
  Repeat
    x = Random(_x - 317,200)
  Until Abs(WindowX(1) - Abs(x)) > 100
  Repeat
    y = Random(_y - 199,200)
  Until Abs(WindowY(1) - Abs(y)) > 100
  Debug Str(x) +"  "+Str(y)
  ResizeWindow(1, Abs(x),Abs(y), #PB_Ignore,#PB_Ignore)
EndProcedure

Procedure TripTimer() ;system regulated - failproof interval trigger
  ; Goofy internal Timer_() callback workaround
  tripTimer1 = #True ; allows timer event to occur ONLY once on queue.
  SECOND.W = Second(Date())
  ; Required to prevent sluggish system after oneLook terminaltes.
EndProcedure

; &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

Structure MCHITTESTINFO
  cbSize.l
  pt.POINT
  uHIt.l
  st.SYSTEMTIME
EndStructure

Procedure WinCallback(WindowID1.l,message.l,wParam.l,lParam.l)
  Result.l = #PB_ProcessPureBasicEvents
  If WindowID1.l = WnHdl.l
    Select message
      Case #WM_LBUTTONDBLCLK
        mcht.MCHITTESTINFO\cbSize = SizeOf(MCHITTESTINFO)
        mcht\pt\x = DesktopMouseX()
        mcht\pt\y = DesktopMouseY()
        ScreenToClient_(GadgetID(0), @mcht\pt)
        SendMessage_(GadgetID(0),#MCM_HITTEST,0,mcht)
        If mcht\uHIt = #MCHT_CALENDARDATE
          Debug "Date selected through double-click : " + FormatDate("%mm/%dd/%yyyy",GetGadgetState(0))
          ModEntry()
          HideWindow(0,1)
          SetActiveGadget(2)
          SaveEvents()
        EndIf
    EndSelect
    CallDebugger
    Result = CallWindowProc_(lpPrevFunc,WindowID1.l,message,wParam,lParam)
  EndIf
  ProcedureReturn Result
EndProcedure

; &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
; Locate 24hr crossover in milliseconds for title change and list update
crossover.l = TopOfToday() + 86400  ; one full day into the future

; CREATE WINDOWS   CREATE WINDOWS   CREATE WINDOWS   CREATE WINDOWS   CREATE WINDOWS
If OpenWindow(#DateWindow,440,113,355,320,"Edit event and DoubleClick",#PB_Window_SystemMenu | #PB_Window_Invisible)
  LoadFont(1, "Segoe UI", 14)
  WnHdl.l = CalendarGadget(0,5,35,345,280)
  SetWindowTheme_(GadgetID(0), @"", @"")
  SetGadgetFont(0, FontID(1))
  lpPrevFunc = SetWindowLong_(GadgetID(0),#GWL_WNDPROC,@WinCallback())
  SetClassLong_(GadgetID(0),#GCL_STYLE,GetClassLong_(GadgetID(0),#GCL_STYLE) | #CS_DBLCLKS)
  StringGadget(1, 5, 10, 160, 20, "") ;, #ES_MULTILINE|#ES_AUTOVSCROLL|$10000000)
  SetGadgetAttribute(1,#PB_String_MaximumLength,24)  
  fontVerd9B.i = LoadFont(#PB_Default,"Verdana",34,#PB_Font_Bold)
  
  HWND1 = OpenWindow(#MainWindow, 312, 113, 570, 336, " Reminder", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_TitleBar)
  If HWND1
    LIG_Yval = 5
    ;      SetGadgetFont(2,FontID(fontVerd9B.i))
    If LoadFont(0, "Arial", 16)
      SetGadgetFont(#PB_Default, FontID(0))   ; Set the loaded Arial 16 font as new standard
    EndIf
    hLIG = ListIconGadget(2, 10, LIG_Yval, 553, 290, "", 170,   #PB_ListIcon_AlwaysShowSelection | #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect | #LVS_NOCOLUMNHEADER)
    AddGadgetColumn ( 2 ,1 , "" ,377 )
    GadgetToolTip(2, "This is my tip.")
    ;SendMessage_(GadgetID(2), #LVM_SETEXTENDEDLISTVIEWSTYLE, 0, #LVS_EX_LABELTIP) 
    SendMessage_(GadgetID(2), #LVM_SETCOLUMN, 0, @lvc)  ; Right justify column 1
    If LoadFont(1, "Arial", 12)
      SetGadgetFont(#PB_Default, FontID(1))   ; Set the loaded Arial 16 font as new standard
    EndIf
    ButtonGadget(3,10,300,155,23,"Add New Event")
    ButtonGadget(4,185,300,150,23,"Discard Event")
    ButtonGadget(5,350,300,195,23,"Discard All Changes")
    SetForegroundWindow_(WindowID(1))
    SetActiveWindow(1)
    LoadEvents()
    check.l = 10000 ; used to monitor ElapsedMilliseconds status
    ; Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
    ; End
    Repeat ; drop into timer initialization on first "even" second!
    Until (Second(Date()) % 2) =  0
    trip.l = SetTimer_(WindowID(1),0,2000,@TripTimer()) ; Timer set at 2000 = 2 seconds
    
    ;  TOP OF LOOP     TOP OF LOOP     TOP OF LOOP     TOP OF LOOP     TOP OF LOOP
    Repeat
      EventID.l=WaitWindowEvent(check.l)
      If GetForegroundWindow_() <> WindowID(#DateWindow)
        If IsWindowVisible_(WindowID(#DateWindow))
          HideWindow(0,1)
          DisableGadget(3,0)
          SetGadgetState(2,-1) ; deselect all items
        EndIf
      ElseIf EventID = #PB_Event_CloseWindow
        ;MessageRequester("LKJHGF","Good")
        EventID = 0
        HideWindow(0,1)
        reList()
        DisableGadget(3,0)
        SetGadgetState(2,-1) ; deselect all items
      EndIf
      Select EventID
        Case #WM_KEYDOWN  ;  PRESSED THE [ENTER} KEY
          Select EventwParam()
            Case #VK_ESCAPE
              If GetForegroundWindow_() = WindowID(#DateWindow)
                EventID = 0
                HideWindow(0,1)
                reList()
                DisableGadget(3,0)
                SetGadgetState(2,-1) ; deselect all items
                ;
                ;
                If AllowESC
                  selected.l = 0
                  SelectElement(Ocassion(), selected)
                  DeleteElement(Ocassion())
                  RemoveGadgetItem(2, selected)
                  SaveEvents()
                  AllowESC = #False
                EndIf 
              EndIf
            Case #VK_RETURN
              Select GetActiveWindow()
                Case #MainWindow
                  h.l = GetGadgetState(2) ; first selected item
                  If h.l > -1 ;Something selected so edit
                    ResizeWindow(#DateWindow, WindowX(1)+112, WindowY(1), #PB_Ignore, #PB_Ignore)
                    HideWindow(#DateWindow,0)
                    DisableGadget(3,1)
                    selected.l = GetGadgetState(2)
                    SelectElement(Ocassion(), selected)
                    date1 = Ocassion()\chronos
                    s$ = Ocassion()\Descript$
                    
                    SetGadgetState(0, date1)
                    SetGadgetText(1,s$)
                    SetActiveGadget(1)
                    h.l = Len(GetGadgetText(1))
                    SendMessage_(GadgetID(1), #EM_SETSEL, h, h) ; 
                    Repeat
                      WaitWindowEvent()
                    Until IsWindow(#DateWindow)
                    Repeat
                      WaitWindowEvent()
                    Until IsGadget(0)
                    While WindowEvent(): Wend
                  EndIf
                Case #DateWindow
                  ModEntry()
                  HideWindow(0,1)
                  SetActiveGadget(2)
                  SaveEvents()
              EndSelect
          EndSelect
        Case #PB_EventType_LostFocus ; useless message... so do nothing
        Case #PB_Event_Gadget
          If GetActiveGadget() = 1
            s$=GetGadgetText(1)
            h.l=FindString(s$,TAG_CR$,1) ; Stop CR/Esc Ding
            If h.l<>0  ; Was Enter pressed on the StringGadget?
              Debug "Pressed Enter on Calendar"
              SetGadgetText(1,ReplaceString(s$,TAG_CR$,"")) ; Yes, so remove CR+LF.
              SendMessage_(GadgetID(1), #EM_SETSEL, h.l-1, h.l-1)  ; Set cursor position back.
              While WindowEvent(): Wend
              Debug "Date selected through Enter Key : " + FormatDate("%mm/%dd/%yyyy",GetGadgetState(0))
              Debug GetGadgetState(0)
              ModEntry()
              HideWindow(0,1)
              SaveEvents()
            EndIf
          EndIf
          Select EventGadget()
            Case 1
              While WindowEvent(): Wend
            Case 2  ;  DOUBLECLICK TO EDIT EVENT
              If EventType() = #PB_EventType_LeftDoubleClick
                If GetGadgetState(2) > -1
                  ResizeWindow(#DateWindow, WindowX(1)+112, WindowY(1), #PB_Ignore, #PB_Ignore)
                  HideWindow(#DateWindow,0)
                  DisableGadget(3,1)
                  selected.l = GetGadgetState(2)
                  If selected > -1
                    SelectElement(Ocassion(), selected)
                    date1 = Ocassion()\chronos
                    s$ = Ocassion()\Descript$
                    
                    SetGadgetState(0, date1)
                    SetGadgetText(1,s$)
                    SetActiveGadget(1)
                    h.l = Len(GetGadgetText(1))
                    SendMessage_(GadgetID(1), #EM_SETSEL, h, h) ; 
                    Repeat
                      WaitWindowEvent()
                    Until IsWindow(#DateWindow)
                    Repeat
                      WaitWindowEvent()
                    Until IsGadget(0)
                    While WindowEvent(): Wend
                  EndIf
                EndIf
              EndIf
            Case 3 ; ADD NEW EVENT
              If GetForegroundWindow_() = WindowID(1)
                AllowESC = #True
                Debug "add event"
                DisableGadget(3,1)
                AddGadgetItem(2,0,"1 day until")
                SetGadgetItemText(2,0,"undefined event",1)
                selected.l = 0
                SelectElement(Ocassion(), selected)
                InsertElement(Ocassion())
                
                TopOfToday()
                date1 = ParseDate("%mm/%dd/%yyyy",FormatDate("%mm/%dd/%yyyy",now + 86400))
                SetGadgetState(0, date1)
                Debug now
                Debug date1
                Debug date1 - now
                SelectElement(Ocassion(), selected)
                Ocassion()\chronos = date1
                Ocassion()\Descript$ = "undefined event"
                
                date1 = Ocassion()\chronos
                days = (date1 - now) /86400
                event$ = Str(days) + " days until"
                SetGadgetItemText(2,0,event$,0)
                SetGadgetItemText(2,0,Ocassion()\Descript$,1)
                ResizeWindow(#DateWindow, WindowX(1)+112, WindowY(1), #PB_Ignore, #PB_Ignore)
                HideWindow(#DateWindow,0)
                SetGadgetText(1,"undefined event")
                SetActiveGadget(2)
                SetActiveGadget(1)
                h.l = Len(GetGadgetText(1))
                SendMessage_(GadgetID(1), #EM_SETSEL, 0, h.l) ; 
                Repeat
                  WaitWindowEvent()
                Until IsWindow(#DateWindow)
                Repeat
                  WaitWindowEvent()
                Until IsGadget(0)
                While WindowEvent(): Wend
              EndIf
              
            Case 4 ; DISCARD SELECTED EVENT
              Debug "discard event"
              If GetGadgetState(2) = -1
                MessageRequester(" Nothing To Do", "Please highlight an item in the list and try again. ", #MB_OK)
              Else
                Select MessageRequester(" Delete Event From The List", "Are you sure you want to delete the selected event?  ", #MB_YESNO)
                  Case #IDYES
                    selected.l = GetGadgetState(2)
                    SelectElement(Ocassion(), selected)
                    DeleteElement(Ocassion())
                    RemoveGadgetItem(2, selected)
                    SaveEvents()
                EndSelect
                SetGadgetState(2,-1) ; deselect all items
              EndIf
              SetActiveGadget(2)
            Case 5 ; FULL REVERT 
              Debug "discard all changes"
              Select MessageRequester(" Discard All Changes", "         Discard all changes" + Chr(10) + "     and revert to original list?  ", #MB_YESNO)
                Case #IDYES
                  ClearList(Ocassion())
                  ClearGadgetItems(2)
                  CopyFile(eventBack$,eventFile$) ; make backup so we can discard all changes
                  LoadEvents()
              EndSelect
              SetActiveGadget(2)
          EndSelect
        Default
          If AnimateReminder = #True
            Debug "should be Jogging"
            GetLastInputInfo_(@lippi)
            timeNow.l = ElapsedMilliseconds() ; get current timestamp value for comparison calculations
            If timeNow.l - lippi\dwTime > 1500 ; user fell asleep so jog the reminder window
              If tripTimer1
                jog + 1
                tripTimer1 = #False ; disable timer events.
              EndIf
              If jog > 1
                JogReminder()
                jog = 0
              EndIf
            Else
              HideWindow(#MainWindow,0)
              SetForegroundWindow_(HWND1)
              SetActiveWindow(1)
              ResizeWindow(#MainWindow, _x/2-160, _y/2-100, #PB_Ignore,#PB_Ignore)
              AnimateReminder.l = #False
              check.l = 1000 ; restore normal monitoring on main loop
            EndIf
          Else
            Debug "Not Jogging"
            If dayZero.l = #True
              If GetForegroundWindow_() <> HWND1 ; don't bother if already doing HWND1 'reminder'
                GetLastInputInfo_(@lippi)
                timeNow.l = ElapsedMilliseconds() ; get current timestamp value for comparison calculations
                If timeNow.l - lippi\dwTime > 300000 ; No recent user activity so lets show and animate 'reminder'
                  HideWindow(1,0)
                  ReallySetForegroundWindow(WindowID(1))
                  SetActiveWindow(1)
                  AnimateReminder.l = #True
                  check.l = 50 ; expidite monitoring so we can quickly restore normal monitoring
                EndIf
              EndIf
            EndIf
            GetCursorPos_(@CursorPosition.POINT) 
            a1.l = WindowFromPoint_(CursorPosition\y<<  32 + CursorPosition\x) ;where on the screen?
            If a1 = hLIG  ;  using a1 to validate mouse inside #MyGadget
              Debug " _ _ _ _ INSIDE THE LIST _ _ _ _"
              y = ((WindowMouseY(1)) - LIG_Yval)
              Debug "y = " + Str(y)
              If y > 2 ; Adjust y value to compensate for column_header_height
                y - 3  ; Adjust y value to compensate for column_header_height 
                itemLine = y / 14  ; Divide y by pixel_height given to single_line_item.
                Debug "itemLine = " + Str(itemLine)
                If lastLine <> itemLine ; Anti-Flicker -- update tooltip only if required
                  If itemLine < CountGadgetItems(2) ; Range restriction
                    SelectElement(Ocassion(), itemLine)
                    date1 = Ocassion()\chronos
                    s$ = " " + FormatDate("%mm/%dd/%yyyy",date1) + " is " + Ocassion()\Descript$ + " "
                  Else ; out of range
                    s$ = " DoubleClick item to edit an event or Single click" +Chr(13)+Chr(10)+ "To highlight an event And press enter To edit," +Chr(13)+Chr(10)+ "Or click [Delete eevent] To remove it.  "
                  EndIf
                  Debug itemLine
                  GadgetToolTip(2, s$)
                EndIf
                lastLine = itemLine
              EndIf
            EndIf
          EndIf
          Debug "check"
          If crossover.l - Date() < check.l ; <<< Check value is usesd in WaitWindowEvent() to force time checks
            check.l = 500 ; expidite monitoring when approaching crossover to new day
          EndIf
          If Date() >= crossover.l
            Debug "Crossover to next day"
            reList() ; will adjust title date and countdown values in the list
            crossover.l + 86400 ; increment trigger to next day
            check.l = 10000 ; revert to non-aggressive ElapsedMilliseconds monitoring
          EndIf
      EndSelect
      If EventID=#PB_Event_CloseWindow
        DisableGadget(2,1)
        Select MessageRequester("  Event Reminder", "                     Reminder will Minimize or Quit." + Chr(10) + "                        Do you really want to Quit?", #MB_YESNOCANCEL)
          Case #IDNO
            DisableGadget(2,0)
            SetWindowState(1,#PB_Window_Minimize)
            EventID.l=WaitWindowEvent(check.l)
          Case #IDCANCEL
            DisableGadget(2,0)
            EventID=0
        EndSelect
      EndIf
    Until EventID=#PB_Event_CloseWindow
    ; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ;eventFile$="E:\Temp\MyEvent.txt"
    SaveEvents()
    CloseWindow(1)
    CloseWindow(0)
  EndIf
EndIf
Last edited by Randy Walker on Sun Dec 01, 2024 6:00 am, edited 9 times in total.
- - - - - - - - - - - - - - - -
Randy
I *never* claimed to be a programmer.
User avatar
oryaaaaa
Addict
Addict
Posts: 825
Joined: Mon Jan 12, 2004 11:40 pm
Location: Okazaki, JAPAN

Re: A Personal *Event Coundown Reminder* (Feedback Welcome)

Post by oryaaaaa »

I tested your app.
  • I alway use cell phone event reminder.
  • You should use StartDrawing(Windowoutput()), then use graphical interface.
  • coz Windows gadget is a fairy tale.
  • and USB Portable app target
  • Event name shortcut action
Japanese cell phone event remider
  • 2 month calender displayed
  • Please select event, holiday or aniversery?
  • 1.Icon Select
  • 2.day and night?
  • 3.start time/day
  • 4.finish time/day
  • 5.repeat? (day, week, monthry, year)
  • 6.Alarm ( annouce, prepare announce, off)
  • 7.Alarm sound ( FullSong/Melody, Music, Movie, OFF)
  • 8.event detail
Randy Walker
Addict
Addict
Posts: 991
Joined: Sun Jul 25, 2004 4:21 pm
Location: USoA

Re: A Personal *Event Coundown Reminder* (Feedback Welcome)

Post by Randy Walker »

Hi oryaaaaa :)
I guess I should have explained the exact intent of this little utility. To begin, I should also explain that I am ''chronologically challenged'' (to be politically correct). I have a big problem with people using dates on a calendar. Would be easier for me if weeks were all 10 days and months were 100 days... you know. Something less abstact than 7, 31 or 28, or 30 and sometimes 29 :shock:

I have a simple brain with simple capacitly so calendar dates just cause my brain to short circuit. On the other hand, when someone says 3 days from now, thats something I can easily relate to. You probably never have that problem. What I need for a scheduler is a very plain and dry list that shows days until the event and a short description. Short and simple. Thats me. (yeh, well... whatever :oops: )

Anyway, not indended to be glamorous in any way. Don't need alarms and whistles to make the world a noisier place. I can tell time of day so if I just have an item in my reminder that says '' 1 days until Dentist appnt at 2:30pm'' then thats enough to keep me on track.

Japan :!: :?: People in Japan really using PuireBasic? Thats too cool! Shoot me a note if you ever visit Bangkok.
- - - - - - - - - - - - - - - -
Randy
I *never* claimed to be a programmer.
MachineCode
Addict
Addict
Posts: 1482
Joined: Tue Feb 22, 2011 1:16 pm

Re: A Personal *Event Coundown Reminder* (Feedback Welcome)

Post by MachineCode »

Love the dentist joke... it never gets old. :)
Microsoft Visual Basic only lasted 7 short years: 1991 to 1998.
PureBasic: Born in 1998 and still going strong to this very day!
User avatar
oryaaaaa
Addict
Addict
Posts: 825
Joined: Mon Jan 12, 2004 11:40 pm
Location: Okazaki, JAPAN

Re: A Personal *Event Coundown Reminder* (Feedback Welcome)

Post by oryaaaaa »

I hate PuireBasic.

There is a special forum of PureBasic in the bulletin board that a special security force in Japan uses.
Because their request for participation standards were very high, I cannot pass it.
The forum was started up for myself therefore.

A special security force is excellent.
Middleware that beats the band without relying on the library in the foreign country is made.
As for me, they cannot oppose it.

A special security force Solicitation video

It's a Joke.

True story
The annual income of the software engineer of Japan is one million dollar.
Why is PureBasic needed though they are using Visual Studio Team Edition?
I introduced it to the community of Ubunutu.
However, they say for expensive PureBasic that to buy by 1/4 of the daily wages is high.

It's a Joke.

If you are new development, I have software that wants you to make it.
Trac like standalone, Version management in Purebasic
http://trac.edgewall.org/
Randy Walker
Addict
Addict
Posts: 991
Joined: Sun Jul 25, 2004 4:21 pm
Location: USoA

Re: A Personal *Event Coundown Reminder* (Feedback Welcome)

Post by Randy Walker »

MachineCode wrote:Love the dentist joke... it never gets old. :)
Ok, I edited code in my original post so it no longer shows '' 1 days until ...''
Now it shows '' 1 day until...' (<<singular) and I added background color to the '1day' and current day events.
Also did some houskeeping/renovation to throw out redundant code and organize the overall code.
- - - - - - - - - - - - - - - -
Randy
I *never* claimed to be a programmer.
MachineCode
Addict
Addict
Posts: 1482
Joined: Tue Feb 22, 2011 1:16 pm

Re: A Personal *Event Coundown Reminder* (Feedback Welcome)

Post by MachineCode »

The joke wasn't about "day" or "days" (singular/plural). It was something else. Was it not intentional :?:
Microsoft Visual Basic only lasted 7 short years: 1991 to 1998.
PureBasic: Born in 1998 and still going strong to this very day!
User avatar
HeX0R
Addict
Addict
Posts: 1189
Joined: Mon Sep 20, 2004 7:12 am
Location: Hell

Re: A Personal *Event Coundown Reminder* (Feedback Welcome)

Post by HeX0R »

Code: Select all

Procedure LoadEvents()
  If ReadFile(0,source$)
    If Lof(0) > 10
      Repeat
        F2$ = ReadString(0,#PB_Ascii)
        F1.l = Val(F2$)
        F2$ = ReadString(0,#PB_Ascii)
        AddElement(Ocassion())
        Ocassion()\chronos = F1
        Ocassion()\Descript$ = F2$
        AddGadgetItem(2,-1,"Loading...")
      Until Eof(0)
      CloseFile(0)
      refresh()
    EndIf
  EndIf
EndProcedure
If the file is less then 11 Bytes, it will never get closed.
Randy Walker
Addict
Addict
Posts: 991
Joined: Sun Jul 25, 2004 4:21 pm
Location: USoA

Re: A Personal *Event Coundown Reminder* (Feedback Welcome)

Post by Randy Walker »

HeX0R wrote:

Code: Select all

      Until Eof(0)
      refresh()
      CloseFile(0)  ; REMOVED THIS LINE !!!
    EndIf
    CloseFile(0)  ; ADDED THIS LINE
  EndIf
EndProcedure
If the file is less then 11 Bytes, it will never get closed.
Ouch!! Eww, yuck!! See now why I never claim to be a programmer.

Thanks HeXOR ... I also corrected code in my original post at top of this thread.
- - - - - - - - - - - - - - - -
Randy
I *never* claimed to be a programmer.
Randy Walker
Addict
Addict
Posts: 991
Joined: Sun Jul 25, 2004 4:21 pm
Location: USoA

Re: A Personal *Event Coundown Reminder* (Feedback Welcome)

Post by Randy Walker »

MachineCode wrote:The joke wasn't about "day" or "days" (singular/plural). It was something else. Was it not intentional :?:
Oh Crap :? I made a joke and don't even know what it is :o
No, I really have no clue what the joke was. What's the punchline? Er, uh. What was the joke? :oops:
I hate it when that happens :lol:

BTW: I updated code listing in the original post. More housekeeping. More comment lines. More bug fixes.
- - - - - - - - - - - - - - - -
Randy
I *never* claimed to be a programmer.
MachineCode
Addict
Addict
Posts: 1482
Joined: Tue Feb 22, 2011 1:16 pm

Re: A Personal *Event Coundown Reminder* (Feedback Welcome)

Post by MachineCode »

Randy Walker wrote:Oh Crap :? I made a joke and don't even know what it is :o
No, I really have no clue what the joke was. What's the punchline? Er, uh. What was the joke? :oops:
I hate it when that happens :lol:
Okay, here it is:
Randy Walker wrote:1 days until Dentist appnt at 2:30pm
Now do you get it? ;)
Microsoft Visual Basic only lasted 7 short years: 1991 to 1998.
PureBasic: Born in 1998 and still going strong to this very day!
Randy Walker
Addict
Addict
Posts: 991
Joined: Sun Jul 25, 2004 4:21 pm
Location: USoA

Re: A Personal *Event Coundown Reminder* (Feedback Welcome)

Post by Randy Walker »

MachineCode wrote:Okay, here it is:
Randy Walker wrote:1 days until Dentist appnt at 2:30pm
Now do you get it? ;)
Nooo :? Call me dense. :|
Are you reading that?: ''One daze until dentist appointment at 2:30 PM.''
I don't get it. :(
- - - - - - - - - - - - - - - -
Randy
I *never* claimed to be a programmer.
MachineCode
Addict
Addict
Posts: 1482
Joined: Tue Feb 22, 2011 1:16 pm

Re: A Personal *Event Coundown Reminder* (Feedback Welcome)

Post by MachineCode »

Randy Walker wrote:I don't get it. :(
http://www.urbandictionary.com/define.p ... th%20hurty

8)
Microsoft Visual Basic only lasted 7 short years: 1991 to 1998.
PureBasic: Born in 1998 and still going strong to this very day!
User avatar
Demivec
Addict
Addict
Posts: 4260
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: A Personal *Event Coundown Reminder* (Feedback Welcome)

Post by Demivec »

MachineCode wrote:Randy Walker wrote:
I don't get it.

http://www.urbandictionary.com/define.p ... th%20hurty
That is funny, thanks for explaining it to us less observant types. :)
Randy Walker
Addict
Addict
Posts: 991
Joined: Sun Jul 25, 2004 4:21 pm
Location: USoA

Re: A Personal *Event Coundown Reminder* (Feedback Welcome)

Post by Randy Walker »

Thought I would recompile using v6.12 but ran into a couple issues -- one minor issue and one catastrophic. Fonts used in my original creation were too big for the listbox and buttons so I've made changes there as seen in the code posted below.

The catastrophic issue is a crash with when I double click an item in the list or click add event:
"The Debugged Executable Quit Unexpectedly"
No clue why or what caused this, but net result is Unuseable.

Code: Select all

; Snipppet from 'Fluid byte' over there in the German forum
; used here as base starting point for 'Event Countdown Reminder':
; http://www.purebasic.fr/german/viewtopic.php?t=17692&start=4

; With special thanks to members of this thread:
; http://www.purebasic.fr/english/viewtopic.php?f=13&t=38387
;Define.i
Global active.w, targetWindow$, hWin.l
Procedure.l ListWindows(Window, Parameter) ; used inside Gt_Prog()
  ;  WindowClass.s = Space(255) 
  WindowTitle.s = Space(255) 
  ; e.l = GetWindowLong_(Window,#GWL_ID) ; PB Window_# (0,1,2,3, etc)
  ; GetClassName_(Window, WindowClass, 255) 
  GetWindowText_(Window, WindowTitle, 255)
  WindowTitle = LCase(WindowTitle)
  If LCase(WindowTitle) = targetWindow$
    active.w = 1
    hWin.l = Window
  ElseIf Left(WindowTitle,11) = targetWindow$
    active.w = 1
    hWin.l = Window
  ElseIf Left(WindowTitle,6) = Left(targetWindow$,6) ; "From: "
    If Right(WindowTitle,9) = Right(targetWindow$,9) ; " - E-mail"
      If Left(WindowTitle,6) <> Right(targetWindow$,6)
        active.w = 1
        hWin.l = Window
      EndIf
    EndIf
  EndIf 
  ProcedureReturn #True  
EndProcedure
Procedure Gt_Prog(dmy$)   ;   input : 11 char PROCESS name  ,  active.w = true if running : hWin.l holds Window handle
  targetWindow$ = LCase(dmy$)
  active.w = 0
  hWin.l = 0
  EnumWindows_(@ListWindows(), 0) ; Windows CallBack operation.
  ProcedureReturn active.w
EndProcedure
If Gt_Prog(" Event Coun")   ; Prevent 2nd instance if already running
  SetForegroundWindow_(hWin.l) ; and bring current instance into foreground.
  ShowWindow_(hWin.l, #SW_RESTORE)
  Delay(250)
  Debug "already running"
  ;While WindowEvent() <> 0 : Wend
  End ; Quit from this duplicate instance.
EndIf  

#MCM_HITTEST = #MCM_FIRST + 14
#MCHT_CALENDAR = $20000
#MCHT_CALENDARDATE = #MCHT_CALENDAR | $0001
lvc.LV_COLUMN  ; set up structure for global use to format ListIconGadget columns
lvc\mask = #LVCF_FMT
lvc\fmt  = #LVCFMT_RIGHT
Global lpPrevFunc, WnHdl.l, now.l, selected.l, eventFile$
TAG_CR$ = Chr(13)+Chr(10)
eventFile$=GetEnvironmentVariable("USERPROFILE") + "\MyEvents.txt"
If FileSize(eventFile$)= -1
  CreateFile(0,eventFile$)
  CloseFile(0)
EndIf

Structure Cells
  chronos.l
  Descript$
EndStructure

Global NewList Ocassion.Cells()

Procedure FixTitle()
  s$ = " Event Coundown Reminder  " + FormatDate("%mm/%dd/%yyyy",Date())
  SetWindowTitle(1,s$)
EndProcedure

Procedure TopOfToday()
  Protected TODAY$
  TODAY$ = Str(Month(Date()))
  TODAY$ + "/" + Str(Day(Date()))
  TODAY$ + "/" + Str(Year(Date()))
  Debug TODAY$
  now=ParseDate("%mm/%dd/%yyyy", TODAY$)
  ProcedureReturn now
EndProcedure

Procedure reList()
  Protected place
  ;FixTitle()
  TopOfToday()
  ;SortStructuredList(Ocassion(), 0, OffsetOf(Cells\chronos), #PB_Sort_Long)
  SortStructuredList(Ocassion(), 0, OffsetOf(Cells\chronos), #PB_Long)
  place = 0
  ForEach Ocassion()
    date1 = Ocassion()\chronos
    days = (date1 - now) /86400
    If days = 0
      event$ = "TODAY is"
      If IsWindowVisible_(WindowID(0))
        ResizeWindow(0, WindowX(1)+112, WindowY(1), #PB_Ignore, #PB_Ignore)
        HideWindow(1,0)
        ShowWindow_(WindowID(1),#SW_RESTORE)
        HideWindow(0,0)
      Else
        HideWindow(1,0)
        ShowWindow_(WindowID(1),#SW_RESTORE)
      EndIf ;                                               BBGGRR
      SetGadgetItemColor(2,  place, #PB_Gadget_BackColor,  $10F8F8, -1)
    ElseIf days < 2
      event$ = Str(days) + " day until"
      SetGadgetItemColor(2,  place, #PB_Gadget_BackColor,  $0AE0F0, -1)
    ElseIf days < 35
      event$ = Str(days) + " days until"
      SetGadgetItemColor(2,  place, #PB_Gadget_BackColor,  -1, -1)
    Else
      event$ = Str(days/7) + " weeks until"
      SetGadgetItemColor(2,  place, #PB_Gadget_BackColor,  -1, -1)
    EndIf
    SetGadgetItemText(2,place,event$,0)
    SetGadgetItemText(2,place,Ocassion()\Descript$,1)
    place + 1
  Next
EndProcedure

Procedure ModEntry()
  date1 = ParseDate("%mm/%dd/%yyyy",FormatDate("%mm/%dd/%yyyy",GetGadgetState(0)))
  SelectElement(Ocassion(), selected)
  Ocassion()\chronos = date1
  s$ = GetGadgetText(1)
  If s$ = ""
    s$ = "undefined event"
  EndIf
  Ocassion()\Descript$ = s$
  reList()
  DisableGadget(3,0)
  SetGadgetState(2,-1) ; deselect all items
EndProcedure

Procedure LoadEvents()
  Protected F1.l, F2$
  If ReadFile(0,eventFile$)
    If Lof(0) > 10
      Repeat
        F2$ = ReadString(0,#PB_Ascii)
        F1.l = Val(F2$)
        F2$ = ReadString(0,#PB_Ascii)
        AddElement(Ocassion())
        Ocassion()\chronos = F1
        Ocassion()\Descript$ = F2$
        AddGadgetItem(2,-1,"Loading...")
      Until Eof(0)
      reList()
    EndIf
    CloseFile(0)
  EndIf
EndProcedure

; &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

Structure MCHITTESTINFO
  cbSize.l
  pt.POINT
  uHIt.l
  st.SYSTEMTIME
EndStructure

Procedure WinCallback(WindowID1.l,Message.l,wParam.l,lParam.l)
  Result.l = #PB_ProcessPureBasicEvents
  If WindowID1.l = WnHdl.l
    Select Message
      Case #WM_LBUTTONDBLCLK
        mcht.MCHITTESTINFO\cbSize = SizeOf(MCHITTESTINFO)
        mcht\pt\x = DesktopMouseX()
        mcht\pt\y = DesktopMouseY()
        ScreenToClient_(GadgetID(0), @mcht\pt)
        SendMessage_(GadgetID(0),#MCM_HITTEST,0,mcht)
        If mcht\uHIt = #MCHT_CALENDARDATE
          Debug "Date selected through double-click : " + FormatDate("%mm/%dd/%yyyy",GetGadgetState(0))
          ModEntry()
          HideWindow(0,1)
          SetActiveGadget(2)
        EndIf
    EndSelect
    ProcedureReturn CallWindowProc_(lpPrevFunc,WindowID1.l,Message,wParam,lParam)
  EndIf
  ProcedureReturn Result
EndProcedure

; &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
; Locate 24hr crossover in milliseconds for title change and list update
crossover.l = TopOfToday() + 86400  ; one full day into the future

; CREATE WINDOWS   CREATE WINDOWS   CREATE WINDOWS   CREATE WINDOWS   CREATE WINDOWS
  ;LoadFont(1, "Segoe UI", 24)
  LoadFont(1, "Rockwell", 24)
If OpenWindow(0,440,113, 250, 230,"Edit event and DoubleClick",#PB_Window_SystemMenu | #PB_Window_Invisible)
  WnHdl.l = CalendarGadget(0,5,35, 240, 220)
  SetWindowTheme_(GadgetID(0), @"", @"")
  SetGadgetFont(0, FontID(1))
  lpPrevFunc = SetWindowLong_(GadgetID(0),#GWL_WNDPROC,@WinCallback())
  SetClassLong_(GadgetID(0),#GCL_STYLE,GetClassLong_(GadgetID(0),#GCL_STYLE) | #CS_DBLCLKS)
  ;LoadFont(1, "Segoe UI", 12)
  StringGadget(1, 5, 10, 195, 20, "", #ES_MULTILINE|#ES_AUTOVSCROLL|$10000000)
  
  If OpenWindow(1, 312, 113, 317, 215, " Event Coundown Reminder", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_TitleBar)
    LIG_Yval = 5
    hLIG = ListIconGadget(2, 10, LIG_Yval, 298, 184, "", 80,   #PB_ListIcon_AlwaysShowSelection | #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect | #LVS_NOCOLUMNHEADER)
    AddGadgetColumn ( 2 ,1 , "" ,196 )
    GadgetToolTip(2, "This is my tip.")
    ;SendMessage_(GadgetID(2), #LVM_SETEXTENDEDLISTVIEWSTYLE, 0, #LVS_EX_LABELTIP) 
    SendMessage_(GadgetID(2), #LVM_SETCOLUMN, 0, @lvc)  ; Right justify column 1
    LoadFont(1, "Arial Rounded MT Bold", 8)
    SetGadgetFont(#PB_Default, FontID(1))
    ButtonGadget(3,15,190,90,17,"Add New Event")
    ButtonGadget(4,110,190,80,17,"Discard Event")
    ButtonGadget(5,193,190,110,17,"Discard All Changes")
    SetForegroundWindow_(WindowID(1))
    SetActiveWindow(1)
    LoadEvents()
    check.l = 10000 ; used to monitor ElapsedMilliseconds status
    
    ;  TOP OF LOOP     TOP OF LOOP     TOP OF LOOP     TOP OF LOOP     TOP OF LOOP
    Repeat
      EventID.l=WaitWindowEvent(check.l)
      If GetForegroundWindow_() <> WindowID(0)
        If IsWindowVisible_(WindowID(0))
          HideWindow(0,1)
          DisableGadget(3,0)
          SetGadgetState(2,-1) ; deselect all items
        EndIf
      ElseIf EventID = #PB_Event_CloseWindow
        EventID = 0
        HideWindow(0,1)
        reList()
        DisableGadget(3,0)
        SetGadgetState(2,-1) ; deselect all items
      EndIf
      Select EventID
        Case #WM_KEYDOWN  ;  PRESSED THE [ENTER} KEY
          Select EventwParam()
            Case #VK_RETURN
              h.l = GetGadgetState(2) ; first selected item
              If h.l > -1 ;Domething selected so edit
                If GetActiveWindow() = 1
                  ResizeWindow(0, WindowX(1)+112, WindowY(1), #PB_Ignore, #PB_Ignore)
                  HideWindow(0,0)
                  DisableGadget(3,1)
                  selected.l = GetGadgetState(2)
                  SelectElement(Ocassion(), selected)
                  date1 = Ocassion()\chronos
                  s$ = Ocassion()\Descript$
                  
                  SetGadgetState(0, date1)
                  SetGadgetText(1,s$)
                  SetActiveGadget(1)
                  h.l = Len(GetGadgetText(1))
                  SendMessage_(GadgetID(1), #EM_SETSEL, h, h) ; 
                  Repeat
                    WaitWindowEvent()
                  Until IsWindow(0)
                  Repeat
                    WaitWindowEvent()
                  Until IsGadget(0)
                  While WindowEvent(): Wend
                EndIf
              EndIf
          EndSelect
        Case #PB_EventType_LostFocus ; useless message... so do nothing
        Case #PB_Event_Gadget
          If GetActiveGadget() = 1
            s$=GetGadgetText(1)
            h.l=FindString(s$,TAG_CR$,1) ; Stop CR/Esc Ding
            If h.l<>0  ; Was Enter pressed on the StringGadget?
              Debug "Pressed Enter on Calendar"
              SetGadgetText(1,ReplaceString(s$,TAG_CR$,"")) ; Yes, so remove CR+LF.
              SendMessage_(GadgetID(1), #EM_SETSEL, h.l-1, h.l-1)  ; Set cursor position back.
              While WindowEvent(): Wend
              Debug "Date selected through Enter Key : " + FormatDate("%mm/%dd/%yyyy",GetGadgetState(0))
              Debug GetGadgetState(0)
              ModEntry()
              HideWindow(0,1)
            EndIf
          EndIf
          Select EventGadget()
            Case 1
              While WindowEvent(): Wend
            Case 2  ;  DOUBLECLICK TO EDIT EVENT
              If EventType() = #PB_EventType_LeftDoubleClick
                If GetGadgetState(2) <> -1
                  Debug "Ok"
                  ResizeWindow(0, WindowX(1)+112, WindowY(1), #PB_Ignore, #PB_Ignore)
                  HideWindow(0,0)
                  DisableGadget(3,1)
                  selected.l = GetGadgetState(2)
                  SelectElement(Ocassion(), selected)
                  date1 = Ocassion()\chronos
                  s$ = Ocassion()\Descript$
                  
                  SetGadgetState(0, date1)
                  SetGadgetText(1,s$)
                  SetActiveGadget(1)
                  h.l = Len(GetGadgetText(1))
                  SendMessage_(GadgetID(1), #EM_SETSEL, h, h) ; 
                  Repeat
                    WaitWindowEvent()
                  Until IsWindow(0)
                  Repeat
                    WaitWindowEvent()
                  Until IsGadget(0)
                  While WindowEvent(): Wend
                EndIf
              EndIf
            Case 3 ; ADD NEW EVENT
              If GetForegroundWindow_() = WindowID(1)
                Debug "add event"
                DisableGadget(3,1)
                AddGadgetItem(2,0,"1 day until")
                SetGadgetItemText(2,0,"undefined event",1)
                selected.l = 0
                SelectElement(Ocassion(), selected)
                InsertElement(Ocassion())
                
                TopOfToday()
                date1 = ParseDate("%mm/%dd/%yyyy",FormatDate("%mm/%dd/%yyyy",now + 86400))
                SetGadgetState(0, date1)
                Debug now
                Debug date1
                Debug date1 - now
                SelectElement(Ocassion(), selected)
                Ocassion()\chronos = date1
                Ocassion()\Descript$ = "undefined event"
                
                date1 = Ocassion()\chronos
                days = (date1 - now) /86400
                event$ = Str(days) + " days until"
                SetGadgetItemText(2,0,event$,0)
                SetGadgetItemText(2,0,Ocassion()\Descript$,1)
                ResizeWindow(0, WindowX(1)+112, WindowY(1), #PB_Ignore, #PB_Ignore)
                HideWindow(0,0)
                SetGadgetText(1,"undefined event")
                SetActiveGadget(2)
                SetActiveGadget(1)
                h.l = Len(GetGadgetText(1))
                SendMessage_(GadgetID(1), #EM_SETSEL, 0, h.l) ; 
                Repeat
                  WaitWindowEvent()
                Until IsWindow(0)
                Repeat
                  WaitWindowEvent()
                Until IsGadget(0)
                While WindowEvent(): Wend
              EndIf
              
            Case 4 ; DISCARD SELECTED EVENT
              Debug "discard event"
              If GetGadgetState(2) = -1
                MessageRequester(" Nothing To Do", "Please highlight an item in the list and try again. ", #MB_OK)
              Else
                Select MessageRequester(" Delete Event From The List", "Are you sure you want to delete the selected event?  ", #MB_YESNO)
                  Case #IDYES
                    selected.l = GetGadgetState(2)
                    SelectElement(Ocassion(), selected)
                    DeleteElement(Ocassion())
                    RemoveGadgetItem(2, selected)
                EndSelect
                SetGadgetState(2,-1) ; deselect all items
              EndIf
              SetActiveGadget(2)
            Case 5 ; FULL REVERT 
              Debug "discard all changes"
              Select MessageRequester(" Discard All Changes", "         Discard all changes" + Chr(10) + "     and revert to original list?  ", #MB_YESNO)
                Case #IDYES
                  ClearList(Ocassion())
                  ClearGadgetItems(2)
                  LoadEvents()
              EndSelect
              SetActiveGadget(2)
          EndSelect
        Default
          GetCursorPos_(@CursorPosition.POINT) 
          a1.l = WindowFromPoint_(CursorPosition\y<<  32 + CursorPosition\x) ;where on the screen?
          If a1 = hLIG  ;  using a1 to validate mouse inside #MyGadget
            Debug " _ _ _ _ INSIDE THE LIST _ _ _ _"
            y = ((WindowMouseY(1)) - LIG_Yval)
            Debug "y = " + Str(y)
            If y > 2 ; Adjust y value to compensate for column_header_height
              y - 3  ; Adjust y value to compensate for column_header_height 
              itemLine = y / 14  ; Divide y by pixel_height given to single_line_item.
              Debug "itemLine = " + Str(itemLine)
              itemLine + SendMessage_(hLIG,#LVM_GETTOPINDEX,0,0)
              If lastLine <> itemLine ; Anti-Flicker -- update tooltip only if required
                If itemLine < CountGadgetItems(2) ; Range restriction
                  SelectElement(Ocassion(), itemLine)
                  date1 = Ocassion()\chronos
                  s$ = " " + FormatDate("%mm/%dd/%yyyy",date1) + " is " + Ocassion()\Descript$ + " "
                Else ; out of range
                  s$ = " DoubleClick item to edit an event "
                EndIf
                GadgetToolTip(2, s$)
              EndIf
              lastLine = itemLine
            EndIf
          EndIf
          Debug "check"
          If crossover.l - Date() < check.l ; <<< Check value is usesd in WaitWindowEvent() to force time checks
            check.l = 500 ; expidite monitoring when approaching crossover to new day
          EndIf
          If Date() >= crossover.l
            Debug "Crossover to next day"
            reList() ; will adjust title date and countdown values in the list
            crossover.l + 86400 ; increment trigger to next day
            check.l = 10000 ; revert to non-aggressive ElapsedMilliseconds monitoring
          EndIf
      EndSelect
      If EventID=#PB_Event_CloseWindow
        Select MessageRequester("  Event Reminder", "               Reminder will Minimize or Quit." + Chr(10) + "                 Do you really want to Quit?", #MB_YESNOCANCEL|#MB_DEFBUTTON2)
          Case #IDYES
          Case #IDCANCEL
            EventID.l=WaitWindowEvent(check.l)
          Case #IDNO
            SetWindowState(1,#PB_Window_Minimize)
            EventID.l=WaitWindowEvent(check.l)
        EndSelect
      EndIf
    Until EventID=#PB_Event_CloseWindow
    ; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ;eventFile$="E:\Temp\MyEvent.txt"
    If CreateFile(0,eventFile$)
      ForEach Ocassion()
        F1 = Ocassion()\chronos
        F2$ = Str(F1)
        WriteStringN(0,F2$,#PB_Ascii)
        F2$ = Ocassion()\Descript$
        WriteStringN(0,F2$,#PB_Ascii)
      Next
      CloseFile(0)
    EndIf
    CloseWindow(1)
    CloseWindow(0)
  EndIf
EndIf
Is it a bug or something I did wrong? I'm pretty good at that :oops:
- - - - - - - - - - - - - - - -
Randy
I *never* claimed to be a programmer.
Post Reply