 |
Das deutsche QBasic- und FreeBASIC-Forum Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
TimesChange
Anmeldungsdatum: 20.11.2013 Beiträge: 85
|
Verfasst am: 03.12.2013, 00:20 Titel: |
|
|
nemored hat Folgendes geschrieben: | ...Genau das macht MULTIKEY ja. Wenn du das Drücken einer Taste nur einmal registrieren willst, müsstest du ein Array verwalten, in dem du für jede Taste (bzw. für jede, die dich interessiert) speicherst, ob sie zuletzt gedrückt war oder nicht. |
Das ändert aber nichts daran, dass mir MULTIKEY (welches ja in einer Schleife wiederholt aufgerufen wird) ein und dasselbe Zeichen dann x-mal zurückliefert.
Einen passenden Wert für SLEEP herauszufinden, bei dem bei "normaler" Tasten-Drück-Dauer nur ein Tastenanschlag zurückgegeben wird, erscheint mir suboptimal.
Etwas Seltsames zu SLEEP bei Complierung mit #lang "qb":
Warum werden in folgendem Code die ersten beiden SLEEPs akzeptiert, beim dritten bekomme ich aber die Fehlermeldung #1 "Argument count mismatch" ?
Der Compilre müsset wenn dann doch beim zweiten SLEEP meckern?
Code: | __sleep 100
sleep 100,1
__sleep 100,1 |
nemored hat Folgendes geschrieben: | Das wäre dir aber bei SCREENEVENT bereits abgenommen. |
Muss ich mir noch genauer ansehen...
Zitat: | Evtl. die Pause (SLEEP) erhöhen ... allerdings kann ich mit dem unveränderten Beispiel zwar auch keine "Einzelschritt-"Abfrage erreichen, um vom linken zum rechten Rand zu gelangen, muss ich die Taste aber schon so anderthalb Sekunden gedrückt halten.
... der Artikel in der FBREF_11-18-2013D.CHM müsste da ja identisch sein.) |
Müsste eigentlich, ist er aber nicht: In der Dateiversion fehlt der SLEEP-Befehl am Anfang der Schleife.
Mit Sleep 1 kann ich den Kreis ebenfalls wie erwartet steuern (auch keine Einzelschritte, aber ca. 1 sec von links nach rechts). Und ich dachte schon ich habe den Ferrari unter den Tastaturen
Stelle ich mich eigentlich dabei zu blöd an, oder ist es tatsächlich so kompliziert, mit FB die gewünschte Eingabe zu realisieren?
Bei einem "nicht-mehr-16-Bit-DOS-Programm" wie es FB erzeugt, wäre es vermutlich kein gute Idee, mittels ASM direkt den Interrupt &h16 aufzurufen, um meine alte - funktionierende - Routine zu verwenden?
Viele Grüße
Rainer |
|
Nach oben |
|
 |
Jojo alter Rang

Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
|
Verfasst am: 03.12.2013, 00:47 Titel: |
|
|
TimesChange hat Folgendes geschrieben: | nemored hat Folgendes geschrieben: | ...Genau das macht MULTIKEY ja. Wenn du das Drücken einer Taste nur einmal registrieren willst, müsstest du ein Array verwalten, in dem du für jede Taste (bzw. für jede, die dich interessiert) speicherst, ob sie zuletzt gedrückt war oder nicht. |
Das ändert aber nichts daran, dass mir MULTIKEY (welches ja in einer Schleife wiederholt aufgerufen wird) ein und dasselbe Zeichen dann x-mal zurückliefert. |
Es ändert aber die Tatsache, dass du dir merken kannst, ob die Taste schon im vorherigen Frame gedrückt wurde; somit kannst du dann einfach den Tastendruck ignorieren. _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
 |
|
Nach oben |
|
 |
TimesChange
Anmeldungsdatum: 20.11.2013 Beiträge: 85
|
Verfasst am: 03.12.2013, 01:49 Titel: |
|
|
Jojo hat Folgendes geschrieben: | Es ändert aber die Tatsache, dass du dir merken kannst, ob die Taste schon im vorherigen Frame gedrückt wurde; somit kannst du dann einfach den Tastendruck ignorieren. |
Da heißt für den interessierten Laien (im vorherigen "Frame")?
Selbst wenn ich den Sonderfall "Dauerdrücken" für z.b. "AAAAAAAAAA..." weglasse, wie unterscheide ich dann, ob das 5. zurückgelieferte "A" noch aus dem ersten Tastenanschlag stammt, oder ob der Benutzer zweimal "A" gedrückt hat, weil er "AA..." eingeben will?
Viele Grüße
Rainer
P.S.: Die Frage, ob ich mich besonders dämlich anstelle, war schon ernst gemeint, auch wenn mir ein NEIN als Antwort lieber wäre  |
|
Nach oben |
|
 |
St_W

Anmeldungsdatum: 22.07.2007 Beiträge: 957 Wohnort: Austria
|
Verfasst am: 03.12.2013, 02:14 Titel: |
|
|
Ich geb dir Recht: MULTIKEY ist für deinen Anwendungsfall unpassend und die Tastenwiederholung selbst zu programmieren fehleranfällig und wohl für den Anwender in einigen Fällen unerwartet (wenn z.B. die Anschlagrate im System anders eingestellt wurde).
Das mit den SLEEPs passt schon so wie es ist. Wenn du in die Referenz schaust, wirst du sehen, dass es zwei Varianten gibt: eine mit einem Parameter und eine weitere mit zwei Parametern. Die spezielle Variante "__SLEEP" wird nur textuell als Funktion mit einem Parameter in Millisekunden beschrieben. Wie generell für den QB Modus ist die Dokumentation hier nicht so vollständig und umfangreich, wie etwa beim FB-Modus.
Zum Interrupt &h16 (oder irgendeinem anderen): Es ist keine gute Idee weil es wohl schlicht und einfach nicht funktionieren würde. Wir sind hier weit entfernt von Real Mode und DOS.
Wie gesagt, ScreenEvent scheint in deinem Fall die optimale Variante zu sein, die jedoch nicht im QB Modus direkt verfügbar ist. Es ist schwierig diese Funktion manuell zu implementieren, da man an die Keyboard Events nicht so einfach ran kommt. Wenn du eine normale Win32 Anwendung hättest könnte man einfach einen Keyboard Hook registrieren. Bei Konsolenfenstern geht dies jedoch nicht. Bei FB's Grafikfenstern hat man das Problem, dass die Eingabe eventuell in einem anderen Thread bzw. von DirectInput behandelt wird.
Wie du siehst ist der QB Kompatibilitätsmodus sehr eingeschränkt und du solltest wirklich darüber nachdenken - womöglich auch über den Umweg von fblite - auf fb zu migrieren.
Man kann jedoch die SCREENEVENT Funktion aus der FB runtime lib auch direkt aufrufen, wie in folgendem Beispiel demonstriert: Code: | #Lang "qb"
'#Include "fbgfx.bi"
type EVENT field = 1
typ as Long
a as Long
b as Long
c as Long
d as Long
end Type
Screen 1
Declare Function ScreenEvent Alias "fb_GfxEvent" (ByVal event As EVENT __Pointer = 0) As Long
Dim evt As EVENT
Do
ScreenEvent(@evt)
__Sleep 10
Print evt.typ
Loop Until InKey$ = Chr$(27) | Beachte die "Declare function" Zeile, die die Funktion "fb_GfxEvent" aus der fbrtlib unter dem Namen ScreenEvent deklariert.
Die Struktur EVENT wird üblicherweise in fbgfx.bi definiert, aber diese ist zum QB Modus auch inkompatibel, darum die minimalistische Deklaration im Programm. _________________ Aktuelle FreeBasic Builds, Projekte, Code-Snippets unter http://users.freebasic-portal.de/stw/
http://www.mv-lacken.at Musikverein Lacken (MV Lacken)
Zuletzt bearbeitet von St_W am 05.12.2013, 02:24, insgesamt einmal bearbeitet |
|
Nach oben |
|
 |
TimesChange
Anmeldungsdatum: 20.11.2013 Beiträge: 85
|
Verfasst am: 05.12.2013, 02:08 Titel: |
|
|
Danke für deine erneute Übersetzungshilfe
Ok Interrupts vergesse ich.
Ob oder wie ich es schaffe, SCREENEVENT mit deinem Vorschlag zu nutzen, muss ich noch versuchen.
Eine Frage vorab dazu:
Du definierst beim EVENT-Typ 5 Integer-Variablen (in #lang qb, also 5 x 16 bit).
Wenn ich den Typ EVENT in der Hilfedatei (oder Online-Referenz) ansehe, besteht dieser aus 10 INTEGER Untervariablen (die in FB je 32 Bit lang sein müssten).
Schreibt mir der Aufruf von SCREENEVENT alias "fb_GfxEvent" dann nicht unkalkulierbar 10x32 Bit "irgendwo" in den Speicher?
Viele Grüße
Rainer |
|
Nach oben |
|
 |
St_W

Anmeldungsdatum: 22.07.2007 Beiträge: 957 Wohnort: Austria
|
Verfasst am: 05.12.2013, 02:23 Titel: |
|
|
Du hast teilweise Recht:
Du hast völlig korrekt erkannt, dass ich hier den Type zu klein gemacht hab - ich hab ganz einfach die unterschiedliche Größe von Integer übersehen, nachdem ich das zuerst in lang fb ausprobiert habe. Vielen Dank für den Hinweis - ich habs ausgebessert.
Das mit den 5 32-Bit Zahlen stimmt allerdings. Man kann dies leicht überprüfen mit sizeof(FB.EVENT) bzw. __sizeof(EVENT). Beachte dass der Type einen Union enthält, d.h. nur Speicherplatz für den größten Sub-Type vorhanden ist (alle Types auf den gleichen Speicherbereich verweisen).
Ob die Verwendung von ScreenEvent in lang qb darüber hinaus noch irgendwelche Probleme bereitet hab ich nicht getestet - die Basisfunktionalität scheint jedoch gegeben. _________________ Aktuelle FreeBasic Builds, Projekte, Code-Snippets unter http://users.freebasic-portal.de/stw/
http://www.mv-lacken.at Musikverein Lacken (MV Lacken) |
|
Nach oben |
|
 |
TimesChange
Anmeldungsdatum: 20.11.2013 Beiträge: 85
|
Verfasst am: 06.12.2013, 00:51 Titel: |
|
|
Die raffinierte Definitionswirkung von UNIT war mir nicht klar, daher die ursprüngliche Sorge, dass mein Speicher überschrieben wird.
So, das Programmbeispiel habe ich ausprobiert, auch als "echte" FB-Version.
Leider kann SCREENEVENT offenbar keine Tasten mit ALT erkennen.
Von daher also noch weniger geeignet als MULTIKEY.
Ansonsten ist das Verhalten ähnlich wie bei MULTIKEY, ein einziger kurzer Tastendruck liefert (je nach Größe des Parameter für SLEEP) mehrere Rückgabewerte.
Schon für meine eigene Übersicht fasse ich meine Versuche für eine Eingaberoutine nochmal zusammen:
1. MULTIKEY, gefolgt von GETKEY:
Erlaubt keine Unterscheidung, ob die ALT-Taste durchgehend gedrückt wurde, oder nicht
2. GetKeyboardState:
Hat beim ersten Versuch keinen nachvollziehbaren Ergebnisse geliefert...zunächst nicht weiter verfolgt
3. ScreenEvent:
Reagiert nicht auf Alt-Taste
"Rein gefühlsmäßig" würde ich sagen, dass bisher MULTIKEY am erfolgversprechendsten scheint, um meine Eingabe umzusetzen. Ich weiß nur noch nicht wie...
Kann es denn wirklich so schwierig sein, die gewünschte Eingaberoutine in FB zu realisieren?
Ihr habt mir schon bei so vielen Fragen geholfen, da muss doch auch das noch hinzubekommen sein
Noch zur Ergänzung:
Ich könnte die Bedienung meines Programmes natürlich ändern. Statt Schnellsuche mit ALT + "Buchstabenkombination" könnte ich auf "STRG" + "Buchstabenkombination" ausweichen. Und die bisher mit STRG+Zeichen erreichbaren Funktionen (wie STRG-E für "Export" auf Funktionstasten legen).
"Lebenswichtig" ist es also nicht, die bisherige Eingaberoutine von der Funktion 1:1 umzusetzen.
Aber da packt mich ein gewisser Ehrgeiz, und ich denke mir "ich lasse mir doch von der Programmiersprache nicht vorschreiben, wie mein Programm bedient werden soll. Irgendwie muss das doch lösbar sein, wenn auch mit Eurer Hilfe.
Viele Grüße
Rainer |
|
Nach oben |
|
 |
St_W

Anmeldungsdatum: 22.07.2007 Beiträge: 957 Wohnort: Austria
|
Verfasst am: 06.12.2013, 02:34 Titel: |
|
|
ScreenEvent liefert dir bei einem Tastendruck nur ein Press Event. Dass die Alt Taste nicht erkannt wird und z.B. auch nicht zwischen L/R Shift/Ctrl unterschieden wird musste ich auch feststellen, trotzdem hier ein etwas sinnvolleres Beispiel als jenes oberhalb: Code: | #Lang "qb"
'' Deklarationen aus fbgfx.bi BEGINN
type EVENT field = 1
typ as Long
a as Long
b as Long
c as Long
d as Long
end Type
#Define EVENT_KEY_PRESS 1
#Define EVENT_KEY_RELEASE 2
#Define EVENT_KEY_REPEAT 3
'' Deklarationen aus fbgfx.bi ENDE
__ScreenRes 250, 500
Declare Function ScreenEvent Alias "fb_GfxEvent" (ByVal event As EVENT __Pointer = 0) As Long
Dim evt As EVENT
Do
evt.typ = 0 'jedes Mal zurücksetzen, damit Events nicht öfters bearbeitet werden
ScreenEvent(@evt)
__Sleep 10
Select Case evt.typ
Case EVENT_KEY_PRESS
Print "Taste gedrueckt: "; evt.a 'scancode
Case EVENT_KEY_RELEASE
Print "Taste losgelassen: "; evt.a 'scancode
Case EVENT_KEY_REPEAT
Print " Tastenwiederholung: "; evt.a 'scancode
Case Else
'ignorieren
End Select
Loop Until InKey$ = Chr$(27) |
Verwendest du eigentlich einen Grafikmodus (SCREEN bzw. __SCREENRES) ? oder Textmodus (SCREEN 0) ?
Im Grafikmodus könnte man z.B. versuchen (das gilt jetzt nur für win32) dem Fenster eine alternative Fensterprozedur (WndProc) zuzuweisen, über die man die Tastatureingaben filtert und dann an die ursprüngliche WndProc übergibt, um die restliche Funktionalität aufrecht zu erhalten.
Ich hab das auch schon versucht - allerdings bis jetzt leider noch nicht erfolgreich; es crasht ziemlich schnell bei meiner eigenen WndProc und tut auch nicht wirklich was ich erwarten würde.
Ob das dann schöner ist, als mit Multikey irgendwas zu basteln ist allerdings nicht so eindeutig. Wirklich schön sind beide Lösungen nicht. _________________ Aktuelle FreeBasic Builds, Projekte, Code-Snippets unter http://users.freebasic-portal.de/stw/
http://www.mv-lacken.at Musikverein Lacken (MV Lacken) |
|
Nach oben |
|
 |
Muttonhead

Anmeldungsdatum: 26.08.2008 Beiträge: 565 Wohnort: Jüterbog
|
Verfasst am: 06.12.2013, 10:41 Titel: |
|
|
TimesChange hat Folgendes geschrieben: |
Noch zur Ergänzung:
Ich könnte die Bedienung meines Programmes natürlich ändern. Statt Schnellsuche mit ALT + "Buchstabenkombination" könnte ich auf "STRG" + "Buchstabenkombination" ausweichen. |
Nach C zu suchen in Verbindung mit STRG ist gaaanz schlecht...
Ich lese hier mit und knobel auch schon nen weilchen
Mutton |
|
Nach oben |
|
 |
TimesChange
Anmeldungsdatum: 20.11.2013 Beiträge: 85
|
Verfasst am: 06.12.2013, 12:21 Titel: |
|
|
St_W hat Folgendes geschrieben: | ...Verwendest du eigentlich einen Grafikmodus (SCREEN bzw. __SCREENRES) ? oder Textmodus (SCREEN 0) ? |
Dein ScreenEvent-Beispiel habe ich mit "SCREEN 9" (640x350 bzw. 80x25 Zeichen) aufgerufen. Das entspricht von der Größe den alten QB-Fenstern.
Das erste auf FB umgesetzte Programm hat lediglich einen WIDTH 80,25 Befehl am Anfang. Bei diesem Programm habe ich aber das Problem mit der ALT-Eingabe nicht, und habe eine "normale" Eingaberoutine mit INKEY$.
Viele Grüße
Rainer |
|
Nach oben |
|
 |
TimesChange
Anmeldungsdatum: 20.11.2013 Beiträge: 85
|
Verfasst am: 06.12.2013, 12:33 Titel: |
|
|
Muttonhead hat Folgendes geschrieben: | Nach C zu suchen in Verbindung mit STRG ist gaaanz schlecht... |
Oh, der war gut - hätt' ich ganz übersehen
Wenn das Programm aber im Grafikmodus (mit SCREENRES) läuft, wird STRG-C doch wie jede andere Tastenkombination einfach nur in den Tastaturpuffer geschrieben, und führt nicht zum Abbruch.
Viele Grüße
Rainer |
|
Nach oben |
|
 |
St_W

Anmeldungsdatum: 22.07.2007 Beiträge: 957 Wohnort: Austria
|
Verfasst am: 06.12.2013, 13:00 Titel: |
|
|
Habs jetzt hinbekommen: Code: | #Lang "qb"
'aus fbgfx.bi
#Define GET_WINDOW_HANDLE 2
'aus winuser.bi
Type HWND As Long
Type WPARAM As Long
Type LPARAM As Long
Type LRESULT As Long
Declare Function SetWindowLong StdCall Lib "user32" Alias "SetWindowLongA" (byval hWnd As HWND, ByVal nIndex As Long, ByVal dwNewLong As Long) as Long
#Define GWL_WNDPROC -4
Declare Function CallWindowProc StdCall Lib "user32" Alias "CallWindowProcA" (byval lpPrevWndFunc As Long, ByVal HWnd As HWND, ByVal uMsg As Long, ByVal wParam As WPARAM, ByVal lParam As LPARAM) as Long
#Define WM_KEYDOWN &h0100
#Define WM_SYSKEYDOWN &h0104
#define WM_KEYUP &h0101
#define WM_SYSKEYUP &h0105
Dim As HWND hWin
Dim Shared As Long oldWndProc
' einfacher Ring-Puffer
Const BufSz As Long = 64
Dim Shared KeyBuf(0 To BufSz-1) As __ULongInt
Dim Shared KeyBufPos As Long
Dim Shared KeyBufCnt As Long
KeyBufPos = 0
KeyBufCnt = 0
Function KeyBufGet() As __LongInt
If KeyBufCnt > 0 Then
KeyBufGet = KeyBuf(KeyBufPos)
KeyBufPos = (KeyBufPos +1) Mod BufSz
KeyBufCnt -= 1
Else
KeyBufGet = 0
EndIf
End Function
Sub KeyBufPut(kv As __LongInt)
If KeyBufCnt < BufSz Then
KeyBuf((KeyBufPos+KeyBufCnt) Mod BufSz) = kv
KeyBufCnt += 1
EndIf
End Sub
' neue WndProc für das fbgfx Fenster
Function WndProc StdCall (ByVal hWnd As HWND, ByVal uMsg As Long, ByVal wParam As WPARAM, ByVal lParam As LPARAM) As LRESULT
Dim tmpKey As __ULongInt
If uMsg = WM_KEYDOWN Or uMsg = WM_SYSKEYDOWN Or uMsg = WM_KEYUP Or uMsg = WM_SYSKEYUP Then
tmpKey = __cast(__ULong, lParam) Or (__cast(__ULongInt, wParam) __shl 32)
'Print Hex$(tmpKey)
KeyBufPut(tmpKey)
EndIf
WndProc = CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam)
End Function
__ScreenRes 750, 500
__ScreenControl(GET_WINDOW_HANDLE, hWin)
oldWndProc = SetWindowLong(hWin, GWL_WNDPROC, @WndProc)
Do
Dim tmpKey As __ULongInt
tmpKey = KeyBufGet()
If tmpKey <> 0 Then
Dim repeatCnt As __ULong '16 bits (0-15)
Dim scanCode As __ULong '8 bits (16-24)
Dim extKeyFlag As __ULong '1 bit (24)
Dim ctxCode As __ULong '1 bit (29)
Dim prevState As __ULong '1 bit (30)
Dim transState As __ULong '1 bit (31)
Dim vKeyCode As __ULong '32 bits (32-63)
vKeyCode = tmpKey __shr 32
transState = tmpKey And &H80000000ul
prevState = tmpKey And &H40000000ul
ctxCode = tmpKey And &H20000000ul
extKeyFlag = tmpKey And &H01000000ul
scanCode = (tmpKey And &H00FF0000ul) __shr 16
repeatCnt = (tmpKey And &HFFFFul)
If transState Then
Print "KeyUp ";
Else
If prevState Then
Print "KeyRepeat ";
Else
Print "KeyDown ";
EndIf
EndIf
Print "VK:"; vKeyCode;
Print " Scancode:"; scanCode;
If extKeyFlag Then Print " Ext";
If repeatCnt > 0 Then Print " Repeat:"; repeatCnt;
Print
EndIf
__Sleep 10
Loop Until InKey$ = Chr$(27)
SetWindowLong(hWin, GWL_WNDPROC, oldWndProc) |
Die Auswertung in der Schleife funktioniert noch nicht ganz so wie sie soll (z.B. Repeat Count) - hier ergaben sich im QB Modus unerwartete Probleme, die im FB Modus nicht da sind und mir auch vorerst unerklärlich sind. z.B. folgendes: Code: | Dim As ULong d
d = &H0000FFFF
Print Hex(d) | bzw. Code: | #lang "qb"
Dim As __ULong d
d = &H0000FFFF
Print Hex$(d) | ergibt z.b. unterschiedliche Ergebnisse?!
Edit: Danke an nemored für den Tipp (s.u.) ! Ich hab das Beispiel oberhalb nun entsprechend geändert und nun sollte alles soweit funktionieren.
Dass der RepeatCount so gut wie immer 1 ist, ist übrigens korrekt, falls diese Frage auftauchen sollte - denn dieser Wert wird genutzt falls Events schneller eintrudeln als Windows sie verarbeiten kann; in diesem Fall werden mehrere Events zusammengefasst und RepeatCnt entspricht der Anzahl der zusammengefassten Events. _________________ Aktuelle FreeBasic Builds, Projekte, Code-Snippets unter http://users.freebasic-portal.de/stw/
http://www.mv-lacken.at Musikverein Lacken (MV Lacken)
Zuletzt bearbeitet von St_W am 07.12.2013, 01:59, insgesamt einmal bearbeitet |
|
Nach oben |
|
 |
nemored

Anmeldungsdatum: 22.02.2007 Beiträge: 4704 Wohnort: ~/
|
Verfasst am: 07.12.2013, 01:10 Titel: |
|
|
St_W hat Folgendes geschrieben: | Die Auswertung in der Schleife funktioniert noch nicht ganz so wie sie soll (z.B. Repeat Count) - hier ergaben sich im QB Modus unerwartete Probleme, die im FB Modus nicht da sind und mir auch vorerst unerklärlich sind. z.B. folgendes: Code: | Dim As ULong d
d = &H0000FFFF
Print Hex(d) | bzw. Code: | #lang "qb"
Dim As __ULong d
d = &H0000FFFF
Print Hex$(d) | ergibt z.b. unterschiedliche Ergebnisse?! |
Ich habe mal nachgefragt - es liegt daran, dass in -lang qb &hFFFF ein (16bit-)Integer und damit -1 ist, und dieses -1 wird dann in dein __ULONG geschrieben. Mit Suffix "ul" funktioniert es dann:
_________________ Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1. |
|
Nach oben |
|
 |
Muttonhead

Anmeldungsdatum: 26.08.2008 Beiträge: 565 Wohnort: Jüterbog
|
Verfasst am: 08.12.2013, 11:49 Titel: |
|
|
vielleicht ist so ein Ansatz brauchbar
Code: | #include "fbgfx.bi"
using FB
screen 17
declare function PseudoInkey as string
dim as string char
do
sleep 1
char=PseudoInkey
if char<>"" then print char
loop until inkey = chr(27)
end
function PseudoInkey as string
function=""
static charmem as string
static holdtimer as double
static holdstatus as integer
dim as integer scancode,scblockstart,scblockend,numblocks,blockcount
dim as string char,chartable
scancode=0
numblocks=3
blockcount=0
char=""
do
blockcount +=1
select case blockcount
case 1
scblockstart=SC_Q
scblockend=SC_P'SC_RIGHTBRACKET bis Ü
chartable="qwertzuiop"
case 2
scblockstart=SC_A
scblockend=SC_L'SC_QUOTE bis Ä (mit Ö)
chartable="asdfghjkl"
case 3
scblockstart=SC_Z
scblockend=SC_M
chartable="yxcvbnm"
end select
scancode=scblockstart
do
if multikey(scancode) then
char=mid(chartable,scancode-scblockstart+1,1)
end if
scancode +=1
loop until (scancode>scblockend) or (char<>"")
loop until (blockcount=numblocks) or (char<>"")
if char="" then
holdstatus=0
holdtimer=0
end if
if charmem=char then
'Trigger
if holdstatus=2 and timer >= holdtimer+.05 then
holdtimer=timer
function=char
end if
'Pause
if holdstatus=1 and timer >= holdtimer+.8 then
holdtimer=timer
holdstatus=2
end if
if holdstatus=0 then
holdtimer=timer
holdstatus=1
end if
else'charmem<>char
function=char
end if
charmem=char
end function |
Mutton |
|
Nach oben |
|
 |
TimesChange
Anmeldungsdatum: 20.11.2013 Beiträge: 85
|
Verfasst am: 08.12.2013, 23:59 Titel: |
|
|
@St_W: Dein Programmbeispiel läuft problemlos und ist sicher recht "mächtig", da man wirklich jeden einzelnen Tastendruck auswerten kann - allerdings dann auch muss.
Leider ist es für mich schon sehr "fortgeschrittenes" Programmieren, dem ich nicht wirklich folgen kann. Gut, muss einen auch nicht stören wenn's funktioniert. Und dafür, dass ich's nicht kapiere kannst du ja nichts
@Mutton: Bei deinem Code verstehe ich schon bisschen mehr...
Ist der Befehl "blockcount +=1" nur eine Erleichterung beim Schreiben, oder wird dadurch auch der Programmcode kürzer? Das ist doch vergleichbar mit "INC" (in C / Pascal ?)?
In der Zwischenzeit habe auch ich noch weiter herumprobiert, da ich mich nicht damit abfinden wollte, dass ich das mit "Bordmitteln" nicht hinbekomme.
Es ist eine vielleicht etwas krude Kombination aus MULTIKEY (insb. für den Status der ALT-Taste) und INKEY (um die mehrfache Ausgabe eines Zeichens zu unterbinden).
So im Groben funktioniert das nun. Da sind mit Sicherheit noch Fehler drin, einiges wohl zu umständlich etc. Aber zumindest kann ich damit "normale" Zeichen einlesen, als auch Zeichenketten während ALT gedrückt ist:
Code: | Declare Function Holzeich(ByRef Scancode as integer, ByRef AltAlt as Integer, ByRef AltNeu as Integer, BYREF AltChg as Integer ) as Integer
Declare Function ScanToAscii (BYVAL ScanCode as Integer) as integer
Dim as Integer AA, AN , HZ, Chg, s
Dim Wort As String
Print "Bel. Tasten dr"; CHR$(129);"cken - ESC fuer Ende"
AA= 0: AN=0 : Chg = 0
Wort = ""
Do
HZ = Holzeich (s, AA, AN, Chg)
Print "Zeichencode: ";HZ; "/&h";hEx$(HZ);
IF s and 1 then print " STRG";
IF s and 2 then print " SHIFT";
If s and 4 Then Print " ALT";
if s and 8 Then Print " Extended Code";
Print
If AN Then
if Chg=1 Then Wort = ""
Wort=Wort + CHR$(ScanToAscii(HZ))
Print "Eingabe mit ALT: "; Wort
Endif
AA=AN
Sleep 100
Loop until HZ=27
Print "Ende mit bel. taste"
Sleep
End
Function Holzeich(Byref Scan as integer, Byref AltA as integer, Byref AltN as integer, BYREF Change as integer) as integer
' Wartet auf einen Tastaturdruck und gibt den ScanCode zurück
' SCAN: Bit0: STRG BIT1: SHIFT Bit2: ALT Bit3: Extended Code
' AltA: 1, wenn Alt-Taste vor Aufruf gedrückt war, sonst 0
' AltN: 1, wenn Alt-Taste beim VErlassen gedrückt ist
' Change: 1, wenn sich Status Alt-Taste ändert
DIM as Integer i, MK, MK2, Einzeltaste, Taste
DIm as Integer ALT, STRG, Shift
Dim KS as String
Change =0: Scan =0
' Status Alt-Taste zu Beginn:
AltN=MultiKey(&H38)*(-1)
if AltN<>AltA then Change=1
Do
Taste =0: Scan=0: Einzeltaste = 0
For i=1 to &h53
MK=Multikey(i)*(-1)
'Alt-Taste ständig überprüfen:
if I=&H38 then
AltN=MK
if AltN<>AltA then Change=1
end if
if MK then
Einzeltaste = 1
select case i
case &h1D
SCAN = Scan OR 1: Einzeltaste=0 ' STRG
case &H2A
Scan = Scan OR 2: EinzelTaste =0 ' SHIFT, auch &H36
case &H3A
Einzeltaste =0
case &h38
SCAN=SCAN OR 4: Einzeltaste = 0 ' ALT
case 1 to &H53
' nix tun, ist Einzeltaste
case else
Einzeltaste =0
end select
If (Taste= 0) AND (Einzeltaste =1) Then Taste =i
end if
next i
MK=0
if Taste> 0 then
'Status Alt-Taste nochmal prüfen
AltN=MultiKey(&H38)*(-1)
if AltN<>AltA then Change=1
KS = INKEY$
MK=ASC(KS)
If len(KS)>1 then
MK=ASC(KS,2)
MK2=ASC(KS,1)
SCAN=SCAN OR 8
end if
End if
sleep 10
Loop until MK>0
HolZeich = MK
While Inkey$<>"": Wend
End function
Function ScanToAscii (BYVAL ScanCode as Integer) as integer
' Erweiterte Codes (255) noch ergänzen...
Dim CodeTab (1 to &H53) as uByte = {_
27, 49, 50, 51, 52, 53, 54, 55, 56, 57, _ ' ESC, "123456789"
48, 45, 43, 0, 0,113,119,101,114,116, _ ' "0-+", BackSpace, Tab "QWERT"
121,117,105,111,112,225,239, 13, 0, 97, _ ' "YUIOPß´", Enter, STRG, "A"
115,100,102,103,104,106,107,108,129,132, _ ' "SDFGHJKLÜÄ"
148, 0, 0,122,120, 99,118, 98,110,109, _ ' "Ö", Shift, <, "ZXCVBNM"
44, 46, 35, 0, 42, 0, 32, 0, 59, 60, _ '",.#", Shift, "*", ALT, " ", CapsLock, F1, F2
61, 62, 63, 64, 65, 66, 67, 68, 0, 0, _ ' F3...F10, NumLock, Rollen
71, 72, 73, 0, 75, 0, 77, 43, 79, 80, _ ' Pos1, Pfeilauf, PageUp, ??, PfeilLi, Num5, PfeilRe, "+", Ende, PfeilAb
81, 82, 83} ' PageDown, Einf, Entf
ScanToAscii = CodeTab(ScanCode)
End Function |
Das Programm würde auch mit "lang qb" laufen, aber da habe ich noch das Problem, dass ich keinen SLEEP -Befehl mit Millisekunden bekomme. Laut Hilfereferenz sollte das zwar mit "__SLEEP" und Millisekunden klappen:
In der Dialektform Befehlsreferenzeintrag-lang qb wartet SLEEP wie unter QB die angegebene Zeit in Sekunden. Wird 'Flag' angegeben oder __SLEEP verwendet, dann wird die angegebene Zeit in Millisekunden gewartet.
Aber bei mir gibt es dann zu große Verzögerungen, und FLAG akzeptiert der Compiler dabei auch nicht. Hat jemand dazu eine Idee?
Für Hinweise, wie ich das noch Eindampfen / besser schreiben / ggf. sinnvoll mit den anderen Vorschlägen kombinieren kann, bin ich immer dankbar.
Viele Grüße
Rainer |
|
Nach oben |
|
 |
TimesChange
Anmeldungsdatum: 20.11.2013 Beiträge: 85
|
Verfasst am: 13.12.2013, 14:35 Titel: |
|
|
Bin ich irgendjemandem "auf die Füße gestiegen", so dass keiner mehr Lust hat zu antworten ?
Grüße
Rainer |
|
Nach oben |
|
 |
Sebastian Administrator

Anmeldungsdatum: 10.09.2004 Beiträge: 5969 Wohnort: Deutschland
|
Verfasst am: 13.12.2013, 15:36 Titel: Shorthand operators und __SLEEP |
|
|
TimesChange hat Folgendes geschrieben: | Bin ich irgendjemandem "auf die Füße gestiegen", so dass keiner mehr Lust hat zu antworten ? |
Ne, bestimmt nicht.
Das kommt vielleicht daher, dass du die neue, offene Frage zu "__SLEEP in lang qb" in dem langen Thread und dem langen, code-reichen Posting "versteckt" hast. Da denken sich vielleicht viele, die nicht intensiv in der bisherigen Diskussion drin sind und die dutzenden Vorpostings nicht gelesen haben, einfach "TL;DR".
Von daher ist es immer empfehlenswert, für eine abgrenzbare Frage immer einen separaten Frage-Thread aufzumachen, damit sowas nicht untergeht und man nicht zu viel lesen muss, um die aktuelle Problemstellung zu erkennen.
Zum eigentlichen Thema:
Zitat: | Ist der Befehl "blockcount +=1" nur eine Erleichterung beim Schreiben, oder wird dadurch auch der Programmcode kürzer? Das ist doch vergleichbar mit "INC" (in C / Pascal ?)? |
Ja, das soll dem Programmierer überflüssiges Tippen ersparen, hat aber die gleiche Funktion wie die lange Schreibweise. Ich denke nicht, dass der Compiler hier anderen ASM- oder C-Code emittet als in der Langvariante. In der Kurzvariante ("Shorthand Operator") kann sich der Compiler schlicht den ersten Operanden der arithmetischen Operation selber "denken" anhand der Zuweisung, sodass man ihn nicht tippen muss.
In QB musstest du schreiben:
Code: | MeineVariable = MeineVariable + 1 |
In FB reicht, um dasselbe auszudrücken:
Das funktioniert nicht nur mit dem Summand 1, sondern auch mit anderen Werten oder auch Variablen/Ausdrücken. Die Schreibweise ist also nicht aufs Inkrementieren um 1 beschränkt.
Zitat: | Aber bei mir gibt es dann zu große Verzögerungen, und FLAG akzeptiert der Compiler dabei auch nicht. Hat jemand dazu eine Idee? |
Ich habe leider schon länger nichts mehr mit -lang qb gemacht. Könnte es vielleicht helfen,
mit Klammern zu verwenden, damit das zweite Argument (Flag) erkannt wird? _________________
Die gefährlichsten Familienclans | Opas Leistung muss sich wieder lohnen - für 6 bis 10 Generationen! |
|
Nach oben |
|
 |
Elor
Anmeldungsdatum: 12.07.2013 Beiträge: 205 Wohnort: Konstanz
|
Verfasst am: 13.12.2013, 16:40 Titel: |
|
|
Zitat: |
In der Dialektform Befehlsreferenzeintrag-lang qb wartet SLEEP wie unter QB die angegebene Zeit in Sekunden. Wird 'Flag' angegeben oder __SLEEP verwendet, dann wird die angegebene Zeit in Millisekunden gewartet.
Aber bei mir gibt es dann zu große Verzögerungen, und FLAG akzeptiert der Compiler dabei auch nicht. Hat jemand dazu eine Idee?
|
Unter QB war fuer SLEEP die angabe von Millisekunden nicht moeglich, auch kann dort kein Flag gesetzt werden. Unter FB im qb lang kann zwar Millisekunden angegeben werden, aber ebenfalls kein Flag (so jedenfalls mein Test).
In diesem fall wuerde ich mir ne eigene Delay-SUB Basteln die z.B. so aussehen koennte:
Code: |
Sub Delay(ByVal Warte As Single)
Dim As Single StartZeit
StartZeit= Timer
Do
If(Timer- StartZeit >= Warte) Then Exit Do
Loop Until(InKey$ <> "")
End Sub
|
Du kannst ja mal mit dem Testprogram die unterschiede von SLEEP und der Delay (TIMER) SUB ausprobieren in dem du verschiedene Delay-Zeiten verwendest.
Code: |
#Lang "qb"
Declare Sub Delay(ByVal Warte As Single)
Dim As Single StartZeit, EndZeit
Print "Start"
StartZeit= Timer
__Sleep 700
EndZeit= Timer
Print "Ende"
Print "Vergangene Zeit: ";:Print Using "##.##"; EndZeit- StartZeit;
Print " Sekunden.": Print
Print "Start"
StartZeit= Timer
Delay(0.7)
EndZeit= Timer
Print "Ende"
Print "Vergangene Zeit: ";:Print Using "##.##"; EndZeit- StartZeit;
Print " Sekunden."
__GetKey
Sub Delay(ByVal Warte As Single)
Dim As Single StartZeit
StartZeit= Timer
Do
If(Timer- StartZeit >= Warte) Then Exit Do
Loop Until(InKey$ <> "")
End Sub
|
Viel Spass.
EDIT1: Ich glaub das mit dem Timer kann man wieder vergessen, er ist wohl etwas genauer, aber ich habe uebersehen, dass er das System zu 100% Auslastet. Wenn er nicht in einer Schleife verwendet wird und die Delay-Zeit <= 1 Sekunde betraegt ist er jedoch brauchbar. |
|
Nach oben |
|
 |
nemored

Anmeldungsdatum: 22.02.2007 Beiträge: 4704 Wohnort: ~/
|
Verfasst am: 13.12.2013, 17:56 Titel: |
|
|
Zitat: | EDIT1: Ich glaub das mit dem Timer kann man wieder vergessen, er ist wohl etwas genauer, aber ich habe uebersehen, dass er das System zu 100% Auslastet. Wenn er nicht in einer Schleife verwendet wird und die Delay-Zeit <= 1 Sekunde betraegt ist er jedoch brauchbar. |
Möglich ist noch, den Programmablauf mittlels SLEEP 1 (bzw. hier __SLEEP 1) immer kurz zu unterbrechen. Sofern es in -lang qb genauso gut funktioniert wie in -lang fb, versteht sich.
Code: | Sub Delay(ByVal Warte As Single)
Dim As Single StartZeit
StartZeit= Timer
Do
If(Timer- StartZeit >= Warte) Then Exit Do
__Sleep 1
Loop Until(InKey$ <> "")
End Sub |
_________________ Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1. |
|
Nach oben |
|
 |
Elor
Anmeldungsdatum: 12.07.2013 Beiträge: 205 Wohnort: Konstanz
|
Verfasst am: 13.12.2013, 18:58 Titel: |
|
|
Zitat: |
Möglich ist noch, den Programmablauf mittlels SLEEP 1 (bzw. hier __SLEEP 1) immer kurz zu unterbrechen. Sofern es in -lang qb genauso gut funktioniert wie in -lang fb, versteht sich. grinsen
|
Das Funktioniert Wunderbar, die Zeiten sind jetzt zwar nicht mehr ganz so genau aber ich Denke mit dem kleinen unterschied, der sich im 0.0xx-Bereich abspielt, kann man Leben. |
|
Nach oben |
|
 |
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
|