【发布时间】:2011-11-10 18:41:08
【问题描述】:
我正在编写一个可以启动控制台进行调试的 Windows 窗体应用程序。我想禁用控制台的关闭按钮,以便无法通过控制台的关闭按钮关闭 windows 窗体应用程序。我已经构建了测试代码框架并且它可以工作。代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace bsa_working
{
public partial class Form1 : Form
{
static bool console_on = false;
public Form1()
{
InitializeComponent();
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
if (ViewConsole.Checked)
{
Win32.AllocConsole();
ConsoleProperties.ConsoleMain();
// Set console flag to true
console_on = true; // will be used later
}
else
Win32.FreeConsole();
}
}
public class Win32
{
[DllImport("kernel32.dll")]
public static extern Boolean AllocConsole();
[DllImport("kernel32.dll")]
public static extern Boolean FreeConsole();
}
public class ConsoleProperties
{
[DllImport("user32.dll")]
static extern bool EnableMenuItem(IntPtr hMenu, uint uIDEnableItem, uint uEnable);
[DllImport("user32.dll")]
static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
[DllImport("user32.dll")]
static extern IntPtr RemoveMenu(IntPtr hMenu, uint nPosition, uint wFlags);
internal const uint SC_CLOSE = 0xF060;
internal const uint MF_GRAYED = 0x00000001;
internal const uint MF_BYCOMMAND = 0x00000000;
public static void ConsoleMain()
{
IntPtr hMenu = Process.GetCurrentProcess().MainWindowHandle;
IntPtr hSystemMenu = GetSystemMenu(hMenu, false);
EnableMenuItem(hSystemMenu, SC_CLOSE, MF_GRAYED);
RemoveMenu(hSystemMenu, SC_CLOSE, MF_BYCOMMAND);
// Set console title
Console.Title = "Test Console";
// Set console surface foreground and background color
Console.BackgroundColor = ConsoleColor.DarkBlue;
Console.ForegroundColor = ConsoleColor.White;
Console.Clear();
}
}
}
代码运行良好,除了:
第一次编译和运行代码时,控制台上的 X 不是灰显的,但它在 Windows 窗体应用程序中灰显。但是,当代码关闭并再次运行时,代码会正常工作;也就是说,控制台上的 X 是灰色的,Windows 窗体应用程序应该是这样的。任何想法为什么以及如何解决这个问题?
有时控制台会出现在 win 表单后面。有什么方法可以强制控制台始终排在首位?
顺便说一句,有什么方法可以将控制台固定到 WinForm 上的特定位置?应用程序?我可以设置它的大小,所以如果我可以将它固定在特定位置,我可以在表单上为其创建一个位置。
【问题讨论】:
-
你为什么不在你的应用程序中简单地有一个 Windows 窗体,例如另一个窗体或控件在启用多行的文本框中,然后你将控制台的标准输出重定向到这个控件,而不需要所有这些魔法你正在尝试做什么?
-
因为控制台主要是调试用的,我不一定想一直看。
-
@Zeos6:我在一些应用程序中做同样的事情。我真的很喜欢它的工作方式。而不是调用
Process.GetCurrentProcess().MainWindowHandle(这可能导致窗体和控制台窗口之间的竞争),在调用 AllocConsole() 之后,通过调用GetConsoleWindow()获取控制台窗口句柄 -
我认为 GetConsoleWindow() 只适用于 XP,我希望它即使在非 XP OS 环境中也能工作。
-
我无法在我的系统(Win7 64 位)上进行复制。这确实支持了 Boo 关于比赛条件的建议。虽然我不明白为什么控制台会成为进程的主窗口。
标签: c# winforms winforms-interop