控制台应用程序鼠标单击 XY 坐标检测/比较

发布于 2024-08-15 11:01:26 字数 276 浏览 3 评论 0原文

我正在 C# 控制台应用程序中开发一款游戏,纯粹是作为使用更好方法之前的练习。与使用诸如内置按钮功能的 Windows 窗体应用程序之类的东西相反,我努力抓住光标位置(我知道如何做)并将其与控制台应用程序内定义的多个区域进行比较也许是像素位置,但我也不知道除了像素之外是否还有某种内置的空间单位(最后一位是我无法计算的部分)。

PS我知道这是一般性的,没有提供任何代码,但我不觉得有必要,因为我所要求的只是简要解释如何在控制台应用程序中获取 XY 坐标,并将它们粘贴到 int 中变量。

非常感谢! :D

I have a game that I am working on in a C# console application, purely as practice before going on to better methods. As opposed to using something such as a Windows Forms App, which has button functionality built in, I am endeavoring to grab the cursor position (which I know how to do) and compare it to a number of area's inside a console application as defined by perhaps pixel location, but I also do not know if there is some sort of built in unit of space other than pixels (this last bit is the part I am unable to figure).

P.S. I know this is in general terms, with no code already provided, but I do not feel that it is needed as all I am asking for is a brief explanation of how to grab X Y coordinates inside a console application, and stick them in int variables.

Many Thanks in advance! :D

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

So尛奶瓶 2024-08-22 11:01:26

经过很长时间的搜索,我终于找到了这个例子。下载页面上的示例程序。除其他外,它还为您提供控制台窗口中的鼠标位置(基于字符)。

编辑:这是我的ConsoleListener类(包含我的NativeMethods类的一部分)。
您可以将处理程序附加到 MouseEvent(调用 Start() 方法之后)。

using System;
using System.Runtime.InteropServices;
using System.Threading;
using static ConsoleLib.NativeMethods;

namespace ConsoleLib
{
    public static class ConsoleListener
    {
        public static event ConsoleMouseEvent MouseEvent;

        public static event ConsoleKeyEvent KeyEvent;

        public static event ConsoleWindowBufferSizeEvent WindowBufferSizeEvent;

        private static bool Run = false;


        public static void Start()
        {
            if (!Run)
            {
                Run = true;
                IntPtr handleIn = GetStdHandle(STD_INPUT_HANDLE);
                new Thread(() =>
                {
                    while (true)
                    {
                        uint numRead = 0;
                        INPUT_RECORD[] record = new INPUT_RECORD[1];
                        record[0] = new INPUT_RECORD();
                        ReadConsoleInput(handleIn, record, 1, ref numRead);
                        if (Run)
                            switch (record[0].EventType)
                            {
                                case INPUT_RECORD.MOUSE_EVENT:
                                    MouseEvent?.Invoke(record[0].MouseEvent);
                                    break;
                                case INPUT_RECORD.KEY_EVENT:
                                    KeyEvent?.Invoke(record[0].KeyEvent);
                                    break;
                                case INPUT_RECORD.WINDOW_BUFFER_SIZE_EVENT:
                                    WindowBufferSizeEvent?.Invoke(record[0].WindowBufferSizeEvent);
                                    break;
                            }
                        else
                        {
                            uint numWritten = 0;
                            WriteConsoleInput(handleIn, record, 1, ref numWritten);
                            return;
                        }
                    }
                }).Start();
            }
        }

        public static void Stop() => Run = false;


        public delegate void ConsoleMouseEvent(MOUSE_EVENT_RECORD r);

        public delegate void ConsoleKeyEvent(KEY_EVENT_RECORD r);

        public delegate void ConsoleWindowBufferSizeEvent(WINDOW_BUFFER_SIZE_RECORD r);

    }


    public static class NativeMethods
    {
        public struct COORD
        {
            public short X;
            public short Y;

            public COORD(short x, short y)
            {
                X = x;
                Y = y;
            }
        }

        [StructLayout(LayoutKind.Explicit)]
        public struct INPUT_RECORD
        {
            public const ushort KEY_EVENT = 0x0001,
                MOUSE_EVENT = 0x0002,
                WINDOW_BUFFER_SIZE_EVENT = 0x0004; //more

            [FieldOffset(0)]
            public ushort EventType;
            [FieldOffset(4)]
            public KEY_EVENT_RECORD KeyEvent;
            [FieldOffset(4)]
            public MOUSE_EVENT_RECORD MouseEvent;
            [FieldOffset(4)]
            public WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;
            /*
            and:
             MENU_EVENT_RECORD MenuEvent;
             FOCUS_EVENT_RECORD FocusEvent;
             */
        }

        public struct MOUSE_EVENT_RECORD
        {
            public COORD dwMousePosition;

            public const uint FROM_LEFT_1ST_BUTTON_PRESSED = 0x0001,
                FROM_LEFT_2ND_BUTTON_PRESSED = 0x0004,
                FROM_LEFT_3RD_BUTTON_PRESSED = 0x0008,
                FROM_LEFT_4TH_BUTTON_PRESSED = 0x0010,
                RIGHTMOST_BUTTON_PRESSED = 0x0002;
            public uint dwButtonState;

            public const int CAPSLOCK_ON = 0x0080,
                ENHANCED_KEY = 0x0100,
                LEFT_ALT_PRESSED = 0x0002,
                LEFT_CTRL_PRESSED = 0x0008,
                NUMLOCK_ON = 0x0020,
                RIGHT_ALT_PRESSED = 0x0001,
                RIGHT_CTRL_PRESSED = 0x0004,
                SCROLLLOCK_ON = 0x0040,
                SHIFT_PRESSED = 0x0010;
            public uint dwControlKeyState;

            public const int DOUBLE_CLICK = 0x0002,
                MOUSE_HWHEELED = 0x0008,
                MOUSE_MOVED = 0x0001,
                MOUSE_WHEELED = 0x0004;
            public uint dwEventFlags;
        }

        [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)]
        public struct KEY_EVENT_RECORD
        {
            [FieldOffset(0)]
            public bool bKeyDown;
            [FieldOffset(4)]
            public ushort wRepeatCount;
            [FieldOffset(6)]
            public ushort wVirtualKeyCode;
            [FieldOffset(8)]
            public ushort wVirtualScanCode;
            [FieldOffset(10)]
            public char UnicodeChar;
            [FieldOffset(10)]
            public byte AsciiChar;

            public const int CAPSLOCK_ON = 0x0080,
                ENHANCED_KEY = 0x0100,
                LEFT_ALT_PRESSED = 0x0002,
                LEFT_CTRL_PRESSED = 0x0008,
                NUMLOCK_ON = 0x0020,
                RIGHT_ALT_PRESSED = 0x0001,
                RIGHT_CTRL_PRESSED = 0x0004,
                SCROLLLOCK_ON = 0x0040,
                SHIFT_PRESSED = 0x0010;
            [FieldOffset(12)]
            public uint dwControlKeyState;
        }

        public struct WINDOW_BUFFER_SIZE_RECORD
        {
            public COORD dwSize;
        }

        public const uint STD_INPUT_HANDLE = unchecked((uint)-10),
            STD_OUTPUT_HANDLE = unchecked((uint)-11),
            STD_ERROR_HANDLE = unchecked((uint)-12);

        [DllImport("kernel32.dll")]
        public static extern IntPtr GetStdHandle(uint nStdHandle);


        public const uint ENABLE_MOUSE_INPUT = 0x0010,
            ENABLE_QUICK_EDIT_MODE = 0x0040,
            ENABLE_EXTENDED_FLAGS = 0x0080,
            ENABLE_ECHO_INPUT = 0x0004,
            ENABLE_WINDOW_INPUT = 0x0008; //more

        [DllImportAttribute("kernel32.dll")]
        public static extern bool GetConsoleMode(IntPtr hConsoleInput, ref uint lpMode);

        [DllImportAttribute("kernel32.dll")]
        public static extern bool SetConsoleMode(IntPtr hConsoleInput, uint dwMode);


        [DllImportAttribute("kernel32.dll", CharSet = CharSet.Unicode)]
        public static extern bool ReadConsoleInput(IntPtr hConsoleInput, [Out] INPUT_RECORD[] lpBuffer, uint nLength, ref uint lpNumberOfEventsRead);

        [DllImportAttribute("kernel32.dll", CharSet = CharSet.Unicode)]
        public static extern bool WriteConsoleInput(IntPtr hConsoleInput, INPUT_RECORD[] lpBuffer, uint nLength, ref uint lpNumberOfEventsWritten);

    }
}

为了使其正常工作,您可能需要首先执行此代码:

IntPtr inHandle = GetStdHandle(STD_INPUT_HANDLE);
uint mode = 0;
GetConsoleMode(inHandle, ref mode);
mode &= ~ENABLE_QUICK_EDIT_MODE; //disable
mode |= ENABLE_WINDOW_INPUT; //enable (if you want)
mode |= ENABLE_MOUSE_INPUT; //enable
SetConsoleMode(inHandle, mode);

使用此文件头:

using System;
using static ConsoleLib.NativeMethods;

After searching for a long time I finally found this example. Download the example program on the page. It gives you, among other things, the mouse location in the console window (character-based).

EDIT: This is my ConsoleListener class (with part of my NativeMethods class).
You can attach a handler to the MouseEvent (after calling the Start() method).

using System;
using System.Runtime.InteropServices;
using System.Threading;
using static ConsoleLib.NativeMethods;

namespace ConsoleLib
{
    public static class ConsoleListener
    {
        public static event ConsoleMouseEvent MouseEvent;

        public static event ConsoleKeyEvent KeyEvent;

        public static event ConsoleWindowBufferSizeEvent WindowBufferSizeEvent;

        private static bool Run = false;


        public static void Start()
        {
            if (!Run)
            {
                Run = true;
                IntPtr handleIn = GetStdHandle(STD_INPUT_HANDLE);
                new Thread(() =>
                {
                    while (true)
                    {
                        uint numRead = 0;
                        INPUT_RECORD[] record = new INPUT_RECORD[1];
                        record[0] = new INPUT_RECORD();
                        ReadConsoleInput(handleIn, record, 1, ref numRead);
                        if (Run)
                            switch (record[0].EventType)
                            {
                                case INPUT_RECORD.MOUSE_EVENT:
                                    MouseEvent?.Invoke(record[0].MouseEvent);
                                    break;
                                case INPUT_RECORD.KEY_EVENT:
                                    KeyEvent?.Invoke(record[0].KeyEvent);
                                    break;
                                case INPUT_RECORD.WINDOW_BUFFER_SIZE_EVENT:
                                    WindowBufferSizeEvent?.Invoke(record[0].WindowBufferSizeEvent);
                                    break;
                            }
                        else
                        {
                            uint numWritten = 0;
                            WriteConsoleInput(handleIn, record, 1, ref numWritten);
                            return;
                        }
                    }
                }).Start();
            }
        }

        public static void Stop() => Run = false;


        public delegate void ConsoleMouseEvent(MOUSE_EVENT_RECORD r);

        public delegate void ConsoleKeyEvent(KEY_EVENT_RECORD r);

        public delegate void ConsoleWindowBufferSizeEvent(WINDOW_BUFFER_SIZE_RECORD r);

    }


    public static class NativeMethods
    {
        public struct COORD
        {
            public short X;
            public short Y;

            public COORD(short x, short y)
            {
                X = x;
                Y = y;
            }
        }

        [StructLayout(LayoutKind.Explicit)]
        public struct INPUT_RECORD
        {
            public const ushort KEY_EVENT = 0x0001,
                MOUSE_EVENT = 0x0002,
                WINDOW_BUFFER_SIZE_EVENT = 0x0004; //more

            [FieldOffset(0)]
            public ushort EventType;
            [FieldOffset(4)]
            public KEY_EVENT_RECORD KeyEvent;
            [FieldOffset(4)]
            public MOUSE_EVENT_RECORD MouseEvent;
            [FieldOffset(4)]
            public WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;
            /*
            and:
             MENU_EVENT_RECORD MenuEvent;
             FOCUS_EVENT_RECORD FocusEvent;
             */
        }

        public struct MOUSE_EVENT_RECORD
        {
            public COORD dwMousePosition;

            public const uint FROM_LEFT_1ST_BUTTON_PRESSED = 0x0001,
                FROM_LEFT_2ND_BUTTON_PRESSED = 0x0004,
                FROM_LEFT_3RD_BUTTON_PRESSED = 0x0008,
                FROM_LEFT_4TH_BUTTON_PRESSED = 0x0010,
                RIGHTMOST_BUTTON_PRESSED = 0x0002;
            public uint dwButtonState;

            public const int CAPSLOCK_ON = 0x0080,
                ENHANCED_KEY = 0x0100,
                LEFT_ALT_PRESSED = 0x0002,
                LEFT_CTRL_PRESSED = 0x0008,
                NUMLOCK_ON = 0x0020,
                RIGHT_ALT_PRESSED = 0x0001,
                RIGHT_CTRL_PRESSED = 0x0004,
                SCROLLLOCK_ON = 0x0040,
                SHIFT_PRESSED = 0x0010;
            public uint dwControlKeyState;

            public const int DOUBLE_CLICK = 0x0002,
                MOUSE_HWHEELED = 0x0008,
                MOUSE_MOVED = 0x0001,
                MOUSE_WHEELED = 0x0004;
            public uint dwEventFlags;
        }

        [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)]
        public struct KEY_EVENT_RECORD
        {
            [FieldOffset(0)]
            public bool bKeyDown;
            [FieldOffset(4)]
            public ushort wRepeatCount;
            [FieldOffset(6)]
            public ushort wVirtualKeyCode;
            [FieldOffset(8)]
            public ushort wVirtualScanCode;
            [FieldOffset(10)]
            public char UnicodeChar;
            [FieldOffset(10)]
            public byte AsciiChar;

            public const int CAPSLOCK_ON = 0x0080,
                ENHANCED_KEY = 0x0100,
                LEFT_ALT_PRESSED = 0x0002,
                LEFT_CTRL_PRESSED = 0x0008,
                NUMLOCK_ON = 0x0020,
                RIGHT_ALT_PRESSED = 0x0001,
                RIGHT_CTRL_PRESSED = 0x0004,
                SCROLLLOCK_ON = 0x0040,
                SHIFT_PRESSED = 0x0010;
            [FieldOffset(12)]
            public uint dwControlKeyState;
        }

        public struct WINDOW_BUFFER_SIZE_RECORD
        {
            public COORD dwSize;
        }

        public const uint STD_INPUT_HANDLE = unchecked((uint)-10),
            STD_OUTPUT_HANDLE = unchecked((uint)-11),
            STD_ERROR_HANDLE = unchecked((uint)-12);

        [DllImport("kernel32.dll")]
        public static extern IntPtr GetStdHandle(uint nStdHandle);


        public const uint ENABLE_MOUSE_INPUT = 0x0010,
            ENABLE_QUICK_EDIT_MODE = 0x0040,
            ENABLE_EXTENDED_FLAGS = 0x0080,
            ENABLE_ECHO_INPUT = 0x0004,
            ENABLE_WINDOW_INPUT = 0x0008; //more

        [DllImportAttribute("kernel32.dll")]
        public static extern bool GetConsoleMode(IntPtr hConsoleInput, ref uint lpMode);

        [DllImportAttribute("kernel32.dll")]
        public static extern bool SetConsoleMode(IntPtr hConsoleInput, uint dwMode);


        [DllImportAttribute("kernel32.dll", CharSet = CharSet.Unicode)]
        public static extern bool ReadConsoleInput(IntPtr hConsoleInput, [Out] INPUT_RECORD[] lpBuffer, uint nLength, ref uint lpNumberOfEventsRead);

        [DllImportAttribute("kernel32.dll", CharSet = CharSet.Unicode)]
        public static extern bool WriteConsoleInput(IntPtr hConsoleInput, INPUT_RECORD[] lpBuffer, uint nLength, ref uint lpNumberOfEventsWritten);

    }
}

To make it work properly, you probably want to execute this code first:

IntPtr inHandle = GetStdHandle(STD_INPUT_HANDLE);
uint mode = 0;
GetConsoleMode(inHandle, ref mode);
mode &= ~ENABLE_QUICK_EDIT_MODE; //disable
mode |= ENABLE_WINDOW_INPUT; //enable (if you want)
mode |= ENABLE_MOUSE_INPUT; //enable
SetConsoleMode(inHandle, mode);

With this file header:

using System;
using static ConsoleLib.NativeMethods;
静水深流 2024-08-22 11:01:26

此外,控制台不仅仅用于文本处理。你可以为它编写相当不错的窗口管理器。你可以用它做任何事情。只是更难了。

不过速度比较慢。
我使用 C# 实现了一个虚拟机,使用用户界面的控制台。它不会逐行打印文本;而是逐行打印文本。它[界面]的作用很像GUI。

如果你想在控制台上使用鼠标输入,请尝试这个钩子:
链接

Also, the console isn't just for text processing. You can write pretty decent window managers for it. You can do anything with it. It's just harder.

It's slower, though.
I implemented a virtual machine in C# using the console for the user interface. It doesn't print lines of text one after the other; it [the interface] acts rather like a GUI.

If you want mouse input on the console, try this hook:
Link

妖妓 2024-08-22 11:01:26

当您在不使用事件的情况下编写游戏时……您实际上是在自己实现事件。这是有利的,因为与使用语言的内置事件相比,您可以使其更加高效。如果您知道自己在做什么,以这种方式编写的游戏就不太容易出错。

例如,当我试图教我的兄弟如何编写游戏时,我为他编写了一个简单的贪吃蛇游戏。我在一个线程中有主循环,移动蛇并将其绘制在循环中的新位置。我会同时运行一个线程,连续检查 4 件事:

  1. 如果蛇撞到了自己(游戏结束);如果游戏结束,则停止更新蛇主位置的主线程,将游戏打印到屏幕上,等待按键输入,然后重新启动游戏。

  2. 如果蛇吃了一个苹果;增加表示已经吃掉了多少个苹果的计数器变量,并在屏幕上打印这个新值,覆盖之前的值。

  3. 可被 10 整除的苹果数量(蛇增长了 1 个细胞,从等待变量中减去,该变量表示蛇每次运动之间应该经过多长时间)

  4. 如果按下箭头键。如果向左,则将移动设置为 0,如果向右,则设置移动为 1,如果向下,则设置移动为 2,如果向上,则设置移动为 3。 存储的 int 是指向使蛇移动的 4 个委托的数组的指针朝正确的方向。

更新蛇位置的主循环将告诉线程检查这 4 件事蛇正在做什么。我这样做的方法是让蛇头移动的屏幕上的每个单元格都引用二维代表数组。关于这组代表:

游戏是在控制台模式下编写的,并使用控制台颜色。控制台设置为 80x50 字符。委托如下:“delegate void ptr()”;然后我使用以下命令创建数组:
“ptr[,] pos = 新 ptr[80,50]”。假设蛇的头部位于屏幕上的位置 (4,5),当它移动到那里后,主循环将执行“pos[4,5].Invoke();”。

其中之一:
当蛇移动到新位置时,主循环线程将获取蛇在屏幕上覆盖的每个单元格,并将该位置的委托设置为指向名为“void gameover()”的函数,该函数将设置 gameover_ 变量为真。因此,当检查游戏状态的循环线程检查游戏结束时,它会冻结游戏并在屏幕上打印游戏结束。

其他:
当在屏幕上绘制一个苹果时,它被绘制的委托位置(随机的)被设置为指向“voidincrement_apple()”,它会增加苹果计数器,从视图中删除当前的苹果,并绘制一个新的苹果在屏幕上,将旧苹果位置设置为指向“void nop()”,该位置不执行任何操作,并将新苹果位置指向“voidincrement_apple()”。

这基本上就是游戏的运作方式。正如您所看到的,蛇移动到屏幕上的这些位置,并且它没有执行任何显式检查,例如“if(snake_position == some_position)”,游戏会自动为游戏中发生的所有事情执行它应该执行的所有操作,就像当您单击表单上的按钮时,分配给该事件的操作会自动执行,而无需您自己检查该事件。

所以你看,我本可以使用 C# 提供的表单和默认事件,但我没有。我使用控制台界面,并实现了我自己的事件系统。

这就是它在幕后的工作原理:
表单应用程序的主循环将在一个线程中运行,该线程检查屏幕上所有按钮等的输入。这些项目中的每一个都会将它们使用的布尔变量设置为 true。当您单击此按钮时,另一个运行循环的线程会检查您按下的内容,并假设您按下了一个名为“button1”的按钮,该按钮将分配有一个委托;然后,该委托将执行它所指向的任何内容。

有点难以解释,但这对你来说有意义吗?

When you write a game without using events... all you are really doing it implementing events yourself. This is advantageous because you can make it much more efficient than by using your language's built-in events. Games written this way are less error-prone if you know what you are doing.

For example, when I was trying to teach my brother how games are written, I wrote a simple snake game for him. I had the main loop in a thread, move the snake and draw it at its new position in a cycle. I would have a thread running at the same time that continuously checks 4 things:

  1. If the snake crashed into itself (game over); if game over occurs, halt the main thread that updates the main position of the snake, print game over onto the screen, await key input, then restart the game.

  2. If the snake had eaten an apple; increment the counter variable that says how many apples have been eaten, and print this new value on the screen, over-writing what was previously there.

  3. If the snake had eaten a number of apples divisible by 10 (snake grows by 1 cell, subtract from a wait variable that says how much time should pass between each movement the snake makes)

  4. If an arrow key has been pressed. If left, set move to 0, if right set move to 1, if down set move to 2, if up set move to 3. The int that this is stored in is a pointer to an array of 4 delegates that make the snake move in the right direction.

The main loop that updates the position of the snake would tell the thread checking these 4 things what the snake is doing. The way I do this is I have every cell on the screen that the snake's head moves to refer to a 2-dimensional array of delegates. About this array of delegates:

The game is written in console mode, and uses console colours. The console is set to 80x50 characters. A delegate as follows: "delegate void ptr()"; then I create the array with:
"ptr[,] pos = new ptr[80,50]". Say the snake's head is at position (4,5) on the screen, after it has moved there the main loop would execute "pos[4,5].Invoke();".

One of them:
When the snake moves to a new position, the main loop thread would get each cell that the snake covers on the screen, and set the delegate at that position to point to a function called "void gameover()" which would set the gameover_ variable to true. So when the loop thread that checks the status of the game checks for gameover, it freezes the game and prints game over on the screen.

Another:
When an apple is drawn on the screen, the delegate position it gets drawn at (which is randomized) is set to point to "void increment_apple()" which increments the apple counter, removes the current apple from view, and draws a new apple on the screen, setting the old apple position to point to a "void nop()" which does nothing, and the new apple position to point to "void increment_apple()".

This is basically how the game works. As you can see, the snake moves to these positions on the screen, and it without performing any explicit checks like "if(snake_position == some_position)", the game automatically does everything it is supposed to for everything that happens in the game, much like how when you click a button on a form, an action assigned to that event is automatically executed, without you having to check for the event yourself.

So you see, I could have used a form and the default events that C# provides, but I didn't. I used the console interface, and implemented my own events system.

This is how it works behind the scenes:
the main loop for your form app will run in a thread that checks for input from all the buttons, etc on the screen. Each of these items will set a boolean variable they use to true. When you click this button, another thread running a loop checks what you have pressed, and say you pressed a button called "button1", that button would have had a delegate assigned to it; that delegate is then executed with whatever it points to.

Kind of hard to explain, but does this make sense to you?

泪意 2024-08-22 11:01:26

我知道这是不久前的事,但在控制台中获取鼠标位置并不难。我只会向您展示我使用的代码,以防其他人想要答案:

public static class Input
{
    [DllImport("user32.dll")]
    static extern bool GetCursorPos(out POINT point);

    struct POINT
    {
        public int x;
        public int y;
    }
    public static POINT GetMousePosition()
    {
        POINT pos;
        GetCursorPos(out pos);
        return pos;
    }
}

享受!

编辑:
我刚刚想出了一种简单的方法来获得鼠标点击(这也适用于键盘按钮,只需参考 https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes?redirectedfrom=MSDN你需要什么

[DllImport("user32.dll")]
public static extern bool GetAsyncKeyState(int button);
public static bool IsMouseButtonPressed(MouseButton button)
{
    return GetAsyncKeyState((int)button);
}
public enum MouseButton
{
    LeftMouseButton = 0x01,
    RightMouseButton = 0x02,
    MiddleMouseButton = 0x04,
}

I know this is a while ago, but it's not super hard to get the mouse position in the Console. I'll just show you the code I use in case someone else wants an answer:

public static class Input
{
    [DllImport("user32.dll")]
    static extern bool GetCursorPos(out POINT point);

    struct POINT
    {
        public int x;
        public int y;
    }
    public static POINT GetMousePosition()
    {
        POINT pos;
        GetCursorPos(out pos);
        return pos;
    }
}

Enjoy!

Edit:
I just figured out a simple way to get mouse clicks as well (this also works with keyboard buttons, just refer to https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes?redirectedfrom=MSDN for what you need

[DllImport("user32.dll")]
public static extern bool GetAsyncKeyState(int button);
public static bool IsMouseButtonPressed(MouseButton button)
{
    return GetAsyncKeyState((int)button);
}
public enum MouseButton
{
    LeftMouseButton = 0x01,
    RightMouseButton = 0x02,
    MiddleMouseButton = 0x04,
}
乙白 2024-08-22 11:01:26

@Frank Krueger 说的话。你真的想这样做吗? Windows 窗体旨在使此过程变得更加容易。

如果这样做,您将需要在低级 Windows API 中使用 PInvoke。尝试作为起点 - 但请注意这比 Windows 窗体应用程序要复杂得多。

What @Frank Krueger said. Do you really want to do this? Windows Forms is designed to make this much easier.

If you do, you'll need to use PInvoke into the low level Windows API. Try this as a starting point - but be aware that this is considerably more complex than the Windows Forms application would be.

最笨的告白 2024-08-22 11:01:26

经过大量研究,我找到了解决方案。

使用 Button 类和我在下面创建的 GUI,可以制作一个按钮,并用鼠标单击它(它不能完美工作)。
并且您需要导入System.Windows.FormsSystem.Drawing

After much studying, I found a solution.

With the Button class and the GUI that I created below, it is possible to make a button, and it is clicked with or mouse (it does not work perfectly).
And you need to import System.Windows.Forms and System.Drawing.

白衬杉格子梦 2024-08-22 11:01:26
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Traingames.NetElements;
//using System.Windows.Forms;
using System.Drawing;

namespace ConsoleTools.NET
{
    class Program
    {
        static ConsoleFramework c = new ConsoleFramework();
        static public Point MousePos;
        static Button One = new Button();
        static Pixel Mouse = new Pixel();

        static void Main(string[] args)
        {
            Console.ForegroundColor = ConsoleColor.White;
            // t.Draw(10, 40, ConsoleColor.Gray);
            One.Set(0, 10, "░░1░░", ConsoleColor.Gray);

            GUI.Add(One);
            GUI.CalculateOnStart();
            for (;;)
            {
                MousePos = new Point(System.Windows.Forms.Control.MousePosition.X / (Console.LargestWindowWidth / 24), System.Windows.Forms.Control.MousePosition.Y / (Console.LargestWindowHeight / 7));
                if (One.Pressed(MousePos))
                {
                    Console.Write("1");
                }
                //   Console.Clear();
            }
        }
    }
    }

    namespace Traingames.NetElements
    {
        public class ConsoleFramework
        {
        public char[] chars = { '█', '▓', '▒', '░' };

        Point MousePos()
        {
            return new Point((System.Windows.Forms.Control.MousePosition.X / (Console.LargestWindowWidth / 24)) - 100, System.Windows.Forms.Control.MousePosition.Y / (Console.LargestWindowHeight / 7));
        }

        public void SetPixel(int x, int Y, ConsoleColor color)
        {
            int y = (int)Math.Floor(Y / 1.5f);

            for (int i = 0; i < y; i++)
            {
                Console.WriteLine("");
            }

            for (int i = 0; i < x - 1; i++)
            {
                Console.Write(" ");
            }
            Console.BackgroundColor = color;
            Console.Write(" ");
            Console.BackgroundColor = ConsoleColor.Black;
        }
    }

    public class Pixel : GUI
    {
        public void Set(int X, int Y, string text)
        {
            ConsoleColor backColor = ConsoleColor.Black;
            BackColor = backColor;
            int yyyyyy = (int)Math.Floor(Y / 1.5f);
            Text = text;
            y = Y;
            x = X;
        }
    }

    public class GUI
    {
        public int x, y;
        public static GUI[,] GraphicalUserInterfaces = new GUI[1000, 1000];
        public ConsoleColor BackColor;
        public string Text;

        public void Draw()
        {
            int X = x;
            int Y = y;
            ConsoleColor backColor = BackColor;
            string text = Text;


            for (int i = 0; i < y; i++)
            {
                Console.WriteLine("");
            }

            for (int i = 0; i < x - 1; i++)
            {
                Console.Write(" ");
            }
            Console.BackgroundColor = BackColor;
            Console.Write("[" + text + "]");
            Console.BackgroundColor = ConsoleColor.Black;
            Point M = ConsoleTools.NET.Program.MousePos;

            // return M.X >= xx && M.X <= (xx + Text.Length + 1) && M.Y >= yy && M.Y <= yy + 2 && Control.MouseButtons == MouseButtons.Left;
        }
        static GUI Last;
        public static void Add(GUI gui)
        {
            GraphicalUserInterfaces[gui.x, gui.y] = gui;
        }

        public static void CalculateOnStart()
        {
            for (int x = 0; x < 1000; x++)
            {
                for (int y = 0; y < 1000; y++)
                {
                    if (GraphicalUserInterfaces[x, y] != null)
                    {

                        if (Last != null && y < Last.y)
                        {
                            GraphicalUserInterfaces[x, y].x = Last.x - GraphicalUserInterfaces[x, y].x;
                            GraphicalUserInterfaces[x, y].y = Last.y - GraphicalUserInterfaces[x, y].y;
                        }
                        GraphicalUserInterfaces[x, y].Draw();
                        GraphicalUserInterfaces[x, y].x = x;
                        GraphicalUserInterfaces[x, y].y = y;
                        Last = GraphicalUserInterfaces[x, y];
                    }

                }
            }
        }

    }

    public class Button : GUI
    {

        public bool Over(Point M)
        {
            int yy = ((y * 2) - y / 3) + 2;

            int xx = (x / (Console.LargestWindowWidth / 24)) + Text.Length;

            if (M.X >= xx && M.X <= (xx + Text.Length + 1) && M.Y >= yy && M.Y <= yy + 2)
                Console.BackgroundColor = ConsoleColor.DarkBlue;

            return M.X >= xx && M.X <= (xx + Text.Length + 1) && M.Y >= yy && M.Y <= yy + 2;
        }

        public bool Pressed(Point M)
        {
            int yy = ((y * 2) - y / 3) + 1;

            int xx = (x / (Console.LargestWindowWidth / 24));

            return M.X >= xx && M.X <= (xx + Text.Length * 1.5f) && M.Y >= yy && M.Y <= yy + 2 && System.Windows.Forms.Control.MouseButtons == System.Windows.Forms.MouseButtons.Left;
        }

        public void CalculateClick(Point M)
        {
            if (Pressed(M))
            {
                Console.Clear();
                Draw();
            }
        }

        public void Set(int X, int Y, string text, ConsoleColor backColor)
        {
            BackColor = backColor;
            int yyyyyy = (int)Math.Floor(Y / 1.5f);
            Text = text;
            y = Y;
            x = X;

            int xx = (x / (Console.LargestWindowWidth / 24)) + Text.Length;
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Traingames.NetElements;
//using System.Windows.Forms;
using System.Drawing;

namespace ConsoleTools.NET
{
    class Program
    {
        static ConsoleFramework c = new ConsoleFramework();
        static public Point MousePos;
        static Button One = new Button();
        static Pixel Mouse = new Pixel();

        static void Main(string[] args)
        {
            Console.ForegroundColor = ConsoleColor.White;
            // t.Draw(10, 40, ConsoleColor.Gray);
            One.Set(0, 10, "░░1░░", ConsoleColor.Gray);

            GUI.Add(One);
            GUI.CalculateOnStart();
            for (;;)
            {
                MousePos = new Point(System.Windows.Forms.Control.MousePosition.X / (Console.LargestWindowWidth / 24), System.Windows.Forms.Control.MousePosition.Y / (Console.LargestWindowHeight / 7));
                if (One.Pressed(MousePos))
                {
                    Console.Write("1");
                }
                //   Console.Clear();
            }
        }
    }
    }

    namespace Traingames.NetElements
    {
        public class ConsoleFramework
        {
        public char[] chars = { '█', '▓', '▒', '░' };

        Point MousePos()
        {
            return new Point((System.Windows.Forms.Control.MousePosition.X / (Console.LargestWindowWidth / 24)) - 100, System.Windows.Forms.Control.MousePosition.Y / (Console.LargestWindowHeight / 7));
        }

        public void SetPixel(int x, int Y, ConsoleColor color)
        {
            int y = (int)Math.Floor(Y / 1.5f);

            for (int i = 0; i < y; i++)
            {
                Console.WriteLine("");
            }

            for (int i = 0; i < x - 1; i++)
            {
                Console.Write(" ");
            }
            Console.BackgroundColor = color;
            Console.Write(" ");
            Console.BackgroundColor = ConsoleColor.Black;
        }
    }

    public class Pixel : GUI
    {
        public void Set(int X, int Y, string text)
        {
            ConsoleColor backColor = ConsoleColor.Black;
            BackColor = backColor;
            int yyyyyy = (int)Math.Floor(Y / 1.5f);
            Text = text;
            y = Y;
            x = X;
        }
    }

    public class GUI
    {
        public int x, y;
        public static GUI[,] GraphicalUserInterfaces = new GUI[1000, 1000];
        public ConsoleColor BackColor;
        public string Text;

        public void Draw()
        {
            int X = x;
            int Y = y;
            ConsoleColor backColor = BackColor;
            string text = Text;


            for (int i = 0; i < y; i++)
            {
                Console.WriteLine("");
            }

            for (int i = 0; i < x - 1; i++)
            {
                Console.Write(" ");
            }
            Console.BackgroundColor = BackColor;
            Console.Write("[" + text + "]");
            Console.BackgroundColor = ConsoleColor.Black;
            Point M = ConsoleTools.NET.Program.MousePos;

            // return M.X >= xx && M.X <= (xx + Text.Length + 1) && M.Y >= yy && M.Y <= yy + 2 && Control.MouseButtons == MouseButtons.Left;
        }
        static GUI Last;
        public static void Add(GUI gui)
        {
            GraphicalUserInterfaces[gui.x, gui.y] = gui;
        }

        public static void CalculateOnStart()
        {
            for (int x = 0; x < 1000; x++)
            {
                for (int y = 0; y < 1000; y++)
                {
                    if (GraphicalUserInterfaces[x, y] != null)
                    {

                        if (Last != null && y < Last.y)
                        {
                            GraphicalUserInterfaces[x, y].x = Last.x - GraphicalUserInterfaces[x, y].x;
                            GraphicalUserInterfaces[x, y].y = Last.y - GraphicalUserInterfaces[x, y].y;
                        }
                        GraphicalUserInterfaces[x, y].Draw();
                        GraphicalUserInterfaces[x, y].x = x;
                        GraphicalUserInterfaces[x, y].y = y;
                        Last = GraphicalUserInterfaces[x, y];
                    }

                }
            }
        }

    }

    public class Button : GUI
    {

        public bool Over(Point M)
        {
            int yy = ((y * 2) - y / 3) + 2;

            int xx = (x / (Console.LargestWindowWidth / 24)) + Text.Length;

            if (M.X >= xx && M.X <= (xx + Text.Length + 1) && M.Y >= yy && M.Y <= yy + 2)
                Console.BackgroundColor = ConsoleColor.DarkBlue;

            return M.X >= xx && M.X <= (xx + Text.Length + 1) && M.Y >= yy && M.Y <= yy + 2;
        }

        public bool Pressed(Point M)
        {
            int yy = ((y * 2) - y / 3) + 1;

            int xx = (x / (Console.LargestWindowWidth / 24));

            return M.X >= xx && M.X <= (xx + Text.Length * 1.5f) && M.Y >= yy && M.Y <= yy + 2 && System.Windows.Forms.Control.MouseButtons == System.Windows.Forms.MouseButtons.Left;
        }

        public void CalculateClick(Point M)
        {
            if (Pressed(M))
            {
                Console.Clear();
                Draw();
            }
        }

        public void Set(int X, int Y, string text, ConsoleColor backColor)
        {
            BackColor = backColor;
            int yyyyyy = (int)Math.Floor(Y / 1.5f);
            Text = text;
            y = Y;
            x = X;

            int xx = (x / (Console.LargestWindowWidth / 24)) + Text.Length;
        }
    }
}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文