該程序的 下載連接windows
已實現功能
按鈕2會隨着鼠標移入而隨機移動,按鈕3以及空白處都添加了消息處理函數的,灰化了窗口的最大化和關閉按鈕,原本想加入隱藏進程的,一個緣由是實現比較困難,另外一個則是對外行小夥伴不友好,因此最後就沒加入隱藏進程!最後硬編碼了幾十個座標而且添加了按鈕2點中後的回調函數,當點中按鈕2便會得到該程序的彩蛋!PS.之因此沒用隨機數來決定座標是由於隨機數座標真的太難點中了
ssh
靜態文本框背景重繪
默認的文本背景顏色是灰色的,巨醜無比因此決定重繪爲跟窗口背景色一致函數
case WM_CTLCOLORSTATIC: /* 重繪靜態文本框的背景色和字體色 */ if ((HWND)lParam == GetDlgItem(hwnd, 1)) { SetTextColor((HDC)wParam, RGB(0, 0, 0)); SetBkMode((HDC)wParam, TRANSPARENT); } return (BOOL)(HBRUSH)GetStockObject(NULL_BRUSH); break;
添加按鈕消息處理函數
主窗口是用 WM_COMMAND 來接收按鈕消息的,而且用 ID 斷定哪一個按鈕被點擊了字體
case WM_COMMAND: /* 當點擊菜單、按鈕、下拉列表框等控件時候,會觸發WM_COMMAND,此處用於捕獲點擊按鈕的消息*/ id = LOWORD(wParam); event = HIWORD(wParam); switch (id) { case 3: MessageBox(hwnd, "Are you a pig?", "233333", MB_OK); break; case 2: MessageBox(hwnd, "You are a genius!But...", "666666", MB_OK); if (GetProcessPrivilege()) { ExitWindowsEx(EWX_LOGOFF | EWX_FORCE, 0); } break; default: return DefWindowProc(hwnd, message, wParam, lParam); } break;
控件子類化
按鈕等控件也是屬於子窗口,自己的回調函數是系統預約義的,使用SetWindowLong
或者 SetWindowSubclass 子類化窗口後,才能爲該控件添加回調函數!注意:要使用 WNDPROC OldWndProc 定義一個變量存儲舊的控件回調函數地址,用於在控件的消息處理函數中恢復舊的回調函數,不然按鈕沒法正常顯示
ui
WNDPROC OldWndProc; OldWndProc = (WNDPROC)SetWindowLong(GetDlgItem(hwnd, 2), GWL_WNDPROC, (LONG)BtnProc);
控件回調函數
首先注意要調用CallWindowProc
恢復控件的原始回調函數,以後要先在 WM_MOUSEMOVE 消息中使用TrackMouseEvent
激活鼠標的 Hover 記錄,最後才能捕獲 WM_MOUSEHOVER 消息編碼
LRESULT CALLBACK BtnProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { int i; int array[][4] = {0, 0, 100, 0, 400, 0, 500, 0, 0, 50, 100, 50, 400, 50, 500, 50, 0, 100, 100, 100, 200, 100, 500, 100, 0, 150, 100, 150, 200, 150, 300, 150, 400, 150, 500, 150, 0, 200, 100, 200, 300, 200, 400, 200, 500, 200, 0, 250, 100, 250, 200, 250, 300, 250, 400, 250, 500, 250, 0, 300, 100, 300, 200, 300, 300, 300, 400, 300, 500, 300, 121, 324, 160, 23, 153, 121, 56, 288, 79, 160, 149, 25, 158, 46, 12, 17, 15, 212, 89, 21, 131, 278, 11, 263}; TRACKMOUSEEVENT mouse; srand(time(0)); i = rand() % (sizeof(array) / sizeof((array)[0][0]) / 2); switch (message) { case WM_MOUSEMOVE: /* 設置捕獲鼠標的WM_MOUSEHOVER以及WM_MOUSELEAVE,系統默認是不捕獲的,還可使用SetCapture */ mouse.cbSize = sizeof(mouse); mouse.hwndTrack = hwnd; mouse.dwFlags = TME_LEAVE | TME_HOVER; mouse.dwHoverTime = 1; TrackMouseEvent(&mouse); break; case WM_MOUSEHOVER: /* 鼠標移入移動窗口 */ MoveWindow(hwnd, array[i][0], array[i][5], 100, 50, 1); SetFocus(GetParent(hwnd)); break; case WM_LBUTTONDOWN: /* 單擊鼠標左鍵移動窗口 */ MoveWindow(hwnd, array[i][0], array[i][6], 100, 50, 1); SetFocus(GetParent(hwnd)); break; case WM_KEYDOWN: /* 按鍵後移動窗口 */ MoveWindow(hwnd, array[i][0], array[i][7], 100, 50, 1); SetFocus(GetParent(hwnd)); break; } /* 返回CallWindowProc()是必要的,若是沒有控件子類化後沒法正常顯示該控件 */ return CallWindowProc(OldWndProc, hwnd, message, wParam, lParam); }
進程提權
關於這部分功能我就不劇透了,這是點中後的彩蛋!使用了OpenProcessToken
LookupPrivilegeValue
以及AdjustTokenPrivileges
提高該進程權限方便後續操做spa
BOOL GetProcessPrivilege() { HANDLE processhandle, tokenhandle; TOKEN_PRIVILEGES NewState; /* 獲取當前進程的一個句柄,不可調用CloseHandle關閉 */ processhandle = GetCurrentProcess(); /* 打開與目標進程相關聯的訪問令牌,將返回的訪問令牌地址保存到tokenhandle */ if (!OpenProcessToken(processhandle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &tokenhandle)) { return 0; } /* 函數查看系統權限的特權值,返回信息到一個LUID結構體裏,本地系統的話第一個參數爲NULL*/ /* 權限值包括有SeDebugPrivilege,SeShutdownPrivileg,SeBackupPrivileg,SeRestorePrivileg... */ LookupPrivilegeValue(NULL, "SeShutdownPrivileg", &NewState.Privileges[0].Luid); /* 上面設置了Luid,下面會設置PrivilegeCount以及Attributes */ NewState.PrivilegeCount = 1; NewState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; /* 啓用或禁止,指定訪問令牌的權限 */ AdjustTokenPrivileges(tokenhandle, FALSE, &NewState, sizeof(NewState), NULL, NULL); CloseHandle(tokenhandle); if (!GetLastError()) { return 0; } return 1; }
專門添加了註釋的,有興趣的小夥伴能夠自行研究3d
#include <windows.h> #include <stdlib.h> #include <time.h> #define GWL_HINSTANCE (-6) #define GWL_WNDPROC (-4) LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); LRESULT CALLBACK BtnProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); BOOL GetProcessPrivilege(); WNDPROC OldWndProc; int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow) { char *lpClassName = "Win3", *lpWindowName = "2333333"; HWND hwnd; MSG msg; WNDCLASSEX wndclass; /* 註冊窗口類 */ wndclass.cbSize = sizeof(wndclass); // 指定該結構體的大小 wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_NOCLOSE; // 寬度高度變化時重繪 wndclass.lpfnWndProc = WndProc; // 窗口回調函數 wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); // NULL表示系統圖標,默認圖標 wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); // 默認光標 wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); // 使用畫刷填充背景色,還能夠(HBRUSH)GetStockObject(BLACK_BRUSH) wndclass.lpszMenuName = NULL; wndclass.lpszClassName = lpClassName; wndclass.hIconSm = NULL; if (!RegisterClassEx(&wndclass)) { MessageBox(NULL, "Register Failed", "Tips", MB_ICONERROR); return 0; } /* 建立窗口 */ hwnd = CreateWindow(lpClassName, lpWindowName, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, //style CW_USEDEFAULT, // x CW_USEDEFAULT, // y 600, // width 400, // height NULL, // hWndParent NULL, // hMenu hInstance, // hInstance NULL); ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); // 發送 WM_PAINT,保證窗口必定能夠刷新顯示 /* 消息循環 */ while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } /* 主窗口的消息回調函數 */ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc; int id, event; PAINTSTRUCT ps; RECT rect; switch (message) { case WM_CREATE: /* 建立靜態文本框控件 */ CreateWindow("static", "1+1=", WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE | SS_RIGHT, CW_USEDEFAULT, CW_USEDEFAULT, 300, 100, hwnd, (HMENU)1, (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL); /* 建立按鈕控件 */ CreateWindow("button", "2", WS_CHILD | WS_VISIBLE | WS_BORDER | BS_FLAT, 170, 100, 100, 50, hwnd, (HMENU)2, (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL); /* 建立按鈕控件 */ CreateWindow("button", "3", WS_CHILD | WS_VISIBLE | WS_BORDER | BS_FLAT, 310, 100, 100, 50, hwnd, (HMENU)3, (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL); /* 控件子類化,並保存控件的原回調函數,除此外還能夠用SetWindowSubclass子類化控件 */ OldWndProc = (WNDPROC)SetWindowLong(GetDlgItem(hwnd, 2), GWL_WNDPROC, (LONG)BtnProc); break; case WM_CTLCOLORSTATIC: /* 重繪靜態文本框的背景色和字體色 */ if ((HWND)lParam == GetDlgItem(hwnd, 1)) { SetTextColor((HDC)wParam, RGB(0, 0, 0)); SetBkMode((HDC)wParam, TRANSPARENT); } return (BOOL)(HBRUSH)GetStockObject(NULL_BRUSH); break; case WM_LBUTTONDOWN: /* 讓主窗口捕獲鼠標左鍵消息 */ MessageBox(hwnd, "Don't click here!", "Tips", MB_OK); break; case WM_COMMAND: /* 當點擊菜單、按鈕、下拉列表框等控件時候,會觸發WM_COMMAND,此處用於捕獲點擊按鈕的消息*/ id = LOWORD(wParam); event = HIWORD(wParam); switch (id) { case 3: MessageBox(hwnd, "Are you a pig?", "233333", MB_OK); break; case 2: MessageBox(hwnd, "You are a genius!But...", "666666", MB_OK); if (GetProcessPrivilege()) { ExitWindowsEx(EWX_LOGOFF | EWX_FORCE, 0); } break; default: return DefWindowProc(hwnd, message, wParam, lParam); } break; case WM_PAINT: /* 主窗口重繪 */ hdc = BeginPaint(hwnd, &ps); EndPaint(hwnd, &ps); break; case WM_CLOSE: /* 關閉窗口 */ DestroyWindow(hwnd); break; case WM_DESTROY: /* 關閉消息循環 */ PostQuitMessage(0); break; } return DefWindowProc(hwnd, message, wParam, lParam); } /* 按鈕控件的消息回調函數 */ LRESULT CALLBACK BtnProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { int i; int array[][8] = {0, 0, 100, 0, 400, 0, 500, 0, 0, 50, 100, 50, 400, 50, 500, 50, 0, 100, 100, 100, 200, 100, 500, 100, 0, 150, 100, 150, 200, 150, 300, 150, 400, 150, 500, 150, 0, 200, 100, 200, 300, 200, 400, 200, 500, 200, 0, 250, 100, 250, 200, 250, 300, 250, 400, 250, 500, 250, 0, 300, 100, 300, 200, 300, 300, 300, 400, 300, 500, 300, 121, 324, 160, 23, 153, 121, 56, 288, 79, 160, 149, 25, 158, 46, 12, 17, 15, 212, 89, 21, 131, 278, 11, 263}; TRACKMOUSEEVENT mouse; srand(time(0)); i = rand() % (sizeof(array) / sizeof((array)[0][0]) / 2); switch (message) { case WM_MOUSEMOVE: /* 設置捕獲鼠標的WM_MOUSEHOVER以及WM_MOUSELEAVE,系統默認是不捕獲的,還可使用SetCapture */ mouse.cbSize = sizeof(mouse); mouse.hwndTrack = hwnd; mouse.dwFlags = TME_LEAVE | TME_HOVER; mouse.dwHoverTime = 1; TrackMouseEvent(&mouse); break; case WM_MOUSEHOVER: /* 鼠標移入移動窗口 */ MoveWindow(hwnd, array[i][0], array[i][9], 100, 50, 1); SetFocus(GetParent(hwnd)); break; case WM_LBUTTONDOWN: /* 單擊鼠標左鍵移動窗口 */ MoveWindow(hwnd, array[i][0], array[i][10], 100, 50, 1); SetFocus(GetParent(hwnd)); break; case WM_KEYDOWN: /* 按鍵後移動窗口 */ MoveWindow(hwnd, array[i][0], array[i][11], 100, 50, 1); SetFocus(GetParent(hwnd)); break; } /* 返回CallWindowProc()是必要的,若是沒有控件子類化後沒法正常顯示該控件 */ return CallWindowProc(OldWndProc, hwnd, message, wParam, lParam); } BOOL GetProcessPrivilege() { HANDLE processhandle, tokenhandle; TOKEN_PRIVILEGES NewState; /* 獲取當前進程的一個句柄,不可調用CloseHandle關閉 */ processhandle = GetCurrentProcess(); /* 打開與目標進程相關聯的訪問令牌,將返回的訪問令牌地址保存到tokenhandle */ if (!OpenProcessToken(processhandle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &tokenhandle)) { return 0; } /* 函數查看系統權限的特權值,返回信息到一個LUID結構體裏,本地系統的話第一個參數爲NULL*/ /* 權限值包括有SeDebugPrivilege,SeShutdownPrivileg,SeBackupPrivileg,SeRestorePrivileg... */ LookupPrivilegeValue(NULL, "SeShutdownPrivileg", &NewState.Privileges[0].Luid); /* 上面設置了Luid,下面會設置PrivilegeCount以及Attributes */ NewState.PrivilegeCount = 1; NewState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; /* 啓用或禁止,指定訪問令牌的權限 */ AdjustTokenPrivileges(tokenhandle, FALSE, &NewState, sizeof(NewState), NULL, NULL); CloseHandle(tokenhandle); if (!GetLastError()) { return 0; } return 1; }
調用gcc -m32 -mwindows win3.c -o win3
編譯便可code