"Reichweite" des DateGadgets

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
Kurzer
Beiträge: 1617
Registriert: 25.04.2006 17:29
Wohnort: Nähe Hamburg

Re: "Reichweite" des DateGadgets

Beitrag von Kurzer »

Hallo RSBasic,

diese Version funktioniert bei mir mit dem CalendarGadget() leider auch nicht. Mit dem DateGadget geht es zwar, aber das geht ja auch schon ohne Callback.

Tausche in Deinem Code mal das DateGadget() gegen das hier aus:

Code: Alles auswählen

CalendarGadget(1,10,10,200,170, Date())
Geht das dann bei Dir immer noch?
"Never run a changing system!" | "Unterhalten sich zwei Alleinunterhalter... Paradox, oder?"
PB 6.02 x64, OS: Win 7 Pro x64 & Win 11 x64, Desktopscaling: 125%, CPU: I7 6500, RAM: 16 GB, GPU: Intel Graphics HD 520
Useralter in 2024: 56 Jahre.
Benutzeravatar
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Re: "Reichweite" des DateGadgets

Beitrag von edel »

Warum sollte das funktionieren? Es ist doch ein ganz anderes Control.

Statt #DTN_DATETIMECHANGE benutze #MCN_SELCHANGE (-749)
Benutzeravatar
RSBasic
Admin
Beiträge: 8047
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: "Reichweite" des DateGadgets

Beitrag von RSBasic »

@Kurzer
Jetzt hab ich mich zu sehr auf das Ursprungsthema konzentriert. Mein Code funktioniert nur mit dem DateGadget.
CalendarGadget ist ein anderes Gadget, wie edel bereits sagte, und da musst du andere WinAPI-Konstanten verwenden.
Hier der Code für CalendarGadget:

Code: Alles auswählen

EnableExplicit

#MCN_SELCHANGE = #MCN_FIRST + 1
#MCN_SELECT = #MCN_FIRST + 4

Procedure WinCallback(hWnd, uMsg, wParam, lParam)
  Protected *NMHDR.NMHDR
  Protected SYSTEMTIME.SYSTEMTIME
 
  Select uMsg
    Case #WM_NOTIFY
      *NMHDR = lParam
      Select *NMHDR\hwndFrom
        Case GadgetID(1)
          Select *NMHDR\code
            Case #MCN_SELECT
              SendMessage_(GadgetID(1), #MCM_GETCURSEL, 0, SYSTEMTIME)
              Debug Str(SYSTEMTIME\wDay) + "." + Str(SYSTEMTIME\wMonth) + "." + Str(SYSTEMTIME\wYear)
          EndSelect
      EndSelect
  EndSelect
 
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

If OpenWindow(0, 0, 0, 500, 400, "Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  CalendarGadget(1, 10, 10, 200, 200, Date())
 
  SetWindowCallback(@WinCallback())
 
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        End
    EndSelect
  ForEver
EndIf
Kurzer hat geschrieben:Mit dem DateGadget geht es zwar, aber das geht ja auch schon ohne Callback.
Nicht ganz, das ist eben genau der Grund, warum ich es mit dem Callback gemacht habe. Hast du schon mal versucht, mit dem Code von edel einen beliebigen Tag vor 1969 oder nach 2038 auszuwählen? Da wird kein PB-Event mehr ausgelöst.
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Benutzeravatar
Kurzer
Beiträge: 1617
Registriert: 25.04.2006 17:29
Wohnort: Nähe Hamburg

Re: "Reichweite" des DateGadgets

Beitrag von Kurzer »

Edel, danke für den Hinweis. Ich stecke nicht in der API Programmierung, daher meine naive Annahme es müsse auch bei einem anderen GadgetTypen funktionieren.
RSBasic hat geschrieben:
Kurzer hat geschrieben:Mit dem DateGadget geht es zwar, aber das geht ja auch schon ohne Callback.
Nicht ganz, das ist eben genau der Grund, warum ich es mit dem Callback gemacht habe. Hast du schon mal versucht, mit dem Code von edel einen beliebigen Tag vor 1969 oder nach 2038 auszuwählen? Da wird kein PB-Event mehr ausgelöst.
Ja, das geht beim DateGadget mit Edels code. Irgend eine Art von Event wird dort offenbar auch bei Daten jenseits von 2038 erzeugt. Nur beim CalendarGadget zuckt sich nach 2038 nichts mehr.

Hmm das mit dem Callback ist ja nicht so optimal, wenn man innerhalb einer Datums-Lib ein GetDate() / SetDate() realisieren will.

Ich hatte mich bzgl. eines anderen threads letztendlich doch für Wilberts 64 bit Date-Funktionen entschieden und gehofft, dass ich dafür nun passende Set- und Get-Routinen erstellen kann. Ist aber wohl doch nicht so einfach realisierbar, wenn man dabei völlige Unabhängigkeit vom Hauptcode haben möchte.
"Never run a changing system!" | "Unterhalten sich zwei Alleinunterhalter... Paradox, oder?"
PB 6.02 x64, OS: Win 7 Pro x64 & Win 11 x64, Desktopscaling: 125%, CPU: I7 6500, RAM: 16 GB, GPU: Intel Graphics HD 520
Useralter in 2024: 56 Jahre.
Benutzeravatar
RSBasic
Admin
Beiträge: 8047
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: "Reichweite" des DateGadgets

Beitrag von RSBasic »

In der "WinAPI-Welt" ist Callback die Eventabfrage. PB hat seine eigene, separate Ereignisschleife.
Du kannst alternativ im Callback ein eigenes Event mit PostEvent() auslösen und die ausgelesenen Datumswerte weiterleiten, so dass du wieder in der "PureBasic-Welt" bist und weiterhin wie gewohnt in der typischen PB-Schleife das Event abfragen und auswerten kannst.
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Benutzeravatar
Kurzer
Beiträge: 1617
Registriert: 25.04.2006 17:29
Wohnort: Nähe Hamburg

Re: "Reichweite" des DateGadgets

Beitrag von Kurzer »

Ja, aber man muss sein CalendarGadget vorher irgendwo registrieren, damit der Callback die Gadgetnummer kennt, oder nicht? Die Set/Get Prozeduren sollen eigentlich in einem unabhängigen Modul liegen und sich neutral zum Hauptcode verhalten.

Wenn ich das mit dem Callback richtig verstehe, braucht es doch mindestens noch eine Prozedur ála RegisterDateGadget(GadgetNrMeinesCalendarGadgets) die nötig ist, damit die Sache mit dem Callback funktioniert.
"Never run a changing system!" | "Unterhalten sich zwei Alleinunterhalter... Paradox, oder?"
PB 6.02 x64, OS: Win 7 Pro x64 & Win 11 x64, Desktopscaling: 125%, CPU: I7 6500, RAM: 16 GB, GPU: Intel Graphics HD 520
Useralter in 2024: 56 Jahre.
Benutzeravatar
RSBasic
Admin
Beiträge: 8047
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: "Reichweite" des DateGadgets

Beitrag von RSBasic »

Wenn der Code neutral und unabhängig sein soll:

Code: Alles auswählen

EnableExplicit

Global CalendarProc

Procedure CalendarProc(hWnd, uMsg, wParam, lParam)
  Protected SYSTEMTIME.SYSTEMTIME
  
  Select uMsg
    Case #WM_LBUTTONUP
      SendMessage_(hWnd, #MCM_GETCURSEL, 0, SYSTEMTIME)
      Debug Str(SYSTEMTIME\wDay) + "." + Str(SYSTEMTIME\wMonth) + "." + Str(SYSTEMTIME\wYear)
  EndSelect
  
  ProcedureReturn CallWindowProc_(CalendarProc, hWnd, uMsg, wParam, lParam)
EndProcedure

If OpenWindow(0, 0, 0, 500, 400, "Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  CalendarGadget(1, 10, 10, 200, 200, Date())
  
  CalendarProc = SetWindowLongPtr_(GadgetID(1), #GWL_WNDPROC, @CalendarProc())
  
  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Ein anderes Event als "#WM_LBUTTONUP" habe ich nicht gefunden.
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Benutzeravatar
Kurzer
Beiträge: 1617
Registriert: 25.04.2006 17:29
Wohnort: Nähe Hamburg

Re: "Reichweite" des DateGadgets

Beitrag von Kurzer »

Aha, ich habe gerade festgestellt, dass diese Windowsstruktur NMHDR auch die GadgetNummer enthält.
Damit kann ich dynamisch jedes CalendarGadget bearbeiten.

Code: Alles auswählen

Procedure WinCallback(hWnd, uMsg, wParam, lParam)
  Protected *NMHDR.NMHDR
  Protected SYSTEMTIME.SYSTEMTIME
 
  If uMsg = #WM_NOTIFY
  	*NMHDR = lParam
  	If GadgetType(*NMHDR\idFrom) = #PB_GadgetType_Calendar And *NMHDR\code = #MCN_SELECT
      SendMessage_(GadgetID(*NMHDR\idFrom), #MCM_GETCURSEL, 0, SYSTEMTIME)
      Debug Str(SYSTEMTIME\wDay) + "." + Str(SYSTEMTIME\wMonth) + "." + Str(SYSTEMTIME\wYear)
    EndIf
  EndIf
 
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
Einziger "Schwachpunkt" ist halt das explizite Setzen des Callbacks außerhalb des Moduls bevor man die Set/Get Routnen benutzen kann. Dann muss ich halt eine Init Routine bereitstellen, die den Callback installiert.
"Never run a changing system!" | "Unterhalten sich zwei Alleinunterhalter... Paradox, oder?"
PB 6.02 x64, OS: Win 7 Pro x64 & Win 11 x64, Desktopscaling: 125%, CPU: I7 6500, RAM: 16 GB, GPU: Intel Graphics HD 520
Useralter in 2024: 56 Jahre.
Benutzeravatar
Kurzer
Beiträge: 1617
Registriert: 25.04.2006 17:29
Wohnort: Nähe Hamburg

Re: "Reichweite" des DateGadgets

Beitrag von Kurzer »

@RSBasic / Edel:
Erstmal vielen Dank für Deinen Input, das bringt mich auf jeden Fall weiter. :allright:

Noch eine Frage: Was muss/darf der Callback zurückgeben, wenn das PureBasic Event explizit nicht verarbeitet werden soll? Bei meinem Test habe ich den Fall, dass das DateGadget im gültigen Datumsbereich (1970 - 2038) selbst auch noch einen Event feuert und man so im Eventloop einen doppelten Event bekommt.

Möglicherweise bekomme ich damit auch die umständliche Unterdrückung der doppelten Ausgabe des Datums im Callback geregelt (dLastDateGadgetDate und dLastCalendarGadgetDate). Da das aber nur Testausgaben sind, ist das später eh irrelevant.

Bild

Code: Alles auswählen

EnableExplicit

#MCN_SELCHANGE = #MCN_FIRST + 1
;#MCN_SELECT = #MCN_FIRST + 4

Procedure WinCallback(hWnd, uMsg, wParam, lParam)
	Static.d  dLastCalendarGadgetDate, dLastDateGadgetDate
	Protected *NMHDR.NMHDR
  Protected SYSTEMTIME.SYSTEMTIME
  
  If uMsg = #WM_NOTIFY
  	*NMHDR = lParam
  	If GadgetType(*NMHDR\idFrom) = #PB_GadgetType_Calendar And *NMHDR\code = #MCN_SELCHANGE
  		SendMessage_(GadgetID(*NMHDR\idFrom), #MCM_GETCURSEL, 0, SYSTEMTIME)
  		If dLastCalendarGadgetDate <> PeekQ(@SYSTEMTIME)
  			PostEvent(#PB_Event_Gadget, GetParent_(*NMHDR\hwndFrom), *NMHDR\idFrom, #PB_EventType_Change)
  			dLastCalendarGadgetDate = PeekQ(@SYSTEMTIME)
  			Debug Str(SYSTEMTIME\wDay) + "." + Str(SYSTEMTIME\wMonth) + "." + Str(SYSTEMTIME\wYear)
  		EndIf
  	ElseIf GadgetType(*NMHDR\idFrom) = #PB_GadgetType_Date And *NMHDR\code = #DTN_DATETIMECHANGE
  		SendMessage_(GadgetID(*NMHDR\idFrom), #DTM_GETSYSTEMTIME, 0, SYSTEMTIME)
  		If dLastDateGadgetDate <> PeekQ(@SYSTEMTIME)
	    	PostEvent(#PB_Event_Gadget, GetParent_(*NMHDR\hwndFrom), *NMHDR\idFrom, #PB_EventType_Change)
				dLastDateGadgetDate = PeekQ(@SYSTEMTIME)
				Debug Str(SYSTEMTIME\wDay) + "." + Str(SYSTEMTIME\wMonth) + "." + Str(SYSTEMTIME\wYear)
    	EndIf  
    EndIf
  EndIf
 
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

If OpenWindow(0, 0, 0, 500, 400, "Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	CalendarGadget(1, 10, 10, 200, 200, Date())
	DateGadget(2, 220, 10, 250, 20)
 
  SetWindowCallback(@WinCallback())
 
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
      	End
      Case #PB_Event_Gadget
      	If EventType() = #PB_EventType_Change
      		Debug "Event: " + Str(EventGadget())
      	EndIf
    EndSelect
  ForEver
EndIf
"Never run a changing system!" | "Unterhalten sich zwei Alleinunterhalter... Paradox, oder?"
PB 6.02 x64, OS: Win 7 Pro x64 & Win 11 x64, Desktopscaling: 125%, CPU: I7 6500, RAM: 16 GB, GPU: Intel Graphics HD 520
Useralter in 2024: 56 Jahre.
Benutzeravatar
RSBasic
Admin
Beiträge: 8047
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: "Reichweite" des DateGadgets

Beitrag von RSBasic »

Zum Beispiel:

Code: Alles auswählen

EnableExplicit

#MCN_SELCHANGE = #MCN_FIRST + 1
;#MCN_SELECT = #MCN_FIRST + 4

#PB_EventType_Calendar_Change = #PB_Event_FirstCustomValue + #PB_EventType_Change

Procedure WinCallback(hWnd, uMsg, wParam, lParam)
  Static.d  dLastCalendarGadgetDate, dLastDateGadgetDate
  Protected *NMHDR.NMHDR
  Protected SYSTEMTIME.SYSTEMTIME
  
  If uMsg = #WM_NOTIFY
    *NMHDR = lParam
    If GadgetType(*NMHDR\idFrom) = #PB_GadgetType_Calendar And *NMHDR\code = #MCN_SELCHANGE
      SendMessage_(GadgetID(*NMHDR\idFrom), #MCM_GETCURSEL, 0, SYSTEMTIME)
      If dLastCalendarGadgetDate <> PeekQ(@SYSTEMTIME)
        PostEvent(#PB_Event_Gadget, GetParent_(*NMHDR\hwndFrom), *NMHDR\idFrom, #PB_EventType_Calendar_Change)
        dLastCalendarGadgetDate = PeekQ(@SYSTEMTIME)
        Debug Str(SYSTEMTIME\wDay) + "." + Str(SYSTEMTIME\wMonth) + "." + Str(SYSTEMTIME\wYear)
      EndIf
    ElseIf GadgetType(*NMHDR\idFrom) = #PB_GadgetType_Date And *NMHDR\code = #DTN_DATETIMECHANGE
      SendMessage_(GadgetID(*NMHDR\idFrom), #DTM_GETSYSTEMTIME, 0, SYSTEMTIME)
      If dLastDateGadgetDate <> PeekQ(@SYSTEMTIME)
        PostEvent(#PB_Event_Gadget, GetParent_(*NMHDR\hwndFrom), *NMHDR\idFrom, #PB_EventType_Calendar_Change)
        dLastDateGadgetDate = PeekQ(@SYSTEMTIME)
        Debug Str(SYSTEMTIME\wDay) + "." + Str(SYSTEMTIME\wMonth) + "." + Str(SYSTEMTIME\wYear)
      EndIf 
    EndIf
  EndIf
  
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

If OpenWindow(0, 0, 0, 500, 400, "Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  CalendarGadget(1, 10, 10, 200, 200, Date())
  DateGadget(2, 220, 10, 250, 20)
  
  SetWindowCallback(@WinCallback())
  
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        End
      Case #PB_Event_Gadget
        If EventType() = #PB_EventType_Calendar_Change
          Debug "Event: " + Str(EventGadget())
        EndIf
    EndSelect
  ForEver
EndIf
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Antworten