2011-11-26 33 views
2

我試圖將控制檯的文本顏色設置爲給定顏色,打印一行(或更多),然後將顏色方案改回原來的樣子。這裏是我有什麼:對GetStdHandle的第二次調用返回一個「無效」的句柄

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一個靜態變量,只有打電話GetStdHandle如果conHandle等於零(在REALbasic的新數值變量的默認值。)

,我總是告訴自己以後清理。我應該打開這個手柄嗎?

+3

是的,你應該清理自己,但你也應該被告知要尊重別人的財產。在這種情況下,你沒有創建控制檯句柄,所以你也不應該銷燬它。 –

+0

我以爲我確實創造了手柄,或者至少它是屬於我的。 –

+1

GetStdHandle不創建句柄,它只是獲取現有的句柄。處理創建函數是CreateFile,CreateMutex等。 –

回答

3

是的,你應該打開手柄。

當您的進程退出時,此句柄會自動關閉。

+0

我明白了。感謝那。 –

0

通過對各種網站進行研究,在GetStdHandle返回的句柄上使用CloseHandle時,看起來很糟糕。很多時候,似乎人們的回答是因爲它得到一個句柄而不是創建一個句柄(因爲Get,Not Create這個詞在函數名中),很明顯它會得到系統創建的句柄,關閉這是一個壞主意。但是,實際的答案並不明顯(可悲)。雖然GetStdHandle的確如此,但並不是每個與句柄相關的Get函數都會獲得一個現有的句柄。一些創建新的句柄。例如,GetDC實際上爲設備上下文創建一個新的句柄,並且由於它是一個新的句柄,它必須用CloseHandle正確關閉。與某些人的回覆不同,沒有規則說明如果函數包含單詞Create it將創建一個新句柄,而如果它包含單詞Get,它只會引用已由系統創建的句柄。根本沒有這樣的規則。你如何知道何時需要關閉句柄?一種方法是,如果MSDN沒有明確聲明CloseHandle需要用於由這樣的函數返回的句柄,那麼假設你不應該在該句柄上使用CloseHandle是安全的。另一種解決方法是通過試驗和錯誤。如果使用CloseHandle會導致程序出現更多錯誤,那麼請勿使用CloseHandle。如果不使用CloseHandle會導致程序出現更多錯誤,則使用CloseHandle。我經常使用這些方法的組合。如果在遵循MSDN文檔之後,我的程序似乎有錯誤,但以與MSDN指定的方式不同的方式來減少程序中的錯誤,我會通過反覆試驗確定工作方式。

+0

'GetDC'不會「創建」設備上下文,您不應該對結果調用'CloseHandle'。實際上,你不要在任何* GDI對象句柄上調用'CloseHandle'。對應於'CreateDC'的清理函數是'DeleteDC' ...並且你不會在'GetDC'獲得的'HDC'上使用它。 'GetDC'中的'HDC'後來進入'ReleaseDC'。 (然後對於具有OWN DC風格的類和/或窗口有特殊規則) –

+0

我的意思是,在這個答案中隱藏了一個有效的點,即通過閱讀文檔知道是否傳遞一個句柄給'CloseHandle',而不是API是否以字母'C'''''''''''''''''''''''''開頭。但不幸的是,它埋在了一道錯誤的牆上。 –

相關問題