防止在关闭控制台时关闭Windows窗体应用程序

6

我有一个标准的Windows Forms应用程序,需要在Windows Forms应用程序中打开控制台的解决方案。我想出了这个解决方案:

Public Class Win32

    <DllImport("kernel32.dll")>
    Public Shared Function AllocConsole() As Boolean
    End Function

    <DllImport("kernel32.dll")>
    Public Shared Function FreeConsole() As Boolean
    End Function

' ...

Win32.AllocConsole()
Console.WriteLine("Test")

使用上述P/Invoke函数,我可以打开一个控制台而不必将我的应用程序设置为“控制台应用程序”。
现在我遇到的问题是,当我关闭控制台窗口时,它会退出我的程序并关闭所有表单和窗口。有没有办法防止用户关闭控制台窗口,或者在控制台窗口关闭时防止程序退出?(我可以使用Win32.FreeConsole()来编程关闭控制台。)

我已经尝试澄清您的问题。如果我理解错了,您可以打开修订历史记录并回滚到之前的版本。 - JDB
2
我尝试了那个答案,但对我没有用! - Tom
该问题和可能的答案在那个问题/答案中已经被深入地讨论了。请查看其他答案以获取可能的解决方案。 - Mark Hall
3
这些回答中没有什么可以“尝试”的。它们都表达了同样的意思:你无法阻止这种情况发生。如果你负担不起这种情况,请不要创建控制台。 - Hans Passant
@HansPassant,我想说你错了,你可以停下来了,我这样做过,而且效果很好! - Trevor
1个回答

1

我认为你可能会觉得这很有趣,试试看;对我来说效果很好!另外注意:用户无法点击关闭按钮,因为它被禁用了,唯一的退出方式就是按照你设定的方法...

 Imports System.Collections.Generic
 Imports System.Windows.Forms
 Imports System.Runtime.InteropServices
 Imports System.Diagnostics
 Imports Microsoft.Win32

 Public Class Form1

 <DllImport("kernel32.dll", SetLastError:=True)> _
Private Shared Function AllocConsole() As Boolean
End Function

<DllImport("kernel32.dll", SetLastError:=True)> _
Private Shared Function FreeConsole() As Boolean
End Function

Private Declare Function DeleteMenu Lib "user32" (ByVal hMenu As Integer, _
 ByVal uPosition As Integer, ByVal uFlags As Integer) As Boolean
Private Declare Function GetForegroundWindow Lib "user32" () As Integer
Private Declare Function GetSystemMenu Lib "user32" (ByVal hWnd As Integer, _
   ByVal bRevert As Boolean) As Integer
Private Declare Function GetWindow Lib "user32" (ByVal hWnd As Integer, _
   ByVal uCmd As Integer) As Integer
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _
   (ByVal hWnd As Integer, ByVal lpString As String, ByVal nMaxCount As Integer) As Integer


Private Sub btnStartConsole_Click(sender As Object, e As EventArgs) Handles btnStartConsole.Click
    StartConsole()
End Sub

Private Sub StartConsole()
    AllocConsole()
    Console.Title = "TEST"
    ' Obtain a handle to the console application window by passing the title of your application.
    Dim hWnd As Integer = ObtainWindowHandle("TEST") 'Can change this, but must match the name you give it!'

    ' Obtain a handle to the console application system menu.
    Dim hMenu As Integer = GetSystemMenu(hWnd, False)

    ' Delete the Close menu item from the console application system menu.
    ' This will automatically disable the Close button on the console application title bar.
    DeleteMenu(hMenu, 6, 1024)

    Console.WriteLine("We have a console! Enter something!")
    ' Read value.
    Dim s As String = Console.ReadLine()
    ' Write the value.
    Console.WriteLine("You typed " + s)
    Console.WriteLine("Press any key! ...")
    Console.ReadLine()

    FreeConsole()
End Sub

Private Function ObtainWindowHandle(ByVal lpstrCaption As String) As Integer

    ' To store the handle to a window.
    Dim hWnd As Integer
    ' Maximum number of characters in the GetWindowText method.
    Dim nMaxCount As Integer
    ' Actual number of characters copied in the GetWindowText method.
    Dim nCopiedLength As Integer
    ' To store the text of the title bar of the window.
    Dim lpString As String

    nMaxCount = 255
    ' Obtain a handle to the first window.
    hWnd = GetForegroundWindow

    ' Loop through the various windows until you encounter the console application window, _
    ' or there are no more windows.
    While hWnd <> 0

        ' Fill lpString with spaces.
        lpString = Space(nMaxCount)
        ' Get the text of the title bar of the window in lpString.
        nCopiedLength = GetWindowText(hWnd, lpString, nMaxCount)

        ' Verify that lpString is neither empty, nor NULL.
        If Len(Trim(lpString)) <> 0 And Asc(Trim(lpString)) <> 0 Then
            ' Verify that the title of the retrieved window is the same as the title of the console application window.
            If CType(InStr(Microsoft.VisualBasic.Left(lpString, nCopiedLength), lpstrCaption), Boolean) Then
                ' Return hWnd to the Main method.
                Return hWnd
            End If
        End If

        ' Get the next window.
        hWnd = GetWindow(hWnd, 2)

    End While

    ' If no corresponding windows are found, return 0.
    Return 0

End Function
End Class

这也是经过尝试和测试的!让我知道它对你有什么作用! - Trevor
他的主要关注点是,如果有人通过单击关闭按钮关闭控制台,它 终止应用程序。 - Mark Hall
@MarkHall,现在没问题了,我以前做过这个,必须找到它。它禁用了菜单关闭,但最大化和最小化功能仍然可用...试试看吧... - Trevor
@Mr CoDeXeR,是的,您的代码是解决问题的方法,但从技术上讲,它并不是对问题的真正回答,因为您阻止了关闭按钮的显示,但没有说明如何在按下关闭按钮时停止窗体关闭,但您的答案不允许关闭按钮被按下。 - Tom
好的,让我提醒您您所问的问题.... "我现在遇到的问题是,当我关闭控制台窗口时,它会退出我的程序并关闭所有的表单和窗口。有没有办法阻止用户关闭控制台窗口,或者在关闭控制台窗口时阻止程序退出?" 这就是您所问的问题,我给您提供了一个解决方案。如果您不停止该可恶的关闭按钮,他们就可以退出! - Trevor
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接