Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht Das deutsche QBasic- und FreeBASIC-Forum
Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
 
FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen  RegistrierenRegistrieren
ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin
Zur Begleitseite des Forums / Chat / Impressum
Aktueller Forenpartner:

Probleme bei Konvertierung von QB4.5 zu FB
Gehe zu Seite Zurück  1, 2, 3, 4  Weiter
 
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC.
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
TimesChange



Anmeldungsdatum: 20.11.2013
Beiträge: 85

BeitragVerfasst am: 03.12.2013, 00:20    Titel: Antworten mit Zitat

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 lächeln

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
Benutzer-Profile anzeigen Private Nachricht senden
Jojo
alter Rang


Anmeldungsdatum: 12.02.2005
Beiträge: 9736
Wohnort: Neben der Festplatte

BeitragVerfasst am: 03.12.2013, 00:47    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
TimesChange



Anmeldungsdatum: 20.11.2013
Beiträge: 85

BeitragVerfasst am: 03.12.2013, 01:49    Titel: Antworten mit Zitat

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 zwinkern
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
St_W



Anmeldungsdatum: 22.07.2007
Beiträge: 957
Wohnort: Austria

BeitragVerfasst am: 03.12.2013, 02:14    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
TimesChange



Anmeldungsdatum: 20.11.2013
Beiträge: 85

BeitragVerfasst am: 05.12.2013, 02:08    Titel: Antworten mit Zitat

Danke für deine erneute Übersetzungshilfe Daumen rauf!

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
Benutzer-Profile anzeigen Private Nachricht senden
St_W



Anmeldungsdatum: 22.07.2007
Beiträge: 957
Wohnort: Austria

BeitragVerfasst am: 05.12.2013, 02:23    Titel: Antworten mit Zitat

Du hast teilweise Recht: zwinkern
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
Benutzer-Profile anzeigen Private Nachricht senden
TimesChange



Anmeldungsdatum: 20.11.2013
Beiträge: 85

BeitragVerfasst am: 06.12.2013, 00:51    Titel: Antworten mit Zitat

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" zwinkern 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 zwinkern

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
Benutzer-Profile anzeigen Private Nachricht senden
St_W



Anmeldungsdatum: 22.07.2007
Beiträge: 957
Wohnort: Austria

BeitragVerfasst am: 06.12.2013, 02:34    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
Muttonhead



Anmeldungsdatum: 26.08.2008
Beiträge: 565
Wohnort: Jüterbog

BeitragVerfasst am: 06.12.2013, 10:41    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
TimesChange



Anmeldungsdatum: 20.11.2013
Beiträge: 85

BeitragVerfasst am: 06.12.2013, 12:21    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
TimesChange



Anmeldungsdatum: 20.11.2013
Beiträge: 85

BeitragVerfasst am: 06.12.2013, 12:33    Titel: Antworten mit Zitat

Muttonhead hat Folgendes geschrieben:
Nach C zu suchen in Verbindung mit STRG ist gaaanz schlecht...


Oh, der war gut - hätt' ich ganz übersehen Daumen rauf!
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
Benutzer-Profile anzeigen Private Nachricht senden
St_W



Anmeldungsdatum: 22.07.2007
Beiträge: 957
Wohnort: Austria

BeitragVerfasst am: 06.12.2013, 13:00    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
nemored



Anmeldungsdatum: 22.02.2007
Beiträge: 4704
Wohnort: ~/

BeitragVerfasst am: 07.12.2013, 01:10    Titel: Antworten mit Zitat

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:
Code:
d = &H0000FFFFul

_________________
Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Muttonhead



Anmeldungsdatum: 26.08.2008
Beiträge: 565
Wohnort: Jüterbog

BeitragVerfasst am: 08.12.2013, 11:49    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
TimesChange



Anmeldungsdatum: 20.11.2013
Beiträge: 85

BeitragVerfasst am: 08.12.2013, 23:59    Titel: Antworten mit Zitat

@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 zwinkern

@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
Benutzer-Profile anzeigen Private Nachricht senden
TimesChange



Anmeldungsdatum: 20.11.2013
Beiträge: 85

BeitragVerfasst am: 13.12.2013, 14:35    Titel: Antworten mit Zitat

Bin ich irgendjemandem "auf die Füße gestiegen", so dass keiner mehr Lust hat zu antworten ? traurig

Grüße
Rainer
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Sebastian
Administrator


Anmeldungsdatum: 10.09.2004
Beiträge: 5969
Wohnort: Deutschland

BeitragVerfasst am: 13.12.2013, 15:36    Titel: Shorthand operators und __SLEEP Antworten mit Zitat

TimesChange hat Folgendes geschrieben:
Bin ich irgendjemandem "auf die Füße gestiegen", so dass keiner mehr Lust hat zu antworten ? traurig

Ne, bestimmt nicht. lächeln

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". zwinkern

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:
Code:
MeineVariable += 1

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,
Code:
__SLEEP (2000, 1)

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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Elor



Anmeldungsdatum: 12.07.2013
Beiträge: 205
Wohnort: Konstanz

BeitragVerfasst am: 13.12.2013, 16:40    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
nemored



Anmeldungsdatum: 22.02.2007
Beiträge: 4704
Wohnort: ~/

BeitragVerfasst am: 13.12.2013, 17:56    Titel: Antworten mit Zitat

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. grinsen

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
Benutzer-Profile anzeigen Private Nachricht senden
Elor



Anmeldungsdatum: 12.07.2013
Beiträge: 205
Wohnort: Konstanz

BeitragVerfasst am: 13.12.2013, 18:58    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC. Alle Zeiten sind GMT + 1 Stunde
Gehe zu Seite Zurück  1, 2, 3, 4  Weiter
Seite 3 von 4

 
Gehe zu:  
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.

 Impressum :: Datenschutz