Welcome, Guest
You have to register before you can post on our site.

Username/Email:
  

Password
  





Search Forums

(Advanced Search)

Forum Statistics
» Members: 482
» Latest member: zaalexijuniorz5256
» Forum threads: 2,793
» Forum posts: 26,345

Full Statistics

Latest Threads
QB64PE v4.0 is now live!!
Forum: Announcements
Last Post: Kernelpanic
17 minutes ago
» Replies: 33
» Views: 971
Tenary operator in QB64 w...
Forum: Utilities
Last Post: Kernelpanic
19 minutes ago
» Replies: 0
» Views: 5
Need help capturng unicod...
Forum: General Discussion
Last Post: doppler
1 hour ago
» Replies: 22
» Views: 276
games or graphics for 3-D...
Forum: General Discussion
Last Post: madscijr
4 hours ago
» Replies: 26
» Views: 758
Text-centring subs
Forum: Utilities
Last Post: SierraKen
Today, 05:46 AM
» Replies: 2
» Views: 49
Video Renamer
Forum: Works in Progress
Last Post: Pete
Today, 05:14 AM
» Replies: 0
» Views: 22
QB64-PE v4's new 4-voice ...
Forum: Learning Resources and Archives
Last Post: a740g
Today, 02:51 AM
» Replies: 6
» Views: 146
Sound Ball
Forum: Programs
Last Post: SierraKen
Yesterday, 11:34 PM
» Replies: 0
» Views: 28
InForm-PE
Forum: a740g
Last Post: a740g
Yesterday, 10:58 PM
» Replies: 78
» Views: 6,046
Spriggsy's API Collection
Forum: Utilities
Last Post: SpriggsySpriggs
Yesterday, 07:13 PM
» Replies: 8
» Views: 195

 
  CIRCLE issue
Posted by: TerryRitchie - 10-12-2024, 05:35 PM - Forum: GitHub Discussion - Replies (2)

The CIRCLE statement is not closing pie slices correctly.

SCREEN _NEWIMAGE(640, 480, 32)
CIRCLE (319, 239), 30, _RGB32(255, 255, 255), -.000001, -1, 1

Print this item

  GoogleTime
Posted by: SMcNeill - 10-12-2024, 02:14 PM - Forum: Works in Progress - Replies (1)

Using Goggle-Eyes to tell time!

Code: (Select All)
$Color:32
_Title "Google Time"
dx = _DesktopWidth
dy = _DesktopHeight
Screen _NewImage(dx, dy, 32)
_FullScreen
Do
Cls
Googletime
_Limit 10
_Display
Loop Until _KeyHit



Sub Googletime
t# = Timer + 12 * 3600
h = t# \ 3600
m = (t# - h * 3600) \ 60
s = t# Mod 60
cx = _Width / 2
cy = _Height / 2
EllipseFill _Width \ 4, cy, cx \ 4, cy, White
EllipseFill 3 * _Width \ 4, cy, cx \ 4, cy, White
x = Sin(_D2R(h * 30)) * cx \ 9
y = -Cos(_D2R(h * 30)) * 2 * cy \ 3
EllipseFill _Width \ 4 + x, cy + y, 100, 100, Black
If h > 11 Then
Color Red, 0
_PrintString (_Width \ 4 + x - 8, cy + y - 4), "AM"
Else
Color Blue, 0
_PrintString (_Width \ 4 + x - 8, cy + y - 4), "PM"
End If
x = Sin(_D2R(m * 6)) * cx \ 9
y = -Cos(_D2R(m * 6)) * 2 * cy \ 3
EllipseFill 3 * _Width \ 4 + x, cy + y, 100, 100, Black
x1 = Sin(_D2R(s * 6)) * 30
y1 = -Cos(_D2R(s * 6)) * 30
EllipseFill 3 * _Width \ 4 + x + x1, cy + y + y1, 20, 20, Red
End Sub

Sub EllipseFill (CX As Integer, CY As Integer, a As Integer, b As Integer, C As _Unsigned Long)
' CX = center x coordinate
' CY = center y coordinate
' a = semimajor axis
' b = semiminor axis
' C = fill color
If a = 0 Or b = 0 Then Exit Sub
Dim h2 As _Integer64
Dim w2 As _Integer64
Dim h2w2 As _Integer64
Dim x As Integer
Dim y As Integer
w2 = a * a
h2 = b * b
h2w2 = h2 * w2
Line (CX - a, CY)-(CX + a, CY), C, BF
Do While y < b
y = y + 1
x = Sqr((h2w2 - y * y * w2) \ h2)
Line (CX - x, CY + y)-(CX + x, CY + y), C, BF
Line (CX - x, CY - y)-(CX + x, CY - y), C, BF
Loop
End Sub

Print this item

  Hardware vs Software
Posted by: SMcNeill - 10-11-2024, 11:45 PM - Forum: Help Me! - Replies (3)

I had a couple of people on Discord message me asking about if I could toss up a performance difference between software and hardware images for them.  I swear, I know I had some already here somewhere, but I couldn't find them when I snooped for them earlier, so -- by request -- here's a quick and dirty demo of the difference:

Code: (Select All)
Screen _NewImage(1280, 720, 32)

box = _NewImage(320, 180, 32) 'make a screen to just hold a box
Cls , &HFFFF0000&&, box 'make that box red

count = 0: t# = Timer + 1
Do
count = count + 1
Cls
If Timer > t# Then
box_moves = count
count = 0
t# = Timer + 1
End If
bx = (bx + 1) Mod 960
_PrintString (0, 0), "The box moved" + Str$(box_moves) + " times per second with software images."
_PutImage (bx, 100), box
_Display
Loop Until _KeyHit


_Delay .5
_KeyClear

box2 = _CopyImage(box, 33) 'make us a hardware image of that same box
_DisplayOrder _Hardware , _Hardware1 'and we're only going to display hardware screens
t# = Timer + 1: count = 0
Do
count = count + 1
If Timer > t# Then
hardbox_moves = count
count = 0
t# = Timer + 1
Cls
_PrintString (0, 0), "The box moved" + Str$(box_moves) + " times per second with software images."
_PrintString (0, 20), "The box moved" + Str$(hardbox_moves) + " times per second with hardware images."
If temp <> 0 Then _FreeImage temp
temp = _CopyImage(0, 33)
End If
bx = (bx + 1) Mod 960
_PutImage , temp 'place this image on the hardware screen
_PutImage (bx, 100), box2, 1 'place this image on the hardware screen 1 (the 2nd hardware screen)
_Display
Loop Until _KeyHit
System


Run that. Open your program manager and watch your CPU usage. Let it go for several seconds and you can see how quickly it moves a simple red box across the screen for you.

Then hit the space bar... Give it a couple of seconds to swap over from software to hardware images, and watch and see what the difference in those numbers might be.

Note that in the second portion of the program, where we're tossing out our hardware image, that I'm STILL drawing to a software image in the background. (Well, clearing it and printing to it.) Then I'm making a hardware copy of that image to display. While ALSO using a second hardware image for the box itself...

And yet, it still runs just a *wee* bit faster for us, with lesser CPU usage and all the other benefits that hardware brings over software.

Now tell me, is it perhaps a *wee* bit faster on your machines as well?

Print this item

  Need a little help with updating a FileSelect function.
Posted by: Dav - 10-11-2024, 12:33 PM - Forum: Help Me! - Replies (12)

I'm updating my old FileSelect function to use _Files$ instead of SHELLing and making temp files to get file/dir info.  Working OK doing that (I think) but have a couple a questions using CHDIR with it.

If there a way to see if a directory is accessible before trying to navigate to it?  When I try to navigate to a directory with permissions it errors out.  I'd like to not allow user to open those directories.  

Also, what is a good way (cross-platform) to see if the user is at the root directory?

Here's the code I'm working on.  Thanks.

- Dav 

Code: (Select All)
'====================
'FILESELECT-FILES.BAS  v1.00
'====================
'A simple file selector box function using _FILES$.
'Coded by Dav for QB64-PE, OCT/2024

'Lists files in current directory in a scroll box.

'Use arrows, page up/down, home/end to navigate.
'ENTER selects highlighted filename, ESC cancels.

'Selecting a directory will navigate to that
'directory and list files under it.

'Background screen is preserved and restored.

'Works under windows & Linux (havent tested Mac).
'Works in text and graphical screen modes.
'

'=== DEMO FOLLOWS...

Screen _NewImage(700, 500, 32)
_ScreenMove _Middle

'=== draw a background

Cls , _RGB(32, 32, 32)
For x = 1 To _Width Step 3
    For y = 1 To _Height Step 3
        PSet (x, y), _RGB(Rnd * 255, Rnd * 255, Rnd * 255)
    Next
Next

Print "Use arrows to navigate to a filename.  "
Print "Press ENTER to select highlighted file."
Print "Press ESC to cancel and close file box."

'=== Define filebox colors here...

fsborder& = _RGB(255, 0, 0) 'filebox order color
fsfile& = _RGB(255, 255, 255) 'filename color
fsdir& = _RGB(255, 255, 64) 'directories color
fsback& = _RGB(64, 0, 0) 'Background color
fshigh& = _RGB(255, 255, 128) 'highlighted line color

'=== Ask user to select a file

a$ = FileSelect$(5, 15, 20, 55, "*", fsborder&, fsback&, fsfile&, fsdir&, fshigh&)

'=== Show results...

Print
If a$ <> "" Then
    Print "You selected: "; a$
Else
    Print "No file selected."
End If

End


Function FileSelect$ (y, x, y2, x2, Filespec$, fsborder&, fsback&, fsfile&, fsdir&, fshigh&)
    'FileSelect$ function by Dav, OCT/2024

    'This function returns a selected filename.

    'Show files in current directory in a scroll box.
    'Use arrows, page up/down, home/end to navigate.
    'ENTER selects highlighted filename, ESC cancels.
    'Selecting a directory will navigate to that dir
    'and list files under that directory.

    'y,x = top left of box
    'y2,x2 = bottom right of box
    'Filespec$ = spec of files to list in box
    'fsborder& = color of box border
    'fsback& = background color of file box.
    'fsfile& = color of filenames
    'fsdir& = color of directories
    'fshigh& = color of highlighted line
    '=================================================

    '=== save original place of cursor
    origy = CsrLin
    origx = Pos(1)

    '=== save colors
    fg& = _DefaultColor
    bg& = _BackgroundColor

    '=== Save whole screen
    Dim scr1 As _MEM, scr2 As _MEM
    scr1 = _MemImage(0): scr2 = _MemNew(scr1.SIZE)
    _MemCopy scr1, scr1.OFFSET, scr1.SIZE To scr2, scr2.OFFSET

    '========
    loadagain:
    '=======

    '=== get total file + dir count
    c = 0
    x$ = _Files$(Filespec$)
    Do
        If x$ = "" Then Exit Do
        c = c + 1
        x$ = _Files$
    Loop

    'if no files found, at least add 1 for ".."
    If c = 0 Then c = 1

    '=== make room for names
    ReDim FileNames$(0 To c)

    '=== first line always go up a directory
    FileNames$(0) = ".."
    LineCount = 1

    '=== get dir names first, add to Filename$ array
    x$ = _Files$(Filespec$)
    Do
        If x$ = "" Then Exit Do
        'skip "." and ".." from this list
        If x$ = "./" Or x$ = ".\" Then GoTo jump
        If x$ = "../" Or x$ = "..\" Then GoTo jump
        If Right$(x$, 1) = "/" Or Right$(x$, 1) = "\" Then
            FileNames$(LineCount) = "[" + Left$(x$, Len(x$) - 1) + "]"
            LineCount = LineCount + 1
        End If
        jump:
        x$ = _Files$
    Loop

    '=== get file names next, add to Filename$ array
    x$ = _Files$(Filespec$)
    Do
        If x$ = "" Then Exit Do
        'skip all dir this time
        If Right$(x$, 1) = "/" Or Right$(x$, 1) = "\" Then
            ' do nothing
        Else
            FileNames$(LineCount) = x$
            LineCount = LineCount + 1
        End If
        x$ = _Files$
    Loop


    '=== draw a box
    Color fsborder&
    For L = 0 To y2 + 1
        Locate y + L, x: Print String$(x2 + 4, Chr$(219));
    Next

    '=== show current working dir at top
    Color fsfile&, fsborder&
    CurDir$ = _CWD$
    '=== Shorten it is too long, for display purposes
    If Len(CurDir$) > x2 - x Then
        CurDir$ = Mid$(CurDir$, 1, x2 - x - 3) + "..."
    End If
    Locate y, x + 2: Print CurDir$;


    '=== scroll through list...
    top = 0: selection = 0

    Do

        For L = 0 To (y2 - 1)

            Locate (y + 1) + L, (x + 2)

            topl = top + L: If topl > LineCount Then topl = LineCount

            If topl = selection Then
                Color fsback&, fshigh& 'selected line
            Else
                Color fsfile&, fsback& 'regular
                '=== directories get a different color...
                If Mid$(FileNames$(topl), 1, 1) = "[" Then
                    Color fsdir&, fsback&
                End If
            End If
            Print Left$(FileNames$(topl) + String$(x2, " "), x2);
        Next

        '=== Get user input
        Do
            k$ = InKey$: _Limit 30
        Loop Until k$ <> ""

        Select Case k$

            Case Is = Chr$(0) + Chr$(72) 'Up arrow
                If selection > 0 Then selection = selection - 1
                If selection < top Then top = selection

            Case Is = Chr$(0) + Chr$(80) 'Down Arrow
                If selection < (LineCount - 1) Then selection = selection + 1
                If selection > (top + (y2 - 2)) Then top = selection - y2 + 1

            Case Is = Chr$(0) + Chr$(73) 'Page up
                top = top - y2
                selection = selection - y2
                If top < 0 Then top = 0
                If selection < 0 Then selection = 0

            Case Is = Chr$(0) + Chr$(81) 'Page Down
                top = top + y2
                selection = selection + y2
                If top >= LineCount - y2 Then top = LineCount - y2
                If top < 0 Then top = 0
                If selection >= LineCount Then selection = LineCount - 1

            Case Is = Chr$(0) + Chr$(71) 'Home
                top = 0: selection = 0

            Case Is = Chr$(0) + Chr$(79) 'End
                selection = LineCount - 1
                top = selection - y2 + 1
                If top < 0 Then top = 0

            Case Is = Chr$(27) ' ESC cancels
                FileSelect$ = ""
                Exit Do

            Case Is = Chr$(13) 'Enter

                '=== if .. then go up one dir
                If RTrim$(FileNames$(selection)) = ".." Then
                    cd$ = _CWD$
                    If InStr(_OS$, "WIN") Then
                        cd$ = Left$(cd$, _InStrRev(cd$, "\"))
                    Else
                        cd$ = Left$(cd$, _InStrRev(cd$, "/"))
                    End If
                    ChDir cd$
                    Erase FileNames$
                    GoTo loadagain
                End If

                'see if directory
                test$ = RTrim$(FileNames$(selection))
                If Left$(test$, 1) = "[" Then
                    test$ = Mid$(test$, 2, Len(test$) - 2)
                    ChDir test$
                    Erase FileNames$
                    GoTo loadagain
                Else
                    If InStr(_OS$, "WIN") Then
                        If Right$(_CWD$, 1) = "\" Then
                            C$ = _CWD$
                        Else
                            C$ = _CWD$ + "\"
                        End If
                    Else
                        If Right$(_CWD$, 1) = "/" Then
                            C$ = _CWD$
                        Else
                            C$ = _CWD$ + "/"
                        End If
                    End If

                    FileSelect$ = C$ + RTrim$(FileNames$(selection))
                    Exit Do

                End If

        End Select

    Loop

    _KeyClear

    '=== Restore the whole screen
    _MemCopy scr2, scr2.OFFSET, scr2.SIZE To scr1, scr1.OFFSET
    _MemFree scr1: _MemFree scr2

    '=== restore original y,x and color
    Locate origy, origx

    Color fg&, bg&

End Function

Print this item

  Game Development Tutorial
Posted by: johnno56 - 10-11-2024, 03:48 AM - Forum: General Discussion - Replies (11)

I wasn't sure  if I should post this here or in "Learning Resources".

Since I have recently retired I find that I now have a little more "free time". I was curious to know if anyone in the QB64 community has, or knows of, any game development tutorials for QB64? (and yes. I am aware of Terry's tutorials)

I am not wanting to know how "Halo" is created, although that would be cool, but more like the classic "8 bit" games. After all... I am "old school"... lol

I realize that this sounds a bit vague, but then again, so is my understanding of game development... Any information would be greatly appreciated.

J

Print this item

  Smooothness
Posted by: NakedApe - 10-10-2024, 10:31 PM - Forum: Help Me! - Replies (9)

I was just messing around with a particle fountain. Sometimes the program runs smoothly, but if I change the _limit a little it can become hurky-jerky. Like the below seems to do great at 60 or 80 FPS, though runs less smoothly at 50 or 70. Is it my laptop?  Is smoothness in graphics always a dance between run-speed and the number of pixels that items move per cycle?  I'm curious how this could be made to run smoothly at various _limits. Any thoughts or insights appreciated!

Code: (Select All)
OPTION _EXPLICIT
SCREEN _NEWIMAGE(1280, 720, 32)
RANDOMIZE TIMER: _MOUSEHIDE
_DELAY .25: _SCREENMOVE _MIDDLE

TYPE particle
    x AS SINGLE
    y AS SINGLE
    Vx AS SINGLE
    Vy AS SINGLE
END TYPE

DIM AS INTEGER c
DIM AS particle p(200)

start:
c = -1
DO '
    c = c + 1 '                                   init particles
    p(c).x = _WIDTH / 2
    p(c).y = c * -5 - 140
    p(c).Vx = 0
    p(c).Vy = 3 + (RND - RND) / 4
LOOP UNTIL c = UBOUND(p)

DO
    c = -1
    CLS
    _LIMIT 60
    DO '                                            move em
        c = c + 1
        p(c).x = p(c).x + p(c).Vx
        p(c).y = p(c).y + p(c).Vy
        IF p(c).y > 20 AND p(c).y < 26 THEN p(c).Vx = (RND - RND) / 1.75 '  only change em once
        IF p(c).y > 14 THEN p(c).Vy = p(c).Vy + .06 '  a little gravity
    LOOP UNTIL c = UBOUND(p)

    c = -1
    DO '                                            draw em
        c = c + 1
        PSET (p(c).x, p(c).y), _RGB32(255)
    LOOP UNTIL c = UBOUND(p)

    _DISPLAY
    IF p(200).y > _HEIGHT + 140 THEN GOTO start
LOOP UNTIL _KEYDOWN(27)
SYSTEM

Print this item

  _File$ is not behaving as expected, cannot determine why
Posted by: hanness - 10-10-2024, 02:47 AM - Forum: General Discussion - Replies (6)

I'm having some difficulties with _Files$ not behaving as expected. A detailed description of the issue can be found in the comments of the code sample below.

To summarize briefly, _Files$ works fine by itself, but when I introduce a number of lines of code that I currently have commented out, those lines for some unknown reason cause _Files$ to no longer work. Again, see the full description in the comments.

My test scenario:

QB64PE 3.14.1
Windows 11 24H2, latest public release (build 26100.2033)
Logged on as an Administrator

If anyone can provide a clue why this is failing, I would really appreciate some insight. I've been at this for a few hours and cannot put my finger on the problem.


Code: (Select All)
$Debug
$Console:Only
Option _Explicit

Dim MountedImageDriveLetter As String
Dim Cmd As String
Dim GetLine As String
Dim count As Integer
Dim FullPathToImage As String
Dim ISO_Path As String
Dim CurrentFile As String
Dim ff1 As Long
Dim FileSpec As String

' This program is placed in a folder that contains a number of files including files that take the form
' "EXPORTED DRIVERS*.iso". The program is supposed to mount each ISO image file (the first powershell command),
' and then it runs another command sending the output of that command to a file called MountInfo.txt. Next,
' we open MountInfo.txt and read 4 lines. The 4th line will contain the drive letter to which the ISO image was
' mounted. We save the drive letter and a colon (D: as an example) in MountedImageDriveLetter$. We then close
' MountInfo.txt and delete it. As a confirmation we print the drive letter to the screen.
'
' Here now is where the problem begins: We use _File$ to retrieve the next file matching the pattern
' "EXPORTED DRIVERS*.iso". However, upon running this command it returns an empty string rather than the next
' file name. Why???? For the life of me I cannot figure it out!

' Please note that I have commented out all of the lines that do the heavy lifting. In the current state, this
' program simply gets the first file name, prints it to the screen, then it gets the next file name. This works
' flawlessly! But when I uncomment all the lines in the DO loop the line "CurrentFile$ = _Files$" simply returns
' an empty string.

' TIP: I suggest running this in debug mode and then start the program paused. Press F4 and add all variables
' to watch. Then press F7 to step through one line at a time. You will see that the first file name is retrieved
' correctly, but when you reach line 68 it fails to get the next file name when the lines in the DO loop are
' uncommented but it does work with those lines commented out.

' Make sure to create a number of files with a .iso extension in the same folder with the program. These should
' be real ISO image files because we are actually mounting them with this program.

ISO_Path$ = _CWD$

FileSpec$ = ISO_Path$ + "\EXPORTED DRIVERS*.iso"

CurrentFile$ = _Files$(FileSpec$)

Do While Len(CurrentFile$) > 0
    '    MountedImageDriveLetter$ = ""
    '    FullPathToImage$ = ISO_Path$ + "\" + CurrentFile$

    '    Cmd$ = "powershell.exe -command " + Chr$(34) + "Mount-DiskImage " + Chr$(34) + "'" + FullPathToImage$ + "'" + Chr$(34) + Chr$(34) + " > NUL"
    '    Shell Cmd$
    '    Cmd$ = "powershell.exe -command " + Chr$(34) + "Get-DiskImage -ImagePath '" + FullPathToImage$ + "' | Get-Volume" + Chr$(34) + " > MountInfo.txt"
    '    Shell Cmd$

    '    ff1 = FreeFile
    '    Open "MountInfo.txt" For Input As #ff1

    '    For count = 1 To 4
    '        Line Input #ff1, GetLine$
    '    Next count

    '    MountedImageDriveLetter$ = Left$(GetLine$, 1) + ":"
    '    Close #ff1
    '    Kill "MountInfo.txt"

    '    Print MountedImageDriveLetter$
    Print CurrentFile$

    CurrentFile$ = _Files$
Loop


End

Print this item

  Timer Trap Problem
Posted by: eoredson - 10-09-2024, 01:30 AM - Forum: Help Me! - Replies (9)

Hi,

This code does not work:

Code: (Select All)

Rem sample of timer return
t1 = _FreeTimer
On Timer(t1, 1) GoSub Trap
Timer(t1) On
Start:
Do
  x$ = InKey$
  If x$ = Chr$(27) Then End
Loop
End
Trap:
Count = Count + 1
Print "Trap count:"; Count
Return Start

Print this item

Lightbulb Inkey for non-US keyboards (Cp1252 based languages)
Posted by: RhoSigma - 10-08-2024, 06:59 PM - Forum: RhoSigma - No Replies

This is a alternative Inkey$ function for many Cp1252 languages.
It takes the input from the respective local keyboards and maps the keyhits to the DOS Cp437 as good  as possible without the need of _MAPUNICODE.

Set it to the right keybord/language ID in line 16 before testing.

InkeyHit.bas

Code: (Select All)
'----------------------
'--- InkeyHit$ test ---
'----------------------
PRINT "start pressing keys..."
PRINT "- try single keys incl. arrows, Ins, Del etc."
PRINT "- use shift, ctrl, alt combos with keys"
PRINT "- if you have that key, check AltGr + key combos"
PRINT "- Enter will end the program": PRINT

DO
i$ = ""
WHILE i$ = ""
_LIMIT 50
' Keyboard layout/language ID 1031 = german de-DE,
' find all supported IDs in lines 94-97 below.
i$ = InkeyHit$(1031)
WEND
IF LEN(i$) = 2 THEN
PRINT "CHR$(0) +", ASC(i$, 2), RIGHT$(i$, 1)
ELSE
PRINT "-------->", ASC(i$, 1), i$
END IF
IF i$ = CHR$(27) THEN CLS
LOOP UNTIL i$ = CHR$(13)
END

'-----------------
'--- InkeyHit$ ---
'-----------------
' This alternative INKEY$ function is made for use with western european
' languages (Cp1252 based) and any QB64 versions >= 1.000. It will
' directly map the inputs to the chars available in Cp437, hence you don't
' need to setup a custom unicode font and _MAPUNICODE table, you can stay
' with QB64's built-in fonts and standard codepage 437.
' By this means it solves the INKEY$ issues introduced with the transition
' from using SDL to using OpenGL regarding special/international chars.
' However, it does not fix the regular INPUT, LINE INPUT and INPUT$ when
' used for keyboard input, here you should create your own functions,
' which use this function to get its inputs.
' This function is based on my old function made for Germany/Austria only,
' but now also implements support for other languages (keyboard layouts)
' based on the research work done by forum member moises1953.
'----------
' SYNTAX:
' keypress$ = InkeyHit$ (kbl%)
'----------
' INPUTS:
' --- kbl% ---
' The keyboard layout/language ID (eg. 1031 for de-DE), which is in
' effect on your system. Make sure your language is listed in the CONSTs
' at the beginning of the function. If you use this function with any
' unsupported language, then some keys might not work as expected
' (eg. accents, umlauts or AltGr key triggered chars).
'----------
' RESULT:
' --- keypress$ ---
' Equivalent to the INKEY$ result (see Wiki).
'----------
' ACCENTS:
' Note that the accents keys on most keyboards are so called
' preselection keys, different from modifier keys (Shift/Ctrl/Alt)
' you don't need to hold them while typing accented chars. You just
' press it once followed by pressing the letter key once to get the
' respective accented char. To get the accent char itself you either
' press the space bar after the accent preselection or you press the
' accent preselection key twice.
'----------
' LIMITS:
' Note that the following keys and key combos are not supported
' for various reasons:
'
' Two Byte Characters Key CHR$(0) + "?"
' -------------------------------------------------------------
' CHR$(0) + CHR$(16-50) [Alt] + letter
' rarely used, not in alphabetical order, KB layout dependent,
' => returns the regular char instead (Alt modifier ignored)
' CHR$(0) + CHR$(76) [5 NumberPad] "L" (NumLock off in QB64)
' rarely used, almost useless for most applications,
' => returns nothing
' CHR$(0) + CHR$(120-129) [Alt] + number
' ignored in favor for alternative Alt + ASCII code input method,
' => returns nothing, but collects numbers to built an ASCII code,
' the respective char is returned when releasing the Alt-Key
' CHR$(0) + CHR$(130 or 131) [Alt] + _/- or +/= "‚" or "ƒ"
' rarely used, KB layout dependent,
' => returns the regular char instead (Alt modifier ignored)
'---------------------------------------------------------------------
FUNCTION InkeyHit$ (kbl%)
'--- option _explicit requirements ---
DIM charCode&, hitVal&, oPreKey&, modShift%, modCtrl%, modAltGr%, modAlt%, modNone%
DIM modShiftOnly%, modCtrlOnly%, modAltOnly%, modCtrlNoAlt%, inChar%, outChar%

'--- keyboard layouts supported by this routine ---
CONST kbDaDk% = 1030, kbDeDe% = 1031, kbEnUs% = 1033, kbEsEs% = 1034, kbFrFr% = 1036
CONST kbItIt% = 1040, kbNlNl% = 1043, kbNbNo% = 1044, kbSvSe% = 1053
CONST kbDeCh% = 2055, kbEnGb% = 2057, kbEsMx% = 2058, kbFrBe% = 2060, kbPtPt% = 2070
CONST kbFrCh% = 4108, kbEnIe% = 6153
'--- accent preselection key types ---
CONST pkAcute% = 1, pkGrave% = 2, pkUmlau% = 3, pkCircu% = 4

'--- variables init ---
STATIC lastKey&, preKey&, ascNum$
InkeyHit$ = "": charCode& = 0

'--- flush regular input buffer & get next key hit ---
DO: LOOP UNTIL INKEY$ = ""
hitVal& = _KEYHIT
IF hitVal& <> 0 THEN
'--- get modifiers ---
modShift% = _KEYDOWN(100303) OR _KEYDOWN(100304)
modCtrl% = _KEYDOWN(100305) OR _KEYDOWN(100306)
modAltGr% = _KEYDOWN(100307) AND _KEYDOWN(100306)
modAlt% = (_KEYDOWN(100307) OR _KEYDOWN(100308)) AND NOT modAltGr%
'--- special conditions ---
modNone% = NOT modShift% AND NOT modCtrl% AND NOT modAlt% AND NOT modAltGr%
modShiftOnly% = modShift% AND NOT modCtrl% AND NOT modAlt% AND NOT modAltGr%
modCtrlOnly% = modCtrl% AND NOT modShift% AND NOT modAlt% AND NOT modAltGr%
modAltOnly% = modAlt% AND NOT modShift% AND NOT modCtrl% 'not AltGr implied in Alt
modCtrlNoAlt% = modCtrl% AND NOT modAlt% AND NOT modAltGr% 'shift allowed

'--- start evaluation ---
IF hitVal& > 0 THEN
IF hitVal& <= 255 THEN lastKey& = hitVal& 'for later release detection
'--- lookup preselected accent (if any) ---
IF hitVal& >= 32 AND hitVal& <= 127 THEN
SELECT CASE preKey&
CASE pkAcute%
RESTORE InkeyHit_Acute
DO: READ inChar%, outChar%: LOOP UNTIL inChar% = hitVal& OR inChar% = 0
charCode& = outChar%
CASE pkGrave%
RESTORE InkeyHit_Grave
DO: READ inChar%, outChar%: LOOP UNTIL inChar% = hitVal& OR inChar% = 0
charCode& = outChar%
CASE pkUmlau%
RESTORE InkeyHit_Umlau
DO: READ inChar%, outChar%: LOOP UNTIL inChar% = hitVal& OR inChar% = 0
charCode& = outChar%
CASE pkCircu%
RESTORE InkeyHit_Circu
DO: READ inChar%, outChar%: LOOP UNTIL inChar% = hitVal& OR inChar% = 0
charCode& = outChar%
END SELECT
END IF
'Regardless of the lookup result, any non-modifier key press
'has to properly cancel any pending preselection.
IF hitVal& <= 65535 THEN preKey& = 0

'--- if no accent was found or preselected, then move on ---
IF charCode& = 0 THEN
'take the regular key code as default
charCode& = hitVal&
'check shift/ctrl/alt conditions and special behavior
SELECT CASE hitVal&
CASE 9 'tab & reverse tab
IF modShiftOnly% THEN charCode& = 15 * 256
CASE 48 TO 57 'numeric keys 0-9
IF NOT modNone% THEN charCode& = 0
CASE 65 TO 90 'CTRL CAPS A-Z: 1-26
IF modCtrlNoAlt% THEN charCode& = hitVal& - 64
CASE 97 TO 122 'CTRL a-z: 1-26
IF modCtrlNoAlt% THEN charCode& = hitVal& - 96
CASE 128 TO 255 'Ext. ASCII (Cp1252 to Cp437 mapping, if available)
RESTORE InkeyHit_Regul
DO: READ inChar%, outChar%: LOOP UNTIL inChar% = hitVal& OR inChar% = 0
charCode& = outChar%
CASE 256 TO 65535 'double char chr$(0) +
IF (hitVal& AND 255) = 0 THEN
hitVal& = hitVal& \ 256
SELECT CASE hitVal& 'Alt overrides Ctrl overrides Shift
CASE 59 TO 68 'F1-F10
IF modShift% THEN charCode& = (hitVal& + 25) * 256
IF modCtrl% THEN charCode& = (hitVal& + 35) * 256
IF modAlt% THEN charCode& = (hitVal& + 45) * 256
CASE 133, 134 'F11-F12
IF modShift% THEN charCode& = (hitVal& + 2) * 256
IF modCtrl% THEN charCode& = (hitVal& + 4) * 256
IF modAlt% THEN charCode& = (hitVal& + 6) * 256
CASE 71 'Home
IF modCtrl% THEN charCode& = 119 * 256
IF modAlt% THEN charCode& = 151 * 256
CASE 72 'ArrowUp
IF modCtrl% THEN charCode& = 141 * 256
IF modAlt% THEN charCode& = 152 * 256
CASE 73 'PageUp
IF modCtrl% THEN charCode& = 132 * 256
IF modAlt% THEN charCode& = 153 * 256
CASE 75 'ArrowLeft
IF modCtrl% THEN charCode& = 115 * 256
IF modAlt% THEN charCode& = 155 * 256
CASE 77 'ArrowRight
IF modCtrl% THEN charCode& = 116 * 256
IF modAlt% THEN charCode& = 157 * 256
CASE 79 'End
IF modCtrl% THEN charCode& = 117 * 256
IF modAlt% THEN charCode& = 159 * 256
CASE 80 'ArrowDown
IF modCtrl% THEN charCode& = 145 * 256
IF modAlt% THEN charCode& = 160 * 256
CASE 81 'PageDown
IF modCtrl% THEN charCode& = 118 * 256
IF modAlt% THEN charCode& = 161 * 256
CASE 82 'Insert
IF modCtrl% THEN charCode& = 146 * 256
IF modAlt% THEN charCode& = 162 * 256
CASE 83 'Delete
IF modCtrl% THEN charCode& = 147 * 256
IF modAlt% THEN charCode& = 163 * 256
END SELECT
END IF
END SELECT
END IF
ELSE
oPreKey& = preKey& 'save current preselection state
SELECT CASE hitVal&
CASE -57 TO -48 'collect numbers (Alt + char code input)
IF modAltOnly% THEN ascNum$ = ascNum$ + CHR$(-hitVal&): _
ELSE IF hitVal& = -50 AND modAltGr% AND kbl% = kbFrFr% THEN charCode& = 126 '~
CASE -100308 'Alt released: build char from last 3 digits
IF ascNum$ <> "" THEN
charCode& = VAL(RIGHT$(ascNum$, 3))
IF charCode& < 32 OR charCode& > 255 THEN charCode& = 0
lastKey& = 0: preKey& = 0: ascNum$ = "" 'cancel all
END IF
CASE -lastKey& 'cancel the last key
lastKey& = 0
'This case is just here to trap the releases of regular keys.
'It is required to avoid the generation of false positives
'for the following accent preselection cases, if the regular
'key release would generate the same value as any accent key.
CASE -186
SELECT CASE kbl%
CASE kbPtPt% 'acute & grave
IF modNone% THEN preKey& = pkAcute%
IF modShiftOnly% THEN preKey& = pkGrave%
CASE kbEsEs% 'grave & circumflex
IF modNone% THEN preKey& = pkGrave%
IF modShiftOnly% THEN preKey& = pkCircu%
CASE kbDaDk%, kbSvSe%, kbNbNo% 'umlaut & circumflex
IF modNone% THEN preKey& = pkUmlau%
IF modShiftOnly% THEN preKey& = pkCircu%
CASE kbEsMx% 'acute & umlaut
IF modNone% THEN preKey& = pkAcute%
IF modShiftOnly% THEN preKey& = pkUmlau%
END SELECT
CASE -187
SELECT CASE kbl%
CASE kbPtPt% 'umlaut
IF modNone% THEN preKey& = pkUmlau%
END SELECT
CASE -191
SELECT CASE kbl%
CASE kbPtPt% 'circumflex
IF modNone% THEN preKey& = pkCircu%
CASE kbEsMx% 'grave
IF modNone% THEN preKey& = pkGrave%
END SELECT
CASE -192
SELECT CASE kbl%
CASE kbNlNl% 'acute & grave
IF modNone% THEN preKey& = pkAcute%
IF modShiftOnly% THEN preKey& = pkGrave%
CASE kbDeCh% 'umlaut
IF modNone% THEN preKey& = pkUmlau%
CASE kbFrFr%, kbFrBe% 'acute
IF modNone% THEN preKey& = pkAcute%
END SELECT
CASE -219
SELECT CASE kbl%
CASE kbDeCh% 'acute
IF modNone% THEN preKey& = pkAcute%
CASE kbDaDk%, kbSvSe%, kbNbNo% 'acute & grave
IF modNone% THEN preKey& = pkAcute%
IF modShiftOnly% THEN preKey& = pkGrave%
END SELECT
CASE -220
SELECT CASE kbl%
CASE kbFrBe% 'grave
IF modNone% THEN preKey& = pkGrave%
CASE kbDeDe% 'circumflex
IF modNone% THEN preKey& = pkCircu%
END SELECT
CASE -221
SELECT CASE kbl%
CASE kbFrFr%, kbFrBe% 'circumflex & umlaut
IF modNone% THEN preKey& = pkCircu%
IF modShiftOnly% THEN preKey& = pkUmlau%
CASE kbNlNl% 'umlaut & circumflex
IF modNone% THEN preKey& = pkUmlau%
IF modShiftOnly% THEN preKey& = pkCircu%
CASE kbDeCh% 'circumflex & grave
IF modNone% THEN preKey& = pkCircu%
IF modShiftOnly% THEN preKey& = pkGrave%
CASE kbDeDe% 'acute & grave
IF modNone% THEN preKey& = pkAcute%
IF modShiftOnly% THEN preKey& = pkGrave%
END SELECT
CASE -222
SELECT CASE kbl%
CASE kbEsEs% 'acute & umlaut
IF modNone% THEN preKey& = pkAcute%
IF modShiftOnly% THEN preKey& = pkUmlau%
CASE kbEsMx% 'circumflex
IF modNone% THEN preKey& = pkCircu%
END SELECT
CASE -226
SELECT CASE kbl%
CASE kbPtPt% '\
IF modNone% THEN charCode& = 92
END SELECT
CASE ELSE
oPreKey& = 0 'no case did match, cancel saved state
END SELECT
'--- check double-preselection key press (if any) ---
IF oPreKey& > 0 AND oPreKey& = preKey& THEN
SELECT CASE preKey&
CASE pkAcute%: charCode& = 39
CASE pkGrave%: charCode& = 96
CASE pkUmlau%: charCode& = 34
CASE pkCircu%: charCode& = 94
END SELECT
END IF
END IF
END IF
'--- finally encode the usual INKEY$ result ---
IF charCode& > 0 AND charCode& <= 65535 THEN
IF charCode& <= 255 THEN InkeyHit$ = CHR$(charCode&)
IF charCode& >= 256 AND charCode& <= 65535 AND (charCode& AND 255) = 0 THEN InkeyHit$ = CHR$(0) + CHR$(charCode& \ 256)
lastKey& = 0: preKey& = 0
END IF
EXIT FUNCTION
'-----------------------------
'Char lookup tables:
'=> pairs of Input ASC (Cp1252), Output ASC (Cp437)
'=> lists must be double 0-terminated
InkeyHit_Regul:
DATA 128,238,161,173,162,155,163,156,164,15,165,157,166,124,167,21,170,166,171,174
DATA 172,170,176,248,177,241,178,253,179,252,181,230,182,20,183,250,186,167,187,175
DATA 188,172,189,171,191,168,196,142,197,143,198,146,199,128,201,144,209,165,214,153
DATA 220,154,223,225,224,133,225,160,226,131,228,132,229,134,230,145,231,135,232,138
DATA 233,130,234,136,235,137,236,141,237,161,238,140,239,139,241,164,242,149,243,162
DATA 244,147,246,148,247,246,248,232,249,151,250,163,251,150,252,129,255,152,0,0
InkeyHit_Acute:
DATA 32,39,97,160,101,130,105,161,111,162,117,163,69,144,0,0
InkeyHit_Grave:
DATA 32,96,97,133,101,138,105,141,111,149,117,151,0,0
InkeyHit_Umlau:
DATA 97,132,101,137,105,139,111,148,117,129,65,142,79,153,85,154,121,152,0,0
InkeyHit_Circu:
DATA 32,94,97,131,101,136,105,140,111,147,117,150,65,143,0,0
END FUNCTION

Print this item

  A little IDE color glitch maybe
Posted by: Dav - 10-08-2024, 06:51 PM - Forum: General Discussion - Replies (2)

No big deal, but thought I'd mention this in case it could reveal a greater IDE syntax coloring issue. 

I noticed that the IDE doesn't correctly color the name of a SUB or FUNCTION named smooth for some reason.  Load this in the current IDE to see.

- Dav

Code: (Select All)
Function smooth: End Function 'Not colored
Function smoothy: End Function 'colored

Sub smooth: End Sub 'not colored
Sub smoothy: End Sub 'colored

Print this item