2

我正在尝试将控制台的文本颜色设置为给定颜色,打印一行(或更多行),然后将配色方案更改回原来的颜色。这是我所拥有的:

Function SetConsoleTextColor(NewColor As UInt16) As UInt16
    Declare Function SetConsoleTextAttribute Lib "Kernel32" (hConsole As Integer, attribs As UInt16) As Boolean
    Declare Function GetStdHandle Lib "Kernel32" (hIOStreamType As Integer) As Integer
    Declare Function GetConsoleScreenBufferInfo Lib "Kernel32" (hConsole As Integer, ByRef buffinfo As CONSOLE_SCREEN_BUFFER_INFO) As Boolean
    Declare Sub CloseHandle Lib "Kernel32" (HWND As Integer)

    Const STD_OUTPUT_HANDLE = -12

    Dim conHandle As Integer = GetStdHandle(STD_OUTPUT_HANDLE)
    Dim buffInfo As CONSOLE_SCREEN_BUFFER_INFO  //A structure defined elsewhere
    If GetConsoleScreenBufferInfo(conHandle, buffInfo) Then
      Call SetConsoleTextAttribute(conHandle, NewColor)
      CloseHandle(conHandle)
      Return buffInfo.Attribute
    Else
      Return 0
    End If
End Function

这在第一次通话时效果很好。更改控制台上新输出的文本颜色并返回以前的属性。但是,当我第二次调用它来重置属性时,GetStdHandle返回的句柄与前一次调用相同,但现在无效(因为我关闭了它。)

当然,当我尝试使用句柄时,这会导致错误。如果我创建conHandle一个静态变量并且仅在等于零时调用GetStdHandleconHandleRealBasic 中新数字变量的默认值),它可以正常工作。

我总是被告知要自己清理。我应该让这个把手打开吗?

4

2 回答 2

4

是的,您应该打开手柄。

当您的进程退出时,此句柄会自动关闭。

于 2011-11-26T10:32:02.187 回答
0

通过对各种站点的研究,当您在 GetStdHandle 返回的句柄上使用 CloseHandle 时,似乎会发生不好的事情。很多时候,似乎人们的回答是,因为它获得了一个句柄而不是创建一个句柄(因为函数名称中出现了 Get,而不是 Create 这个词),所以它应该很明显它获得了一个由系统创建的句柄,并且关闭这是一个坏主意。然而,实际的答案并不那么明显(可悲)。虽然 GetStdHandle 确实如此,但并不是每个与句柄相关的 Get 函数实际上都获得了现有的句柄。有些会创建新的句柄。例如,GetDC 实际上为设备上下文创建了一个新句柄,并且由于它是一个新句柄,因此必须使用 CloseHandle 正确关闭它。与某些人的回复不同,没有规定如果函数包含单词 Create 它会创建一个新句柄,而如果它包含单词 Get 它只引用系统已经创建的句柄。根本没有这样的规则。你怎么知道什么时候真正需要关闭一个句柄呢?一种方法是,如果 MSDN 没有明确说明需要在某某函数返回的句柄上使用 CloseHandle,那么可以安全地假设您不应该在该句柄上使用 CloseHandle。另一种解决方法是反复试验。如果使用 CloseHandle 会导致您的程序有更多的错误,那么不要使用 CloseHandle。如果不使用 CloseHandle 会导致您的程序有更多错误,请使用 CloseHandle。我经常结合使用这些方法。如果在遵循 MSDN 文档之后我的程序似乎有错误,但与 MSDN 指定的方式不同的做法往往会减少我程序中的错误,我会按照我的要求去做

于 2016-01-11T02:05:58.837 回答