--------------------------------------------------------------------------------------------------------------------------------------- .h
#include "RdWrtIni.h" #include <time.h> #include <atlbase.h> #include <pm.h> // 重啟數據定義 #define CTL_CODE( DeviceType, Function, Method, Access ) ( ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) ) #define FILE_DEVICE_HAL 0x00000101 #define METHOD_BUFFERED 0 #define FILE_ANY_ACCESS 0 #define IOCTL_HAL_REBOOT CTL_CODE(FILE_DEVICE_HAL, 15, METHOD_BUFFERED, FILE_ANY_ACCESS) extern "C" __declspec(dllimport) BOOL KernelIoControl(DWORD dwIoControlCode, LPVOID lpInBuf, DWORD nInBufSize, LPVOID lpOutBuf, DWORD nOutBufSize, LPDWORD lpBytesReturned); #define MAX_LOADSTRING 100 #define TimeInterval 1 // 計時器間隔 #define PROFILE _T(".\\MetroOff.ini") void DrawUI(HDC hDC, int type, int Distance); // 繪圖操作 void FillSolidRect(HDC hDC, RECT rect, COLORREF clr); // 填充純色(當Profile.isLoadImage == FALSE) void CALLBACK TimerProc(HWND hwnd, UINT message, UINT iTimerID, DWORD dwTime); // 用作釋放光標后滑塊恢復原狀 void ShutDownWM(); // 僅支持HTC struct Profile { BOOL isLoadImage; // 是否加載圖片 WCHAR szScreenOff[MAX_PATH]; // 關屏圖片路徑 WCHAR szReboot[MAX_PATH]; // 重啟圖片路徑 WCHAR szShutDown[MAX_PATH]; // 關機圖片路徑 COLORREF clrScreenOff; // 關屏色彩 COLORREF clrReboot; // 重啟色彩 COLORREF clrShutDown; // 關機色彩 int Status; // 初始操作狀態:(0:關屏 1:關機 2:重啟) }; Profile g_Profile; // 配置文件 int g_Pos; // 滑塊位置 注意:考慮最大最小值,防止超過最大位移 int g_Width; // 屏幕寬度 int g_Height; // 屏幕長度 POINT g_Spt; // 起始座標 POINT g_Ept; // 瞬時座標 UINT_PTR g_TimerID; // 定時器ID HWND g_hWnd; // 全局窗口句柄 HFONT g_FontL; // 大字體 退出時銷毀 HFONT g_FontS; // 小字體 退出時銷毀 LOGFONT g_lf; // 初始化時使用 HDC g_ScrDC; // 原始桌面DC 退出時銷毀 HDC g_BkgDC; // 保存桌面的DC 退出時銷毀 HBITMAP g_BkgBmp; // 保存桌面的畫布 退出時銷毀 HBITMAP g_BlkBmp; // 內存畫布,用作滑塊貼圖 退出時銷毀 BOOL g_Drag; // 是否在拖動滑塊
--------------------------------------------------------------------------------------------------------------------------------------- .cpp
// MetroOff.cpp : 定义应用程序的入口点。 // #include "stdafx.h" #include "MetroOff.h" // 全局变量: HINSTANCE g_hInst; // 当前实例 // 此代码模块中包含的函数的前向声明: ATOM MyRegisterClass(HINSTANCE, LPTSTR); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { MSG msg; // 执行应用程序初始化: if (!InitInstance(hInstance, nCmdShow)) { return FALSE; } // 主消息循环: while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; } // // 函数: MyRegisterClass() // // 目的: 注册窗口类。 // // 注释: // ATOM MyRegisterClass(HINSTANCE hInstance, LPTSTR szWindowClass) { WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(hInstance, _T("MetroOff.ico")); wc.hCursor = 0; wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); wc.lpszMenuName = 0; wc.lpszClassName = szWindowClass; return RegisterClass(&wc); } // // 函数: InitInstance(HINSTANCE, int) // // 目的: 保存实例句柄并创建主窗口 // // 注释: // // 在此函数中,我们在全局变量中保存实例句柄并 // 创建和显示主程序窗口。 // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; TCHAR szTitle[MAX_LOADSTRING] = _T(""); // 标题栏文本 TCHAR szWindowClass[MAX_LOADSTRING] = _T("MetroOff"); // 主窗口类名 g_hInst = hInstance; // 将实例句柄存储在全局变量中 // 在应用程序初始化期间,应调用一次 SHInitExtraControls 以初始化 // 所有设备特定控件,例如,CAPEDIT 和 SIPPREF。 SHInitExtraControls(); //如果它已经在运行,则将焦点置于窗口上,然后退出 hWnd = FindWindow(szWindowClass, szTitle); if (hWnd) { // 将焦点置于最前面的子窗口 // “| 0x00000001”用于将所有附属窗口置于前台并 // 激活这些窗口。 SetForegroundWindow((HWND)((ULONG) hWnd | 0x00000001)); return 0; } if (!MyRegisterClass(hInstance, szWindowClass)) { return FALSE; } hWnd = CreateWindow(szWindowClass, szTitle, WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } ShowWindow(hWnd, SW_HIDE); UpdateWindow(hWnd); // 加入初始化代碼 g_Profile.isLoadImage = (BOOL)GetPrivateProfileInt(_T("Load"), _T("Bool"), 0, PROFILE); GetPrivateProfileString(_T("Image"), _T("ScreenOff"), _T(""), g_Profile.szScreenOff, MAX_PATH, PROFILE); GetPrivateProfileString(_T("Image"), _T("Reboot"), _T(""), g_Profile.szReboot, MAX_PATH, PROFILE); GetPrivateProfileString(_T("Image"), _T("ShutDown"), _T(""), g_Profile.szShutDown, MAX_PATH, PROFILE); g_Profile.clrScreenOff = (COLORREF)GetPrivateProfileInt(_T("Color"), _T("ScreenOff"), 47746, PROFILE); g_Profile.clrReboot = (COLORREF)GetPrivateProfileInt(_T("Color"), _T("Reboot"), 14851176, PROFILE); g_Profile.clrShutDown = (COLORREF)GetPrivateProfileInt(_T("Color"), _T("ShutDown"), 13260, PROFILE); g_Profile.Status = (int)GetPrivateProfileInt(_T("Initial"), _T("Status"), 0, PROFILE); g_Width = GetSystemMetrics(SM_CXSCREEN); g_Height = GetSystemMetrics(SM_CYSCREEN); g_Pos = g_Height / 2; g_Spt.x = 0; g_Spt.y = 0; g_Ept.x = 0; g_Ept.y = 0; g_TimerID = 0; g_hWnd = hWnd; g_Drag = FALSE; // 設置字體 memset(&g_lf, 0, sizeof(LOGFONT)); g_lf.lfQuality = CLEARTYPE_QUALITY; g_lf.lfHeight = g_Width/5; g_lf.lfWeight = g_Width/10; g_FontL = CreateFontIndirect(&g_lf); g_lf.lfHeight = g_Width/16; g_lf.lfWeight = g_Width/16; g_FontS = CreateFontIndirect(&g_lf); // 獲取屏幕圖像 g_ScrDC = GetDC(NULL); g_BkgBmp = CreateCompatibleBitmap(g_ScrDC, g_Width, g_Height); g_BkgDC = CreateCompatibleDC(g_ScrDC); SelectObject(g_BkgDC, g_BkgBmp); BitBlt(g_BkgDC, 0, 0, g_Width, g_Height, g_ScrDC, 0, 0, SRCCOPY); if (g_Profile.isLoadImage) { switch (g_Profile.Status) { case 0: g_BlkBmp = SHLoadImageFile(W2T(g_Profile.szScreenOff)); break; case 1: g_BlkBmp = SHLoadImageFile(W2T(g_Profile.szShutDown)); break; case 2: g_BlkBmp = SHLoadImageFile(W2T(g_Profile.szReboot)); break; default: break; } } else { g_BlkBmp = CreateCompatibleBitmap(g_ScrDC, g_Width, g_Height); } // 窗口全屏化 ShowWindow(hWnd, SW_SHOW); RECT rc; GetWindowRect(hWnd, &rc); SHFullScreen(hWnd, SHFS_HIDETASKBAR | SHFS_HIDESIPBUTTON); HWND hWndCB = ::SHFindMenuBar(hWnd); ShowWindow(hWndCB, SW_HIDE); MoveWindow(hWnd, rc.left, rc.top - g_Width / 240 * 26, rc.right, rc.bottom + g_Width / 240 * 26, TRUE); return TRUE; } // // 函数: WndProc(HWND, UINT, WPARAM, LPARAM) // // 目的: 处理主窗口的消息。 // // WM_COMMAND - 处理应用程序菜单 // WM_PAINT - 绘制主窗口 // WM_DESTROY - 发送退出消息并返回 // // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; static SHACTIVATEINFO s_sai; switch (message) { case WM_CREATE: // 初始化外壳程序激活信息结构 memset(&s_sai, 0, sizeof (s_sai)); s_sai.cbSize = sizeof (s_sai); break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // TODO: 在此添加任意绘图代码... DrawUI(hdc, g_Profile.Status, g_Pos); EndPaint(hWnd, &ps); break; case WM_ERASEBKGND: return 0; break; case WM_DESTROY: PostQuitMessage(0); break; case WM_QUIT: ReleaseDC(NULL, g_ScrDC); DeleteDC(g_BkgDC); DeleteObject(g_BkgBmp); if (g_Profile.isLoadImage) { DeleteObject(g_BlkBmp); } DeleteObject(g_FontL); DeleteObject(g_FontS); break; case WM_ACTIVATE: // 向外壳程序通知我们的激活消息 SHHandleWMActivate(hWnd, wParam, lParam, &s_sai, FALSE); break; case WM_SETTINGCHANGE: SHHandleWMSettingChange(hWnd, wParam, lParam, &s_sai); break; case WM_LBUTTONDOWN: if (HIWORD(lParam) < g_Pos) { g_Drag = TRUE; if (g_Spt.x == 0) { g_Spt.x = LOWORD(lParam); g_Spt.y = HIWORD(lParam); } } if (g_TimerID != 0) { KillTimer(NULL, g_TimerID); g_TimerID = 0; } break; case WM_MOUSEMOVE: if (g_Drag) { g_Ept.x = LOWORD(lParam); g_Ept.y = HIWORD(lParam); g_Pos = g_Ept.y - g_Spt.y + g_Height/2; if (g_Pos > g_Height) { g_Pos = g_Height; } else if (g_Pos < 0) { g_Pos = 0; } InvalidateRect(hWnd, NULL, FALSE); UpdateWindow(hWnd); } break; case WM_LBUTTONUP: if (g_Drag) { g_Ept.x = LOWORD(lParam); g_Ept.y = HIWORD(lParam); g_Pos = g_Ept.y - g_Spt.y + g_Height/2; if (g_Pos > g_Height) { g_Pos = g_Height; } else if (g_Pos < 0) { g_Pos = 0; } POINT Dist; Dist.x = g_Ept.x - g_Spt.x; Dist.y = g_Ept.y - g_Spt.y; if (Dist.x < 0) { Dist.x = -Dist.x; } if (Dist.y < 0) { Dist.y = -Dist.y; } if (Dist.x < 16 && Dist.y < 16) { g_Profile.Status += 1; if (g_Profile.Status > 2) { g_Profile.Status = 0; } DeleteObject(g_BlkBmp); switch (g_Profile.Status) { case 0: g_BlkBmp = SHLoadImageFile(W2T(g_Profile.szScreenOff)); break; case 1: g_BlkBmp = SHLoadImageFile(W2T(g_Profile.szShutDown)); break; case 2: g_BlkBmp = SHLoadImageFile(W2T(g_Profile.szReboot)); break; default: break; } } g_TimerID = SetTimer(NULL, 0, TimeInterval, TimerProc); g_Drag = FALSE; InvalidateRect(hWnd, NULL, FALSE); UpdateWindow(hWnd); } break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } void ShutDownWM() { typedef int(*lpAPIFun)(BOOL); lpAPIFun HTCUtilDeviceOff; HINSTANCE hDll = LoadLibrary(_T("HTCUtil.dll")); if (hDll != NULL) { HTCUtilDeviceOff = (lpAPIFun)GetProcAddress(hDll, _T("HTCUtilDeviceOff")); if (HTCUtilDeviceOff != NULL) { HTCUtilDeviceOff(TRUE); } else { PostQuitMessage(0); } } else { PostQuitMessage(0); } FreeLibrary(hDll); } void FillSolidRect(HDC hDC, RECT rect, COLORREF clr) { SetBkColor(hDC, clr); ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL); } void DrawUI(HDC hDC, int type, int Distance) { // 創建內存畫布,並將屏幕背景貼到內存畫布上 HDC MemDC = CreateCompatibleDC(NULL); HBITMAP MemBmp = CreateCompatibleBitmap(g_ScrDC, g_Width, g_Height); SelectObject(MemDC, MemBmp); BitBlt(MemDC, 0, 0 , g_Width, g_Height, g_BkgDC, 0 , 0, SRCCOPY); // 滑塊貼圖相關操作 HDC blkDC = CreateCompatibleDC(NULL); // 創建滑塊內存DC SelectObject(blkDC, g_BlkBmp); TCHAR strInfo[] = _T("向下滑动以关机"); // 初始化說明文字 RECT rc; rc.left = 0; rc.right = g_Width; rc.top = 0; rc.bottom = g_Height; switch (type) { case 0: // 關屏 if (!g_Profile.isLoadImage) { FillSolidRect(blkDC, rc, g_Profile.clrScreenOff); } wsprintf(strInfo, _T("向下滑动以关屏")); break; case 1: // 關機 if (!g_Profile.isLoadImage) { FillSolidRect(blkDC, rc, g_Profile.clrShutDown); } wsprintf(strInfo, _T("向下滑动以关机")); break; case 2: // 重啟 if (!g_Profile.isLoadImage) { FillSolidRect(blkDC, rc, g_Profile.clrReboot); } wsprintf(strInfo, _T("向下滑动以重启")); break; default: break; } BitBlt(MemDC, 0, 0, g_Width, Distance, blkDC, 0, g_Height - Distance, SRCCOPY); // ------------------------------------------文字部份 SetBkMode(MemDC, TRANSPARENT); SetTextColor(MemDC, RGB(255, 255, 255)); SelectObject(MemDC, g_FontL); rc.left = g_Width/3; rc.top = Distance - g_Height/2; rc.bottom = Distance - g_Height/4; // 時間貼圖 TCHAR str[8]; LPSYSTEMTIME lpSystemTime = new SYSTEMTIME; GetLocalTime(lpSystemTime); wsprintf(str, _T("%02d:%02d"), lpSystemTime->wHour, lpSystemTime->wMinute); DrawText(MemDC, str, -1, &rc, DT_CENTER | DT_VCENTER); // 文字貼圖 rc.left = 0; rc.top = Distance - g_Height/16; rc.bottom = Distance; SelectObject(MemDC, g_FontS); DrawText(MemDC, strInfo, -1, &rc, DT_CENTER | DT_VCENTER); // 完成貼圖 BitBlt(hDC, 0, 0, g_Width, g_Height, MemDC, 0, 0, SRCCOPY); // 清理 DeleteDC(MemDC); DeleteDC(blkDC); DeleteObject(MemBmp); if (Distance >= g_Height) { switch (type) { case 0: // 關屏 ReleaseDC(NULL, g_ScrDC); DeleteDC(g_BkgDC); DeleteObject(g_BkgBmp); if (g_Profile.isLoadImage) { DeleteObject(g_BlkBmp); } DeleteObject(g_FontL); DeleteObject(g_FontS); SetSystemPowerState(NULL, POWER_STATE_SUSPEND, POWER_FORCE); exit(0); break; case 1: // 關機 ShutDownWM(); break; case 2: // 重啟 KernelIoControl(IOCTL_HAL_REBOOT, NULL, 0, NULL, 0, NULL); break; default: break; } } else if (Distance <= g_Height/4) { PostQuitMessage(0); } } void CALLBACK TimerProc(HWND hwnd, UINT message, UINT iTimerID, DWORD dwTime) { if (g_Pos == g_Height/2) { InvalidateRect(g_hWnd, NULL, FALSE); UpdateWindow(g_hWnd); g_Spt.x = 0; KillTimer(NULL, g_TimerID); } else { g_Pos = ((g_Pos - g_Height/2)*7)/8 + g_Height/2; InvalidateRect(g_hWnd, NULL, FALSE); UpdateWindow(g_hWnd); } }
由於用到了HTCUtil,因此關機只能用於HTC機型,其他機型只能實現休眠。
轉載請注明http://www.cnblogs.com/ZzzZzz/原創。