habe ich mal eine Include geschrieben und das Thema als Interface realisiert.
Ein Interface ist flexibler, auch wenn es etwas mehr Arbeit macht. Und wenn man die Aufrufe in Macros packt, dann sieht es aus wie ganz normale Befehle/Prozeduraufrufe.
Bei der Auswertung des Keys habe ich mich darauf beschränkt, die Länge zu prüfen. Das macht jeder wie er es benötigt.
PS: Fehler ? es gibt sie aber wo

Mainprogramm:
Code: Alles auswählen
XIncludeFile "icLizenz.pbi"
Enumeration
#mainwindow
#button1
#button2
#button3
EndEnumeration
Enumeration
#menu
#menu_1
#menu_2
#menu_3
#menu_4
#menu_lizenz
EndEnumeration
Define lizenz.Interface_LizenzWindow
Define event
OpenWindow(#mainwindow, 0, 0, 800, 500, "Main", #PB_Window_ScreenCentered |#PB_Window_SystemMenu)
CreateMenu(#menu, WindowID(#mainwindow))
MenuTitle("x")
MenuItem(#menu_1, "blah")
MenuTitle("xyz")
MenuItem(#menu_3, "blah")
MenuTitle("Lizenz")
MenuItem(#menu_lizenz, "Key eingeben")
ButtonGadget(#button1, 10, 450, 88, 22, "tuenix")
ButtonGadget(#button2, 110, 450, 88, 22, "tuenix")
ButtonGadget(#button3, 210, 450, 88, 22, "tuenix")
Repeat
event = WaitWindowEvent()
Select EventWindow()
Case #mainwindow
Select event
Case #PB_Event_Gadget
Select EventGadget()
Case #button1: Debug "tue nix"
EndSelect
Case #PB_Event_Menu
Select EventMenu()
Case #menu_1:
Case #menu_3:
Case #menu_lizenz: lizenz = LizenzInput(#mainwindow, 4, 5)
EndSelect
EndSelect
Case LizenzWindow(lizenz)
Select event
Case #WM_QUIT ;Button im LizenzWindow gedrückt
Debug LizenzString(lizenz)
If LizenzCheck(lizenz) = #True
Debug "Software freigegeben"
Else
Debug "Key hat falsche Länge, Software bleibt gesperrt"
EndIf
LizenzEnd(lizenz)
event = 0
EndSelect
EndSelect
Until Event = #PB_Event_CloseWindow
Code: Alles auswählen
;Reihenfolge in der Interface Definition muß gleich der DataSection sein !!!
Interface Interface_LizenzWindow
GetKey.s()
GetWindow.i()
CheckKey()
Release.i()
EndInterface
Structure cLizenzWindow
*VTable_cLizenzWindow
window.i ;Subwindow
stringid.i[11] ;Index 1-10, max Anzahl Felder
stringlp.i ;Zeiger auf OriginalStringGadgetCallback, sollte immer gleich sein
button1id.i ;Button ok
button2id.i ;Button Abbruch
buttonlp.i ;Zeiger auf OriginalButtonGadgetCallback
dummy1id.i ;DummyGadget vor den Keyfeldern, muß WS_TABSTOP style haben z.B. StringGadget
dummy2id.i ;DummyGadget nach den Keyfeldern,
keyfelder.i ;Anzahl Eingabefelder
keyanzchr.i ;Anzahl Character pro Eingabefeld
keystring.s ;Lizenzkey
EndStructure
Macro LizenzInput(parentwindow, felder = 5, anzchr = 5)
IcLizenzWindow(parentwindow, felder, anzchr)
EndMacro
Macro LizenzEnd(nr)
nr\Release()
EndMacro
Macro LizenzString(nr)
nr\GetKey()
EndMacro
Macro LizenzWindow(nr)
nr\GetWindow()
EndMacro
Macro LizenzCheck(nr)
nr\CheckKey()
EndMacro
;interne Prozeduren
Procedure.i IcLizenzWindowI_CBButtonGadget(hWnd, Msg, wParam, lParam)
;hwnd ist hier gleich der ID vom Gadget
Protected *p.cLizenzWindow = GetWindowLongPtr_(hWnd, #GWL_USERDATA)
With *p
Select msg
Case #WM_CHAR
Select wparam
Case 13, 32
Select hwnd
Case \button1id: PostMessage_(GetParent_(hWnd), #WM_QUIT, #True, 0)
Case \button2id: PostMessage_(GetParent_(hWnd), #WM_QUIT, #False, 0)
EndSelect
EndSelect
Case #WM_LBUTTONDOWN
Select hwnd
Case \button1id: PostMessage_(GetParent_(hWnd), #WM_QUIT, #True, 0)
Case \button2id: PostMessage_(GetParent_(hWnd), #WM_QUIT, #False, 0)
EndSelect
EndSelect
ProcedureReturn CallWindowProc_(\buttonlp, hWnd, msg, wParam, lParam)
EndWith
EndProcedure
Procedure.i IcLizenzWindowI_CBStringGadget(hWnd, Msg, wParam, lParam)
;hwnd ist hier gleich der ID vom Gadget
Protected *p.cLizenzWindow = GetWindowLongPtr_(hWnd,#GWL_USERDATA)
With *p
Protected j, x, y
Protected nr = GetDlgCtrlID_(hwnd)
Protected parent = GetParent_(hWnd)
Protected nexthandle, prevhandle
Protected maxchr = \keyanzchr - 1 ;es wird ab null gezählt
Select msg
Case #WM_KILLFOCUS
If wparam = \dummy2id: SetFocus_(\button1id): EndIf
\keystring = ""
For j = 1 To \keyfelder
\keystring + GetGadgetText(GetDlgCtrlID_(\stringid[j]))
Next
;welche Zeichen sind erlaubt
Case #WM_CHAR
;nur Backspace, Zahlen und Buchstaben
Select wparam
Case 8, 48 To 57
Case 97 To 122: wparam - 32 ;klein wird groß
Default: ProcedureReturn 0
EndSelect
;Tatendruck
Case #WM_KEYUP
;wo ist Caret
SendMessage_(hwnd, #EM_GETSEL, @x, @y)
;nächstes/vorheriges handle
nexthandle = GetNextDlgTabItem_(parent, hWnd, #False)
prevhandle = GetNextDlgTabItem_(parent, hWnd, #True)
;welche Taste gedrückt ?
Select wparam
Case #VK_ESCAPE
;simuliere Click auf Abbruch-Button
PostMessage_(\button2id, #BM_CLICK, 0, 0)
Case #VK_LEFT, #VK_RIGHT ;Pfeil links/rechts
If x < 1
If prevhandle = \dummy1id: prevhandle = hwnd: EndIf
SetFocus_(prevhandle)
ElseIf x > maxchr
If nexthandle = \dummy2id: nexthandle = hwnd: EndIf
SetFocus_(nexthandle)
EndIf
Case #VK_0 To #VK_9, #VK_A To #VK_Z, #VK_NUMPAD0 To #VK_NUMPAD9
If x < 1
If prevhandle = \dummy1id: prevhandle = hwnd: EndIf
SetFocus_(prevhandle)
ElseIf x > maxchr
If nexthandle = \dummy2id: nexthandle = hwnd: EndIf
SetFocus_(nexthandle)
EndIf
Default: ProcedureReturn 0
EndSelect
EndSelect
ProcedureReturn CallWindowProc_(\stringlp, hWnd, msg, wParam, lParam)
EndWith
EndProcedure
;externe Prozeduren
Procedure.i IcLizenzWindow_CheckKey(*this.cLizenzWindow)
Protected result = #False
With *this
If EventwParam() = #True
If Len(\keystring) = \keyfelder * \keyanzchr
result = #True
EndIf
;hier mehr Checks
EndIf
EndWith
ProcedureReturn result
EndProcedure
Procedure.s IcLizenzWindow_GetKey(*this.cLizenzWindow)
ProcedureReturn *this\keystring
EndProcedure
Procedure.i IcLizenzWindow_GetWindow(*this.cLizenzWindow)
ProcedureReturn *this\window
EndProcedure
Procedure.i IcLizenzWindow_Release(*this.cLizenzWindow)
CloseWindow(*this\window)
FreeMemory(*this)
ProcedureReturn #Null
EndProcedure
Procedure.i IcLizenzWindow(parentwindow, felder = 5, anzchr = 5)
If felder > 10: felder = 10: EndIf ;auf 10 Felder begrenzt, siehe Structur
Protected *p.cLizenzWindow = AllocateMemory(SizeOf(cLizenzWindow))
If Not *p: ProcedureReturn #Null: EndIf
*p\VTable_cLizenzWindow = ?VTable_cLizenzWindow
With *p
\keyfelder = felder
\keyanzchr = anzchr
Protected flags = #PB_Window_Tool | #PB_Window_ScreenCentered
Protected pbnr, j, x, y, null
Protected abstand = 10, br = 70, hh = 22
Protected winbr = abstand + (\keyfelder * abstand) + (\keyfelder * br)
Protected winhh = abstand + (4 * abstand) + (3 * hh)
\window = OpenWindow(#PB_Any, 0, 0, winbr, winhh, "Key-Eingabe", flags, WindowID(parentwindow))
x = abstand: y = abstand
TextGadget(#PB_Any, x, y, winbr - x - x, hh, "Geben Sie den Produkt-Key ein")
\dummy1id = GadgetID(StringGadget(#PB_Any, 0, 0, 0, 0, ""))
y + hh + abstand
For j = 1 To \keyfelder
pbnr = StringGadget(#PB_Any, x, y, br, hh, "")
\stringid[j] = GadgetID(pbnr)
;max Zeichen Stringgadget
SendMessage_(\stringid[j], #EM_LIMITTEXT, \keyanzchr, 0)
;subclassing
\stringlp = SetWindowLongPtr_(\stringid[j], #GWL_WNDPROC, @IcLizenzWindowI_CBStringGadget())
SetWindowLongPtr_(\stringid[j], #GWL_USERDATA, *p)
;posi nächstes Gadget
x + br + abstand
Next
SetFocus_(\stringid[1])
\dummy2id = GadgetID(StringGadget(#PB_Any, 0, 0, 0, 0, ""))
x = abstand: y = winhh - abstand - hh
pbnr = ButtonGadget(#PB_Any, x, y, br, hh, "Ok ?")
\button1id = GadgetID(pbnr)
\buttonlp = SetWindowLongPtr_(\button1id, #GWL_WNDPROC, @IcLizenzWindowI_CBButtonGadget())
SetWindowLongPtr_(\button1id, #GWL_USERDATA, *p)
x + abstand + br ;: x = winbr - abstand - br
pbnr = ButtonGadget(#PB_Any, x, y, br, hh, "Abbruch")
\button2id = GadgetID(pbnr)
\buttonlp = SetWindowLongPtr_(\button2id, #GWL_WNDPROC, @IcLizenzWindowI_CBButtonGadget())
SetWindowLongPtr_(\button2id, #GWL_USERDATA, *p)
ProcedureReturn *p
EndWith
EndProcedure
DataSection
VTable_cLizenzWindow:
Data.i @ IcLizenzWindow_GetKey()
Data.i @ IcLizenzWindow_GetWindow()
Data.i @ IcLizenzWindow_CheckKey()
Data.i @ IcLizenzWindow_Release()
EndDataSection