先判断上次键盘鼠标活动时间,如果时间较长则隔一段时间截屏判断是否在看视频,如果图片符合相似度则执行待机操作。
#include <windows.h>
#include "bitmap.h"
#include "stdio.h"
#include <time.h>
#include <stdlib.h>
#include <PowrProf.h>
#include <math.h>
void echo(CHAR *str);
int getlastinput();
int CheckFullscreen();
int CaptureImage(CHAR *lpbitmap, int width, int height);
int save(char *outfile, CHAR *lpbitmap, DWORD dwBmpSize, int width, int height);
void echo(CHAR *str) {
//MessageBox(NULL, str, NULL, MB_OK);
time_t t1;
struct tm *newtime;
char time_str[128];
t1 = time(NULL);
newtime=localtime(&t1);
strftime(time_str, 128, "%Y%m%d_%H%M%S", newtime);
printf("%s: %s \n", time_str, str);
//printf("%s \n", str);
}
int main(int argc, char *argv[]) {
INT width = GetSystemMetrics(SM_CXSCREEN); // 屏幕宽
INT height = GetSystemMetrics(SM_CYSCREEN); // 屏幕高
DWORD dwBmpSize = width * height * 4;
INT WidthBytes = width * 4;
if (argc == 1) {
printf("use sleep_time(sec) idle_time(min) similarity(<100) save_bmp(1) debug(1)\n");
exit(1);
}
int sleep_idle, sleep_time, idle_time, save_bmp, debug;
sleep_idle = sleep_time = idle_time = save_bmp = debug = 0;
float similarity = 0;
if (argc > 1)
sleep_time = atoi(argv[1]);
if (argc > 2)
idle_time = atoi(argv[2]);
if (argc > 3)
similarity = atof(argv[3]);
if (argc > 4)
save_bmp = atoi(argv[4]);
if (argc > 5)
debug = atoi(argv[5]);
if (!sleep_time && !idle_time) {
exit(1);
}
if (sleep_time >= 30) {
sleep_idle = round(sleep_time/5);
printf("sleep_idle = %d\n", sleep_idle);
sleep_idle = sleep_idle * 1000;
} else {
sleep_idle = sleep_time * 1000;
}
sleep_time = sleep_time * 1000; //sec
idle_time = idle_time * 60 * 1000; //min
HANDLE hDIB;
hDIB = GlobalAlloc(GHND, dwBmpSize);
CHAR *lpbitmap = (char *)GlobalLock(hDIB);
HANDLE hDIB2;
hDIB2 = GlobalAlloc(GHND, dwBmpSize);
CHAR *lpbitmap2 = (char *)GlobalLock(hDIB2);
if (!CaptureImage(lpbitmap, width, height)) {
exit(1);
}
while (1) {
//CheckFullscreen();
long int idle = getlastinput();
printf("%d \n", idle);
if (!debug && idle < idle_time) {
echo ("idle");
Sleep(sleep_idle);
continue;
}
if (!CaptureImage(lpbitmap2, width,height)) {
Sleep(5*1000);
continue;
}
int count = 0;
int cmp = 0;
int index = 0;
for (int i = 0;i < width;++i)
{
for (int j = 0;j < height;++j)
{
count++;
index = i * 4 + j * WidthBytes;
if (lpbitmap[index + 2] != lpbitmap2[index + 2] || lpbitmap[index + 1] != lpbitmap2[index + 1] || lpbitmap[index + 0] != lpbitmap2[index + 0]) {
cmp++;
}
//BYTE r = lpbitmap[index + 2];
//BYTE g = lpbitmap[index + 1];
//BYTE b = lpbitmap[index + 0];
//printf("r = %d\n", r );
//printf("g = %d\n", g );
//printf("b = %d\n", b );
//printf("index = %d\n", index);
//Sleep(1000);
}
}
printf("count = %d\n", count);
printf("cmp = %d\n", cmp);
float percentage = (float)cmp / count * 100.0;
printf("Percentage = %.2f%%\n", percentage);
if (!debug && percentage <= similarity) {
echo("SetSuspendState");
SetSuspendState(0, 1, 1);
Sleep(60*1000);
}
if (save_bmp == 1 && percentage <= similarity) {
time_t t1;
struct tm *newtime;
char time_str[128];
char outfile[128];
t1 = time(NULL);
newtime=localtime(&t1);
//strftime(outfile, 128, "%Y%m%d_%H%M%S.bmp", newtime);
strftime(time_str, 128, "%Y%m%d_%H%M%S", newtime);
sprintf(outfile,"%s_1_%.2f%%.bmp",time_str,percentage);
save(outfile,lpbitmap, dwBmpSize, width, height);
sprintf(outfile,"%s_2_%.2f%%.bmp",time_str,percentage);
save(outfile,lpbitmap2, dwBmpSize, width,height);
}
memcpy(lpbitmap, lpbitmap2, dwBmpSize);
Sleep(sleep_time);
}
// 解锁堆内存并释放
GlobalUnlock(hDIB);
GlobalFree(hDIB);
GlobalUnlock(hDIB2);
GlobalFree(hDIB2);
return 0;
}
int CaptureImage(CHAR *lpbitmap, int width, int height)
{
int ret = 1;
//GetDesktopWindow()
HDC hScreenDC = GetDC(NULL); //获取显示设备上下文环境
HDC hMemoryDC = CreateCompatibleDC(hScreenDC); // 创建与显示设备兼容的内存下文环境(设备描述表)
if (!hMemoryDC) {
echo(TEXT("CreateCompatibleDC has failed"));
ret = 0;
goto done;
}
//创建一个与显示设备描述表兼容的位图
HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, width, height);
if (!hBitmap) {
echo(TEXT("CreateCompatibleBitmap Failed"));
ret = 0;
goto done;
}
//把位图选到内存设备描述表中
SelectObject(hMemoryDC, hBitmap);
//HBITMAP hOldBitmap = (HBITMAP) SelectObject(hMemoryDC, hBitmap);
//把屏幕设备描述表拷贝到内存设备描述表中。
if (!BitBlt(
hMemoryDC, // 目的DC
0, 0, // 目的DC的 x,y 坐标
width, height, // 目的 DC 的宽高
hScreenDC, // 来源DC
0, 0, // 来源DC的 x,y 坐标
SRCCOPY)) // 粘贴方式
{
echo(TEXT("BitBlt has failed"));
ret = 0;
goto done;
}
//BITMAP bmpScreen;
//Get the BITMAP from the HBITMAP
//GetObject(hbmScreen, sizeof(BITMAP), &bmpScreen);
//hBitmap = (HBITMAP) SelectObject(hMemoryDC, hOldBitmap);
BITMAPINFOHEADER bi;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = width;
bi.biHeight = height;
bi.biPlanes = 1;
bi.biBitCount = 32;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
// 获取兼容位图的位并且拷贝结果到一个 lpbitmap 中.
GetDIBits(
hScreenDC, // 设备环境句柄
hBitmap, // 位图句柄
0, // 指定检索的第一个扫描线
(UINT)height, // 指定检索的扫描线数
lpbitmap, // 指向用来检索位图数据的缓冲区的指针
(BITMAPINFO *)&bi, // 该结构体保存位图的数据格式
DIB_RGB_COLORS // 颜色表由红、绿、蓝(RGB)三个直接值构成
);
//printf("sizeof((LPSTR)lpbitmap) = %d\n", sizeof((LPSTR)lpbitmap));
//printf("sizeof(lpbitmap[0]) = %d\n", sizeof(lpbitmap[0]));
done:
DeleteObject(hBitmap);
DeleteObject(hMemoryDC);
//DeleteDC(hMemoryDC);
ReleaseDC(NULL, hScreenDC);
return ret;
}
int getlastinput()
{
long int newTicks; // time value for new ticks
long int inputTicks; // time value for current time
long int elapsedTicks; // time value for elapsed time
LASTINPUTINFO lii; // Structure for Windows time stuff
// Set size of lii.cbsize
lii.cbSize = sizeof(lii);
// Get the time of the most recent (new) user input
GetLastInputInfo(&lii);
newTicks = lii.dwTime;
inputTicks = GetTickCount();
elapsedTicks = inputTicks - newTicks;
return elapsedTicks;
}
int CheckFullscreen() {
int bFullScreen = 0;
HWND hWnd = GetForegroundWindow();
RECT rcApp, rcDesk;
GetWindowRect(GetDesktopWindow(), &rcDesk);
if (hWnd!=GetDesktopWindow() && hWnd!=GetShellWindow()) {
GetWindowRect(hWnd, &rcApp);
if (rcApp.left<=rcDesk.left && rcApp.top<=rcDesk.top && rcApp.right>=rcDesk.right && rcApp.bottom>=rcDesk.bottom) {
char wnd_name[256];
char wnd_title[256];
GetWindowText(hWnd,wnd_title,sizeof(wnd_title));
GetClassName(hWnd, wnd_name, sizeof(wnd_name));
printf("title: %s\n", wnd_title);
printf("name: %s\n", wnd_name);
if (strcmp(wnd_name, "Windows.UI.Core.CoreWindow") != 0 && strcmp(wnd_name, "WorkerW") != 0){
bFullScreen =1;
}
}
}
return bFullScreen;
}
int save(char *outfile, CHAR *lpbitmap, DWORD dwBmpSize, int width, int height) {
HANDLE hFile;
DWORD dwSizeofDIB;
DWORD dwBytesWritten;
BITMAPFILEHEADER bmfHeader;
BITMAPINFOHEADER bi;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = width;
bi.biHeight = height;
bi.biPlanes = 1;
bi.biBitCount = 32;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
// 创建一个文件来保存文件截图
hFile = CreateFile(
outfile,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
// 将 图片头(headers)的大小, 加上位图的大小来获得整个文件的大小
dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
// 设置 Offset 偏移至位图的位(bitmap bits)实际开始的地方
bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
// 文件大小
bmfHeader.bfSize = dwSizeofDIB;
// 位图的 bfType 必须是字符串 "BM"
bmfHeader.bfType = 0x4D42; //BM
dwBytesWritten = 0;
WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);
WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL);
// 关闭文件句柄
CloseHandle(hFile);
return 0;
}
使用tdm-gcc编译:
gcc screen.c -o screen.exe -lgdi32 -lPowrprof
参考:
https://docs.microsoft.com/zh-cn/windows/win32/gdi/capturing-an-image?redirectedfrom=MSDN
https://lellansin.wordpress.com/2014/03/16/c-gdi-%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE/
https://bbs.csdn.net/topics/390838652?page=4
https://bbs.csdn.net/topics/340205786?page=2
https://blog.csdn.net/haogeai123/article/details/7030583