回 帖 发 新 帖 刷新版面

主题:qb4.5编写的程序中显示汉字

下面是一段用QB编写的能在英文下显示汉字的小程序片断,可以运行,运行后会在全屏幕状态下显示汉字,程序利用的是UCDOS的16点阵汉字库,字库后附,有兴趣朋友可以试一下。这是很多年前用过的,拿出来大家分享。其实QB编的小程序很有用,现在本人还时常编一段,用来应付一些烦人的转换,例如将两个STR电影字幕文件合并到一起,等等等等....,核心是子程序SUB xshz16 (zf$),其它部分是例子,说远了,奉上程序,真正原版,没有优化过:

'西文下显示汉字模块,需要文件UCDOS汉字库文件hzk16支持,编写:jmsxdp
DECLARE SUB xshz16 (zf$)  '点阵坐标用,待显字符串
DIM SHARED xsys
DIM SHARED hzk$
DIM SHARED er$
ON ERROR GOTO erro
er$ = "f"
OPEN "b", #4, "HZK16"  '汉字库文件hzk16
IF er$ = "t" THEN
hzk$ = "f"
END IF
SCREEN 12
xsys = 14              '字符颜色0-15,7:浅白,15:亮白,其他为彩色
'                      '++++++以下添加需要程序++++++
'                      '根据你的需要,在需要显示汉字处按下面格式调用

LOCATE 20, 10           '需要显示坐标,为第20行10列
zf$ = "显示汉字1234"     '要显示的字符
CALL xshz16(zf$)      '调用程序显示汉字“显示汉字1234”

'                     '--------------添加部分结束-------------
q:                     '程序退出
SYSTEM

erro:                 '错误处理
  errs = ERR
  er$ = "t"
  RESUME NEXT

SUB xshz16 (zf$)        '显示汉字模块
IF xsys = 0 THEN xsys = 14
IF hzk$ = "f" GOTO hzkcl1
l = LEN(zf$)
hzbz = CSRLIN
zzbz = POS(hzb)
zzb = hzbz * 16 - 15
hzb = zzbz * 8 - 7
IF hzb = 0 THEN hzb = 1
IF zzb = 0 THEN zzb = 1
hzbtmp = hzb
zzbtmp = zzb
l = LEN(zf$)
txtmp = 2
xsmk1:
FOR i = txtmp - 1 TO l
zf1$ = MID$(zf$, i, 1)
zf2$ = MID$(zf$, i + 1, 1)
zf1 = ASC(zf1$)
zf2 = ASC(zf2$)
IF zf1 < 159 GOTO xsasc
no = ((zf1 - 160 - 1) * 94 + zf2 - 160 - 1) * 32 + 1
SEEK #4, no
cch$ = INPUT$(32, 4)
FOR a = 1 TO 16
ch1$ = MID$(cch$, a * 2 - 1, 1)
ch2$ = MID$(cch$, a * 2, 1)
ch$ = ch2$ + ch1$
s = CVI(ch$)
LINE (hzb, zzb)-(hzb + 15, zzb), xsys, , s
zzb = zzb + 1
IF zzb - zzbtmp = 16 THEN
zzb = zzbtmp
hzb = hzb + 16
END IF
NEXT a
i = i + 1
NEXT i
GOTO xshz16subq
xsasc:
LOCATE zzb / 16 + 1, hzb / 8 + 1
PRINT zf1$
txtmp = i + 2
i = txtmp
hzb = hzb + 8
GOTO xsmk1
hzkcl1:
PRINT zf$
xshz16subq:
END SUB 

回复列表 (共9个回复)

沙发

难道现在没有人用QuickBasic?其实QB在DOS下功能还是比较强大的,关键是编程简单,也可以实现中断调用、鼠标、内存读写等功能,这个片断程序是按行列位置显示汉字,也可以改为按坐标显示。QB编写的小程序在平常很有用,比如从利用TXT文件生成HTML文件、统计、计算等等,希望有人在用。[em18][em18][em18]

板凳

现在好像没几个人会用DOS来启动系统了吧?
在Windows下的CMD中是不允许直接调用系统中断的。
还有HTML文件等等,应该都是在Windows下使用的吧?

显示汉字的函数很不错。(你是在等这一句么?)

3 楼

不,发表此段程序决没有炫耀的意思,其实90年代我曾用qb编写过模拟windows的界面的程序作为自己使用的工具,也曾弄过FOXbasce的数据库读写,为克服qb无法输入某些中文字还在程序中专门编写了一个中文输入模块,曾编写打字测速软件、编写安装软件等等等.....,但始终是自用和帮朋友解决难题,因为本人不是编程人员,也不是当时的电脑维修人员,接触的只是自己的电脑而已。qb作为基本编程工具的作用已经不存在了,这是现实,但现在在windows窗口下用qb编写的程序无法显示汉字,已有的汉字系统又都不好用,才贴出此段程序。读写修改html文件确实是windiws窗口下使用的,qb很适合这些工作,例如我现在合并电影中英文srt字幕文件就是用我自己编写的小程序,很方便,还能看到汉字

4 楼


就是这段程序,懒得优化,是一气写出来的,显得乱些:
'合并两个SRT字幕文件
'用于制作双语字幕文件
'第一个字幕文件为1.srt
'第二个字幕文件为2.srt
'合并后的文件为out.SRT
'合并时以第一个文件为主
'如第二个字幕文件显示时间与第一个文件相差超过1秒,则忽略第二个字幕
DECLARE SUB xshz16 (zf$)  '点阵坐标用,待显字符串
DIM SHARED xsys
DIM SHARED hzk$
DIM SHARED er$
ON ERROR GOTO erro
er$ = "f"
OPEN "i", #4, "hzk16"
IF er$ = "t" THEN
hzk$ = "f"
CLOSE #4
ELSE
CLOSE #4
OPEN "b", #4, "HZK16"  '汉字库文件
END IF
SCREEN 12
xsys = 14
LOCATE 2, 1
zf$ = "******用于合并两个SRT字幕文件,制作双语字幕文件的工具******"
CALL xshz16(zf$)
LOCATE 3, 1
zf$ = "第一个字幕文件为1.srt,"
CALL xshz16(zf$)
LOCATE 4, 1
zf$ = "第二个字幕文件为2.srt,"
CALL xshz16(zf$)
LOCATE 5, 1
zf$ = "合并后的文件为OUT.SRT,"
CALL xshz16(zf$)
LOCATE 6, 1
zf$ = "合并时以第一个文件为主,"
CALL xshz16(zf$)
LOCATE 7, 1
zf$ = "如第二个字幕文件显示时间与第一个文件相差超过1秒,则忽略第二个字幕。"
CALL xshz16(zf$)
LOCATE 8, 1
zf$ = "是否进行合并(Y/N)?"
CALL xshz16(zf$)
LOCATE 9, 1
ON ERROR GOTO erro
PRINT "(Y/N):"; : LINE INPUT x$
IF x$ = "" OR x$ = "n" OR x$ = "N" THEN GOTO qx
OPEN "i", #1, "1.srt"
OPEN "i", #2, "2.srt"
OPEN "o", #3, "out.tmp"
m1:
LINE INPUT #1, x$
IF EOF(1) THEN
qu$ = "q"
GOTO m2
END IF
a1$ = MID$(x$, 3, 1)
a2$ = MID$(x$, 6, 1)
a3$ = MID$(x$, 14, 3)
IF a1$ = ":" AND a2$ = ":" AND a3$ = "-->" THEN
a11 = VAL(MID$(x$, 1, 2))
a21 = VAL(MID$(x$, 4, 2))
a31 = VAL(MID$(x$, 7, 2))
a41 = VAL(MID$(x$, 18, 2))
a51 = VAL(MID$(x$, 21, 2))
a61 = VAL(MID$(x$, 24, 2))
t1 = a11 * 3600 + a21 * 60 + a31
PRINT #3, x$
GOTO m1
ELSE
IF x$ = "" THEN
te = te + 1
LOCATE 24, 1: PRINT "  Line ="; te
GOTO m2
END IF
PRINT #3, x$
GOTO m1
END IF

m2:
LINE INPUT #2, y$
IF EOF(2) GOTO mq
m23:
b1$ = MID$(y$, 3, 1)
b2$ = MID$(y$, 6, 1)
b3$ = MID$(y$, 14, 3)
IF b1$ = ":" AND b2$ = ":" AND b3$ = "-->" THEN
b11 = VAL(MID$(y$, 1, 2))
b21 = VAL(MID$(y$, 4, 2))
b31 = VAL(MID$(y$, 7, 2))
b41 = VAL(MID$(y$, 18, 2))
b51 = VAL(MID$(y$, 21, 2))
b61 = VAL(MID$(y$, 24, 2))
t2 = b11 * 3600 + b21 * 60 + b31
GOTO m3
ELSE
z2$ = y$
GOTO m2
END IF

m3:
IF t2 - t1 > 1 OR t1 - t2 > 1 THEN
GOTO m2
ELSE
GOTO m32
END IF

m32:
LINE INPUT #2, y$
IF EOF(2) THEN GOTO mq
PRINT #3, y$
IF y$ = "" GOTO m1
GOTO m32


erro:
 errs = ERR
  er$ = "t"
  RESUME NEXT

q:
CLOSE #1
CLOSE #2
CLOSE #3
GOTO px

mq:
CLOSE #2
IF qu$ = "q" GOTO q
OPEN "i", #2, "2.srt"
PRINT #3, ""
GOTO m1

px:
OPEN "i", #2, "out.tmp"
'ON ERROR GOTO qx
OPEN "o", #3, "out.srt"
'ON ERROR GOTO qx
qq = 0
LINE INPUT #2, z$
IF EOF(2) GOTO qx
mq1:
qq = qq + 1
LOCATE 25, 1: PRINT "line = "; qq
IF qq < 10 THEN q1$ = MID$(STR$(qq), 2, 1)
IF 9 < qq < 100 THEN q1$ = MID$(STR$(qq), 2, 2)
IF 99 < qq < 1000 THEN q1$ = MID$(STR$(qq), 2, 3)
IF 999 < qq < 10000 THEN q1$ = MID$(STR$(qq), 2, 4)
PRINT #3, q1$
mq2:
LINE INPUT #2, z$
PRINT #3, z$
IF EOF(2) GOTO qx
IF z$ = "" THEN GOTO mq3
GOTO mq2
mq3:
LINE INPUT #2, z$
IF z$ = "" GOTO mq3
IF EOF(2) GOTO qx
GOTO mq1

qx:
SYSTEM

SUB xshz16 (zf$)        '显示汉字模块
IF xsys = 0 THEN xsys = 15
IF hzk$ = "f" GOTO hzkcl1
l = LEN(zf$)
hzbz = CSRLIN
zzbz = POS(hzb)
zzb = hzbz * 16 - 15
hzb = zzbz * 8 - 7
IF hzb = 0 THEN hzb = 1
IF zzb = 0 THEN zzb = 1
hzbtmp = hzb
zzbtmp = zzb
l = LEN(zf$)
txtmp = 2
xsmk1:
FOR i = txtmp - 1 TO l
zf1$ = MID$(zf$, i, 1)
zf2$ = MID$(zf$, i + 1, 1)
zf1 = ASC(zf1$)
zf2 = ASC(zf2$)
IF zf1 < 159 GOTO xsasc
no = ((zf1 - 160 - 1) * 94 + zf2 - 160 - 1) * 32 + 1
SEEK #4, no
cch$ = INPUT$(32, 4)
FOR a = 1 TO 16
ch1$ = MID$(cch$, a * 2 - 1, 1)
ch2$ = MID$(cch$, a * 2, 1)
ch$ = ch2$ + ch1$
s = CVI(ch$)
LINE (hzb, zzb)-(hzb + 15, zzb), xsys, , s
zzb = zzb + 1
IF zzb - zzbtmp = 16 THEN
zzb = zzbtmp
hzb = hzb + 16
END IF
NEXT a
i = i + 1
NEXT i
GOTO xshz16subq
xsasc:
LOCATE zzb / 16 + 1, hzb / 8 + 1
PRINT zf1$
txtmp = i + 2
i = txtmp
hzb = hzb + 8
GOTO xsmk1
hzkcl1:
PRINT zf$
xshz16subq:
END SUB

5 楼

[quote]其实90年代我曾用qb编写过模拟windows的界面的程序作为自己使用的工具,也曾弄过FOXbasce的数据库读写,[/quote]
呵呵,这些事情我也做过。
其实,现在可以在EXCEL里使用VBA,兼容QB的大部份内容,更多出无数的新招数,也不需要顾及汉字显示。

6 楼

其实要在QB的输出文件中展现汉字,可以先用记事本编程序,注意所有的标点符号全要用半角,在输出文件中要输出的汉字的引号也要用半角的引号,最后就能在输出文件中输出汉字了。举个例子:


OPEN "A.DOC" FOR OUTPUT AS #1
10 INPUT "M=   (MO SHU)"; M
PRINT #1, "从内齿轮公法线长度计算棒间距M值输出表"
PRINT #1,
PRINT #1, "输入模数:"; M
15 IF M = 0 THEN 230
20 INPUT "Z=   (CHI SHU)"; Z
PRINT #1, "输入齿数:"; Z
IF Z = 0 THEN PRINT #1, "输入齿数为零,程序结束.欢迎再次使用.": END
30 A = 20
40 PRINT "A="; A; "  (YA LI JIAO)"
50 INPUT "A="; A
IF A <= 0 THEN A = 20: PRINT #1, "系统默认压力角为20度": GOTO 60
PRINT #1, "输入压力角为:"; A
60 P = 3.14159265359#
65 Q = 180
70 A = A * P / Q
75 INPUT "Dp=   (LIANG  BANG  ZHI  JING)"; Dp
IF Dp = 0 THEN 75
PRINT #1, "输入量棒直径为:"; Dp
80 INPUT "K=  (KUA CHI SHU)"; K
IF K <= 1 THEN PRINT #1, "你输入的跨齿数为零,不能计算,请再次输入": PRINT "K=2,3,4...": GOTO 80
PRINT #1, "输入公法线跨齿数为:"; K
90 INPUT "W=   (GONG  FA  XIAN)"; W
PRINT #1, "输入公法线长度为:"; W
95 IF W = 0 THEN PRINT #1, "公法线长度为零,程序重新开始": GOTO 10
96 IF G > 10 THEN 110
100 DIM Y(20)
110 Y(1) = M * COS(A) * (P * (K - .5) + Z * (TAN(A) - A))
120 Y(2) = (W - Y(1)) / (2 * M * SIN(A))
PRINT #1, "对应变位系数 X 为:"; Y(2)
PRINT #1, "对应弧齿槽宽 S 为:"; M * P / 2 + 2 * Y(2) * M * TAN(A)
130 Y(3) = M * Z
140 Y(4) = (M * P / 2 + 2 * Y(2) * TAN(A) * M) / Y(3)
145 Y(5) = TAN(A) - A - Dp / Y(3) / COS(A) + Y(4)
146 IF Y(5) < 0 THEN 229
150 T = Y(5)
Q = .7
R = 0
160 S = TAN(Q) - Q - T
Q = Q - S / TAN(Q) ^ 2
IF R = S THEN 170
IF ABS(S) > 1E-09 THEN LET R = S: GOTO 160
170 Y(6) = Q
175 Q = 180
180 IF INT(Z / 2) * 2 <> Z THEN GOTO 200
190 Y(7) = M * Z * COS(A) / COS(Y(6)) - Dp
195 GOTO 210
200 Y(7) = M * Z * COS(A) / COS(Y(6)) * COS(90 / Z * P / Q) - Dp
210 PRINT #1, "与此公法线对应的M值为:"; Y(7)
PRINT "M="; Y(7)
220 GOTO 90
229 PRINT #1, "量棒直径选择错误,计算不能进行.程序结束,欢迎再次使用": GOTO 240
230 PRINT #1, "你输入的模数为零,程序结束.欢迎再次使用"
240 CLOSE #1
END




这是一段计算内齿轮M值的程序,输出的文件中就有大量的汉字出现了。

7 楼

对 xzhz16 子程序进行了优化。

[font=宋体]
DEFINT A-Z
SUB xshz16 (zf$)        '显示汉字模块
    IF xsys = 0 THEN xsys = 14
    IF hzk$ = "f" THEN
        PRINT zf$;
        EXIT SUB
    END IF
    '
    hzbz = CSRLIN
    zzbz = POS(hzb)
    zzb = hzbz * 16 - 15
    hzb = zzbz * 8 - 7
    hzbtmp = hzb
    l = LEN(zf$)
    i = 1
    COLOR xsys
    '
    DO WHILE i <= l
        zf1 = ASC(MID$(zf$, i, 1)): i = i + 1
        IF zf1 < 159 THEN
            LOCATE hzbz, zzbz
            PRINT CHR$(zf1);
            hzb = hzb + 8
            zzbz = zzbz + 1
        ELSE
            zf2 = ASC(MID$(zf$, i, 1)): i = i + 1
            SEEK #4, ((zf1 - 161) * 94& + zf2 - 161) * 32 + 1
            s32$ = INPUT$(32, #4)
            i2 = 1
            FOR a = 0 TO 15
                s = CVI(MID$(s32$, i2 + 1, 1) + MID$(s32$, i2, 1))
                LINE (hzb, zzb + a)-STEP(15, 0), xsys, , s
                i2 = i2 + 2
            NEXT a
            hzb = hzb + 16
            zzbz = zzbz + 2
        END IF
    LOOP
END SUB
[/font]

8 楼

请问怎样才能实现在qbasic下输出不同字号的汉字。

9 楼

呵呵,这个帖子还浮出来了,好久没来了。不同字号在qbasic中有两种显示方法:一种是用不同点阵字库,如用24点阵、48点阵等,显示方法和上面的类似,只是注意上面的程序是每次显示16点,并且为了加快显示速度(其实现在电脑速度很快了,可一不用则众方法)是利用划直线来代替描点,cpu速度慢时这是一个解决办法,十六点阵字库每字32字节,而且字库有的是横向划线描点,有的是纵向,拟可以试一下,很有意思,会看到显示的字横过来。第二种是用点阵字库描点显示汉字,每个点多显示几次,如24点阵字库每个汉字的每一个点横向显示两点、纵向显示两点,则显示的字变为48点阵,这种方法在早期ccdos213、ccdos4.0及cced、wps、word star打印输出中使用过,当然效果不太好。曾经写过描点的16、24、48点阵显示程序,用来显示操作菜单,可惜找不到了。
上面一个帖子说的对,windows禁止中断调用,所以很多功能就无法实现,如曾编写过直接读写硬盘扇区、鼠标操作、改显示缓存、显示16色图像等。

兼回答2楼:qbasic编写Html文件,是利用Qbasic的特点,编辑页面。如一页有100行,每行的字不同,每行对应不同的链接,如果用程序生产会很麻烦,要一行一行设定、输入,其实你可以用windows应用程序生成一个html文件,里面只有一、二行标准链接,主要是用里面的超文本语言语句,然后用qbasic程序从编辑好的文本文件中提取每一行文字,再从另一个文本文件中提取链接地址,按照生成的样本html文件中已有的一、二个链接的格式和位置,加进去就可以了,我曾经在2000年时用这种方法把很多网上的Html格式电子书,制成集中目录,方便阅读,近千的链接一会就搞定了。当然,书名文本文件的产生同样利用了qbasic,还要先利用DOS命令 dir *.*>menu.txt 来产生,再用qbasic剔出不用的内容,链接同样利用menu.txt中的目录结构(现在叫文件夹....)来产生。

我来回复

您尚未登录,请登录后再回复。点此登录或注册