1. 程式人生 > >windows api實現計算機空閒關機

windows api實現計算機空閒關機

1.實現監聽全域性的滑鼠和鍵盤事件,2分鐘不動則關機

2.實現計算機基本資訊和效能資訊的獲取,比如C盤利用率,CPU利用率,記憶體利用率等等

3.開闢新的執行緒

完整程式碼如下:

#include <windows.h>
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <tchar.h>

#define GB(x) (((x).HighPart << 2) + ((DWORD)(x).LowPart) / 1024.0 / 1024.0 / 1024.0)
typedef long long int64_t;
typedef unsigned long long uint64_t; 
HWND hgWnd;
HHOOK myhook;
HHOOK myhookForKeyboard;
long time0=0,time1=0;
//MSG Msg;
/*int get_io_bytes(uint64_t* read_bytes, uint64_t* write_bytes)  
{  
    IO_COUNTERS io_counter;  
    if(GetProcessIoCounters(GetCurrentProcess(), &io_counter))  
    {  
        if(read_bytes) *read_bytes = io_counter.ReadTransferCount;  
        if(write_bytes) *write_bytes = io_counter.WriteTransferCount;  
        return 0;  
    }  
    return -1;  
}  */

/*char* GetUserName(void)
{
         const int nBufSize = 30;
         char chBuf[nBufSize];
         ZeroMemory(chBuf,nBufSize);
 
        //獲取當前登入使用者的名稱
        DWORD dwRet = nBufSize;
        if (::GetUserName(chBuf,&dwRet))
         {
               //
               OutputDebugString(chBuf);                
         }
         else
         {
               OutputDebugString(_T("獲取登入使用者名稱稱出錯!"));              
         } 
         OutputDebugString(_T("/r/n")); 
         return chBuf;
  }*/
/*void TcharToChar (const TCHAR * tchar, char * _char)  
{  
    int iLength ;  
	//獲取位元組長度   
	iLength = WideCharToMultiByte(CP_ACP, 0, tchar, -1, NULL, 0, NULL, NULL);  
	//將tchar值賦給_char    
	WideCharToMultiByte(CP_ACP, 0, tchar, -1, _char, iLength, NULL, NULL);   
}  
  char* GetPCName()
  {
        const int nBufSize = MAX_COMPUTERNAME_LENGTH + 1;
        TCHAR chBuf[nBufSize];
        ZeroMemory(chBuf,nBufSize); 
         //獲取當前計算機的名稱
        DWORD dwRet = nBufSize;
        GetComputerName(chBuf,&dwRet);
        char charBuf[nBufSize];
        TcharToChar(chBuf,charBuf);
        return charBuf;
  }*/
  
/*//獲取實時網速  
int WIN_GetIfTable(WIN_IfTable& lstIf)
{
 // GetAdaptersAddresses
 // 網口資訊, 準備1個足夠大的buf
 struct
 {
  DWORD dwNumEntries;
  MIB_IFROW table[8];
 }myIfTable;
 memset(&myIfTable, 0, sizeof(myIfTable));
 //  DWORD nNumOfIf = 0;
 //  DWORD ret = GetNumberOfInterfaces(&nNumOfIf);
 ULONG nBufSize = sizeof(myIfTable);
 DWORD ret = GetIfTable((MIB_IFTABLE*)&myIfTable, &nBufSize, TRUE);
 if( ret == 0)
 {
  for(int i=0; i<myIfTable.dwNumEntries; i++)
  {
   WIN_IfEntry entry;
   MIB_IFROW* pRow = &myIfTable.table[i];
   strcpy(entry.strName, "");
   strcpy(entry.strDescr, (char*)pRow->bDescr);
   entry.nIndex = pRow->dwIndex;
   entry.nType = pRow->dwType;
   entry.nInOctets = pRow->dwInOctets; //pRow->dwInUcastPkts + pRow->dwInNUcastPkts;
   entry.nOutOctes = pRow->dwOutOctets; //pRow->dwOutUcastPkts + pRow->dwOutNUcastPkts;
   entry.nAdminStatus = pRow->dwAdminStatus;
   entry.nSpeed = pRow->dwSpeed;
   if(pRow->dwType == 6)
    lstIf.push_back(entry);
  }
 }
 return 0;
}  */
/// 獲得CPU的核數  
int get_processor_number(/*int& dwNumberOfProcessors,*/)  
{  
    SYSTEM_INFO info;  
    GetSystemInfo(&info);  
    //info.dwProcessorType; CPU型別
	//
	//info.wProcessorLevel
	//info.wProcessorRevision
	//info.dwPageSize 
    return (int)info.dwNumberOfProcessors;  
}  

//CPU利用率  
__int64 CompareFileTime2(FILETIME time1, FILETIME time2)  
{  
//memcpy(<__int64>, &FILETIME, 8);
    __int64 a = time1.dwHighDateTime << 32 | time1.dwLowDateTime;  
    __int64 b = time2.dwHighDateTime << 32 | time2.dwLowDateTime;
    return b - a;  
}  
double CpuUseage()  
{  
    FILETIME idleTime;  
    FILETIME kernelTime;  
    FILETIME userTime;  
    
    FILETIME m_preidleTime;  
	FILETIME m_prekernelTime;  
	FILETIME m_preuserTime; 
    HANDLE hEvent = CreateEvent (NULL,FALSE,FALSE,NULL);
    GetSystemTimes(&idleTime, &kernelTime, &userTime);  
    WaitForSingleObject( hEvent,200);
    GetSystemTimes(&m_preidleTime, &m_prekernelTime, &m_preuserTime);
    int idle = CompareFileTime2(m_preidleTime, idleTime);  
    int kernel = CompareFileTime2(m_prekernelTime, kernelTime);  
    int user = CompareFileTime2(m_preuserTime, userTime);  
  
    if (kernel + user == 0)  
        return 0.99;  
    //(總的時間-空閒時間)/總的時間=佔用cpu的時間就是使用率  
    double cpu = abs((kernel + user - idle) * 100 / (kernel + user));  
    //m_preidleTime = idleTime;  
    //m_prekernelTime = kernelTime;  
    //m_preuserTime = userTime;  
    return cpu;  
}  
void GetDiskInfo(float& totalHardDisk,float& freeHardDisk,float& hardDiskUsage){
	ULARGE_INTEGER FreeBytesAvailableC, TotalNumberOfBytesC, TotalNumberOfFreeBytesC;
	GetDiskFreeSpaceEx(_T("C:"), &FreeBytesAvailableC, &TotalNumberOfBytesC, &TotalNumberOfFreeBytesC);
 	totalHardDisk = GB(TotalNumberOfBytesC);  
    freeHardDisk = GB(TotalNumberOfFreeBytesC);  
    hardDiskUsage = 1- freeHardDisk / totalHardDisk;  
}
void GetMemoryStatus(char* status){
	//char bufPreCPU[5];  
	MEMORYSTATUSEX statex;  
	statex.dwLength = sizeof(statex);  
	GlobalMemoryStatusEx(&statex); 
	sprintf(status, "總記憶體使用率:%ld%%    ", statex.dwMemoryLoad);  
}

//獲得系統名稱 
void GetSystemName(char* osname)  
{  
    char buf[128];  
    SYSTEM_INFO info;        //用SYSTEM_INFO結構判斷64位AMD處理器   
    GetSystemInfo(&info);    //呼叫GetSystemInfo函式填充結構   
    OSVERSIONINFOEX os;  
    os.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);  
  
    strcpy(buf, "unknown OperatingSystem.");  
  
    if (GetVersionEx((OSVERSIONINFO *)&os))  
    {  
        //下面根據版本資訊判斷作業系統名稱   
        switch (os.dwMajorVersion)//判斷主版本號  
        {  
        case 4:  
            switch (os.dwMinorVersion)//判斷次版本號   
            {  
            case 0:  
                if (os.dwPlatformId == VER_PLATFORM_WIN32_NT)  
                    strcpy(buf, "Microsoft Windows NT 4.0"); //1996年7月釋出   
                else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)  
                    strcpy(buf, "Microsoft Windows 95");  
                break;  
            case 10:  
                strcpy(buf, "Microsoft Windows 98");   
                break;  
            case 90:  
                strcpy(buf, "Microsoft Windows Me");   
                break;  
            }  
            break;  
  
        case 5:  
            switch (os.dwMinorVersion)  //再比較dwMinorVersion的值  
            {  
            case 0:  
                strcpy(buf, "Microsoft Windows 2000"); //1999年12月釋出  
                break;  
  
            case 1:  
                strcpy(buf, "Microsoft Windows XP"); //2001年8月釋出  
                break;  
  
            case 2:  
                if (os.wProductType == VER_NT_WORKSTATION  
                    && info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)  
                {  
                    strcpy(buf, "Microsoft Windows XP Professional x64 Edition");   
                }  
                else if (GetSystemMetrics(SM_SERVERR2) == 0)  
                    strcpy(buf, "Microsoft Windows Server 2003"); //2003年3月釋出   
                else if (GetSystemMetrics(SM_SERVERR2) != 0)  
                    strcpy(buf, "Microsoft Windows Server 2003 R2");   
                break;  
            }  
            break;  
  
        case 6:  
            switch (os.dwMinorVersion)  
            {  
            case 0:  
                if (os.wProductType == VER_NT_WORKSTATION)  
                    strcpy(buf, "Microsoft Windows Vista");   
                else  
                    strcpy(buf, "Microsoft Windows Server 2008"); //伺服器版本   
                break;  
            case 1:  
                if (os.wProductType == VER_NT_WORKSTATION)  
                    strcpy(buf, "Microsoft Windows 7");   
                else  
                    strcpy(buf, "Microsoft Windows Server 2008 R2");   
                break;  
            }  
            break;  
        }  
    }//if(GetVersionEx((OSVERSIONINFO *)&os))  
  
    strcpy(osname, buf);  
} 

LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) 
{   
    PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)lParam;
    const char *info = NULL;
    char text[50], data[20],tmp[60];
 
    PAINTSTRUCT ps;
    HDC hdc;
    //MessageBox(NULL, TEXT("鍵盤被按下"), TEXT("鍵盤被按下"), MB_ICONEXCLAMATION | MB_OK);
    if (nCode >= 0)
    {
    	//MessageBox(NULL, TEXT("內部鍵盤"), TEXT("內部鍵盤"), MB_ICONEXCLAMATION | MB_OK);
    	hdc = GetDC(hgWnd);    
    	time1 = time(0);
		/*if(time0 != 0){
			if(time1 - time0 > 120){
				//info = "哈哈哈哈哈哈哈哈";
				ZeroMemory(tmp, sizeof(tmp));
				wsprintf(tmp, "keyBoard:time0 is %ld,time1 is %ld,time interval is %ld s", time0,time1,time1-time0);
				TextOut(hdc, 10, 70, tmp, strlen(tmp));
				//system("shutdown -s -t 00")
			}
		}*/ 
		time0 = time1;
        if      (wParam == WM_KEYDOWN)      info = "普通按鍵擡起";
        else if (wParam == WM_KEYUP)        info = "普通按鍵按下";
        else if (wParam == WM_SYSKEYDOWN)   info = "系統按鍵擡起";
        else if (wParam == WM_SYSKEYUP)     info = "系統按鍵按下";
        
        int y = 10;
        char systemName[30];
		ZeroMemory(systemName, sizeof(systemName)); 
		GetSystemName(systemName);
		char title[60];
        ZeroMemory(title, sizeof(title));
		wsprintf(title, "按下任意鍵可以更新狀態(%s)",systemName);
		TextOut(hdc, 10, y, title, strlen(title));
		y += 20;
		char bufPreCPU[30];
        ZeroMemory(bufPreCPU, sizeof(bufPreCPU));
		GetMemoryStatus(bufPreCPU);
		TextOut(hdc, 10, y, bufPreCPU, strlen(bufPreCPU));
		y += 20;
		char diskUsage[30];
		ZeroMemory(diskUsage, sizeof(diskUsage)); 
		float a=0,b=0,c=0;
		GetDiskInfo(a,b,c);
		int ia = a;
		int ib = b;
		int ic = c*100;
		wsprintf(diskUsage, "C盤利用率:%d%%[%d GB / %d GB]    ",ic,ia-ib,ia);
		//MessageBox(NULL, diskUsage, TEXT("錯誤"), MB_OK);
		TextOut(hdc, 10, y, diskUsage, strlen(diskUsage));
		y += 20;
		char processNumber[30];
		ZeroMemory(processNumber,strlen(processNumber));
		int number = get_processor_number();
		wsprintf(processNumber, "CPU核數:%d    ",number);
		TextOut(hdc, 10, y, processNumber, strlen(processNumber));
		y += 20;
		char cpuUsage[30];
		
		ZeroMemory(processNumber,strlen(processNumber));
		double dcpuUsage = CpuUseage();
		int i = dcpuUsage;
		wsprintf(cpuUsage, "CPU利用率:%d%%    ",i);
		TextOut(hdc, 10, y, cpuUsage, strlen(cpuUsage));
		y += 20;
		ZeroMemory(text, sizeof(text));
        ZeroMemory(data, sizeof(data));
        wsprintf(text, "%s - 鍵盤碼 [%04d], 掃描碼 [%04d]  ", info, p->vkCode, p->scanCode);
        wsprintf(data, "按鍵為: %c  ", p->vkCode);
        TextOut(hdc, 10, y, text, strlen(text));
        y += 20;
        TextOut(hdc, 10, y, data, strlen(data));
        y += 20;
		//wsprintf(system, "CPU核數:%d",systemName);
		/*;*/
		//double a = get_processor_number();//CpuUseage();
		//uint64_t a,b,a1,b1;
		//get_io_bytes(&a,&b);
		//HANDLE hEvent = CreateEvent (NULL,FALSE,FALSE,NULL);
    	//WaitForSingleObject( hEvent,200);
		//get_io_bytes(&a1,&b1);
		//char buffer[40];
		//itoa(b,buffer, 10);
		//char* buffer = GetPCName();
		//char* buffer = GetUserName();
		//char* buffer = "hahahah";
		//char mtmp[40];
		//ZeroMemory(mtmp, sizeof(mtmp));
		//wsprintf(mtmp, "name is %s", buffer);
		//TextOut(hdc, 10, 90, mtmp, strlen(mtmp));
        ReleaseDC(hgWnd,hdc);
    }
     
    return CallNextHookEx(myhookForKeyboard, nCode, wParam, lParam);
} 
/**************************************************************** 
  WH_KEYBOARD hook procedure 
  滑鼠鉤子處理過程
 ****************************************************************/
LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam) 
{   
    LPMSLLHOOKSTRUCT p = (LPMSLLHOOKSTRUCT)lParam;
    POINT   pt = p->pt;
    DWORD   mouseData = p->mouseData;
    //const char *info = NULL;
    char *info = NULL;
    char text[60], pData[50], mData[50],tmp[60];


    PAINTSTRUCT ps;
    HDC hdc;
  
    if (nCode >= 0)
    {
    	hdc = GetDC(hgWnd); 
    	time1 = time(0);
		/*if(time0 != 0){
			if(time1 - time0 > 120){
				//info = "哈哈哈哈哈哈哈哈";
				ZeroMemory(tmp, sizeof(tmp));
				wsprintf(tmp, "Mouse:time0 is %ld,time1 is %ld,time interval is %ld s", time0,time1,time1-time0);
				TextOut(hdc, 10, 70, tmp, strlen(tmp));
			
			}
		} */
		time0 = time1;
		//info = "aa";
		
		//strftime(tmp, sizeof(tmp), "%Y/%m/%d %X %A 本年第%j天 %z",localtime(&t) ); 
		//printf("%s",tmp);
		//char buffer[40];
		//itoa( t, buffer, 10 );		 
        if   (wParam == WM_MOUSEMOVE)       info = "滑鼠移動    ";
        else if(wParam == WM_LBUTTONDOWN)   info = "滑鼠【左鍵】按下";
        else if(wParam == WM_LBUTTONUP)     info = "滑鼠【左鍵】擡起";
        else if(wParam == WM_LBUTTONDBLCLK) info = "滑鼠【左鍵】雙擊";
        else if(wParam == WM_RBUTTONDOWN)   info = "滑鼠【右鍵】按下";
        else if(wParam == WM_RBUTTONUP)     info = "滑鼠【右鍵】擡起";
        else if(wParam == WM_RBUTTONDBLCLK) info = "滑鼠【右鍵】雙擊";
        else if(wParam == WM_MBUTTONDOWN)   info = "滑鼠【滾輪】按下";
        else if(wParam == WM_MBUTTONUP)     info = "滑鼠【滾輪】擡起";
        else if(wParam == WM_MBUTTONDBLCLK) info = "滑鼠【滾輪】雙擊";
        else if(wParam == WM_MOUSEWHEEL)    {
			info = "滑鼠【滾輪】滾動";
			
			//system("shutdown -s -t 00"); 
		} 
 
        ZeroMemory(text, sizeof(text));
        ZeroMemory(pData, sizeof(pData));
        ZeroMemory(mData, sizeof(mData));
        
        
        wsprintf( text, "當前狀態: %10s   ", info);
        wsprintf(pData, "0x%x - X: [%04d], Y: [%04d]  ", wParam, pt.x, pt.y);
        wsprintf(mData, "附帶資料: %16u   ", mouseData);
       
 
        //GetSystemName(mData);       
        //TextOut(hdc, 10, 10,  text, strlen(text));
        //TextOut(hdc, 10, 30, pData, strlen(pData));
        //TextOut(hdc, 10, 50, mData, strlen(mData));
        
        ReleaseDC(hgWnd,hdc);
    }
     
    return CallNextHookEx(myhook, nCode, wParam, lParam);
} 
 
// 5. 視窗過程處理
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{   
    hgWnd = hwnd;
 
    switch(msg)
    {
        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}
 
DWORD WINAPI ThreadProc1(LPVOID lpParam)
{
	//printf("sub thread started\n");
	while(1){
	//for(int i = 0;i < 3;i++){
			//if(time(0) - time0 > 100){
			//OutputDebugString("hehe");//system("shutdown -s -t 00");
		//}
		char c[8];
		int interval = time(0) - time0;
		itoa(interval,c,10);
		if((time0 != 0) && (interval > 120)) {
				system("shutdown -s -t 00");//MessageBox(NULL, TEXT(c), TEXT(c),MB_ICONEXCLAMATION | MB_OK);
		} 
		Sleep(10000);
	}
	//}
	//printf("sub thread finished\n");
 return 0;
} 
/*DWORD WINAPI ThreadProc2(LPVOID lpParam)
{
	while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
	return 0;
} */

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
{
	
    WNDCLASSEX wc;  // http://baike.baidu.com/view/1750396.htm
    HWND hwnd;
    MSG Msg;  
    char text[30];
 
    const char szClassName[] = "myWindowClass";
 
    // 1. 設定註冊視窗結構體
    wc.cbSize        = sizeof(WNDCLASSEX);              // 註冊視窗結構體的大小
    wc.style         = 0;                               // 視窗的樣式
    wc.lpfnWndProc   = WndProc;                         // 指向視窗處理過程的函式指標
    wc.cbClsExtra    = 0;                               // 指定緊跟在視窗類結構後的附加位元組數
    wc.cbWndExtra    = 0;                               // 指定緊跟在視窗事例後的附加位元組數
    wc.hInstance     = hInstance;                       // 本模組的例項控制代碼
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION); // 圖示的控制代碼
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);     // 游標的控制代碼
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);        // 背景畫刷的控制代碼
    wc.lpszMenuName  = NULL;                            // 指向選單的指標
    wc.lpszClassName = szClassName;                     // 指向類名稱的指標
    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION); // 和視窗類關聯的小圖示
 
    // 2. 使用【視窗結構體】註冊視窗
    if(!RegisterClassEx(&wc))
    {
        MessageBox(NULL, TEXT("視窗註冊失敗!"), TEXT("錯誤"), MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }
 
    // 3. 建立視窗
    hwnd = CreateWindowEx(
        WS_EX_CLIENTEDGE,       // 視窗的擴充套件風格
        szClassName,            // 指向註冊類名的指標
        TEXT("關機工具 V1.0"),       // 指向視窗名稱的指標
        WS_OVERLAPPEDWINDOW,    // 視窗風格
        CW_USEDEFAULT, CW_USEDEFAULT, 350, 200, // 視窗的 x,y 座標以及寬高
        NULL,                   // 父視窗的控制代碼
        NULL,                   // 選單的控制代碼
        hInstance,              // 應用程式例項的控制代碼
        NULL                    // 指向視窗的建立資料
        );
 
    if(hwnd == NULL)
    {
        MessageBox(NULL, TEXT("視窗建立失敗"), TEXT("錯誤"),MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }
 
    // 4. 顯示視窗
    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);
 
    // 設定滑鼠全域性監聽
    myhook = SetWindowsHookEx( 
        WH_MOUSE_LL,    // 監聽型別【滑鼠】
        MouseProc,  // 處理函式
        hInstance,      // 當前例項控制代碼
        0               // 監聽視窗控制代碼(NULL為全域性監聽)
    ); 
 
    if(myhook == NULL)
    {       
        wsprintf(text, "滑鼠監聽失敗!error : %d \n", GetLastError());
        MessageBox(hwnd, text, TEXT("錯誤"), MB_OK);
    }
 
     // 設定鍵盤全域性監聽
    myhookForKeyboard = SetWindowsHookEx( 
        WH_KEYBOARD_LL, // 監聽型別【鍵盤】
        KeyboardProc,   // 處理函式
        hInstance,      // 當前例項控制代碼
        0               // 監聽視窗控制代碼(NULL為全域性監聽)
    ); 
 
    if(myhookForKeyboard == NULL)
    {       
        wsprintf(text, "鍵盤監聽失敗!error : %d \n", GetLastError());
        MessageBox(hwnd, text, TEXT("錯誤"), MB_OK);
    }
 
	DWORD threadID1;
 	HANDLE hThread1;
 	hThread1 = CreateThread(NULL,0,ThreadProc1,NULL,0,&threadID1); // 建立執行緒
 	//WaitForSingleObject(hThread1,INFINITE);
 	// 5. 訊息迴圈
   /* DWORD threadID2;
 	HANDLE hThread2;
 	hThread1 = CreateThread(NULL,0,ThreadProc2,NULL,0,&threadID2); // 建立執行緒
 	WaitForSingleObject(hThread2,INFINITE);*/
    while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}