📌 更新(2026-09-01):归档复测,只编译不运行——理由见正文,这玩意挂在那里,谁的鼠标一动就锁谁的屏。

这个程序要干的事,全写在它的名字里:不锁屏,防止被动鼠标。为什么又要不锁屏、又要防鼠标?因为电脑设成了从不自动锁屏——图的就是人离开一会儿、回来接着用,不用反复输密码。方便是真方便,可人不在的那段时间,屏幕就这么亮着,谁来都能动两下。这个程序就是给这份方便加的保险:把它挂在后台再走,期间只要有谁动了鼠标,屏幕立刻锁上——防的就是这一手。

实现思路一句话:盯住鼠标,谁动谁锁。整个程序的核心循环:

1
2
3
4
5
6
7
8
9
10
int main()
{
printf("开始计时\n");
while (1)
{
Sleep(100);
GetMouseLocation();
}
return 0;
}

每 100 毫秒查一次鼠标。查的逻辑在 GetMouseLocation 里:GetCursorPos 拿坐标,交给 isMouseMove 判断,一旦返回 false——也就是发现鼠标被动了——立刻锁屏退出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
bool isMouseMove(long long x, long long y)
{
if (flag)
{
if (x != iMouseX || y != iMouseY)
{
return false;
}
return true;
}
else
{
flag = true;
iMouseX = x;
iMouseY = y;
return true;
}
}

void LockScreen()
{
// system("python photo.py");
system("rundll32.exe user32.dll,LockWorkStation");
Sleep(100);
return;
}

这段代码最值得讲的是它的命名陷阱isMouseMove 听起来是”是否移动了鼠标”,但它的返回值语义其实是”鼠标没动,一切正常“——坐标没变返回 true,变了反而返回 false。调用方用一句 if (!isMouseMove(x, y)) 把这个反义词翻译回来:”没动”取反就是”动了”,动了就锁。我第一遍读这段代码就被名字带偏,把行为读成了”鼠标不动才锁”——站长本人复核时一眼戳穿。函数命名是给人读的,正负号千万别拧着来。

第二,flag 的 else 分支是初始化:第一次调用只记录坐标不判断。不然程序刚启动还没有”上次位置”可比,第一轮轮询就会误触发锁屏——绊线还没布好,先把自己绊倒。

第三,LockScreen 的本体只有一行 system("rundll32.exe user32.dll,LockWorkStation")——借用 rundll32 调 user32.dll 导出的 LockWorkStation,是 Windows 上锁屏最省事的野路子,不用写一行真正的 COM 或者凭据 UI 代码。它前面被注释掉的 system("python photo.py") 才是狠角色——锁屏之前先拍张照,看看是谁的手在动你鼠标。锁屏挡人,拍照留证,这一行还躺在注释里,属于留给未来的彩蛋。

第四,坐标用了 long long 存——屏幕坐标其实 LONG(32 位)就够了,用力过猛,但也无害。

锁屏防的是谁?防的不是你自己——你有密码,回来动一下鼠标、输个密码就回去了,代价只是多输一次密码;防的是趁你不在伸向鼠标的其他人。对后者,锁屏是即时的屏障,photo.py 是日后的证据。程序锁完一次就 exit(0) 功成身退,绝不纠缠。

这个程序只编译,没运行。原因很直白:这是一台云虚拟机,跑起来之后任何一次鼠标移动都会把工作会话锁掉,锁完还得费劲解。编译验证是全过的,只有两枚无害警告——typedef struct point {...}; 后面没跟类型名,整个 typedef 被编译器无视;wchar_t* pszText = L"what" 按严格 ISO C++ 不让拿字符串常量初始化非 const 指针。都是老 C 程序员的肌肉记忆在 C++ 编译器面前的正常水土不服。

它和《AutoWrite 自动打字机开发记》是一对:那边模拟键盘输入,这边盯防鼠标;一个替你打字,一个替你看家。Win32 小玩具的两极。

完整源码

C语言不锁屏防止被动鼠标.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <Windows.h>
#include <stdio.h>
using namespace std;

bool isMouseMove(long long x, long long y);
void LockScreen();

long long iMouseX = 0;
long long iMouseY = 0;
bool flag = false;
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);

typedef struct point
{
LONG x;
LONG y;
};

void GetMouseLocation()
{
POINT lpPoint;
if (GetCursorPos(&lpPoint) == 0)
{
wchar_t *pszText = L"what";
WriteConsole(hOut, pszText, wcslen(pszText), NULL, NULL);
}
long long x = lpPoint.x;
long long y = lpPoint.y;
if (!isMouseMove(x, y))
{
LockScreen();
exit(0);
}
return;
}
bool isMouseMove(long long x, long long y)
{
if (flag)
{
if (x != iMouseX || y != iMouseY)
{
return false;
}
return true;
}
else
{
flag = true;
iMouseX = x;
iMouseY = y;
return true;
}
}
void LockScreen()
{
// system("python photo.py");
system("rundll32.exe user32.dll,LockWorkStation");
Sleep(100);
return;
}

int main()
{
printf("开始计时\n");
while (1)
{
Sleep(100);
GetMouseLocation();
}
return 0;
}

两百行不到的绊线,守的是一个很朴素的威胁模型:屏幕亮着,不代表没人来碰。工具不必精巧,够警觉就行——毕竟它防的是那双趁你不在、伸向鼠标的手。