当前位置: 首页 > 编程语言 > C#

控制台应用程序鼠标点击XY坐标检测-比较分享

时间:2023-04-11 12:08:31 C#

控制台应用程序鼠标点击XY坐标检测/比较更好的方法。与使用内置按钮功能的Windows窗体应用程序相反,我试图获取光标位置(我知道该怎么做)并将其与控制台应用程序内的某个区域进行比较,如下所示:可能是像素位置,但是我也不知道是否有某种内置的空间单位而不是像素(最后一点是我无法想象的部分)。PS我知道这是一般性的,没有提供任何代码,但我觉得不需要它,因为我要的是简要说明如何在控制台应用程序中获取XY坐标并将它们粘贴到int变量中。先感谢您!:D@FrankKrueger说的。你真的要这样做吗?Windows窗体旨在使这更容易。如果这样做,您将需要对低级WindowsAPI使用PInvoke。尝试以此为起点-但请注意,这比Windows窗体应用程序复杂得多。找了半天,终于找到了这个例子。下载页面上的示例程序。除其他外,它还为您提供控制台窗口中的鼠标位置(基于字符)。编辑:这是我的ConsoleListener类(其中包含我的NativeMethods类的一部分)。您可以将处理程序附加到MouseEvent(在调用Start()方法之后)。使用系统;使用System.Runtime.InteropServices;使用系统线程;使用静态ConsoleLib.NativeMethods;namespaceConsoleLib{publicstaticclassConsoleListener{publicstaticeventConsoleMouseEventMouseEvent;公共静态事件ConsoleKeyEventKeyEvent;公共静态事件ConsoleWindowBufferSizeEventWindowBufferSizeEvent;私人静态布尔运行=假;publicstaticvoidStart(){if(!Run){Run=true;IntPtrhandleIn=GetStdHandle(STD_INPUT_HANDLE);newThread(()=>{while(true){uintnumRead=0;INPUT_RECORD[]record=newINPUT_RECORD[1];record[0]=newINPUT_RECORD();ReadConsoleInput(handleIn,record,1,refnumRead);if(Run)switch(record[0].EventType){caseINPUT_RECORD.MOUSE_EVENT:MouseEvent?.Invoke(record[0].MouseEvent);break;caseINPUT_RECORD.KEY_EVENT:KeyEvent?.Invoke(record[0].KeyEvent);break;caseINPUT_RECORD.WINDOW_BUFFER_SIZE_EVENT:WindowBufferSizeEvent?.Invoke(记录[0].WindowBufferSizeEve新台币);休息;}else{uintnumWritten=0;WriteConsoleInput(handleIn,record,1,refnumWritten);返回;}}})。开始();}}publicstaticvoidStop()=>Run=false;公共委托voidConsoleMouseEvent(MOUSE_EVENT_RECORDr);公共委托voidConsoleKeyEvent(KEY_EVENT_RECORDr);公共委托voidConsoleWindowBufferSizeEvent(WINDOW_BUFFER_SIZE_RECORDr);}publicstaticclassNativeMethods{publicstructCOORD{publicshortX;公开做空Y;公共坐标(短x,短y){X=x;Y=Y;}}[StructLayout(LayoutKind.Explicit)]publicstructINPUT_RECORD{publicconstushortKEY_EVENT=0x0001,MOUSE_EVENT=0x0002,WINDOW_BUFFER_SIZE_EVENT=0x0004;//更多[FieldOffset(0)]publicushortEventType;[FieldOffset(4)]publicKEY_EVENT_RECORDKeyEvent;[FieldOffset(4)]publicMOUSE_EVENT_RECORD鼠标事件;[FieldOffset(4)]publicWINDOW_BUFFER_SIZE_RECORDWindowBufferSizeEvent;/*和:MENU_EVENT_RECORDMenuEvent;FOCUS_EVENT_RECORD焦点我们的事件;*/}publicstructMOUSE_EVENT_RECORD{publicCOORDdwMousePosition;公共结构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;公共uintdwButtonState;publicconstintcapslock_on=0x0080,Enhanced_Key=0x0100,left_alt_presse=0x0002,left_ctrl_presse=0x0008,numlock_on=0x0020,right_alt_presse=0x0001,right_cttrl_presse=0x0004,scrolllock=0x0004,scrolllock_on=0x0040;公共uintdwControlKeyState;publicconstintDOUBLE_CLICK=0x0002,MOUSE_HWHEELED=0x0008,MOUSE_MOVED=0x0001,MOUSE_WHEELED=0x0004;publicuintdwEventFlags;}[StructLayout(LayoutKind.Explicit,CharSet=CharSet.Unicode)]publicstructKEY_EVENT_RECORD{[FieldOffset(0)]publicboolbKeyDown;[FieldOffset(4)]publicushortwRepeatCount;[FieldOffset(6)]publicushortwVirtualKeyCode;[斐ldOffset(8)]publicushortwVirtualScanCode;[FieldOffset(10)]publiccharUnicodeChar;[FieldOffset(10)]publicbyteAsciiChar;publicconstintcapslock_on=0x0080,Enhanced_Key=0x0100,left_alt_presse=0x0002,left_ctrl_presse=0x0008,numlock_on=0x0020,right_alt_presse=0x0001,right_cttrl_presse=0x0004,scrolllock=0x0004,scrolllock_on=0x0040;[FieldOffset(12)]publicuintdwControlKeyState;}publicstructWINDOW_BUFFER_SIZE_RECORD{publicCOORDdwSize;}publicconstuintSTD_INPUT_HANDLE=unchecked((uint)-10),STD_OUTPUT_HANDLE=unchecked((uint)-11),STD_ERROR_HANDLE=unchecked((uint)-12);[DllImport("kernel32.dll")]publicstaticexternIntPtrGetStdHandle(uintnStdHandle);publicconstuintENABLE_MOUSE_INPUT=0x0010,ENABLE_QUICK_EDIT_MODE=0x0040,ENABLE_EXTENDED_FLAGS=0x0080,ENABLE_ECHO_INPUT=0x0004,ENABLE_WINDOW_INPUT=0x0008;//更多[DllImportAttribute("kernel32.dll")]publicstaticexternboolGetConsoleMode(IntPtrhConsoleInput,refuintlpMode);[DllImportAttribute("kernel32.dll")]publicstaticexternboolSetConsoleMode(IntPtrhConsoleInput,uintdwMode);[DllImportAttribute("kernel32.dll",CharSet=CharubSet.Unicode)]publicstaticexternboolReadConsoleInput(IntPtrhConsoleInput,[Out]INPUT_RECORD[]lpBuffer,uintnLength,refuintlpNumberOfEventsRead);[DllImportAttribute("kernel32.dll",CharSet=CharSet.Unicode)]publicstaticexternboolWriteConsoleInput(IntPtrhConsoleInput,INPUT_RECORD[]lpBuffer,uintnLength,refuintlpNumberOfEventsWritten);为了让它工作,你可能想先执行这段代码:IntPtrinHandle=GetStdHandle(STD_INPUT_HANDLE);单位模式=0;GetConsoleMode(inHandle,ref模式);模式&=~ENABLE_QUICK_EDIT_MODE;//禁用模式|=ENABLE_WINDOW_INPUT;//启用(如果需要)模式|=ENABLE_MOUSE_INPUT;//启用SetConsoleMode(inHandle,mode);使用此标头:使用系统;使用静态ConsoleLib.NativeMethods;此外,控制台不仅用于文本处理您可以为它编写相当不错的窗口管理器。你可以用它做任何事情。这更难。但是比较慢。我使用UI的控制台在C#中实现了一个虚拟机。它不会一个接一个地打印文本行;它[界面]的行为类似于GUI。如果你想在控制台上进行鼠标输入,试试这个钩子:http://blogs.msdn.com/b/toub/archive/2006/05/03/589468.aspx?PageIndex=2#comments当你不在的时候使用事件编写游戏......你真正做的就是自己实现事件。这是有利的,因为您可以比使用语言的内置事件更有效率。如果您知道自己在做什么,以这种方式编写的游戏就不太容易出错。例如,当我试图教我弟弟写游戏时,我给他写了一个简单的贪吃蛇游戏。我在线程中有一个主循环,它移动蛇并将其绘制到循环中的新位置。我会同时运行一个线程,不断检查4件事:1)蛇是否撞到自己(游戏结束);如果游戏结束,停止更新蛇主位置的主线程,将游戏打印到屏幕,等待回车键,然后重新开始游戏。2)如果蛇吃了一个苹果;增加计数器变量,它表示已经吃掉了多少个苹果,并在屏幕上打印这个新值,覆盖以前的数据。3)如果蛇吃了一个能被10整除的苹果(蛇长出1个细胞,从表示蛇在每次移动之间经过多长时间的等待变量中减去)4)如果按下箭头键。如果向左,设置移动到0,如果向右设置移动到1,如果向下设置移动到2,如果向上设置移动到3。存储的int是指向4的数组的指针,表示蛇向右移动。更新蛇位置的主循环将告诉线程检查蛇在做什么这4件事。我这样做的方法是让屏幕上的每个单元格移动蛇的头以引用二维表示数组。关于此表示数组:游戏以控制台模式编写,并使用控制台颜色。控制台设置为80x50个字符。委托如下:“delegatevoidptr()”;然后我创建数组:“ptr[,]pos=newptr[80,50]”。假设蛇的头在屏幕上的位置(4,5),它移动后,主循环会执行“pos[4,5].Invoke();”。其中之一:当蛇移动到新位置时,主循环线程将获取屏幕上蛇覆盖的每个单元格,并将该委托设置为指向一个名为“voidgameover()”的函数,该函数将gameover_变量设置为设置为真。因此,当检查游戏状态的循环线程检查游戏时,它会冻结游戏并将游戏打印在屏幕上。另一个:当一个苹果被绘制在屏幕上时,它被绘制的代表性位置(随机)被设置为指向“voidincrement_apple()”,这增加了苹果计数器,从视图中移除当前的苹果,并绘制新的apple在屏幕上,将旧的苹果位置设置为指向“voidnop()”,什么也不做,并将新的苹果位置设置为指向“voidincrement_apple()”。这基本上就是游戏的运作方式。如你所见,蛇移动到屏幕上的这些位置,它不会执行任何明确的检查,如“if(snake_position==some_position)”,游戏会自动执行游戏中发生的所有事情,比如当你单击表单上的按钮,自动执行分配给该事件的操作,而无需您自己检查事件。所以你看,我可以使用C#提供的表单和默认事件,但我没有。我使用了控制台界面并实现了我自己的事件系统。以下是它在幕后的工作方式:表单应用程序的主循环将在一个线程中运行,该线程检查屏幕上所有按钮等的输入。这些项目中的每一个都将它们使用的布尔变量设置为true。单击此按钮时,运行循环中的另一个线程会检查您按下的内容,然后按下一个名为“button1”的按钮,该按钮为其分配一个委托;然后该委托将遵循它指向的任何内容来实现。有点难以解释,但它对你有意义吗?经过深入研究,我找到了解决方案。使用Button类和我创建的GUI,可以创建一个按钮并单击或鼠标(它不能完美地工作)。您需要导入System.Windows.Forms和System.Drawing。以上就是C#学习教程的全部内容:控制台应用鼠标点击XY坐标检测/对比分享。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注——usingSystem;使用系统。使用System.Linq;使用系统文本;使用System.Threading.Tasks;使用Traininggames.NetElements;//使用System.Windows.Forms;使用系统绘图;命名空间ConsoleTools.NET{类程序{staticConsoleFrameworkc=newConsoleFramework();静态公共点MousePos;静态按钮一=新按钮();静态像素鼠标=newPixel();staticvoidMain(string[]args){Console.ForegroundColor=ConsoleColor.White;//t.Draw(10,40,ConsoleColor.Gray);One.Set(0,10,"??1??",ConsoleColor.Gray);GUI.添加(一);GUI.CalculateOnStart();对于(;;){MousePos=newPoint(System.Windows.Forms.Control.MousePosition.X/(Console.LargestWindowWidth/24),System.Windows.Forms.Control.MousePosition.Y/(Console.LargestWindowHeight/7));if(One.Pressed(MousePos)){控制台。写("1");}//安慰。清除();}}}}命名空间eTraininggames.NetElements{publicclassConsoleFramework{publicchar[]chars={'█','↓','?','?'};PointMousePos(){returnnewPoint((System.Windows.Forms.Control.MousePosition.X/(Console.LargestWindowWidth/24))-100,System.Windows.Forms.Control.MousePosition.Y/(Console.LargestWindowHeight/7));}publicvoidSetPixel(intx,intY,ConsoleColorcolor){inty=(int)Math.Floor(Y/1.5f);for(inti=0;i=xx&&MX=yy&&MY=xx&&MX=yy&&MY=xx&&MX=yy&&MY=xx&&MX=yy&&MY本文收集自网络,不代表立场,如涉及侵权,请点右联系管理员删除,如需转载请注明出处:

最新推荐
猜你喜欢