[Easyx/纯控制台/Windows]三种方法检测鼠标是否离开程序窗口范围(顺带有gotoxy函数实现)

前言:

1.首先介绍的是使用easyx库获得窗口大小和窗口句柄,然后介绍控制台检测的方法,最后再来介绍win程序检测的方法。

2.函数中的getwidth()和getheight()两个函数是easyx库获得窗口大小的功能,可以被替换掉,后面有相应的修改后函数

方法:使用的时候传入要检测的窗口的句柄就能返回是否超出的结果

easyx样图(gif):
[Easyx/纯控制台/Windows]三种方法检测鼠标是否离开程序窗口范围(顺带有gotoxy函数实现)_第1张图片

函数如下:

bool CT_CheckOutWindow(HWND& hWnd) {//检测当前鼠标是否离开窗口所在范围,但无法检测窗口是否激活
	static POINT point;
	GetCursorPos(&point);		// 获取鼠标指针位置(屏幕坐标)
	ScreenToClient(hWnd, &point);	// 将鼠标指针位置转换为窗口坐标
	if (point.x<0 || point.y<0 || point.x>getwidth() || point.y>getheight())
		return 1;//超出
	return 0;//没超出
}

完整实例(easyx):

#include 
#include 
bool CT_CheckOutWindow(HWND& hWnd) {//检测当前鼠标是否离开窗口所在范围,但无法检测窗口是否激活
	static POINT point;
	GetCursorPos(&point);		// 获取鼠标指针位置(屏幕坐标)
	ScreenToClient(hWnd, &point);	// 将鼠标指针位置转换为窗口坐标
	if (point.x<0 || point.y<0 || point.x>getwidth() || point.y>getheight())
		return 1;//超出
	return 0;//没超出
}
int main() {
	HWND hWnd = initgraph(200, 200);
	while (!_kbhit()) {
		CT_CheckOutWindow(hWnd) ? outtextxy(0, 0, "超出范围") : outtextxy(0, 0, "没有超出范围");
		Sleep(50);
		cleardevice();
	}
}

那么,如何摆脱eaxy库,来检测鼠标是否脱离了呢?

Win程序获得句柄就很简单,CreateWindow函数创建窗口就可以获得句柄,窗口宽高由于是自己给的参数,也能通过简单的修改下函数就能检测。

唯独控制台就相对比较麻烦,不过也还是能做到的,首先可以使用如下代码获得控制台窗口句柄

	char ch[100];//用来存储获得的控制台标题
	GetConsoleTitle(ch, 100);//获得控制台标题,参数分别是,存储用的数组,和其大小
	HWND hWnd=FindWindow(NULL, ch);//根据标题名获得控制台窗口句柄

其次,稍微修改下函数

bool CT_CheckOutWindow(HWND& hWnd) {//检测当前鼠标是否离开窗口所在范围,但无法检测窗口是否激活
	static POINT point;
	static _CONSOLE_SCREEN_BUFFER_INFO p;
	static _CONSOLE_FONT_INFO fontp;
	GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &p);//主要拿来获取窗口大小(字符为单位)
	GetCurrentConsoleFont(GetStdHandle(STD_OUTPUT_HANDLE), 0, &fontp);//主要拿来获取字符大小
	//上面这两行代码各位可以丢外面去,这个每次都检测只是怕用户调整控制台大小导致出问题
	GetCursorPos(&point);		// 获取鼠标指针位置(屏幕坐标)
	ScreenToClient(hWnd, &point);	// 将鼠标指针位置转换为窗口坐标
	if (point.x<0 || point.y<0 || point.x>(p.dwSize.X)*(fontp.dwFontSize.X) || point.y>(p.dwSize.Y)*(fontp.dwFontSize.Y))
		return 1;//超出
	return 0;//没超出
}

最后,准备一个gotoxy函数来代替system(“cls”)功能

void gotoxy(int x, int y) {
	COORD pos;
	pos.X = x;
	pos.Y = y;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}

然后,开始!

完整实例(控制台):

#include 
#include 
#include 
using namespace std;
void gotoxy(int x, int y) {
	COORD pos;
	pos.X = x;
	pos.Y = y;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}
bool CT_CheckOutWindow(HWND& hWnd) {//检测当前鼠标是否离开窗口所在范围,但无法检测窗口是否激活
	static POINT point;
	static _CONSOLE_SCREEN_BUFFER_INFO p;
	static _CONSOLE_FONT_INFO fontp;
	GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &p);//主要拿来获取窗口大小(字符为单位)
	GetCurrentConsoleFont(GetStdHandle(STD_OUTPUT_HANDLE), 0, &fontp);//主要拿来获取字符大小
	//上面这两行代码个位可以丢外面
	GetCursorPos(&point);		// 获取鼠标指针位置(屏幕坐标)
	ScreenToClient(hWnd, &point);	// 将鼠标指针位置转换为窗口坐标
	if (point.x<0 || point.y<0 || point.x>(p.dwSize.X)*(fontp.dwFontSize.X) || point.y>(p.dwSize.Y)*(fontp.dwFontSize.Y))
		return 1;//超出
	return 0;//没超出
}
int main() {
	system("mode con cols=20 lines=5");//设置下大小
	char ch[100];
	GetConsoleTitle(ch, 100);
	HWND hWnd=FindWindow(NULL, ch);//完成获得句柄的操作
	while (!_kbhit()) {
		CT_CheckOutWindow(hWnd) ?  cout << "超出\n" : cout << "正常\n";
		Sleep(100);
		gotoxy(0, 0);//回到初始位置,即刷新
	}
}

实现后的效果:
[Easyx/纯控制台/Windows]三种方法检测鼠标是否离开程序窗口范围(顺带有gotoxy函数实现)_第2张图片

那么,最后,虽然说了下Win很简单,但是还是得放下代码的
那么这次就先放一个效果图在前边,让长长的Windows代码留在文章的最后作为结尾吧:)

[Easyx/纯控制台/Windows]三种方法检测鼠标是否离开程序窗口范围(顺带有gotoxy函数实现)_第3张图片
完整实例(Windows):

#include 
#define X (200)
#define Y (200)
bool CT_CheckOutWindow(HWND& hWnd) {//检测当前鼠标是否离开窗口所在范围,但无法检测窗口是否激活
	static POINT point;
	GetCursorPos(&point);		// 获取鼠标指针位置(屏幕坐标)
	ScreenToClient(hWnd, &point);	// 将鼠标指针位置转换为窗口坐标
	if (point.x<0 || point.y<0 || point.x>X || point.y>Y)
		return 1;//超出
	return 0;//没超出
}
LRESULT CALLBACK WindowProc(
	HWND hwnd,
	UINT uMsg,
	WPARAM wParam,
	LPARAM lParam
) {
	switch (uMsg) {
	case WM_CLOSE:
		DestroyWindow(hwnd);//发送一个消息WM_Destroy,表示毁灭窗口,但程序还在
	case WM_DESTROY:
		PostQuitMessage(0);//发送正常程序退出的消息
		break;
	case WM_PAINT://绘图
	{
		PAINTSTRUCT ps;//绘图结构体
		HDC hdc = BeginPaint(hwnd, &ps);
		if(CT_CheckOutWindow(hwnd))
		TextOut(hdc, 100, 100, TEXT("超出"), strlen("超出"));
		else
			TextOut(hdc, 100, 100, TEXT("正常"), strlen("正常"));
		EndPaint(hwnd, &ps);
		break;
	}
	}
	//返回值用默认处理函数
	return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
int WINAPI wWinMain(HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPWSTR    lpCmdLine,
	int       nCmdShow)
{
	WNDCLASS wc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wc.hCursor = LoadCursor(NULL, IDC_HAND);
	wc.hIcon = LoadIcon(NULL, IDI_HAND);
	wc.hInstance = hInstance;
	wc.lpfnWndProc = WindowProc;
	wc.lpszClassName = TEXT("WIN");
	wc.lpszMenuName = NULL;
	wc.style = 0;
	RegisterClass(&wc);
	HWND hwnd = CreateWindow(wc.lpszClassName, TEXT("WINDOWS"), wc.style, CW_USEDEFAULT, CW_USEDEFAULT, X, Y, NULL, NULL, hInstance, NULL);
	ShowWindow(hwnd, SW_SHOWNORMAL);
	UpdateWindow(hwnd);
	MSG msg;
	while (1) {
		if (GetMessage(&msg, NULL, 0, 0) == FALSE) {
			break;
		}
		//翻译消息
		TranslateMessage(&msg);
		//分发消息
		DispatchMessage(&msg);
		Sleep(20);
		InvalidateRect(hwnd, NULL, 1);//刷新
	}
	return 0;
}

好了,致此,本文就告一段落。

本文允许自由转载,但要写明出处,谢谢。

你可能感兴趣的:(原创,函数)