0

我做了一个聊天程序,效果很好,我唯一的问题是 SET /P 命令会等到你按下某个东西然后按下 ENTER 键。我的代码有问题:

:CHAT
CLS
SET TEXT=
TYPE "%FILESDIR%\Files\CHAT.cht" << I need this line active all the time.
ECHO.
SET /P TEXT=Text: 
IF NOT "%TEXT%"=="" ECHO %USERNAME%: %TEXT% >> "%FILESDIR%\Files\CHAT.cht"
PING LOCALHOST -n 1 > nul
GOTO CHAT

我想一直更新 TYPE 命令,但是你需要输入一些东西。无论如何我可以解决这个问题吗?编辑:我真的不想要另一个 cmd 屏幕

4

1 回答 1

2

假设您确实有连续实时更新文本。当用户开始输入文本,然后另一个用户同时发送要显示的文本时会发生什么。你只有一个窗口——所以你会弄得一团糟(假设你能弄清楚如何在技术上实现它)。

你离拥有一个功能性的聊天程序还有很长的路要走——你还没有完全考虑到这些问题。

1)您需要两个独立更新的窗口:

  • 用户可以在其中输入文本的输入窗口

  • 实时显示所有参与者正在运行的对话的对话窗口。

Windows 批处理不支持多个窗口。但是您可以通过为每个用户运行两个批处理来模拟它,一个用于输入,另一个用于对话框输出。单个批处理脚本可用于这两个进程。父脚本可以使用 START 命令启动多个批处理。每个批处理都会有自己的控制台窗口。

2)一次只有一个人(进程)可以写入文本文件。如果两个人同时尝试写作,你认为会发生什么?一个会成功,另一个会失败。您需要一种方法来检测失败并自动重试直到成功。我在您如何在 Windows 下共享日志文件中描述了一种实现此目的的简单方法?.

<Enter>3) 如果用户在没有输入任何内容的情况下按下,SET /P 将简单地返回上一个条目。您应该在 SET /P 语句之前清除文本变量。编辑 - 我现在看到 OP 已经在我没想到的地方有了这个

4) 你不想每次有更新时从头开始重新输入整个对话框。您只想显示新添加的行。可以将输入重定向到一个无限的 FOR /L 循环,并且在循环中您可以使用 SET /P 来读取最近的行。如果没有附加任何内容,则它将不返回任何内容(假设变量在 SET /P 之前被清除)。如果没有收到任何内容,您根本不会 ECHO 任何内容。

这是一个演示上述概念的非常粗略的工作示例。没有办法退出程序。您必须关闭两个控制台窗口才能退出。

@echo off
setlocal enableDelayedExpansion
set "dialog=dialog.txt"
if "%~1" equ ":input" (
  title Chat Input
  goto :input
)
start "" "%~f0" :input
title Chat Dialog

::Show Dialog
<"%dialog%" (  for /l %%N in () do (
  set "text="
  set /p "text="
  if defined text echo(!text!
))


:input
cls
set "text="
set /p "text=>"
:write
2>nul (
  >>"%dialog%" (
    echo(%username%: !text!
    (call )
  ) || goto :write
)
goto :input

要成为真正有用的聊天程序还有很长的路要走。但这是一个很好的起点。一些额外的东西仍然可以添加。

5) 一种为每个独立聊天启动新对话文件的方法。

6) 一种邀请一个或多个用户加入聊天的方式。

7) 退出程序的干净方式,包括关闭附加控制台窗口。这需要进程间通信。我在http://www.dostips.com/forum/viewtopic.php?t=4741的 SNAKE.BAT 游戏中演示了这一点。警告 - 该脚本中有很多高级概念,因此提取相关信息可能是一个挑战;-)

8) 让对话窗口有一个可滚动的显示缓冲区会很好。用户可以通过控制台属性控制缓冲区的大小,但最好以编程方式控制它。本机批处理无法执行此操作,但我展示了混合 PowerShell/批处理如何在CMD 执行此操作:设置缓冲区高度独立于窗口高度

于 2014-06-05T18:01:13.823 回答