Seite 2 von 3

Re: "Reichweite" des DateGadgets

Verfasst: 18.12.2015 11:41
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?

Re: "Reichweite" des DateGadgets

Verfasst: 18.12.2015 12:44
von edel
Warum sollte das funktionieren? Es ist doch ein ganz anderes Control.

Statt #DTN_DATETIMECHANGE benutze #MCN_SELCHANGE (-749)

Re: "Reichweite" des DateGadgets

Verfasst: 18.12.2015 13:23
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.

Re: "Reichweite" des DateGadgets

Verfasst: 18.12.2015 21:40
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.

Re: "Reichweite" des DateGadgets

Verfasst: 18.12.2015 21:50
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.

Re: "Reichweite" des DateGadgets

Verfasst: 18.12.2015 22:01
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.

Re: "Reichweite" des DateGadgets

Verfasst: 18.12.2015 22:09
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.

Re: "Reichweite" des DateGadgets

Verfasst: 18.12.2015 22:13
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.

Re: "Reichweite" des DateGadgets

Verfasst: 18.12.2015 23:39
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

Re: "Reichweite" des DateGadgets

Verfasst: 18.12.2015 23:48
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