"Gadget(s)" für Zeiteingabe gesucht

Für allgemeine Fragen zur Programmierung mit PureBasic.
Omi
Beiträge: 143
Registriert: 25.03.2013 09:59

"Gadget(s)" für Zeiteingabe gesucht

Beitrag von Omi »

Ich suche z.Zt. ein einfache (und platzsparende) Möglichkeit Uhrzeiten eingegeben, wenn möglich ohne 3 SpinGadgets für Std., Min., Sek. zu bemühen. DateGadget und CalendarGadget bieten die Möglichkeit (zumindest unter Linux) ja nicht.

In Windows sieht man gelegentlich folgende (nicht unpraktische) Möglichkeit die jeweils das Segment, in dem Cursor steht mit den Pfeilen verstellt:
http://www.chabba.de/temp/Windows_TimeControl.jpg (kurzzeitig sichtbar)
Weiß jemand, ob dies ein komplettes Windows-API-Control oder eine Programmierer-Bastelei ist?

Oder kennt jemand einen praktischen PB-Code (mind. für Windows + Linux) in den Foren (wurde bisher nicht fündig.)

Gruß, Charly
PureBasic Linux-API-Library: http://www.chabba.de
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: "Gadget(s)" für Zeiteingabe gesucht

Beitrag von ccode_new »

Hallo!

Unter Linux (mit Gtk+) wäre es eine kleine Bastelei aus verschiedenen Widgets.

Unter Windows empfehle ich diesen Link:

https://docs.microsoft.com/en-us/window ... r-controls
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
Nino
Beiträge: 1300
Registriert: 13.05.2010 09:26
Wohnort: Berlin

Re: "Gadget(s)" für Zeiteingabe gesucht

Beitrag von Nino »

Ich würde es evtl. etwa wie folgt machen.
//edit: Code vervollständigt. :-)

Code: Alles auswählen

EnableExplicit

Procedure.s NewTime (time$, SecondsChanged)
   Protected.i hrs, min, sec
   
   hrs = Val(StringField(time$, 1, ":"))
   min = Val(StringField(time$, 2, ":"))
   sec = Val(StringField(time$, 3, ":")) + SecondsChanged
   
   min + Int(sec/60)
   sec % 60
   If sec < 0
      sec + 60
      min - 1
   EndIf   
   
   hrs + Int(min/60)
   min % 60
   If min < 0
      min + 60
      hrs - 1
   EndIf   
   
   hrs % 24
   If hrs < 0
      hrs + 24
   EndIf   
   
   ProcedureReturn RSet(Str(hrs), 2, "0") + ":" + RSet(Str(min), 2, "0") + ":" + RSet(Str(sec), 2, "0")
EndProcedure


Define Event

OpenWindow(0, 0, 0, 140, 70, "SpinGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
SpinGadget   (0, 20, 20, 100, 25, 0, 1000)
SetGadgetText(0, "11:29:53")                ; set initial value

Repeat
   Event = WaitWindowEvent()
   If Event = #PB_Event_Gadget
      If EventGadget() = 0
         Select EventType()
            Case #PB_EventType_Up
               SetGadgetText(0, NewTime(GetGadgetText(0), 1))
            Case #PB_EventType_Down
               SetGadgetText(0, NewTime(GetGadgetText(0), -1))
         EndSelect      
      EndIf
   EndIf
Until Event = #PB_Event_CloseWindow
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: "Gadget(s)" für Zeiteingabe gesucht

Beitrag von ccode_new »

Huhu!

Ich habe hier einmal einen kleinen Testcode erstellt. (Überarbeitung des Codes von Nino)

Der Code funktioniert noch nicht korrekt!

Aber jetzt stellt sich für mich die Frage wie man das hier ersichtliche Fokus-Ändere-Dich (Nicht) - Problem umschiffen/ bzw. lösen kann.

(Anbei: Noch recht unsauber programmiert.)

Code: Alles auswählen

EnableExplicit

;Für Windows:
; OpenWindow(0,0,0,220,50,"",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
; tWnd = CreateWindowEx_(0,"SysDateTimePick32","",#WS_CHILD|#WS_VISIBLE| #DTS_TIMEFORMAT,10,10,200,25,WindowID(0),0, GetModuleHandle_(0),0)
; SendMessage_(tWnd,#DTM_SETSYSTEMTIME,#GDT_NONE,@time.SYSTEMTIME )
; Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow

;Oder es wird selber gemacht/ bzw. erweitert:

;Ich brauche hier mal Tipps für das Focus-Change-Problem !!!

Global tpos.i = 0, tUp.b = #False, tDown.b = #False

Global.i Box1, Box2, Box3, Box4

Procedure.s NewTime (time$, SecondsChanged)
   Protected.i hrs, min, sec
   
   hrs = Val(StringField(time$, 1, ":"))
   min = Val(StringField(time$, 2, ":"))
   sec = Val(StringField(time$, 3, ":")) + SecondsChanged
   
   min + Int(sec/60)
   sec % 60
   If sec < 0
      sec + 60
      min - 1
   EndIf   
   
   hrs + Int(min/60)
   min % 60
   If min < 0
      min + 60
      hrs - 1
   EndIf   
   
   hrs % 24
   If hrs < 0
      hrs + 24
   EndIf   
   
   ProcedureReturn RSet(Str(hrs), 2, "0") + ":" + RSet(Str(min), 2, "0") + ":" + RSet(Str(sec), 2, "0")
 EndProcedure
 
 Procedure.i GetHour(timeStr.s)
   Protected.i regex, pass.b = #False, h, rh
   
   regex = CreateRegularExpression(#PB_Any, "[0-2][0-9]:[0-5][0-9]:[0-5][0-9]")
   
   If regex
     ExamineRegularExpression(regex, timeStr)
     While NextRegularExpressionMatch(regex)
       pass = #True
     Wend
     FreeRegularExpression(regex)
   EndIf
   
   If pass = #True
     h = Val(StringField(timeStr, 1, ":"))
     If h < 25
       rh = h
     EndIf
   EndIf
   ProcedureReturn rh
 EndProcedure
 
 Procedure.i GetMinute(timeStr.s)
   Protected.i regex, pass.b = #False, m, rm
   
   regex = CreateRegularExpression(#PB_Any, "[0-2][0-9]:[0-5][0-9]:[0-5][0-9]")
   
   If regex
     ExamineRegularExpression(regex, timeStr)
     While NextRegularExpressionMatch(regex)
       pass = #True
     Wend
     FreeRegularExpression(regex)
   EndIf
   
   If pass = #True
     m = Val(StringField(timeStr, 2, ":"))
     If m < 60
       rm = m
     EndIf
   EndIf
   ProcedureReturn rm
 EndProcedure
 
 Procedure.i GetSecond(timeStr.s)
   Protected.i regex, pass.b = #False, s, rs
   
   regex = CreateRegularExpression(#PB_Any, "[0-2][0-9]:[0-5][0-9]:[0-5][0-9]")
   
   If regex
     ExamineRegularExpression(regex, timeStr)
     While NextRegularExpressionMatch(regex)
       ;Debug "ok"
       pass = #True
     Wend
     FreeRegularExpression(regex)
   EndIf
   
   If pass = #True
     s = Val(StringField(timeStr, 3, ":"))
     If s < 60
       rs = s
     EndIf
   EndIf
   ProcedureReturn rs
 EndProcedure
 
 Procedure SetHour(gadget.i, h.i)
   Protected atimeStr.s, ntimeStr.s
   
   atimeStr = GetGadgetText(gadget)
   If h >= 0 And h < 25
     ntimeStr = RSet(Str(h), 2, "0") + ":" + RSet(Str(GetMinute(atimeStr)), 2, "0") + ":" + RSet(Str(GetSecond(atimeStr)), 2, "0")
     SetGadgetText(gadget, ntimeStr)
   EndIf
 EndProcedure
 
 Procedure SetMinute(gadget.i, m.i)
   Protected atimeStr.s, ntimeStr.s
   
   atimeStr = GetGadgetText(gadget)
   If m >= 0 And m < 60
     ntimeStr = RSet(Str(GetHour(atimeStr)), 2, "0") + ":" + RSet(Str(m), 2, "0") + ":" + RSet(Str(GetSecond(atimeStr)), 2, "0")
     SetGadgetText(gadget, ntimeStr)
   EndIf
 EndProcedure
 
  Procedure SetSecond(gadget.i, s.i)
   Protected atimeStr.s, ntimeStr.s
   
   atimeStr = GetGadgetText(gadget)
   If s >= 0 And s < 60
     ntimeStr = RSet(Str(GetHour(atimeStr)), 2, "0") + ":" + RSet(Str(GetMinute(atimeStr)), 2, "0") + ":" + RSet(Str(s), 2, "0")
     SetGadgetText(gadget, ntimeStr)
   EndIf
 EndProcedure
 
 Procedure ChangeTimeInControl(gadget.i, pos.i, down.b = #False)
   Protected.i aSec = 0, aMin = 0, aHrs = 0

   If pos >= 0 And pos < 3
     aHrs = GetHour(GetGadgetText(gadget))
     If down = #False
       SetHour(gadget, aHrs+1)
     ElseIf down = #True
       SetHour(gadget, aHrs-1)
     EndIf
   ElseIf pos > 2 And pos < 6
     aMin = GetMinute(GetGadgetText(gadget))
     If down = #False
       SetMinute(gadget, aMin+1)
     ElseIf down = #True
       SetMinute(gadget, aMin-1)
     EndIf
   ElseIf pos > 5 And pos < 9
     aSec = GetSecond(GetGadgetText(gadget))
     If down = #False
       SetSecond(gadget, aSec+1)
     ElseIf down = #True
       SetSecond(gadget, aSec-1)
     EndIf
   EndIf
 
 EndProcedure

Define Event

OpenWindow(0, 0, 0, 140, 70, "Time-Control", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

AddKeyboardShortcut(0, #PB_Shortcut_Up, 1)
AddKeyboardShortcut(0, #PB_Shortcut_Down, 2)

SpinGadget(0, 20, 20, 100, 25, 0, 1000)
SetGadgetText(0, "11:29:00") ;nn:nn:nn Format ist Pflicht! (Eine 60. Leap-Second gibt es bei mir nicht! (No Astro-Time !!!))

Debug GetMinute("00:24:00") 

;Für Linux-Insider
CompilerIf #PB_Compiler_OS = #PB_OS_Linux
  
  ;Na wir gucken mal was sich unter Linux dahinter verbirgt. (Es sieht ja irgendwie stark nach einem gtk_entry aus.)
  Debug PeekS(gtk_widget_get_name_(GadgetID(0)), -1, #PB_UTF8)
  ;Ah! Das ist ja etwas zusammengebasteltes in einem GtkBox-Container.
  
  ;Wir schauen also noch etwas genauer hin:
  Box1 = g_list_nth_data_(gtk_container_get_children_(WindowID(0)), 0) ;GtkBox
  Debug PeekS(gtk_widget_get_name_(Box1), -1, #PB_UTF8)
  
  Box2 = g_list_nth_data_(gtk_container_get_children_(Box1), 0) ;GtkLayout
  Debug PeekS(gtk_widget_get_name_(Box2), -1, #PB_UTF8)
  
  Box3 = g_list_nth_data_(gtk_container_get_children_(Box2), 0) ;GtkBox
  Debug PeekS(gtk_widget_get_name_(Box3), -1, #PB_UTF8)
  
  Box4 = g_list_nth_data_(gtk_container_get_children_(Box3), 0) ;GtkEntry
  Debug PeekS(gtk_widget_get_name_(Box4), -1, #PB_UTF8)
  
CompilerElseIf #PB_Compiler_OS = #PB_OS_Windows
  
  Procedure Get_Edit_Pos(gadget)
    Protected Min, Max
    SendMessage_(GadgetID(gadget),#EM_GETSEL,@Min,@Max)
    ProcedureReturn Max-SendMessage_(GadgetID(gadget),#EM_LINEINDEX,SendMessage_(GadgetID(gadget),#EM_LINEFROMCHAR,Min,0),0)
  EndProcedure
  
CompilerEndIf


Repeat
  Event = WaitWindowEvent()
  
  CompilerIf #PB_Compiler_OS = #PB_OS_Linux
    tpos = gtk_editable_get_position_(Box4) ;Linux
  CompilerElseIf #PB_Compiler_OS = #PB_OS_Windows
    tpos = Get_Edit_Pos(0) ;Windows
  CompilerEndIf
  
  If Event = #PB_Event_Menu
    If EventMenu() = 1
      ChangeTimeInControl(0, tpos, #False)
    ElseIf EventMenu() = 2
      ChangeTimeInControl(0, tpos, #True)
    EndIf
  EndIf
  
  If Event = #PB_Event_Gadget
    If EventGadget() = 0
      Select EventType()
        Case #PB_EventType_Up
          ;SetGadgetText(0, NewTime(GetGadgetText(0), 1))
          ChangeTimeInControl(0, tpos, #False)
        Case #PB_EventType_Down
          ;SetGadgetText(0, NewTime(GetGadgetText(0), -1))
          ChangeTimeInControl(0, tpos, #True)
      EndSelect   
    EndIf
  EndIf
Until Event = #PB_Event_CloseWindow

Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: "Gadget(s)" für Zeiteingabe gesucht

Beitrag von ccode_new »

Das SpinGadget ist nur für Zahlenwerte ausgelegt.
Wenn man jetzt Zeichenketten wie z.B. 11:00:01 oder ähnlich verwendet (also mit : -Zeichen) funktioniert die Auswertung des Minimalwertes und Maximalwertes nicht mehr.

Also der bessere Weg ist die Verwendung eines StringGadgets, aber dort gibt es natürlich auch das Fokusproblem.

Aber es gibt natürlich eine Lösung dafür. :wink:

Mit der Verwendung des Canvas-Gadgets kann man die Zeicheneingabefläche und die dazugehörigen UP/Down-Knöpfe fokusunabhängig auswerten. (Alles ist ein Gadget!)

Naja so ist das halt.

Gute Nacht!

Anbei: Ich melde mich sicherlich auch Morgen wieder mal. :D
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
Omi
Beiträge: 143
Registriert: 25.03.2013 09:59

Re: "Gadget(s)" für Zeiteingabe gesucht

Beitrag von Omi »

Vielen Dank schon mal für eure Bemühungen - und bitte nicht nachlassen :wink: .

@Nino: Dein Einheiten-Übertrag ist sehr elegant gelöst. Ich hab mir im Laufe der Jahre auch so einige Tricks erarbeitet - auf diesen wäre ich nicht gekommen.
Bei ersten Test Deiner Routine trat meine Maus jedoch der Gewerkschaft bei: 86400 Klicks (auf Linux einzelgeklickt) um einen Tag durchzuscrollen war ihr ein zu dicker Verstoß gegen den Arbeitsschutz.
Außerdem tritt auf Linux beim PB-Spezial-SpinGadget eben nachfolgendes Problem mit dem Down-Pfeil auf ...

EIN SpinGadget für h, m + s habe ich erst mal verworfen, da ich das Problem mit Nicht-Integer-Inhalten auch bemerkte -> der DownPfeil ist deaktiviert, falls ein nicht nummerisches Zeichen enthalten ist, d.h. es wird seitens PB als value= 0 interpretiert.
Auch der native GtkSpinButton ist nur auf Integer und Float ausgelegt und dürfte zur Sackgasse werden.
@ ccode_new: Wow, Du hast dich wirklich schon reingehängt und es würde schon mal so aussehen wie gedacht (und hast die Linux-Sache langsam gut im Griff). Ich werd' Dich mal als 'AKK' fürs Linux-API-Lib-Dings vorsehen :wink: . Das Fokussierung / Cursorpositionierungsproblem wäre, glaube ich, in den Griff zu kriegen - evtl. auch mit Markierung des jeweils bearbeiteten Segments.
Ich bin aber vor der Umsetzung zurückgeschreckt wegen des PB-SpinGadget-Integer-Problems und da keine String-Maske (Vorformatierung) möglich ist. D.h. manuelle Eingaben zerstören das erforderliche Stringformat völlig. Eine gute Sofort-Korrektur ist auch sehr aufwändig inkl. der Gefahr der Unbedienbarkeit bei unbedachten String-Konstellationen (aus der Erfahrung). Man wird aber nicht Drum-Rum-Kommen fürchte ich.

Momentanes Fazit:
Auf Windows wäre die API-Version wohl vorzuziehen (hier fehlt es mir jedoch mittlerweile an API-Erfahrung und einem aktuellerem OS). Mit 'altem XP-Rechner umstöpseln' und/oder 'Wine' tue ich es mir nicht an.
Auf Linux muss man das Problem noch wirken lassen - ich tendiere auch zu einer eigenen 'StringGadget + Pfeile-Kombi'. Eine - wie gewünscht - einfache Umsetzung wird's wohl nicht geben können.

Um hier keinen Stress aufkommen zu lassen (lieber im Rahmen der Möglichkeiten gut als schnell) und damit es nicht so aussieht, als würde ich mich bedienen lassen, stelle ich hier mal meine erste Notfall-Backup-Version für Test und Feinschliff rein (die, die eigentlich verbessert werden soll). Ist halt das '3½-Tonner-SUV zum-Brötchen-holen'-Modell.
Es bügelt zumindest einige Linux-Bedien-Handicaps und das mögliche Falschwerte-Direkteingabe-Probleme in Windows-SpinGadgets aus. Vielleicht läuft's ja auch (mit wenig oder keiner Anpassung) auf dem Mac.

Ich muss mich jetzt erst mal ums Vorweihnachtliche (darunter u.a. auch um ein nicht allzu fehlerhaftes Mini-API-Library-Update) kümmern.

Danke bisher, Charly

ps-ps:
Anbei: Ich melde mich sicherlich auch Morgen wieder mal.
Na gerne.

So, hier mal die ungelenke-handarbeits-dicke-Hose Version ...

Code: Alles auswählen

EnableExplicit

; Object constants
#Win_Main  = 0

Enumeration TimeGadgets
	#SpGTimeH
	#SpGTimeM
	#SpGTimeS
	#TxGShowTime
	#TxGShowTimeNo
EndEnumeration

Global.i gEvent, gEventGadget, gQuit

;- Part for tweaked SpinGadgets ...
CompilerIf #PB_Compiler_OS = #PB_OS_Linux
	
	ImportC ""
		g_signal_connect(*instance, detailed_signal.p-utf8, *c_handler, *data, destroy= 0, flags= 0) As "g_signal_connect_data"
		gtk_entry_set_alignment(*entry.GtkEntry, xalign.f)
	EndImport
	
	;see https://git.gnome.org/browse/gtk+/plain/gdk/gdkkeysyms.h
	#GDK_KEY_Up  = $FF52
	#GDK_KEY_Down= $FF54
	
	Structure CALLBACKDATA
		GadgetNo.i
		WindowNo.i
	EndStructure
	Global NewList GadgetData.CALLBACKDATA() 
	
	ProcedureC Callback_SpinGadgetScroll(*widget.GtkWidget, *Event.GdkEventAny, *user_data.CALLBACKDATA); match callback name with the call in SpinGadget_Tweak
		Protected *ev_scroll.GdkEventScroll
		Protected *ev_keypress.GdkEventKey
		Protected Ret= #False
		
		If *Event\type = #GDK_SCROLL
			*ev_scroll= *Event
		ElseIf *Event\type = #GDK_KEY_PRESS
			*ev_keypress= *Event
		EndIf
		If (*ev_scroll And *ev_scroll\direction = #GDK_SCROLL_UP) Or (*ev_keypress And *ev_keypress\keyval = #GDK_KEY_Up)
			SetGadgetText(*user_data\GadgetNo, Str(Val(GetGadgetText(*user_data\GadgetNo))+ 1))
			PostEvent(#PB_Event_Gadget, *user_data\WindowNo, *user_data\GadgetNo, #PB_EventType_Up)
			PostEvent(#PB_Event_Gadget, *user_data\WindowNo, *user_data\GadgetNo, #PB_EventType_Change)
			Ret= #True;                                                    avoids focus change on up/down key
		ElseIf (*ev_scroll And *ev_scroll\direction = #GDK_SCROLL_DOWN) Or (*ev_keypress And *ev_keypress\keyval = #GDK_KEY_Down)
			SetGadgetText(*user_data\GadgetNo, Str(Val(GetGadgetText(*user_data\GadgetNo))- 1))
			PostEvent(#PB_Event_Gadget, *user_data\WindowNo, *user_data\GadgetNo, #PB_EventType_Down)
			PostEvent(#PB_Event_Gadget, *user_data\WindowNo, *user_data\GadgetNo, #PB_EventType_Change)
			Ret= #True;                                                    avoids focus change on up/down key
		EndIf
		ProcedureReturn Ret
	EndProcedure
	
	Procedure.i SpinGadget_GetEntry(Gadget)
		CompilerIf #PB_Compiler_OS = #PB_OS_Linux
			If GadgetType(Gadget) = #PB_GadgetType_Spin
				Protected *entry = g_list_nth_data_(gtk_container_get_children_(GadgetID(Gadget)), 0)
				ProcedureReturn *entry
			EndIf
		CompilerEndIf
	EndProcedure
	
	Procedure SpinGadget_Tweak(Window, Gadget)
		If GadgetType(Gadget) = #PB_GadgetType_Spin
			Protected *entry.GtkEntry = g_list_nth_data_(gtk_container_get_children_(GadgetID(Gadget)), 0)
			
			AddElement(GadgetData())
			GadgetData()\GadgetNo= Gadget
			GadgetData()\WindowNo= Window
			
			gtk_widget_add_events_(*entry, #GDK_SCROLL_MASK | #GDK_KEY_PRESS_MASK)
			g_signal_connect_(*entry, "scroll-event", @Callback_SpinGadgetScroll(), @GadgetData());    event on wheelscrolling over entry
			g_signal_connect_(*entry, "key-press-event", @Callback_SpinGadgetScroll(), @GadgetData()); event on key up/down on focussed entry
		EndIf
	EndProcedure
	
CompilerEndIf
;- ... End of part

Procedure TimeGadget_Check(Gadget)
	CompilerIf #PB_Compiler_OS = #PB_OS_Windows
		If Val(GetGadgetText(Gadget)) > GetGadgetAttribute(Gadget, #PB_Spin_Maximum)
			SetGadgetState(Gadget, GetGadgetAttribute    (Gadget, #PB_Spin_Maximum))
			SetGadgetText(Gadget,  Str(GetGadgetAttribute(Gadget, #PB_Spin_Maximum)))
		ElseIf Val(GetGadgetText(Gadget)) < GetGadgetAttribute(Gadget, #PB_Spin_Minimum)
			SetGadgetState(Gadget, GetGadgetAttribute    (Gadget, #PB_Spin_Minimum))
			SetGadgetText(Gadget,  Str(GetGadgetAttribute(Gadget, #PB_Spin_Minimum)))
		EndIf
	CompilerEndIf
EndProcedure


Procedure Create_WinMain()
	If OpenWindow(#Win_Main, 300, 200, 400, 200, "Set time ", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget)
		TextGadget(#PB_Any,          5,  14, 130,  22, "Set time (h:m:s)")
		SpinGadget(#SpGTimeH,      140,  10,  54,  28,  0, 23, #PB_Spin_Numeric)
		SetGadgetState(#SpGTimeH,    8)
		SpinGadget(#SpGTimeM,      200,  10,  54,  28,  0, 59, #PB_Spin_Numeric)
		SetGadgetState(#SpGTimeM,   30)
		SpinGadget(#SpGTimeS,      260,  10,  54,  28,  0, 59, #PB_Spin_Numeric)
		SetGadgetState(#SpGTimeS,    0)
		TextGadget(#PB_Any,          5,  50, 130,  22, "Time set")
		TextGadget(#TxGShowTime,   140,  50, 130,  22, " 8:30:00")
		TextGadget(#PB_Any,          5,  80, 130,  22, "Time value")
		TextGadget(#TxGShowTimeNo, 140,  80, 130,  22, "")
		
		CompilerIf #PB_Compiler_OS = #PB_OS_Linux
			gtk_entry_set_alignment(SpinGadget_GetEntry(#SpGTimeH), 1.0)
			gtk_entry_set_alignment(SpinGadget_GetEntry(#SpGTimeM), 1.0)
			gtk_entry_set_alignment(SpinGadget_GetEntry(#SpGTimeS), 1.0)
			
			SpinGadget_Tweak(#Win_Main, #SpGTimeH)
			SpinGadget_Tweak(#Win_Main, #SpGTimeM)
			SpinGadget_Tweak(#Win_Main, #SpGTimeS)
		CompilerEndIf
	EndIf
EndProcedure

Create_WinMain()

Repeat
	gEvent= WaitWindowEvent()
	
	Select gEvent
		Case #PB_Event_CloseWindow
			gQuit= #True
			
		Case #PB_Event_Gadget
			
			gEventGadget= EventGadget()
			Select gEventGadget
					
				Case #SpGTimeH, #SpGTimeM, #SpGTimeS
					TimeGadget_Check(gEventGadget)
					SetGadgetText(#TxGShowTime, RSet(GetGadgetText(#SpGTimeH), 2) + ":" + RSet(GetGadgetText(#SpGTimeM), 2, "0") + ":" + RSet(GetGadgetText(#SpGTimeS), 2, "0"))
					SetGadgetText(#TxGShowTimeNo, Str(ParseDate("%hh:%ii:%ss", RSet(GetGadgetText(#SpGTimeH), 2, "0") + ":" + RSet(GetGadgetText(#SpGTimeM), 2, "0") + ":" + RSet(GetGadgetText(#SpGTimeS), 2, "0"))))
			EndSelect
			
	EndSelect
	
Until gQuit
PureBasic Linux-API-Library: http://www.chabba.de
Nino
Beiträge: 1300
Registriert: 13.05.2010 09:26
Wohnort: Berlin

Re: "Gadget(s)" für Zeiteingabe gesucht

Beitrag von Nino »

Hallo Omi!
Omi hat geschrieben:@Nino: Dein Einheiten-Übertrag ist sehr elegant gelöst. Ich hab mir im Laufe der Jahre auch so einige Tricks erarbeitet - auf diesen wäre ich nicht gekommen.
Danke! Ich war selbst ein wenig überrascht, dass die Lösung so elegant war. :-)
Omi hat geschrieben:Bei ersten Test Deiner Routine trat meine Maus jedoch der Gewerkschaft bei: 86400 Klicks (auf Linux einzelgeklickt) um einen Tag durchzuscrollen war ihr ein zu dicker Verstoß gegen den Arbeitsschutz.
Als Katzenfreund bin ich dagegen, dass Mäuse in Gewerkschaften eintreten! :-)
Mein Betrag sollte nur eine Gedankenanregung sein und war v.a. darauf ausgerichtet, dass Du zuvor geschrieben hattest
wenn möglich ohne 3 SpinGadgets für Std., Min., Sek. zu bemühen
Omi hat geschrieben:Außerdem tritt auf Linux beim PB-Spezial-SpinGadget eben nachfolgendes Problem mit dem Down-Pfeil auf ...

EIN SpinGadget für h, m + s habe ich erst mal verworfen, da ich das Problem mit Nicht-Integer-Inhalten auch bemerkte -> der DownPfeil ist deaktiviert, falls ein nicht nummerisches Zeichen enthalten ist, d.h. es wird seitens PB als value= 0 interpretiert.
Unter Windows funktioniert es mit 1 Spingadget. Dass unter Linux dieses Problem auftritt, damit hatte ich nicht gerechnet. Das ist natürlich inakzeptabel.

Schönen 3. Advent, Nino
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: "Gadget(s)" für Zeiteingabe gesucht

Beitrag von ccode_new »

Eine schönen restlichen 3. Advent noch!

Hallo "Omi" !

Ich habe mich an die Umsetzung über das Canvas-Gadget gewagt.

Dabei hatte ich noch einen tollen Einfall.

Ich verwende bei dieser 1. Version (ich nenne sie mal:"Alpha-Version") meines "TimeGadget"-Modules eine PopUp-Menü-Lösung, weil mir die Sache mit den Pfeilen noch zu doof war.

Hier mein erstelltes Programm:

Code: Alles auswählen

;Time-Gadget-Module (mit Canvas-Gadget)

;Einmal ganz ohne Pfeile, aber dafür mit PopUp-Menü. :)

DeclareModule TimeGadget
  Structure TTimeValue
    hour.i
    minute.i
    second.i
  EndStructure
 
  Structure TCursor
    pos.i
    fpos.i
    length.i
  EndStructure
 
  Structure TTimeInput
    gid.i
    value.s
    length.i
    isfocus.b
    x.i
    y.i
    h.i
    w.i
    time.TTimeValue
    cursor.TCursor
  EndStructure
 
  Global m1_id.i, m2_id.i
 
  ;PopUp-Select
  m1_id = CreatePopupMenu(#PB_Any)
  If m1_id
    For k = 0 To 23
      MenuItem(k, Str(k))
    Next k
  EndIf
 
  m2_id = CreatePopupMenu(#PB_Any)
  If m2_id
    For k = 0 To 59
      MenuItem(k, Str(k))
    Next k
  EndIf
 
  Declare.i TimeGadget(gid.i, xpos.i, ypos.i, width.i, height.i, timeStr.s, flags.i = 0)
  Declare TimeInput_Destroy(*pTimeGadget.TTimeInput)
  Declare TimeInput_Event(*pTimeGadget.TTimeInput, Win.i, WindowEvent.i)
  Declare TimeInput_Update(*pTimeGadget.TTimeInput, show_cursor.b = #False)
  Declare.i TimeInput_GetMousePosition(*pTimeGadget.TTimeInput, x.i, y.i)
  Declare.i TimeInput_GetHour(*pTimeGadget.TTimeInput)
  Declare.i TimeInput_GetMinute(*pTimeGadget.TTimeInput)
  Declare.i TimeInput_GetSecond(*pTimeGadget.TTimeInput)
  Declare.s TimeInput_GetTimeString(*pTimeGadget.TTimeInput)
  Declare TimeInput_SetTimeString(*pTimeGadget.TTimeInput, timeStr.s)
  Declare TimeInput_SetHour(*pTimeGadget.TTimeInput, hour.i)
  Declare TimeInput_SetMinute(*pTimeGadget.TTimeInput, minute.i)
  Declare TimeInput_SetSecond(*pTimeGadget.TTimeInput, second.i)
  Declare.i TimeInput_GetCursorPosition(*pTimeGadget.TTimeInput)
  Declare TimeInput_ChangeTime(*pTimeGadget.TTimeInput, pos.i, down.b = #False)
EndDeclareModule

Module TimeGadget
 
  Procedure TimeInput_GetHour(*pTimeGadget.TTimeInput)
    Protected.i regex, pass.b = #False, h, rh
    If IsGadget(*pTimeGadget\gid)
      regex = CreateRegularExpression(#PB_Any, "[0-2][0-9]:[0-5][0-9]:[0-5][0-9]")
      If regex
        ExamineRegularExpression(regex, *pTimeGadget\value)
        While NextRegularExpressionMatch(regex)
          pass = #True
        Wend
        FreeRegularExpression(regex)
      EndIf
      If pass = #True
        h = Val(StringField(*pTimeGadget\value, 1, ":"))
        If h < 24 And h >= 0
          rh = h
          ProcedureReturn rh
        EndIf
      EndIf
    EndIf
    ProcedureReturn -1
  EndProcedure
 
  Procedure TimeInput_GetMinute(*pTimeGadget.TTimeInput)
    Protected.i regex, pass.b = #False, m, rm
    If IsGadget(*pTimeGadget\gid)
      regex = CreateRegularExpression(#PB_Any, "[0-2][0-9]:[0-5][0-9]:[0-5][0-9]")
      If regex
        ExamineRegularExpression(regex, *pTimeGadget\value)
        While NextRegularExpressionMatch(regex)
          pass = #True
        Wend
        FreeRegularExpression(regex)
      EndIf
      If pass = #True
        m = Val(StringField(*pTimeGadget\value, 2, ":"))
        If m < 60 And m >= 0
          rm = m
          ProcedureReturn rm
        EndIf
      EndIf
    EndIf
    ProcedureReturn -1
  EndProcedure
 
  Procedure TimeInput_GetSecond(*pTimeGadget.TTimeInput)
    Protected.i regex, pass.b = #False, s, rs
    If IsGadget(*pTimeGadget\gid)
      regex = CreateRegularExpression(#PB_Any, "[0-2][0-9]:[0-5][0-9]:[0-5][0-9]")
      If regex
        ExamineRegularExpression(regex, *pTimeGadget\value)
        While NextRegularExpressionMatch(regex)
          pass = #True
        Wend
        FreeRegularExpression(regex)
      EndIf
      If pass = #True
        s = Val(StringField(*pTimeGadget\value, 3, ":"))
        If s < 60 And s >= 0
          rs = s
          ProcedureReturn rs
        EndIf
      EndIf
    EndIf
    ProcedureReturn -1
  EndProcedure
 
  Procedure.s TimeInput_GetTimeString(*pTimeGadget.TTimeInput)
    If IsGadget(*pTimeGadget\gid)
      ProcedureReturn *pTimeGadget\value
    Else
      ProcedureReturn "-1"
    EndIf
  EndProcedure
 
  Procedure TimeInput_SetTimeString(*pTimeGadget.TTimeInput, timeStr.s)
    Protected.i regex, pass.b = #False
    If IsGadget(*pTimeGadget\gid)
      regex = CreateRegularExpression(#PB_Any, "[0-2][0-9]:[0-5][0-9]:[0-5][0-9]")
      If regex
        ExamineRegularExpression(regex, *pTimeGadget\value)
        While NextRegularExpressionMatch(regex)
          pass = #True
        Wend
        FreeRegularExpression(regex)
      EndIf
      If pass = #True
        *pTimeGadget\value = timeStr
      Else
        *pTimeGadget\value = "00:00:00"
      EndIf
    EndIf
  EndProcedure
 
  Procedure TimeInput_SetHour(*pTimeGadget.TTimeInput, hour.i)
    Protected ntimeStr.s
    If IsGadget(*pTimeGadget\gid)
      With *pTimeGadget
        If hour >= 0 And hour < 24
          \time\hour = hour
          \time\minute = TimeInput_GetMinute(*pTimeGadget)
          \time\second = TimeInput_GetSecond(*pTimeGadget)
          ntimeStr = RSet(Str(\time\hour), 2, "0") + ":" + RSet(Str(\time\minute), 2, "0") + ":" + RSet(Str(\time\second), 2, "0")
          TimeInput_SetTimeString(*pTimeGadget, ntimeStr)
        EndIf
      EndWith
    EndIf
  EndProcedure
 
  Procedure TimeInput_SetMinute(*pTimeGadget.TTimeInput, minute.i)
    Protected ntimeStr.s   
    If IsGadget(*pTimeGadget\gid)
      With *pTimeGadget
        If minute >= 0 And minute < 60
          \time\hour = TimeInput_GetHour(*pTimeGadget)
          \time\minute = minute
          \time\second = TimeInput_GetSecond(*pTimeGadget)
          ntimeStr = RSet(Str(\time\hour), 2, "0") + ":" + RSet(Str(\time\minute), 2, "0") + ":" + RSet(Str(\time\second), 2, "0")
          TimeInput_SetTimeString(*pTimeGadget, ntimeStr)
        EndIf
      EndWith
    EndIf
  EndProcedure
 
  Procedure TimeInput_SetSecond(*pTimeGadget.TTimeInput, second.i)
    Protected ntimeStr.s   
    If IsGadget(*pTimeGadget\gid)
      With *pTimeGadget
        If second >= 0 And second < 60
          \time\hour = TimeInput_GetHour(*pTimeGadget)
          \time\minute = TimeInput_GetMinute(*pTimeGadget)
          \time\second = second
          ntimeStr = RSet(Str(\time\hour), 2, "0") + ":" + RSet(Str(\time\minute), 2, "0") + ":" + RSet(Str(\time\second), 2, "0")
          TimeInput_SetTimeString(*pTimeGadget, ntimeStr)
        EndIf
      EndWith
    EndIf
  EndProcedure
 
  Procedure TimeInput_ChangeTime(*pTimeGadget.TTimeInput, pos.i, down.b = #False)
    Protected.i aSec = 0, aMin = 0, aHrs = 0
    If IsGadget(*pTimeGadget\gid)
      If pos >= 0 And pos < 3
        aHrs = TimeInput_GetHour(*pTimeGadget)
        If down = #False And aHrs > -1
          TimeInput_SetHour(*pTimeGadget, aHrs + 1)
        ElseIf down = #True And aHrs > 0
          TimeInput_SetHour(*pTimeGadget, aHrs - 1)
        EndIf
      ElseIf pos > 2 And pos < 6
        aMin = TimeInput_GetMinute(*pTimeGadget)
        If down = #False And aMin > -1
          TimeInput_SetMinute(*pTimeGadget, aMin + 1)
        ElseIf down = #True And aMin > 0
          TimeInput_SetMinute(*pTimeGadget, aMin - 1)
        EndIf
      ElseIf pos > 5 And pos < 9
        aSec = TimeInput_GetSecond(*pTimeGadget)
        If down = #False And aSec > -1
          TimeInput_SetSecond(*pTimeGadget, aSec + 1)
        ElseIf down = #True And aSec > 0
          TimeInput_SetSecond(*pTimeGadget, aSec - 1)
        EndIf
      EndIf
    EndIf
  EndProcedure
 
  Procedure TimeInput_GetMousePosition(*pTimeGadget.TTimeInput, x.i, y.i)
    Protected mouse_x.i, mouse_y.i, min_distance.f = Infinity(), distance.f, cursor_pos.i, cursor_x.i, cursor_y.i, i.i
   
    If IsGadget(*pTimeGadget\gid)
      With *pTimeGadget
       
        mouse_x = GetGadgetAttribute(\gid, #PB_Canvas_MouseX)
        mouse_y = GetGadgetAttribute(\gid, #PB_Canvas_MouseY)
       
        \length = Len(\value)
       
        StartDrawing(CanvasOutput(\gid))
        cursor_y = y + TextHeight(\value) / 2
        For i = 0 To \length
          cursor_x = x + TextWidth(Left(\value, i))
          distance = (mouse_x - cursor_x) * (mouse_x - cursor_x) + (mouse_y - cursor_y) * (mouse_y - cursor_y)
          If distance < min_distance
            min_distance = distance
            cursor_pos = i
          EndIf
        Next
        StopDrawing()
        If Not IsInfinity(min_distance)
          ProcedureReturn cursor_pos
        Else
          ProcedureReturn -1
        EndIf
      EndWith
      ProcedureReturn -1
    EndIf
  EndProcedure
 
  Procedure TimeInput_DeleteSelection(*pTimeGadget.TTimeInput)
    If IsGadget(*pTimeGadget\gid)
      With *pTimeGadget
        If \cursor\length < 0
          \value = Left(\value, \cursor\fpos) + Mid(\value, \cursor\pos + 1)
          \cursor\pos = \cursor\fpos
          \cursor\length = 0
          ProcedureReturn #True
        ElseIf \cursor\length > 0
          \value = Left(\value, \cursor\pos) + Mid(\value, \cursor\fpos + 1)
          \cursor\fpos = \cursor\pos
          \cursor\length = 0
          ProcedureReturn #True
        EndIf
      EndWith
    EndIf
    ProcedureReturn #False
  EndProcedure
 
  Procedure TimeInput_Event(*pTimeGadget.TTimeInput, Win.i, WindowEvent.i)
    Protected evt.b = #False
    Protected cursor_pos.i
    Protected afocus.b = #False
    Protected select_mode.b = #False
   
    If IsGadget(*pTimeGadget\gid)
      With *pTimeGadget
        Select WindowEvent
          Case #PB_Event_Gadget
            If EventGadget() = \gid
              Select EventType()
                Case #PB_EventType_LeftButtonDown
                  cursor_pos = TimeInput_GetMousePosition(*pTimeGadget, 2, 2)
                  If cursor_pos <> -1
                    \cursor\pos = cursor_pos
                    \cursor\fpos = cursor_pos
                    \cursor\length = 0
                    evt = #True
                  EndIf
                  select_mode = #True
                Case #PB_EventType_RightButtonDown
                  If \cursor\pos < 3
                    DisplayPopupMenu(m1_id, WindowID(Win))
                  ElseIf \cursor\pos > 2 And \cursor\pos < 6
                    DisplayPopupMenu(m2_id, WindowID(Win))
                  ElseIf \cursor\pos > 5 And \cursor\pos < 9
                    DisplayPopupMenu(m2_id, WindowID(Win))
                  EndIf
                Case #PB_EventType_Focus
                  \isfocus = #True
                Case #PB_EventType_LostFocus
                  \isfocus = #False
                Case #PB_EventType_MouseMove
                  If select_mode = #True
                    cursor_pos = TimeInput_GetMousePosition(*pTimeGadget, 2, 2)
                    If cursor_pos <> -1 And \cursor\pos <> cursor_pos
                      \cursor\pos = cursor_pos
                      \cursor\length = \cursor\fpos - cursor_pos
                      evt = #True
                    EndIf
                  EndIf
                Case #PB_EventType_LeftButtonUp
                  select_mode = #False
                Case #PB_EventType_Input
                  TimeInput_DeleteSelection(*pTimeGadget)
                  \value = Left(\value, \cursor\pos) + Chr(GetGadgetAttribute(\gid, #PB_Canvas_Input)) + Mid(\value, \cursor\pos + 1)
                  \cursor\pos + 1
                  evt = #True
                Case #PB_EventType_KeyDown
                  Select GetGadgetAttribute(\gid, #PB_Canvas_Key)
                    Case #PB_Shortcut_Left
                      If \cursor\pos > 0 : \cursor\pos - 1 : EndIf
                      evt = #True
                    Case #PB_Shortcut_Right
                      If \cursor\pos < Len(\value) : \cursor\pos + 1 : EndIf
                      evt = #True
                    Case #PB_Shortcut_End
                      \cursor\pos = Len(\value)
                      evt = #True
                    Case #PB_Shortcut_Home
                      \cursor\pos = 0
                      evt = #True
                    Case #PB_Shortcut_Back
                      If Not TimeInput_DeleteSelection(*pTimeGadget)
                        If \cursor\pos > 0
                          \value = Left(\value, \cursor\pos - 1) + Mid(\value, \cursor\pos + 1)
                          \cursor\pos - 1
                        EndIf
                      EndIf
                      evt = #True
                    Case #PB_Shortcut_Delete
                      If Not TimeInput_DeleteSelection(*pTimeGadget)
                        If \cursor\pos < Len(\value)
                          \value = Left(\value, \cursor\pos) + Mid(\value, \cursor\pos + 2)
                        EndIf
                      EndIf
                      evt = #True
                  EndSelect
              EndSelect
            EndIf
        EndSelect
      EndWith
    EndIf
  EndProcedure
 
  Procedure GetCursorPosition(*pTimeGadget.TTimeInput)
    ProcedureReturn TextWidth(Left(*pTimeGadget\value, *pTimeGadget\cursor\pos))
  EndProcedure
 
  Procedure GetCursorLength(*pTimeGadget.TTimeInput)
    ProcedureReturn TextWidth(Left(*pTimeGadget\value, *pTimeGadget\cursor\pos + *pTimeGadget\cursor\length)) - TextWidth(Left(*pTimeGadget\value, *pTimeGadget\cursor\pos))
  EndProcedure
 
  Procedure TimeInput_GetCursorPosition(*pTimeGadget.TTimeInput)
    ProcedureReturn *pTimeGadget\cursor\pos
  EndProcedure
 
  Procedure TimeInput_Update(*pTimeGadget.TTimeInput, show_cursor.b = #False)
    Protected.i a
    If IsGadget(*pTimeGadget\gid)
      With *pTimeGadget
        ;a = \w / 100 * 20
        StartDrawing(CanvasOutput(\gid))
        Box(0, 0, \w, \h, RGB(255,255,255))
        DrawText(2, (\h / 2)-(TextHeight(\value) / 2), \value, RGB(0,0,0), RGB(255,255,255))
        ;         ;Up-Button
        ;         LineXY(\w-a, \h/2, \w-a/2, 0, RGB(0, 0, 255))
        ;         LineXY(\w-a, \h/2, \w, \h/2, RGB(0, 0, 255))
        ;         LineXY(\w, \h/2, \w-a/2, 0, RGB(0, 0, 255))
        ;         FillArea(\w-a/2, \h/2-1, RGB(0,0,255), RGB(255,0,255))
        ;         ;Down-Button
        ;         LineXY(\w-a, \h/2, \w-a/2, \h, RGB(0, 0, 255))
        ;         LineXY(\w-a, \h/2, \w, \h/2, RGB(0, 0, 255))
        ;         LineXY(\w, \h/2, \w-a/2, \h, RGB(0, 0, 255))
        ;         FillArea(\w-a/2, \h/2+1, RGB(0,0,255), RGB(0,255,255))
        DrawingMode(#PB_2DDrawing_XOr)
        If \cursor\length < 0
          Box(2 + GetCursorPosition(*pTimeGadget) + GetCursorLength(*pTimeGadget), (\h / 2)-(TextHeight(\value) / 2), -GetCursorLength(*pTimeGadget), TextHeight(" "))
        ElseIf \cursor\length > 0
          Box(2 + GetCursorPosition(*pTimeGadget) + 1, (\h / 2)-(TextHeight(\value) / 2), GetCursorLength(*pTimeGadget) - 1, TextHeight(" "))
        EndIf
        DrawingMode(#PB_2DDrawing_Default)
        If show_cursor = #True And \isfocus = #True
          Line(2 + GetCursorPosition(*pTimeGadget), (\h / 2)-(TextHeight(\value) / 2), 1, TextHeight(" "), RGB(0,0,0))
        EndIf
        StopDrawing()
      EndWith
    EndIf
  EndProcedure
 
  ;Time-Gadget-Constructor
  Procedure.i TimeGadget(gid.i, xpos.i, ypos.i, width.i, height.i, timeStr.s, flags.i = 0)
    Protected *pTimeGadget.TTimeInput = AllocateMemory(SizeOf(TTimeInput))
    Protected pid.i, k.i
    pid = CanvasGadget(gid, xpos, ypos, width, height, #PB_Canvas_Keyboard)
    If pid <> 0
      If gid = -1
        SetGadgetAttribute(pid, #PB_Canvas_Cursor, #PB_Cursor_IBeam)
      Else
        SetGadgetAttribute(gid, #PB_Canvas_Cursor, #PB_Cursor_IBeam)
      EndIf
     
      With *pTimeGadget
        If gid = -1
          \gid = pid
        Else
          \gid = gid
        EndIf
        \value = timeStr
        \x = xpos
        \y = ypos
        \h = height
        \w = width
      EndWith
      ProcedureReturn *pTimeGadget
    EndIf
    ProcedureReturn -1
  EndProcedure
 
  ;Time-Gadget-Destructor
  Procedure TimeInput_Destroy(*pTimeGadget.TTimeInput)
    If IsGadget(*pTimeGadget\gid)
      FreeGadget(*pTimeGadget\gid)
      FreeMemory(*pTimeGadget)
    EndIf
  EndProcedure
 
EndModule



Enumeration
  #Win
  #ControlTimer
  #SecondTimer
EndEnumeration

UseModule TimeGadget


Global *vTimeGadget.TTimeInput, tpos.i, atimeStr.s

Global *vTimeGadget2.TTimeInput, tpos2.i

Global aGadget.i, lastFocus.i

If OpenWindow(#Win, 0, 0, 200, 100, "Time-Control", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
 
  AddKeyboardShortcut(0, #PB_Shortcut_Up, 1)
  AddKeyboardShortcut(0, #PB_Shortcut_Down, 2)
 
  atimeStr = RSet(Str(Hour(Date())), 2, "0") + ":" + RSet(Str(Minute(Date())), 2, "0") + ":" + RSet(Str(Second(Date())), 2, "0")
 
  *vTimeGadget = TimeGadget(0, 10, 10, 80, 20, "00:00:00")
  ;Debug *vTimeGadget
 
  *vTimeGadget2 = TimeGadget(1, 10, 50, 80, 20, "00:00:00")
  ;Debug *vTimeGadget2
 
  TimeInput_SetTimeString(*vTimeGadget, atimeStr)
 
  AddWindowTimer(#Win, #ControlTimer, 200)
  AddWindowTimer(#Win, #SecondTimer, 1000) ;Durch Deaktivieren\Kommentieren läuft die Zeit nicht weiter !
 
  Repeat
    event = WaitWindowEvent()
   
    tpos = TimeInput_GetCursorPosition(*vTimeGadget)
    tpos2 = TimeInput_GetCursorPosition(*vTimeGadget2)
   
    If TimeInput_Event(*vTimeGadget, #Win, event)
      TimeInput_Update(*vTimeGadget, #False)
    EndIf
    If TimeInput_Event(*vTimeGadget2, #Win, event)
      TimeInput_Update(*vTimeGadget2, #False)
    EndIf
   
    If *vTimeGadget\isfocus = #True
      lastFocus = *vTimeGadget\gid
    ElseIf *vTimeGadget2\isfocus = #True
      lastFocus = *vTimeGadget2\gid
    EndIf
   
    Select event
      Case #PB_Event_CloseWindow
        End
      Case #PB_Event_Menu
        If lastFocus = 0
          If EventMenu() = 1
            TimeInput_ChangeTime(*vTimeGadget, tpos, #False)
          ElseIf EventMenu() = 2
            TimeInput_ChangeTime(*vTimeGadget, tpos, #True)
          ElseIf MenuID(m1_id) And tpos < 3
            TimeInput_SetHour(*vTimeGadget, Val(GetMenuItemText(m1_id, EventMenu())))
          ElseIf MenuID(m2_id) And tpos > 2 And tpos < 6
            TimeInput_SetMinute(*vTimeGadget, Val(GetMenuItemText(m2_id, EventMenu())))
          ElseIf MenuID(m2_id) And tpos > 5 And tpos < 9
            TimeInput_SetSecond(*vTimeGadget, Val(GetMenuItemText(m2_id, EventMenu())))
          EndIf
        Else
          If EventMenu() = 1
            TimeInput_ChangeTime(*vTimeGadget2, tpos2, #False)
          ElseIf EventMenu() = 2 And GetActiveGadget() = 1
            TimeInput_ChangeTime(*vTimeGadget2, tpos2, #True)
          ElseIf MenuID(m1_id) And tpos2 < 3
            TimeInput_SetHour(*vTimeGadget2, Val(GetMenuItemText(m1_id, EventMenu())))
          ElseIf MenuID(m2_id) And tpos2 > 2 And tpos2 < 6
            TimeInput_SetMinute(*vTimeGadget2, Val(GetMenuItemText(m2_id, EventMenu())))
          ElseIf MenuID(m2_id) And tpos2 > 5 And tpos2 < 9
            TimeInput_SetSecond(*vTimeGadget2, Val(GetMenuItemText(m2_id, EventMenu())))
          EndIf
        EndIf
      Case #PB_Event_Timer
        Select EventTimer()
          Case #ControlTimer
            TimeInput_Update(*vTimeGadget, #True)
            TimeInput_Update(*vTimeGadget2, #True)
          Case #SecondTimer
            atimeStr = RSet(Str(Hour(Date())), 2, "0") + ":" + RSet(Str(Minute(Date())), 2, "0") + ":" + RSet(Str(Second(Date())), 2, "0")
            TimeInput_SetTimeString(*vTimeGadget, atimeStr)
        EndSelect
    EndSelect
   
  ForEver
 
  TimeInput_Destroy(*vTimeGadget)
 
EndIf

UnuseModule TimeGadget
-Es braucht noch Resize-Funktionen.
-Es braucht noch Font/Color - Set/Get - Funktionen.
-etc.

Zeile:

Code: Alles auswählen

AddWindowTimer(#Win, #SecondTimer, 1000) ;Durch Deaktivieren\Kommentieren läuft die Zeit nicht weiter !
dürfte für Tests noch nützlich sein. :wink

Anbei:
Die Bugsuche kann weiter gehen. :D
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
Omi
Beiträge: 143
Registriert: 25.03.2013 09:59

Re: "Gadget(s)" für Zeiteingabe gesucht

Beitrag von Omi »

@Nino
Mein Betrag sollte nur eine Gedankenanregung sein und war v.a. darauf ausgerichtet, dass Du zuvor geschrieben hattest...
War schon klar. Wär's in der kurzen Zeit perfekt, wär's schon in der Schublade gelegen <) . Allein die 'Umrechung' war schon das Posten wert.
Ich wollte ja auch nur den Mäusespruch los werden :wink: .

@ccode_new
Wow! Echt nicht schlecht und innerhalb der Zeit + Modularisiert. Die Popups fühlen sich zuerst etwas sperrig an (werd' eben schon alt und ein Gewohnheitstier) aber mit jedem Draufklicken gefallen sie einem besser.

Ich hätte in den paar Minuten in denen ich damit rumspielte mal versucht, auch beim Rechtsklick zum Popup öffnen den Cursor mit-umzusetzen, hab das ganze aber in der Zeit noch nicht genug durchschaut.
Ich würde behaupten, das Ding ist schon so weit gediehen und gut umgesetzt, dass es den finalen Feinschliff wirklich verdient hätte. Push, push, push ... ;-)
Auf alle Fälle danke ich Dir für den bisherigen Einsatz.

Ich hoffe während des Weihnachtsurlaubs neben dem (lange überfälligen und fest eingeplanten) Durchrocken meiner Gitarren und Verstärker auch für diese Thema mal Zeit und Muse zu finden - falls noch was übrig ist :wink: .

Und ich schließ' mich hinten an und wünsch noch 'nen stressfreien "Adv-endspurt".

Grüße Charly
PureBasic Linux-API-Library: http://www.chabba.de
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: "Gadget(s)" für Zeiteingabe gesucht

Beitrag von ccode_new »

Hallo Leute!

Hier kommt ein kleines Update.

Das mit den PopUp-Menü habe ich verworfen und Pfeile sucht man vergebens, aber man darf das Scrollrad verwenden.

Es dürfen nur Zahlen(0-9) und das Zeichen(:) eingegeben werden.

Außerdem gibt es jetzt Farb-, Schriftart- und Größenanpassungs -funktionen.

Code: Alles auswählen

;My Time-Gadget-Module
;Code-Name: "PinkPanther"

DeclareModule TimeGadget
  
  ImportC ""
    time(time_t = #Null)
    localtime(*tm = #Null)
    gmtime(time_t.i)
  EndImport
  
  Structure TTimeValue
    second.l
    minute.l
    hour.l
    mday.l
    mon.l
    year.l
    wday.l
    yday.l
    isdst.l
  EndStructure
  
  Structure TCursor
    pos.i
    fpos.i
    cheight.i
    cwidth.i
    length.i
  EndStructure
  
  Structure TTimeInput
    gid.i
    value.s
    length.i
    isfocus.b
    center.b
    x.i
    y.i
    h.i
    w.i
    bgcolor.i
    fgcolor.i
    font.i
    time.TTimeValue
    cursor.TCursor
  EndStructure
  
  Declare.i TimeGadget(gid.i, xpos.i, ypos.i, width.i, height.i, timeStr.s, flag.i = 0)
  Declare TimeGadget_Destroy(*pTimeGadget.TTimeInput)
  Declare TimeGadget_Event(*pTimeGadget.TTimeInput, Win.i, WindowEvent.i)
  Declare TimeGadget_Update(*pTimeGadget.TTimeInput, show_cursor.b = #False)
  Declare.i TimeGadget_GetHour(*pTimeGadget.TTimeInput)
  Declare.i TimeGadget_GetMinute(*pTimeGadget.TTimeInput)
  Declare.i TimeGadget_GetSecond(*pTimeGadget.TTimeInput)
  Declare.s TimeGadget_GetTimeString(*pTimeGadget.TTimeInput)
  Declare TimeGadget_SetTimeString(*pTimeGadget.TTimeInput, timeStr.s)
  Declare TimeGadget_SetHour(*pTimeGadget.TTimeInput, hour.i)
  Declare TimeGadget_SetMinute(*pTimeGadget.TTimeInput, minute.i)
  Declare TimeGadget_SetSecond(*pTimeGadget.TTimeInput, second.i)
  Declare.i TimeGadget_GetCursorPosition(*pTimeGadget.TTimeInput)
  Declare TimeGadget_ChangeTime(*pTimeGadget.TTimeInput, pos.i, down.b = #False)
  Declare TimeGadget_Resize(*pTimeGadget.TTimeInput, x, y, w, h)
  Declare TimeGadget_SetLocalTime(*pTimeGadget.TTimeInput)
  Declare TimeGadget_SetUTCTime(*pTimeGadget.TTimeInput)
  Declare TimeGadget_ChangeFont(*pTimeGadget.TTimeInput, font_nr.i)
  Declare TimeGadget_ChangeColor(*pTimeGadget.TTimeInput, bgcolor.i, fgcolor.i = 0)
  Declare TimeGadget_SetEvent_MenuExceptions(Map MenuExceptions())
  
EndDeclareModule

Module TimeGadget
  
  Global AClockWin.i
  
  Global NewMap MenuExceptions.i()
  
  Procedure TimeGadget_GetHour(*pTimeGadget.TTimeInput)
    Protected.i regex, pass.b = #False, h, rh
    If IsGadget(*pTimeGadget\gid)
      regex = CreateRegularExpression(#PB_Any, "[0-2][0-9]:[0-5][0-9]:[0-5][0-9]")
      If regex
        ExamineRegularExpression(regex, *pTimeGadget\value)
        While NextRegularExpressionMatch(regex)
          pass = #True
        Wend
        FreeRegularExpression(regex)
      EndIf
      If pass = #True
        h = Val(StringField(*pTimeGadget\value, 1, ":"))
        If h < 24 And h >= 0
          rh = h
          ProcedureReturn rh
        EndIf
      EndIf
    EndIf
    ProcedureReturn -1
  EndProcedure
  
  Procedure TimeGadget_GetMinute(*pTimeGadget.TTimeInput)
    Protected.i regex, pass.b = #False, m, rm
    If IsGadget(*pTimeGadget\gid)
      regex = CreateRegularExpression(#PB_Any, "[0-2][0-9]:[0-5][0-9]:[0-5][0-9]")
      If regex
        ExamineRegularExpression(regex, *pTimeGadget\value)
        While NextRegularExpressionMatch(regex)
          pass = #True
        Wend
        FreeRegularExpression(regex)
      EndIf
      If pass = #True
        m = Val(StringField(*pTimeGadget\value, 2, ":"))
        If m < 60 And m >= 0
          rm = m
          ProcedureReturn rm
        EndIf
      EndIf
    EndIf
    ProcedureReturn -1
  EndProcedure
  
  Procedure TimeGadget_GetSecond(*pTimeGadget.TTimeInput)
    Protected.i regex, pass.b = #False, s, rs
    If IsGadget(*pTimeGadget\gid)
      regex = CreateRegularExpression(#PB_Any, "[0-2][0-9]:[0-5][0-9]:[0-5][0-9]")
      If regex
        ExamineRegularExpression(regex, *pTimeGadget\value)
        While NextRegularExpressionMatch(regex)
          pass = #True
        Wend
        FreeRegularExpression(regex)
      EndIf
      If pass = #True
        s = Val(StringField(*pTimeGadget\value, 3, ":"))
        If s < 60 And s >= 0
          rs = s
          ProcedureReturn rs
        EndIf
      EndIf
    EndIf
    ProcedureReturn -1
  EndProcedure
  
  Procedure.s TimeGadget_GetTimeString(*pTimeGadget.TTimeInput)
    If IsGadget(*pTimeGadget\gid)
      ProcedureReturn *pTimeGadget\value
    Else
      ProcedureReturn "-1"
    EndIf
  EndProcedure
  
  Procedure TimeGadget_SetTimeString(*pTimeGadget.TTimeInput, timeStr.s)
    Protected.i regex, h, s.s, pass.b = #False
    If IsGadget(*pTimeGadget\gid)
      regex = CreateRegularExpression(#PB_Any, "[0-2][0-9]:[0-5][0-9]:[0-5][0-9]")
      If regex
        ExamineRegularExpression(regex, timeStr)
        While NextRegularExpressionMatch(regex)
          pass = #True
        Wend
        FreeRegularExpression(regex)
      EndIf
      If pass = #True
        h = Val(StringField(timeStr, 1, ":"))
        s = StringField(timeStr, 3, ":")
        If h < 24 And h >= 0 And Len(s) = 2
          *pTimeGadget\value = timeStr
        Else
          *pTimeGadget\value = "00:00:00"
        EndIf
      Else
        *pTimeGadget\value = "00:00:00"
      EndIf
    EndIf
  EndProcedure
  
  Procedure TimeGadget_SetHour(*pTimeGadget.TTimeInput, hour.i)
    Protected ntimeStr.s
    If IsGadget(*pTimeGadget\gid)
      With *pTimeGadget
        If hour >= 0 And hour < 24
          \time\hour = hour
          \time\minute = TimeGadget_GetMinute(*pTimeGadget)
          \time\second = TimeGadget_GetSecond(*pTimeGadget)
          ntimeStr = RSet(Str(\time\hour), 2, "0") + ":" + RSet(Str(\time\minute), 2, "0") + ":" + RSet(Str(\time\second), 2, "0")
          TimeGadget_SetTimeString(*pTimeGadget, ntimeStr)
        EndIf
      EndWith
    EndIf
  EndProcedure
  
  Procedure TimeGadget_SetMinute(*pTimeGadget.TTimeInput, minute.i)
    Protected ntimeStr.s   
    If IsGadget(*pTimeGadget\gid)
      With *pTimeGadget
        If minute >= 0 And minute < 60
          \time\hour = TimeGadget_GetHour(*pTimeGadget)
          \time\minute = minute
          \time\second = TimeGadget_GetSecond(*pTimeGadget)
          ntimeStr = RSet(Str(\time\hour), 2, "0") + ":" + RSet(Str(\time\minute), 2, "0") + ":" + RSet(Str(\time\second), 2, "0")
          TimeGadget_SetTimeString(*pTimeGadget, ntimeStr)
        EndIf
      EndWith
    EndIf
  EndProcedure
  
  Procedure TimeGadget_SetSecond(*pTimeGadget.TTimeInput, second.i)
    Protected ntimeStr.s   
    If IsGadget(*pTimeGadget\gid)
      With *pTimeGadget
        If second >= 0 And second < 60
          \time\hour = TimeGadget_GetHour(*pTimeGadget)
          \time\minute = TimeGadget_GetMinute(*pTimeGadget)
          \time\second = second
          ntimeStr = RSet(Str(\time\hour), 2, "0") + ":" + RSet(Str(\time\minute), 2, "0") + ":" + RSet(Str(\time\second), 2, "0")
          TimeGadget_SetTimeString(*pTimeGadget, ntimeStr)
        EndIf
      EndWith
    EndIf
  EndProcedure
  
  Procedure TimeGadget_ChangeTime(*pTimeGadget.TTimeInput, pos.i, down.b = #False)
    Protected.i aSec = 0, aMin = 0, aHrs = 0
    If IsGadget(*pTimeGadget\gid)
      If pos >= 0 And pos < 3
        aHrs = TimeGadget_GetHour(*pTimeGadget)
        If down = #False And aHrs > -1
          TimeGadget_SetHour(*pTimeGadget, aHrs + 1)
        ElseIf down = #True And aHrs > 0
          TimeGadget_SetHour(*pTimeGadget, aHrs - 1)
        EndIf
      ElseIf pos > 2 And pos < 6
        aMin = TimeGadget_GetMinute(*pTimeGadget)
        If down = #False And aMin > -1
          TimeGadget_SetMinute(*pTimeGadget, aMin + 1)
        ElseIf down = #True And aMin > 0
          TimeGadget_SetMinute(*pTimeGadget, aMin - 1)
        EndIf
      ElseIf pos > 5 And pos < 9
        aSec = TimeGadget_GetSecond(*pTimeGadget)
        If down = #False And aSec > -1
          TimeGadget_SetSecond(*pTimeGadget, aSec + 1)
        ElseIf down = #True And aSec > 0
          TimeGadget_SetSecond(*pTimeGadget, aSec - 1)
        EndIf
      EndIf
    EndIf
  EndProcedure
  
  Procedure TimeGadget_GetInputPosition(*pTimeGadget.TTimeInput, x.i, y.i)
    Protected mouse_x.d, mouse_y.d, min_distance.d = Infinity(), distance.d, cursor_pos.i, cursor_x.i, cursor_y.i, i.i
    
    If IsGadget(*pTimeGadget\gid)
      With *pTimeGadget
        
        mouse_x = GetGadgetAttribute(\gid, #PB_Canvas_MouseX)
        mouse_y = GetGadgetAttribute(\gid, #PB_Canvas_MouseY)
        
        \length = Len(\value)
        
        StartDrawing(CanvasOutput(\gid))
        cursor_y = y + TextHeight(\value) / 2
        For i = 0 To \length
          cursor_x = x + TextWidth(Left(\value, i))
          distance = (mouse_x - cursor_x) * (mouse_x - cursor_x) + (mouse_y - cursor_y) * (mouse_y - cursor_y)
          If distance < min_distance
            min_distance = distance
            cursor_pos = i
          EndIf
        Next
        StopDrawing()
        If Not IsInfinity(min_distance)
          ProcedureReturn cursor_pos
        Else
          ProcedureReturn -1
        EndIf
      EndWith
      ProcedureReturn -1
    EndIf
  EndProcedure
  
  Procedure TimeGadget_DeleteSelection(*pTimeGadget.TTimeInput)
    If IsGadget(*pTimeGadget\gid)
      With *pTimeGadget
        If \cursor\length < 0
          \value = Left(\value, \cursor\fpos) + Mid(\value, \cursor\pos + 1)
          \cursor\pos = \cursor\fpos
          \cursor\length = 0
          ProcedureReturn #True
        ElseIf \cursor\length > 0
          \value = Left(\value, \cursor\pos) + Mid(\value, \cursor\fpos + 1)
          \cursor\fpos = \cursor\pos
          \cursor\length = 0
          ProcedureReturn #True
        EndIf
      EndWith
    EndIf
    ProcedureReturn #False
  EndProcedure
  
  Procedure TimeGadget_SetLocalTime(*pTimeGadget.TTimeInput)
    Protected now.i, *ltime.TTimeValue, timeStr.s
    time(@now)
    *ltime = localtime(@now)
    timeStr = RSet(Str(*ltime\hour),2,"0") + ":"+ RSet(Str(*ltime\minute),2,"0") + ":" + RSet(Str(*ltime\second),2,"0")
    TimeGadget_SetTimeString(*pTimeGadget, timeStr)
  EndProcedure
  
  Procedure TimeGadget_SetUTCTime(*pTimeGadget.TTimeInput)
    Protected now.i, *utime.TTimeValue, timeStr.s
    time(@now)
    *utime = gmtime(@now)
    timeStr = RSet(Str(*utime\hour),2,"0") + ":"+ RSet(Str(*utime\minute),2,"0") + ":" + RSet(Str(*utime\second),2,"0")
    TimeGadget_SetTimeString(*pTimeGadget, timeStr)
  EndProcedure
  
  Procedure DrawClock(*pTimeGadget.TTimeInput, gid)
    Protected.i hour, minute, ufont
    Protected.i h, m, s
    h = TimeGadget_GetHour(*pTimeGadget)
    m = TimeGadget_GetMinute(*pTimeGadget)
    s = TimeGadget_GetSecond(*pTimeGadget)
    
    StartVectorDrawing(CanvasVectorOutput(gid))
    
    VectorSourceColor(RGBA(0, 0, 0, 255))
    MovePathCursor(0, 0)
    AddPathCircle(50, 50, 50)
    FillPath()
    StrokePath(1)
    ClosePath()
    
    ufont = LoadFont(#PB_Any, "Times", 8)
    VectorFont(FontID(ufont))
    ;Stunden-Ziffern
    For hour = 1 To 12
      ux = 50 + Sin(Radian(360/12*hour)) * 40 - VectorTextWidth(Str(hour))/2
      uy = 50 + -Cos(Radian(360/12*hour)) * 40 - VectorTextHeight(Str(hour))/2
      VectorSourceColor(RGBA(255, 255, 255, 255))
      MovePathCursor(ux, uy)
      DrawVectorText(Str(hour))
    Next
    
    ;Minuten/Sekunden
    For minute = 1 To 60
      ux = 50 + Sin(Radian(360/60*minute)) * 40
      uy = 50 + -Cos(Radian(360/60*minute)) * 40
    Next
    
    ;(Die Uhr wird auf 360 Grad (12 Uhr) oben eingestellt!)
    ;Die Zeiger:
    ;Degree = 360 / Anzahl_Ziffern * Aktuelle_Ziffer
    ;x = mitte_x + Sin(Rad(Degree)) * radius
    ;y = mitte_y + -Cos(Rad(Degree)) * radius
    
    ;Stundenzeiger
    ux = 50 + Sin(Radian(360/12*(h+(m/60)))) * 30
    uy = 50 + -Cos(Radian(360/12*(h+(m/60)))) * 30
    
    MovePathCursor(50, 50)
    AddPathLine(ux, uy)
    StrokePath(3)
    ClosePath()
    
    ;Minutenzeiger
    ux = 50 + Sin(Radian(360/60*m)) * 40
    uy = 50 + -Cos(Radian(360/60*m)) * 40
    
    MovePathCursor(50, 50)
    AddPathLine(ux, uy)
    StrokePath(2)
    ClosePath()
    
    ;Sekundenzeiger
    ux = 50 + Sin(Radian(360/60*s)) * 40
    uy = 50 + -Cos(Radian(360/60*s)) * 40
    
    MovePathCursor(50, 50)
    AddPathLine(ux, uy)
    StrokePath(1)
    ClosePath()
    
    StopVectorDrawing()
  EndProcedure
  
  Procedure TimeGadget_ShowAnalog(*pTimeGadget.TTimeInput)
    Protected.i mouse_x, mouse_y, cav
    If IsGadget(*pTimeGadget\gid)
      ExamineDesktops()
      mouse_x = DesktopMouseX()
      mouse_y = DesktopMouseY()
      AClockWin = OpenWindow(#PB_Any, mouse_x, mouse_y, 100, 100, "", #PB_Window_BorderLess)
      If AClockWin <> 0
        cav = CanvasGadget(#PB_Any, 0, 0, 100, 100)
        DrawClock(*pTimeGadget, cav)
      EndIf
    EndIf
  EndProcedure
  
  Procedure TimeGadget_SetEvent_MenuExceptions(Map vMenuExceptions())
    CopyMap(vMenuExceptions(), MenuExceptions())
  EndProcedure
  
  Procedure TimeGadget_Event(*pTimeGadget.TTimeInput, Win.i, WindowEvent.i)
    Protected evt.b = #False
    Protected cursor_pos.i
    Protected afocus.b = #False
    Protected select_mode.b = #False
    Protected regex.i
    
    If IsGadget(*pTimeGadget\gid)
      With *pTimeGadget
        Select WindowEvent
          Case #PB_Event_Menu
            If GetActiveGadget() = \gid
              ForEach MenuExceptions()
                If Str(EventMenu()) = MapKey(MenuExceptions())
                  Select MenuExceptions()
                    Case #PB_Shortcut_Left
                      If \cursor\pos > 0 : \cursor\pos - 3 : EndIf
                      evt = #True
                    Case #PB_Shortcut_Right
                      If \cursor\pos < Len(\value) : \cursor\pos + 3 : EndIf
                      evt = #True
                    Case #PB_Shortcut_Down
                      TimeGadget_ChangeTime(*pTimeGadget, \cursor\pos, #True)
                      evt = #True
                    Case #PB_Shortcut_Up
                      TimeGadget_ChangeTime(*pTimeGadget, \cursor\pos, #False)
                      evt = #True
                    Case #PB_Shortcut_End
                      \cursor\pos = Len(\value)
                      evt = #True
                    Case #PB_Shortcut_Home
                      \cursor\pos = 0
                      evt = #True
                    Case #PB_Shortcut_Back
                      If Not TimeGadget_DeleteSelection(*pTimeGadget)
                        If \cursor\pos > 0
                          \value = Left(\value, \cursor\pos - 1) + Mid(\value, \cursor\pos + 1)
                          \cursor\pos - 1
                        EndIf
                      EndIf
                      evt = #True
                    Case #PB_Shortcut_Delete
                      If Not TimeGadget_DeleteSelection(*pTimeGadget)
                        If \cursor\pos < Len(\value)
                          \value = Left(\value, \cursor\pos) + Mid(\value, \cursor\pos + 2)
                        EndIf
                      EndIf
                      evt = #True
                  EndSelect
                EndIf
              Next
            EndIf
          Case #PB_Event_Gadget
            If EventGadget() = \gid
              Select EventType()
                Case #PB_EventType_LeftButtonDown
                  If \center = #True
                    cursor_pos = TimeGadget_GetInputPosition(*pTimeGadget, (\w / 2)-(\cursor\cwidth / 2), (\h / 2)-(\cursor\cheight / 2))
                  Else
                    cursor_pos = TimeGadget_GetInputPosition(*pTimeGadget, 2, (\h / 2)-(\cursor\cheight / 2))
                  EndIf
                  If cursor_pos <> -1
                    If cursor_pos < 3
                      cursor_pos = 1
                    ElseIf cursor_pos > 2 And cursor_pos < 6
                      cursor_pos = 4
                    ElseIf cursor_pos > 5 And cursor_pos < 9
                      cursor_pos = 7
                    EndIf
                    \cursor\pos = cursor_pos - 1
                    \cursor\fpos = cursor_pos - 1
                    \cursor\length = 2
                    evt = #True
                  Else
                    \cursor\length = 0
                  EndIf
                Case #PB_EventType_RightButtonDown
                  If AClockWin = 0
                    TimeGadget_ShowAnalog(*pTimeGadget)
                  ElseIf AClockWin <> 0
                    CloseWindow(AClockWin)
                    AClockWin = 0
                  EndIf
                Case #PB_EventType_RightButtonUp
                  If AClockWin <> 0
                    CloseWindow(AClockWin)
                    AClockWin = 0
                  EndIf
                Case #PB_EventType_MouseWheel
                  If GetGadgetAttribute(\gid, #PB_Canvas_WheelDelta) = 1
                    TimeGadget_ChangeTime(*pTimeGadget, \cursor\pos, #False)
                  ElseIf GetGadgetAttribute(\gid, #PB_Canvas_WheelDelta) = -1
                    TimeGadget_ChangeTime(*pTimeGadget, \cursor\pos, #True)
                  EndIf
                Case #PB_EventType_Focus
                  \isfocus = #True
                Case #PB_EventType_LostFocus
                  \isfocus = #False
                  \cursor\length = 0
                Case #PB_EventType_LeftButtonUp
                  select_mode = #False
                Case #PB_EventType_Input
                  regex = CreateRegularExpression(#PB_Any, "[0-9 :]")
                  If regex
                    ExamineRegularExpression(regex, Chr(GetGadgetAttribute(\gid, #PB_Canvas_Input)))
                    If Not NextRegularExpressionMatch(regex)
                      Debug "Input Error!"
                    ElseIf Len(\value) <= 8
                      If TimeGadget_DeleteSelection(*pTimeGadget)
                        \value = Left(\value, \cursor\pos) + Chr(GetGadgetAttribute(\gid, #PB_Canvas_Input)) + Mid(\value, \cursor\pos + 3)
                        If Len(\value) > 8
                          \value = Left(Left(\value, \cursor\pos) + Chr(GetGadgetAttribute(\gid, #PB_Canvas_Input)) + Mid(\value, \cursor\pos + 1), Len(\value)-1)
                        EndIf
                      Else
                        \value = Left(\value, \cursor\pos) + Chr(GetGadgetAttribute(\gid, #PB_Canvas_Input)) + Mid(\value, \cursor\pos + 1)
                        If Len(\value) > 8
                          \value = Left(Left(\value, \cursor\pos) + Chr(GetGadgetAttribute(\gid, #PB_Canvas_Input)) + Mid(\value, \cursor\pos + 1), Len(\value)-1)
                        EndIf
                      EndIf
                      \cursor\pos + 1
                    EndIf
                    FreeRegularExpression(regex)
                  EndIf
                  evt = #True
                Case #PB_EventType_KeyDown
                  Select GetGadgetAttribute(\gid, #PB_Canvas_Key)
                    Case #PB_Shortcut_Left
                      If \cursor\pos > 0 : \cursor\pos - 3 : EndIf
                      evt = #True
                    Case #PB_Shortcut_Right
                      If \cursor\pos < Len(\value) : \cursor\pos + 3 : EndIf
                      evt = #True
                    Case #PB_Shortcut_Down
                      TimeGadget_ChangeTime(*pTimeGadget, \cursor\pos, #True)
                      evt = #True
                    Case #PB_Shortcut_Up
                      TimeGadget_ChangeTime(*pTimeGadget, \cursor\pos, #False)
                      evt = #True
                    Case #PB_Shortcut_End
                      \cursor\pos = Len(\value)
                      evt = #True
                    Case #PB_Shortcut_Home
                      \cursor\pos = 0
                      evt = #True
                    Case #PB_Shortcut_Back
                      If Not TimeGadget_DeleteSelection(*pTimeGadget)
                        If \cursor\pos > 0
                          \value = Left(\value, \cursor\pos - 1) + Mid(\value, \cursor\pos + 1)
                          \cursor\pos - 1
                        EndIf
                      EndIf
                      evt = #True
                    Case #PB_Shortcut_Delete
                      If Not TimeGadget_DeleteSelection(*pTimeGadget)
                        If \cursor\pos < Len(\value)
                          \value = Left(\value, \cursor\pos) + Mid(\value, \cursor\pos + 2)
                        EndIf
                      EndIf
                      evt = #True
                  EndSelect
              EndSelect
            EndIf
        EndSelect
      EndWith
    EndIf
  EndProcedure
  
  Procedure GetCursorPosition(*pTimeGadget.TTimeInput)
    ProcedureReturn TextWidth(Left(*pTimeGadget\value, *pTimeGadget\cursor\pos))
  EndProcedure
  
  Procedure GetCursorLength(*pTimeGadget.TTimeInput)
    ProcedureReturn TextWidth(Left(*pTimeGadget\value, *pTimeGadget\cursor\pos + *pTimeGadget\cursor\length)) - TextWidth(Left(*pTimeGadget\value, *pTimeGadget\cursor\pos))
  EndProcedure
  
  Procedure TimeGadget_GetCursorPosition(*pTimeGadget.TTimeInput)
    ProcedureReturn *pTimeGadget\cursor\pos
  EndProcedure
  
  Procedure TimeGadget_ChangeFont(*pTimeGadget.TTimeInput, font_nr.i)
    If IsGadget(*pTimeGadget\gid)
      With *pTimeGadget
        \font = font_nr
      EndWith
    EndIf
  EndProcedure
  
  Procedure TimeGadget_ChangeColor(*pTimeGadget.TTimeInput, bgcolor.i, fgcolor.i = 0)
    If IsGadget(*pTimeGadget\gid)
      With *pTimeGadget
        \bgcolor = bgcolor
        \fgcolor = fgcolor
      EndWith
    EndIf
  EndProcedure
  
  Procedure TimeGadget_Update(*pTimeGadget.TTimeInput, show_cursor.b = #False)
    Protected.i a
    If IsGadget(*pTimeGadget\gid)
      With *pTimeGadget
        StartDrawing(CanvasOutput(\gid))
        DrawingMode(#PB_2DDrawing_Default)
        If IsFont(\font)
          DrawingFont(FontID(\font))
        EndIf
        \cursor\cheight = TextHeight(\value)
        \cursor\cwidth = TextWidth(\value)
        Box(0, 0, \w, \h, \bgcolor)
        If \center = #True
          DrawText((\w / 2)-(TextWidth(\value) / 2), (\h / 2)-(TextHeight(\value) / 2), \value, \fgcolor, \bgcolor)
        Else
          DrawText(2, (\h / 2)-(TextHeight(\value) / 2), \value, \fgcolor, \bgcolor)
        EndIf
        DrawingMode(#PB_2DDrawing_XOr)
        If \cursor\length < 0
          If \center = #True
            Box((\w / 2)-(TextWidth(\value) / 2) + GetCursorPosition(*pTimeGadget) + GetCursorLength(*pTimeGadget), (\h / 2)-(TextHeight(\value) / 2), -GetCursorLength(*pTimeGadget), TextHeight(" "))
          Else
            Box(2 + GetCursorPosition(*pTimeGadget) + GetCursorLength(*pTimeGadget), (\h / 2)-(TextHeight(\value) / 2), -GetCursorLength(*pTimeGadget), TextHeight(" "))
          EndIf
        ElseIf \cursor\length > 0
          If \center = #True
            Box((\w / 2)-(TextWidth(\value) / 2) + GetCursorPosition(*pTimeGadget) + 1, (\h / 2)-(TextHeight(\value) / 2), GetCursorLength(*pTimeGadget) - 1, TextHeight(" "))
          Else
            Box(2 + GetCursorPosition(*pTimeGadget) + 1, (\h / 2)-(TextHeight(\value) / 2), GetCursorLength(*pTimeGadget) - 1, TextHeight(" "))
          EndIf
        EndIf
        DrawingMode(#PB_2DDrawing_Default)
        If show_cursor = #True And \isfocus = #True
          If \center = #True
            Line((\w / 2)-(TextWidth(\value) / 2) + GetCursorPosition(*pTimeGadget), (\h / 2)-(TextHeight(\value) / 2), 1, TextHeight(" "), RGB(0,0,0))
          Else
            Line(2 + GetCursorPosition(*pTimeGadget), (\h / 2)-(TextHeight(\value) / 2), 1, TextHeight(" "), RGB(0,0,0))
          EndIf
        EndIf
        StopDrawing()
      EndWith
    EndIf
  EndProcedure
  
  Procedure TimeGadget_Resize(*pTimeGadget.TTimeInput, x, y, w, h)
    If IsGadget(*pTimeGadget\gid)
      With *pTimeGadget
        If x <> #PB_Ignore And x > 0
          \x = x
        EndIf
        If y <> #PB_Ignore And y > 0
          \y = y
        EndIf
        If w <> #PB_Ignore And w > 0
          \w = w
        EndIf
        If h <> #PB_Ignore And h > 0
          \h = h
        EndIf
        ResizeGadget(*pTimeGadget\gid, \x, \y, \w, \h)
        TimeGadget_Update(*pTimeGadget)
      EndWith
    EndIf
  EndProcedure
  
  ;Time-Gadget-Constructor
  Procedure.i TimeGadget(gid.i, xpos.i, ypos.i, width.i, height.i, timeStr.s, flag.i = 0)
    Protected *pTimeGadget.TTimeInput = AllocateMemory(SizeOf(TTimeInput))
    Protected pid.i, k.i
    pid = CanvasGadget(gid, xpos, ypos, width, height, #PB_Canvas_Border|#PB_Canvas_Keyboard)
    If pid <> 0
      If gid = -1
        SetGadgetAttribute(pid, #PB_Canvas_Cursor, #PB_Cursor_IBeam)
      Else
        SetGadgetAttribute(gid, #PB_Canvas_Cursor, #PB_Cursor_IBeam)
      EndIf
      
      With *pTimeGadget
        If gid = -1
          \gid = pid
        Else
          \gid = gid
        EndIf
        \x = xpos
        \y = ypos
        \h = height
        \w = width
        If flag = 0
          ;auto-center
          \center = #True
        Else
          ;no-center
          \center = #False
        EndIf
        \font = -1
        \bgcolor = RGB(255,255,255)
        \fgcolor = RGB(0,0,0)
      EndWith
      
      TimeGadget_SetTimeString(*pTimeGadget, timeStr)
      
      ProcedureReturn *pTimeGadget
    EndIf
    ProcedureReturn -1
  EndProcedure
  
  ;Time-Gadget-Destructor
  Procedure TimeGadget_Destroy(*pTimeGadget.TTimeInput)
    If IsGadget(*pTimeGadget\gid)
      FreeGadget(*pTimeGadget\gid)
      FreeMemory(*pTimeGadget)
    EndIf
  EndProcedure
  
EndModule


Enumeration
  #Win
  #ControlTimer
  #SecondTimer
EndEnumeration

UseModule TimeGadget


Global *vTimeGadget.TTimeInput, atimeStr.s

Global *vTimeGadget2.TTimeInput

If OpenWindow(#Win, 0, 0, 200, 100, "Time-Control", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  
  atimeStr = RSet(Str(Hour(Date())), 2, "0") + ":" + RSet(Str(Minute(Date())), 2, "0") + ":" + RSet(Str(Second(Date())), 2, "0")
  
  *vTimeGadget = TimeGadget(0, 10, 10, 80, 20, "00:00:00", #True)
  ;Debug *vTimeGadget
  
  *vTimeGadget2 = TimeGadget(1, 10, 50, 80, 20, "00:00:00")
  ;Debug *vTimeGadget2
  
  TimeGadget_SetTimeString(*vTimeGadget, atimeStr)
  
  TimeGadget_ChangeColor(*vTimeGadget, RGB(0,0,0), RGB(255, 255, 0))
  TimeGadget_ChangeColor(*vTimeGadget2, RGB(255,255,0))
  
  LoadFont(0, "ComicSansMS", 14)
  
  TimeGadget_ChangeFont(*vTimeGadget2, 0)
  
  TimeGadget_Resize(*vTimeGadget2, 10, 40, 180, 50)
  
  ;TimeGadget_SetLocalTime(*vTimeGadget2)
  TimeGadget_SetUTCTime(*vTimeGadget2)
  
  ;Beim Shortcut-Problem ...
  AddKeyboardShortcut(#Win, #PB_Shortcut_Right, 1)
  AddKeyboardShortcut(#Win, #PB_Shortcut_Left, 2)
  AddKeyboardShortcut(#Win, #PB_Shortcut_Up, 3)
  AddKeyboardShortcut(#Win, #PB_Shortcut_Down, 4)
  
  ;.. muss/sollte/kann eine Ausnahmeliste erstellt werden!
  NewMap ExMenuItem.i()
  
  ExMenuItem("1") = #PB_Shortcut_Right
  ExMenuItem("2") = #PB_Shortcut_Left
  ExMenuItem("3") = #PB_Shortcut_Up
  ExMenuItem("4") = #PB_Shortcut_Down
  
  TimeGadget_SetEvent_MenuExceptions(ExMenuItem())
  
  
  AddWindowTimer(#Win, #ControlTimer, 200)
  AddWindowTimer(#Win, #SecondTimer, 1000) ;Durch Deaktivieren\Kommentieren läuft die Zeit nicht weiter !
  
  Repeat
    event = WaitWindowEvent()
    
    If TimeGadget_Event(*vTimeGadget, #Win, event)
      TimeGadget_Update(*vTimeGadget, #False)
    EndIf
    If TimeGadget_Event(*vTimeGadget2, #Win, event)
      TimeGadget_Update(*vTimeGadget2, #False)
    EndIf
    
    Select event
      Case #PB_Event_Menu
        ;Test!
        If EventMenu() = 1 Or EventMenu() = 2 Or EventMenu() = 3 Or EventMenu() = 4
          Debug "Key-Exception!"
        EndIf
      Case #PB_Event_CloseWindow
        End
      Case #PB_Event_Timer
        Select EventTimer()
          Case #ControlTimer
            TimeGadget_Update(*vTimeGadget, #True)
            TimeGadget_Update(*vTimeGadget2, #True)
          Case #SecondTimer
            atimeStr = RSet(Str(Hour(Date())), 2, "0") + ":" + RSet(Str(Minute(Date())), 2, "0") + ":" + RSet(Str(Second(Date())), 2, "0")
            TimeGadget_SetTimeString(*vTimeGadget, atimeStr)
        EndSelect
    EndSelect
    
  ForEver
  
  TimeGadget_Destroy(*vTimeGadget)
  TimeGadget_Destroy(*vTimeGadget2)
  
EndIf

UnuseModule TimeGadget
(Update - 22-12-18/15:38)

Was könnte man so alles an meiner "Wer hat an der Uhr gedreht"(TimeGadget) -Version noch alles verbessern ?
Zuletzt geändert von ccode_new am 22.12.2018 16:39, insgesamt 1-mal geändert.
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
Antworten