win32 最小化工具

来源:互联网 发布:百帝王啤酒知乎 编辑:程序博客网 时间:2024/06/02 06:15

本文是仿照Trayconizer软件制作。

本文的最小化工具是能够随意控制一个程序并使之最小化,恢复的软件。如在命令行中运行:

Trayconizer.exe C;\windows\notepad.exe; 

将会打开一个记事本,当点击最小化按钮时,会影藏到后台运行,并在托盘中显示记事本的图标,双击记事本恢复窗口,右键点击弹出“Restore”,“Close”菜单。当记事本关闭后,工具软件也会关闭。工具软件是一直在后台运行的,不会显示窗口。

用到了3个枚举窗口函数。

// 枚举窗口函数BOOL CALLBACK fnAdd(HWND hwnd,LPARAM lParam){ShowWindowAsync(hwnd,SW_MINIMIZE);return TRUE;}// 枚举窗口,将图标从图片删除,Restore菜单BOOL CALLBACK fnDelRestore(HWND hwnd,LPARAM lParam){Shell_NotifyIcon(NIM_DELETE,&g_nid);ShowWindowAsync(hwnd,SW_SHOW);ShowWindowAsync(hwnd,SW_RESTORE);SetForegroundWindow(hwnd);return TRUE;}// 枚举窗口函数,将图标从托盘删除,Close菜单BOOL CALLBACK fnDelClose(HWND hwnd,LPARAM lParam){Shell_NotifyIcon(NIM_DELETE,&g_nid);PostMessage(hwnd,WM_CLOSE,0,0);return TRUE;}

使用钩子来截取应用程序的最小化消息。

// 窗口最小化处理函数void CALLBACK MinProc(HWINEVENTHOOK hWinEventHook,DWORD dwEvent,HWND hwnd,LONG idObject,LONG idChild,DWORD dwEventThread,DWORD dwMsEventTime){#ifdef _DEBUG_WCHAR pwchMsg[128] = { 0 };wsprintf(pwchMsg,_T("%x %x\n"),dwEvent,dwEventThread);WriteConsole(g_hOutput,pwchMsg,wcslen(pwchMsg),NULL,NULL);#endifif(dwEvent == EVENT_SYSTEM_MINIMIZESTART) // 最小化{g_nid.cbSize = sizeof(NOTIFYICONDATA);g_nid.uID = MY_TRAY_ICON_ID;g_nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;g_nid.hWnd = g_hWnd;g_nid.uCallbackMessage = WM_MYMSG;wcscpy_s(g_nid.szTip,g_pwchCmdLine);HICON hIcon = (HICON)SendMessage(hwnd,WM_GETICON,ICON_SMALL,0);if(NULL == hIcon){hIcon = (HICON)SendMessage(hwnd,WM_GETICON,ICON_SMALL2,0);if(hIcon == NULL){hIcon = (HICON)SendMessage(hwnd,WM_GETICON,ICON_BIG,0);if(hIcon == NULL){hIcon = (HICON)GetClassLong(hwnd,GCL_HICON);if(hIcon == NULL){SHFILEINFO stFileInfo;::SHGetFileInfo(g_pwchCmdLine,0,&stFileInfo,sizeof(stFileInfo),SHGFI_ICON);hIcon = stFileInfo.hIcon;if(NULL==hIcon)hIcon = LoadIcon(g_hInst,MAKEINTRESOURCE(IDI_TRAYCONIZER));}}}}g_nid.hIcon = hIcon;Shell_NotifyIcon(NIM_ADD,&g_nid);ShowWindow(hwnd,SW_HIDE);}/*else if(dwEvent == EVENT_SYSTEM_MINIMIZEEND){EnumThreadWindows(g_dwTrayPid,fnDelRestore,0);}else if(dwEvent == EVENT_OBJECT_DESTROY) // 关闭{SendMessage(g_hWnd,WM_CLOSE,0,0);}*/}
使用线程监视应用进程是否已经关闭。

// 等待进程关闭,然后结束进程DWORD CALLBACK WaitForClose(LPVOID lpParam){HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS,FALSE,g_dwTrayPid);WaitForSingleObject(hProc,INFINITE);SendMessage(g_hWnd,WM_CLOSE,0,0);return 0;}

完整源码:

// Traynizer.cpp : 定义应用程序的入口点。//#include "stdafx.h"#include "Trayconizer.h"#include "shellapi.h"//#define _DEBUG_HINSTANCE g_hInst = NULL;const int WM_MYMSG           =   WM_USER + 1;const int MY_TRAY_ICON_ID    = 152;const int IDM_RESTORE   =   2001;const int IDM_CLOSE     =   2002;const LPWSTR gc_aMinimize = _T("-minimize");HWND g_hWnd = NULL;LPWSTR g_lpAppName = _T("Win32");WCHAR g_pwchCmdLine[128];NOTIFYICONDATA g_nid = { 0 };DWORD g_dwTrayPid,g_dwTrayTid;#ifdef _DEBUG_HANDLE g_hOutput = NULL;  // 输出窗口句柄#endif// 主窗口回调函数LRESULT CALLBACK WinProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);// 枚举窗口函数,将图标添加到托盘BOOL CALLBACK fnAdd(HWND hwnd,LPARAM lParam);// 枚举窗口函数,将图标从托盘删除,Restore菜单BOOL CALLBACK fnDelRestore(HWND hwnd,LPARAM lParam);// 枚举窗口函数,将图标从图片删除,Close菜单BOOL CALLBACK fnDelClose(HWND hwnd,LPARAM lParam);// 窗口最小化处理函数void CALLBACK MinProc(HWINEVENTHOOK hWinEventHook,DWORD dwEvent,HWND hwnd,LONG idObject,LONG idChild,DWORD dwEventThread,DWORD dwMsEventTime);// 等待进程关闭DWORD CALLBACK WaitForClose(LPVOID lpParam);// 结束进程BOOL TerminateProcessFromID(DWORD id);// 解析命令行BOOL DecordCmdLine(LPWSTR lpwstrCmd);// 主函数int APIENTRY _tWinMain(HINSTANCE hInstance,                       HINSTANCE hPrevInstance,                       LPTSTR    lpCmdLine,                       int       nCmdShow){#ifdef _DEBUG_AllocConsole();g_hOutput = GetStdHandle(STD_OUTPUT_HANDLE);#endif//wcscpy(lpCmdLine,_T("-minimize C:\\windows\\notepad.exe"));BOOL bFlag = DecordCmdLine(lpCmdLine);/*********************************************** 进程创建过程 **/STARTUPINFO si = { 0 };si.cb = sizeof(STARTUPINFO);PROCESS_INFORMATION pi = { 0 };if(wcslen(lpCmdLine)<=0){MessageBoxW(NULL,_T("Trayconizer 1.1.1, by WhitSoft Development\n")_T("http://www.whitsoftdev.com/trayconizer/\n")_T("\n")_T("The easiest way to use Trayconizer is to set the target of a shortcut to the path of the Trayconizer executable f")_T("ollowed by the path of the program you want to Trayconize. For example:\n")_T("C:\\path\\to\\Trayconizer.exe C:\\Windows\\Regedit.exe\n")_T("\n")_T("You can also tell Trayconizer to start the program in the Trayconized state using the -minimize command line swit")_T("ch. For example:\n")_T("C:\\path\\to\\Trayconizer.exe -minimize C:\\Windows\\Regedit.exe\n")_T("\n")_T("Note that not all programs can be Trayconized, so your mileage may vary. Enjoy!"),_T("Trayconizer"),0x40u);ExitProcess(0);return 0;}if(!CreateProcess(NULL,lpCmdLine,0,0,0,0,0,0,&si,&pi)){WCHAR pwchMsg[128];DWORD dwErr = GetLastError();if(dwErr == 740){wsprintf(pwchMsg,_T("Unable to start %s . require Administrator!"),lpCmdLine);}else{wsprintf(pwchMsg,_T("Unable to start %s . %d"),lpCmdLine,GetLastError());}MessageBox(NULL,pwchMsg,_T("Trayconizer"),MB_OK | MB_ICONINFORMATION);ExitProcess(0);return 0;}g_dwTrayPid= pi.dwProcessId;g_dwTrayTid = pi.dwThreadId;WaitForInputIdle(pi.hProcess,0xffffffff);#ifdef _DEBUG_WCHAR pwchMsg[128];wsprintf(pwchMsg,_T("pid:%d tid:%d\n"),g_dwTrayPid,g_dwTrayTid);WriteConsole(g_hOutput,pwchMsg,wcslen(pwchMsg),NULL,NULL);#endifCloseHandle(pi.hProcess);CloseHandle(pi.hThread);wcscpy(g_pwchCmdLine,lpCmdLine);/*********************************************************//***************  主窗口创建过程 ***************/HWND hwnd = FindWindow(g_lpAppName,_T("Trayconizer"));if(hwnd){g_hWnd = hwnd;}else{WNDCLASS wndcls = { 0 };wndcls.style = CS_HREDRAW | CS_VREDRAW;wndcls.cbClsExtra = 0;wndcls.cbWndExtra = 0;wndcls.hInstance = hInstance;wndcls.lpfnWndProc = WinProc;wndcls.lpszClassName = g_lpAppName;wndcls.hIcon = LoadIcon(NULL,MAKEINTRESOURCE(IDI_TRAYCONIZER));wndcls.hCursor = LoadCursor(NULL,IDC_ARROW);wndcls.lpszMenuName = NULL;wndcls.hbrBackground = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));if(!RegisterClass(&wndcls)){MessageBox(NULL,_T("注册窗口类失败"),_T("tips"),MB_ICONINFORMATION | MB_OK);return 0;}g_hWnd = CreateWindow(g_lpAppName,_T("Trayconizer"),WS_OVERLAPPEDWINDOW,0,0,0,0,NULL,NULL,hInstance,0);if(g_hWnd == NULL){MessageBox(NULL,_T("窗口创建失败!"),0,0);TerminateProcessFromID(g_dwTrayPid);ExitProcess(0);return 0;}g_hInst = hInstance;}/****************************************************/if(!SetWinEventHook(EVENT_MIN,EVENT_MAX,NULL,MinProc,g_dwTrayPid,g_dwTrayTid,WINEVENT_OUTOFCONTEXT)){WCHAR pwchMsg[64];wsprintf(pwchMsg,_T("SetWinEventHook failed . %d"),GetLastError());MessageBox(NULL,pwchMsg,0,MB_ICONINFORMATION | MB_OK);TerminateProcessFromID(g_dwTrayPid);ExitProcess(0);return 0;}if(bFlag) // 最小化窗口{if(!EnumThreadWindows(g_dwTrayTid,fnAdd,0)){DWORD dwErr = GetLastError();WCHAR lpwstr[64] = { 0 };wsprintf(lpwstr,_T("EnumThreadWindows failed . %d"),dwErr);MessageBox(NULL,lpwstr,_T("Trayconizer"),MB_OK | MB_ICONINFORMATION);TerminateProcessFromID(g_dwTrayPid);SendMessage(g_hWnd,WM_CLOSE,-1,0);ExitProcess(0);return 0;}}DWORD dwId;HANDLE hThrd = CreateThread(NULL,NULL,WaitForClose,NULL,0,&dwId);if(NULL == hThrd){WCHAR pwchMsg[64];wsprintf(pwchMsg,_T("CreateThread failed . %d"),GetLastError());MessageBox(NULL,pwchMsg,_T("tip"),MB_OK | MB_ICONINFORMATION);TerminateProcessFromID(g_dwTrayPid);SendMessage(g_hWnd,WM_CLOSE,0,0);ExitProcess(0);return 0;}MSG msg;while(GetMessage(&msg,NULL,0,0)){TranslateMessage(&msg);DispatchMessage(&msg);}return 0;}//解析命令行BOOL DecordCmdLine(LPWSTR lpwstrCmd){int len = wcslen(lpwstrCmd);LPWSTR lpwstrtmp = new WCHAR[len];memset(lpwstrtmp,0,sizeof(lpwstrtmp));if(*lpwstrCmd == _T('-')){int ispace = 0;for(ispace =0;ispace<len;ispace++){lpwstrtmp[ispace] = lpwstrCmd[ispace];if(lpwstrCmd[ispace] == _T(' ')) {lpwstrtmp[ispace] = 0;;break;}}if(ispace != 0 && ispace < len) {if(wcscmp(lpwstrtmp,gc_aMinimize) == 0){LPWSTR lpwstrNewCmd = new WCHAR[len-ispace+2];memset(lpwstrNewCmd,0,sizeof(lpwstrNewCmd));int j = 0;for(int i=ispace+1;i<len;i++,j++)lpwstrNewCmd[j] = lpwstrCmd[i];lpwstrNewCmd[j] = 0;wcscpy(lpwstrCmd,lpwstrNewCmd);delete[] lpwstrNewCmd;return TRUE;}}}return FALSE;}// 窗口回调函数LRESULT CALLBACK WinProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam){switch (msg){case WM_CLOSE:PostQuitMessage(0);return 1;case WM_COMMAND:{switch(wParam){case IDM_CLOSE:EnumThreadWindows(g_dwTrayTid,fnDelClose,0);PostMessage(g_hWnd,WM_CLOSE,0,0);return 0;case IDM_RESTORE:EnumThreadWindows(g_dwTrayTid,fnDelRestore,0);return 0;}}break;case WM_MYMSG:switch(lParam){case WM_LBUTTONDBLCLK:EnumThreadWindows(g_dwTrayTid,fnDelRestore,0);break;case WM_RBUTTONUP:{POINT pt;GetCursorPos(&pt);HMENU hMenu = CreatePopupMenu();AppendMenu(hMenu,MF_INSERT,IDM_RESTORE,_T("Restore"));AppendMenu(hMenu,MF_INSERT,IDM_CLOSE,_T("Close"));SetMenuDefaultItem(hMenu,IDM_RESTORE,0);TrackPopupMenu(hMenu,TPM_RIGHTBUTTON,pt.x,pt.y,NULL,hwnd,NULL);DestroyMenu(hMenu);}break;}break;}return DefWindowProc(hwnd,msg,wParam,lParam);}// 枚举窗口函数BOOL CALLBACK fnAdd(HWND hwnd,LPARAM lParam){ShowWindowAsync(hwnd,SW_MINIMIZE);return TRUE;}// 枚举窗口,将图标从图片删除,Restore菜单BOOL CALLBACK fnDelRestore(HWND hwnd,LPARAM lParam){Shell_NotifyIcon(NIM_DELETE,&g_nid);ShowWindowAsync(hwnd,SW_SHOW);ShowWindowAsync(hwnd,SW_RESTORE);SetForegroundWindow(hwnd);return TRUE;}// 枚举窗口函数,将图标从托盘删除,Close菜单BOOL CALLBACK fnDelClose(HWND hwnd,LPARAM lParam){Shell_NotifyIcon(NIM_DELETE,&g_nid);PostMessage(hwnd,WM_CLOSE,0,0);return TRUE;}// 窗口最小化处理函数void CALLBACK MinProc(HWINEVENTHOOK hWinEventHook,DWORD dwEvent,HWND hwnd,LONG idObject,LONG idChild,DWORD dwEventThread,DWORD dwMsEventTime){#ifdef _DEBUG_WCHAR pwchMsg[128] = { 0 };wsprintf(pwchMsg,_T("%x %x\n"),dwEvent,dwEventThread);WriteConsole(g_hOutput,pwchMsg,wcslen(pwchMsg),NULL,NULL);#endifif(dwEvent == EVENT_SYSTEM_MINIMIZESTART) // 最小化{g_nid.cbSize = sizeof(NOTIFYICONDATA);g_nid.uID = MY_TRAY_ICON_ID;g_nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;g_nid.hWnd = g_hWnd;g_nid.uCallbackMessage = WM_MYMSG;wcscpy_s(g_nid.szTip,g_pwchCmdLine);HICON hIcon = (HICON)SendMessage(hwnd,WM_GETICON,ICON_SMALL,0);if(NULL == hIcon){hIcon = (HICON)SendMessage(hwnd,WM_GETICON,ICON_SMALL2,0);if(hIcon == NULL){hIcon = (HICON)SendMessage(hwnd,WM_GETICON,ICON_BIG,0);if(hIcon == NULL){hIcon = (HICON)GetClassLong(hwnd,GCL_HICON);if(hIcon == NULL){SHFILEINFO stFileInfo;::SHGetFileInfo(g_pwchCmdLine,0,&stFileInfo,sizeof(stFileInfo),SHGFI_ICON);hIcon = stFileInfo.hIcon;if(NULL==hIcon)hIcon = LoadIcon(g_hInst,MAKEINTRESOURCE(IDI_TRAYCONIZER));}}}}g_nid.hIcon = hIcon;Shell_NotifyIcon(NIM_ADD,&g_nid);ShowWindow(hwnd,SW_HIDE);}/*else if(dwEvent == EVENT_SYSTEM_MINIMIZEEND){EnumThreadWindows(g_dwTrayPid,fnDelRestore,0);}else if(dwEvent == EVENT_OBJECT_DESTROY) // 关闭{SendMessage(g_hWnd,WM_CLOSE,0,0);}*/}// 等待进程关闭,然后结束进程DWORD CALLBACK WaitForClose(LPVOID lpParam){HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS,FALSE,g_dwTrayPid);WaitForSingleObject(hProc,INFINITE);SendMessage(g_hWnd,WM_CLOSE,0,0);return 0;}// 通过进程ID关闭进程BOOL TerminateProcessFromID(DWORD id){HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,id);if(hProcess!=NULL){return TerminateProcess(hProcess,0);}CloseHandle(hProcess);return FALSE;}




原创粉丝点击