有人有实现此功能的示例代码或说明吗?我一直无法完成使用箭头键和 enter 进行选择的突出显示菜单。提前致谢!
我预计这一工作会通过为每个选项绘制方框,并在选择选项时重新绘制彩色方框同时为文本着色来实现。我只是不确定如何设计一个循环来完成此任务。我对 INKEY$
函数和 SELECT CASE
语句非常满意,但我不知道如何将它们考虑在内。
最佳答案
突出显示的菜单将绘制菜单并循环等待按键或使用SLEEP
。一种常见的替代方法是简单地更改前几个字母之一的文本颜色,通知用户按相应的键来选择相应的菜单选项。例如,“退出”中的字母 Q 和“新游戏”中的 N 的颜色将与该行中其余文本的颜色不同。
但是,您要求使用箭头键,所以显然您不想这样做。如何突出显示当前菜单项取决于所使用的屏幕模式。屏幕模式 11、12 和 13 不允许您指定背景颜色,并且我无法让 DOSBox 使用模式 7、8 和 9 渲染背景。作为此问题的解决方法,您可以简单地在当前选择旁边绘制一个框并删除该框(绘制黑色或任何屏幕背景颜色)。或者您可以只使用星号来避免图形/文本大小问题并简化代码。下面是一个带有箭头键、WASD 键和 Vim 样式键(H=左、J=下、K=上、L=右)的框样式示例,假设使用 US-QWERTY 键盘,则均受支持。如果您只需要箭头键,那么您只需将第一个(外部)SELECT CASE...END SELECT
block 更改为简单的 IF LEFT$(k$, 1) = CHR$(0) THEN...END IF
,同时保留使用扩展键的内部 SELECT CASE...END SELECT
block 。
'size% is used in the selIncDec subroutine.
DIM text$(0 TO 3)
DIM SHARED size%
size% = UBOUND(text$) - LBOUND(text$) + 1
selected% = 0
text$(0) = "Example 1"
text$(1) = "Example 2"
text$(2) = "Example 3"
text$(3) = "Example 4"
SCREEN 12
' Width and height of a text cell in pixels.
' I use 8x8 text cells for max screen compatibility, despite 8x16 looking better.
xpxText% = 8
ypxText% = 8
' See the documentation for SCREEN to determine which screen sizes are
' available with the screen mode you want to use.
' 80x60 for mode 12 results in 8x8 text cells. 80x30 results in 8x16 text cells.
WIDTH 80, 60
DO
LOCATE 1, 1
FOR i% = LBOUND(text$) TO UBOUND(text$)
PRINT TAB(3); text$(i%)
' selected% = i%
' is an equality comparison, resulting in -1 for true and 0 for false.
' If false, -(0) * 2 = 0; if true, -(-1) * 2 = 2.
LINE (0, i% * ypxText%)-STEP(xpxText% - 1, xpxText% - 1), -(selected% = i%) * 2, BF
NEXT i%
SLEEP
k$ = INKEY$
SELECT CASE UCASE$(LEFT$(k$, 1))
' Left -- does nothing
CASE "H", "A"
' Right -- does nothing
CASE "L", "D"
' Up
CASE "K", "W"
CALL selIncDec(selected%, -1)
' Down
CASE "J", "S"
CALL selIncDec(selected%, 1)
' Enter key
CASE CHR$(13)
EXIT DO
' Extended key, such as arrows.
CASE CHR$(0)
SELECT CASE RIGHT$(k$, 1)
' Left
CASE "K"
' Right
CASE "M"
' Up
CASE "H"
CALL selIncDec(selected%, -1)
' Down
CASE "P"
CALL selIncDec(selected%, 1)
END SELECT
END SELECT
LOOP
PRINT USING "You selected option #"; selected% + 1
END
SUB selIncDec (selected%, amtInc%)
selected% = selected% + amtInc%
IF selected% >= size% THEN
selected% = selected% - size%
ELSEIF selected% < 0 THEN
selected% = selected% + size%
END IF
END SUB
如果您使用的屏幕模式支持背景颜色或以某种形式突出显示(例如 screen 0),您可能可以在文本模式下简单地“突出显示”整行的背景。您无需指定屏幕的宽度即可获得充当突出显示的“反向视频”效果,但当您突出显示整行而不是仅突出显示文本时,它看起来会更好。打印该菜单项后,只需将颜色更改回默认值并照常继续打印即可。下面显示了上述代码的一些更改(屏幕模式、屏幕宽度设置和菜单显示代码),但其他方面保持不变:
SCREEN 0
'8x8 text cells in SCREEN 0 for VGA adapters.
WIDTH 80, 43
...
FOR i% = LBOUND(text$) TO UBOUND(text$)
' "Reverse video" highlighting.
IF selected% = i% THEN COLOR 0, 7 ELSE COLOR 7, 0
PRINT TAB(3); text$(i%); SPACE$(78 - LEN(text$(i%)))
NEXT i%
' The screen will turn "white" when the last menu item is selected.
' This fixes the issue.
COLOR 7, 0
SLEEP
...
请注意,我假设上面的所有代码都使用带有彩色显示屏的 VGA 适配器,该适配器早已被各种其他显示适配器标准所取代,这些标准甚至在像智能 watch 这样小的设备上也在使用。
您应该能够调整代码以满足您的需求。我设计它的目的是让您可以根据需要简单地添加菜单项。此外,显示代码本身完全包含在 FOR...NEXT
循环中,其功能紧随其后,因此您需要更改的只是 FOR... NEXT
循环来更改内容的显示方式。
关于loops - Qbasic 突出显示菜单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37944159/