[REVISED] 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: 1097
Joined: Sun Jul 25, 2004 4:21 pm
Location: USoA

[REVISED] 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
[EDIT] 10/4/25 -- Revised below to fix bug -- Calendar was not showing and doublclick on calender date not working.
BIG THANKS to Michael Vogel for that calender fix!!!!!

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

Global timenow.i, AnimateReminder.l, _x, _y
_x = GetSystemMetrics_(#SM_CXSCREEN)
_y = GetSystemMetrics_(#SM_CYSCREEN)
Debug Str(_x) +"  "+Str(_y)
Global DoMinimizedcSave
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.i, now.i, selected.i, eventFile$
TAG_CR$ = Chr(13)+Chr(10)
eventFile$=GetEnvironmentVariable("USERPROFILE") + "\MyEvents.txt"
#MainWindow = 1
#DateWindow = 0
If FileSize(eventFile$)= -1
  CreateFile(0,eventFile$)
  CloseFile(0)
EndIf

Procedure ReallySetForegroundWindow(m_hWnd.l)
  ; http://www.drdobbs.com/184405755
  hOtherWnd.l = GetForegroundWindow_()
  ;
  ; get thread handles on our window and foreground window
  hMyThread.l = GetWindowThreadProcessId_(m_hWnd, 0)
  hOtherThread.l = 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 

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.i = ElapsedMilliseconds() ; get current timestamp value for comparison calculations
      If timenow.i - lippi\dwTime > 100
        AnimateReminder.l = #True
      EndIf
      event$ = "TODAY is"
      If IsWindowVisible_(WindowID(0))
        ResizeWindow(#DateWindow, WindowX(1)+112, WindowY(1), #PB_Ignore, #PB_Ignore)
        HideWindow(1,0)
        ShowWindow_(WindowID(1),#SW_RESTORE)
        HideWindow(#DateWindow,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,  $0E0F0, -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
   SendMessage_(GadgetID(2), #LVM_ENSUREVISIBLE, place-1, #False)
  ;SendMessage_(GadgetID(2), #WM_VSCROLL, #SB_BOTTOM, 0) 
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

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 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,message,wParam,lParam)
	Result = #PB_ProcessPureBasicEvents
	If WindowID1 = WnHdl
		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
		Debug "."+lpPrevFunc
		ProcedureReturn CallWindowProc_(lpPrevFunc,WindowID1,message,wParam,lParam)
	EndIf
	Debug "0"
	ProcedureReturn Result
EndProcedure
Procedure OldWinCallback(hWnd, uMsg, WParam, LParam)
  ;Result.l = #PB_ProcessPureBasicEvents
  Select uMsg
    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(#DateWindow,1)
        SetActiveGadget(2)
      EndIf
    Case #WM_SIZE
      Select WParam
        Case #SIZE_MINIMIZED 
          Debug "Window was minimized"
          DoMinimizedcSave = #True
      EndSelect 
  EndSelect
  ProcedureReturn #PB_ProcessPureBasicEvents
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", 13)
If OpenWindow(#DateWindow,440,113,315,300,"Edit event & DblClick Date",#PB_Window_SystemMenu | #PB_Window_Invisible)
  WnHdl.i = CalendarGadget(0,5,35,305,250,Date())
  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)
  EditorGadget(1, 5, 10, 160, 20)
  SetGadgetAttribute(1,#PB_String_MaximumLength,29)  
  fontVerd9B.i = LoadFont(#PB_Default,"Verdana",34,#PB_Font_Bold)
  
  HWND1 = OpenWindow(#MainWindow, 312, 113, 570, 356, " Reminder", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_TitleBar)
  If HWND1
    LIG_Yval = 5
    ;      SetGadgetFont(2,FontID(fontVerd9B.i))
    If LoadFont(1, "Arial", 16)
      SetGadgetFont(#PB_Default, FontID(1))   ; Set the loaded Arial 16 font as new standard
    EndIf
    hLIG = ListIconGadget(2, 10, LIG_Yval, 553, 310, "", 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(2, "Arial", 12)
      SetGadgetFont(#PB_Default, FontID(2))   ; Set the loaded Arial 16 font as new standard
    EndIf
    ButtonGadget(3,10,320,155,25,"Add New Event")
    ButtonGadget(4,185,320,150,25,"Discard Event")
    ButtonGadget(5,350,320,195,25,"Discard All Changes")
    SetForegroundWindow_(WindowID(1))
    SetActiveWindow(1)
    LoadEvents()
    check.l = 10000 ; used to monitor ElapsedMilliseconds status
    SetWindowCallback(@WinCallback(),1)
    
    Repeat ; drop into timer initialization on first "even" second!
      s.w = (Second(Date()) % 2)
    Until (s % 2) =  0
    trip.l = SetTimer_(WindowID(#MainWindow),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(0)
        If IsWindowVisible_(WindowID(0))
          HideWindow(#DateWindow,1)
          DisableGadget(3,0)
          SetGadgetState(2,-1) ; deselect all items
        EndIf
      ElseIf EventID = #PB_Event_CloseWindow
        EventID = 0
        HideWindow(#DateWindow,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 ;Something selected so edit
                If GetActiveWindow() = 1
                  ResizeWindow(#DateWindow, WindowX(1)+112, WindowY(1), #PB_Ignore, #PB_Ignore)
                  HideWindow(#DateWindow,0)
                  DisableGadget(3,1)
                  selected.i = 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
              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(#DateWindow,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
                  Debug "Ok"
                  ResizeWindow(#DateWindow, WindowX(1)+112, WindowY(1), #PB_Ignore, #PB_Ignore)
                  HideWindow(#DateWindow,0)
                  DisableGadget(3,1)
                  selected.i = 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
              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.i = 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.i = 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)
                  LoadEvents()
              EndSelect
              SetActiveGadget(2)
          EndSelect
        Default
          If AnimateReminder = #True
            Debug "should be Jogging"
            GetLastInputInfo_(@lippi)
            timenow.i = ElapsedMilliseconds() ; get current timestamp value for comparison calculations
            If timenow.i - 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(1,0)
              SetForegroundWindow_(HWND20)
              SetActiveWindow(1)
              ResizeWindow(1, _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_() <> HWND20 ; don't bother if already doing hwnd20 'reminder'
                GetLastInputInfo_(@lippi)
                timenow.i = ElapsedMilliseconds() ; get current timestamp value for comparison calculations
                If timenow.i - 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 "
                  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
        Select MessageRequester("  Event Reminder", "Reminder will Minimize or Quit." + Chr(10) + "  Do you really want to Quit?", #MB_YESNO|#MB_DEFBUTTON2)
          Case #IDYES
          Case #IDNO
            SetWindowState(1,#PB_Window_Minimize)
            EventID.l=WaitWindowEvent(check.l)
        EndSelect
      EndIf
    Until EventID=#PB_Event_CloseWindow
    ;- BOTTOM OF LOOP ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    SaveEvents()
    CloseWindow(1)
    CloseWindow(#DateWindow)
  EndIf
  KillTimer_(trip,1)
EndIf
Last edited by Randy Walker on Sat Oct 04, 2025 7:51 pm, edited 10 times in total.
- - - - - - - - - - - - - - - -
Randy
I *never* claimed to be a programmer.
User avatar
oryaaaaa
Addict
Addict
Posts: 826
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: 1097
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: 826
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: 1097
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: 1210
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: 1097
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: 1097
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: 1097
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: 4279
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: 1097
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