1 /* 2 * PROJECT: ReactOS Task Manager 3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) 4 * PURPOSE: Applications Page 5 * COPYRIGHT: Copyright 1999-2001 Brian Palmer <brianp@reactos.org> 6 * Copyright 2005 Klemens Friedl <frik85@reactos.at> 7 * Copyright 2021 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> 8 */ 9 10 #include "precomp.h" 11 12 typedef struct 13 { 14 HWND hWnd; 15 WCHAR szTitle[260]; 16 HICON hIcon; 17 BOOL bHung; 18 } APPLICATION_PAGE_LIST_ITEM, *LPAPPLICATION_PAGE_LIST_ITEM; 19 20 HWND hApplicationPage; /* Application List Property Page */ 21 HWND hApplicationPageListCtrl; /* Application ListCtrl Window */ 22 HWND hApplicationPageEndTaskButton; /* Application End Task button */ 23 HWND hApplicationPageSwitchToButton; /* Application Switch To button */ 24 HWND hApplicationPageNewTaskButton; /* Application New Task button */ 25 static int nApplicationPageWidth; 26 static int nApplicationPageHeight; 27 static BOOL bSortAscending = TRUE; 28 DWORD WINAPI ApplicationPageRefreshThread(void *lpParameter); 29 BOOL noApps; 30 BOOL bApplicationPageSelectionMade = FALSE; 31 32 BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam); 33 void AddOrUpdateHwnd(HWND hWnd, WCHAR *szTitle, HICON hIcon, BOOL bHung); 34 void ApplicationPageUpdate(void); 35 void ApplicationPageOnNotify(WPARAM wParam, LPARAM lParam); 36 void ApplicationPageShowContextMenu1(void); 37 void ApplicationPageShowContextMenu2(void); 38 int CALLBACK ApplicationPageCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); 39 int ProcGetIndexByProcessId(DWORD dwProcessId); 40 41 #ifdef RUN_APPS_PAGE 42 static HANDLE hApplicationThread = NULL; 43 static DWORD dwApplicationThread; 44 #endif 45 46 static INT 47 GetSystemColorDepth(VOID) 48 { 49 DEVMODE pDevMode; 50 INT ColorDepth; 51 52 pDevMode.dmSize = sizeof(DEVMODE); 53 pDevMode.dmDriverExtra = 0; 54 55 if (!EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &pDevMode)) 56 return ILC_COLOR; 57 58 switch (pDevMode.dmBitsPerPel) 59 { 60 case 32: ColorDepth = ILC_COLOR32; break; 61 case 24: ColorDepth = ILC_COLOR24; break; 62 case 16: ColorDepth = ILC_COLOR16; break; 63 case 8: ColorDepth = ILC_COLOR8; break; 64 case 4: ColorDepth = ILC_COLOR4; break; 65 default: ColorDepth = ILC_COLOR; break; 66 } 67 68 return ColorDepth; 69 } 70 71 void AppPageCleanup(void) 72 { 73 int i; 74 LV_ITEM item; 75 LPAPPLICATION_PAGE_LIST_ITEM pData; 76 for (i = 0; i < ListView_GetItemCount(hApplicationPageListCtrl); i++) 77 { 78 memset(&item, 0, sizeof(LV_ITEM)); 79 item.mask = LVIF_PARAM; 80 item.iItem = i; 81 (void)ListView_GetItem(hApplicationPageListCtrl, &item); 82 pData = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam; 83 HeapFree(GetProcessHeap(), 0, pData); 84 } 85 } 86 87 88 INT_PTR CALLBACK 89 ApplicationPageWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 90 { 91 RECT rc; 92 int nXDifference; 93 int nYDifference; 94 LV_COLUMN column; 95 WCHAR szTemp[256]; 96 int cx, cy; 97 98 switch (message) { 99 case WM_INITDIALOG: 100 /* Save the width and height */ 101 GetClientRect(hDlg, &rc); 102 nApplicationPageWidth = rc.right; 103 nApplicationPageHeight = rc.bottom; 104 105 /* Update window position */ 106 SetWindowPos(hDlg, NULL, 15, 30, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER); 107 108 /* Get handles to the controls */ 109 hApplicationPageListCtrl = GetDlgItem(hDlg, IDC_APPLIST); 110 hApplicationPageEndTaskButton = GetDlgItem(hDlg, IDC_ENDTASK); 111 hApplicationPageSwitchToButton = GetDlgItem(hDlg, IDC_SWITCHTO); 112 hApplicationPageNewTaskButton = GetDlgItem(hDlg, IDC_NEWTASK); 113 114 SetWindowTextW(hApplicationPageListCtrl, L"Tasks"); 115 116 /* Initialize the application page's controls */ 117 column.mask = LVCF_TEXT|LVCF_WIDTH; 118 119 LoadStringW(hInst, IDS_TAB_TASK, szTemp, 256); 120 column.pszText = szTemp; 121 column.cx = 250; 122 (void)ListView_InsertColumn(hApplicationPageListCtrl, 0, &column); /* Add the "Task" column */ 123 column.mask = LVCF_TEXT|LVCF_WIDTH; 124 LoadStringW(hInst, IDS_TAB_STATUS, szTemp, 256); 125 column.pszText = szTemp; 126 column.cx = 95; 127 (void)ListView_InsertColumn(hApplicationPageListCtrl, 1, &column); /* Add the "Status" column */ 128 129 (void)ListView_SetImageList(hApplicationPageListCtrl, ImageList_Create(16, 16, GetSystemColorDepth()|ILC_MASK, 0, 1), LVSIL_SMALL); 130 (void)ListView_SetImageList(hApplicationPageListCtrl, ImageList_Create(32, 32, GetSystemColorDepth()|ILC_MASK, 0, 1), LVSIL_NORMAL); 131 132 UpdateApplicationListControlViewSetting(); 133 134 /* Start our refresh thread */ 135 #ifdef RUN_APPS_PAGE 136 hApplicationThread = CreateThread(NULL, 0, ApplicationPageRefreshThread, NULL, 0, &dwApplicationThread); 137 #endif 138 139 /* Refresh page */ 140 ApplicationPageUpdate(); 141 142 return TRUE; 143 144 case WM_DESTROY: 145 /* Close refresh thread */ 146 #ifdef RUN_APPS_PAGE 147 EndLocalThread(&hApplicationThread, dwApplicationThread); 148 #endif 149 AppPageCleanup(); 150 break; 151 152 case WM_COMMAND: 153 /* Handle the button clicks */ 154 switch (LOWORD(wParam)) 155 { 156 case IDC_ENDTASK: 157 ApplicationPage_OnEndTask(); 158 break; 159 case IDC_SWITCHTO: 160 ApplicationPage_OnSwitchTo(); 161 break; 162 case IDC_NEWTASK: 163 SendMessageW(hMainWnd, WM_COMMAND, MAKEWPARAM(ID_FILE_NEW, 0), 0); 164 break; 165 } 166 167 break; 168 169 case WM_SIZE: 170 if (wParam == SIZE_MINIMIZED) 171 return 0; 172 173 cx = LOWORD(lParam); 174 cy = HIWORD(lParam); 175 nXDifference = cx - nApplicationPageWidth; 176 nYDifference = cy - nApplicationPageHeight; 177 nApplicationPageWidth = cx; 178 nApplicationPageHeight = cy; 179 180 /* Reposition the application page's controls */ 181 GetWindowRect(hApplicationPageListCtrl, &rc); 182 cx = (rc.right - rc.left) + nXDifference; 183 cy = (rc.bottom - rc.top) + nYDifference; 184 SetWindowPos(hApplicationPageListCtrl, NULL, 0, 0, cx, cy, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOMOVE|SWP_NOZORDER); 185 InvalidateRect(hApplicationPageListCtrl, NULL, TRUE); 186 187 GetClientRect(hApplicationPageEndTaskButton, &rc); 188 MapWindowPoints(hApplicationPageEndTaskButton, hDlg, (LPPOINT)(PRECT)(&rc), sizeof(RECT)/sizeof(POINT)); 189 cx = rc.left + nXDifference; 190 cy = rc.top + nYDifference; 191 SetWindowPos(hApplicationPageEndTaskButton, NULL, cx, cy, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER); 192 InvalidateRect(hApplicationPageEndTaskButton, NULL, TRUE); 193 194 GetClientRect(hApplicationPageSwitchToButton, &rc); 195 MapWindowPoints(hApplicationPageSwitchToButton, hDlg, (LPPOINT)(PRECT)(&rc), sizeof(RECT)/sizeof(POINT)); 196 cx = rc.left + nXDifference; 197 cy = rc.top + nYDifference; 198 SetWindowPos(hApplicationPageSwitchToButton, NULL, cx, cy, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER); 199 InvalidateRect(hApplicationPageSwitchToButton, NULL, TRUE); 200 201 GetClientRect(hApplicationPageNewTaskButton, &rc); 202 MapWindowPoints(hApplicationPageNewTaskButton, hDlg, (LPPOINT)(PRECT)(&rc), sizeof(RECT)/sizeof(POINT)); 203 cx = rc.left + nXDifference; 204 cy = rc.top + nYDifference; 205 SetWindowPos(hApplicationPageNewTaskButton, NULL, cx, cy, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER); 206 InvalidateRect(hApplicationPageNewTaskButton, NULL, TRUE); 207 208 break; 209 210 case WM_NOTIFY: 211 ApplicationPageOnNotify(wParam, lParam); 212 break; 213 214 case WM_KEYDOWN: 215 if (wParam == VK_DELETE) 216 ProcessPage_OnEndProcess(); 217 break; 218 } 219 220 return 0; 221 } 222 223 void RefreshApplicationPage(void) 224 { 225 #ifdef RUN_APPS_PAGE 226 /* Signal the event so that our refresh thread 227 * will wake up and refresh the application page */ 228 PostThreadMessage(dwApplicationThread, WM_TIMER, 0, 0); 229 #endif 230 } 231 232 void UpdateApplicationListControlViewSetting(void) 233 { 234 DWORD dwStyle = GetWindowLongPtrW(hApplicationPageListCtrl, GWL_STYLE); 235 236 dwStyle &= ~(LVS_REPORT | LVS_ICON | LVS_LIST | LVS_SMALLICON); 237 238 switch (TaskManagerSettings.ViewMode) { 239 case ID_VIEW_LARGE: dwStyle |= LVS_ICON; break; 240 case ID_VIEW_SMALL: dwStyle |= LVS_SMALLICON; break; 241 case ID_VIEW_DETAILS: dwStyle |= LVS_REPORT; break; 242 } 243 SetWindowLongPtrW(hApplicationPageListCtrl, GWL_STYLE, dwStyle); 244 245 RefreshApplicationPage(); 246 } 247 248 DWORD WINAPI ApplicationPageRefreshThread(void *lpParameter) 249 { 250 MSG msg; 251 INT i; 252 BOOL bItemRemoved = FALSE; 253 LV_ITEM item; 254 LPAPPLICATION_PAGE_LIST_ITEM pAPLI = NULL; 255 HIMAGELIST hImageListLarge; 256 HIMAGELIST hImageListSmall; 257 258 /* If we couldn't create the event then exit the thread */ 259 while (1) 260 { 261 /* Wait for an the event or application close */ 262 if (GetMessage(&msg, NULL, 0, 0) <= 0) 263 return 0; 264 265 if (msg.message == WM_TIMER) 266 { 267 // FIXME: Should this be EnumDesktopWindows() instead? 268 noApps = TRUE; 269 EnumWindows(EnumWindowsProc, 0); 270 if (noApps) 271 { 272 (void)ListView_DeleteAllItems(hApplicationPageListCtrl); 273 bApplicationPageSelectionMade = FALSE; 274 } 275 276 /* Get the image lists */ 277 hImageListLarge = ListView_GetImageList(hApplicationPageListCtrl, LVSIL_NORMAL); 278 hImageListSmall = ListView_GetImageList(hApplicationPageListCtrl, LVSIL_SMALL); 279 280 /* Check to see if we need to remove any items from the list */ 281 for (i=ListView_GetItemCount(hApplicationPageListCtrl)-1; i>=0; i--) 282 { 283 memset(&item, 0, sizeof(LV_ITEM)); 284 item.mask = LVIF_IMAGE|LVIF_PARAM; 285 item.iItem = i; 286 (void)ListView_GetItem(hApplicationPageListCtrl, &item); 287 288 pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam; 289 if (!IsWindow(pAPLI->hWnd)|| 290 (wcslen(pAPLI->szTitle) <= 0) || 291 !IsWindowVisible(pAPLI->hWnd) || 292 (GetParent(pAPLI->hWnd) != NULL) || 293 (GetWindow(pAPLI->hWnd, GW_OWNER) != NULL) || 294 (GetWindowLongPtr(pAPLI->hWnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW)) 295 { 296 ImageList_Remove(hImageListLarge, item.iItem); 297 ImageList_Remove(hImageListSmall, item.iItem); 298 299 (void)ListView_DeleteItem(hApplicationPageListCtrl, item.iItem); 300 HeapFree(GetProcessHeap(), 0, pAPLI); 301 bItemRemoved = TRUE; 302 } 303 } 304 305 /* 306 * If an item was removed from the list then 307 * we need to resync all the items with the 308 * image list 309 */ 310 if (bItemRemoved) 311 { 312 for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) 313 { 314 memset(&item, 0, sizeof(LV_ITEM)); 315 item.mask = LVIF_IMAGE; 316 item.iItem = i; 317 item.iImage = i; 318 (void)ListView_SetItem(hApplicationPageListCtrl, &item); 319 } 320 bItemRemoved = FALSE; 321 } 322 323 ApplicationPageUpdate(); 324 } 325 } 326 } 327 328 BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam) 329 { 330 HICON hIcon; 331 WCHAR szText[260]; 332 BOOL bLargeIcon; 333 BOOL bHung = FALSE; 334 LRESULT bAlive; 335 336 typedef int (FAR __stdcall *IsHungAppWindowProc)(HWND); 337 IsHungAppWindowProc IsHungAppWindow; 338 339 /* Skip our window */ 340 if (hWnd == hMainWnd) 341 return TRUE; 342 343 bLargeIcon = (TaskManagerSettings.ViewMode == ID_VIEW_LARGE); 344 345 GetWindowTextW(hWnd, szText, 260); /* Get the window text */ 346 347 /* Check and see if this is a top-level app window */ 348 if ((wcslen(szText) <= 0) || 349 !IsWindowVisible(hWnd) || 350 (GetParent(hWnd) != NULL) || 351 (GetWindow(hWnd, GW_OWNER) != NULL) || 352 (GetWindowLongPtrW(hWnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW)) 353 { 354 return TRUE; /* Skip this window */ 355 } 356 357 noApps = FALSE; 358 359 #define GET_ICON(type) \ 360 SendMessageTimeoutW(hWnd, WM_GETICON, (type), 0, SMTO_ABORTIFHUNG, 100, (PDWORD_PTR)&hIcon) 361 362 /* Get the icon for this window */ 363 hIcon = NULL; 364 bAlive = GET_ICON(bLargeIcon ? ICON_BIG : ICON_SMALL); 365 if (!hIcon) 366 { 367 /* We failed, try to retrieve other icons... */ 368 if (!hIcon && bAlive) 369 GET_ICON(bLargeIcon ? ICON_SMALL : ICON_BIG); 370 if (!hIcon) 371 hIcon = (HICON)(LONG_PTR)GetClassLongPtrW(hWnd, bLargeIcon ? GCL_HICON : GCL_HICONSM); 372 if (!hIcon) 373 hIcon = (HICON)(LONG_PTR)GetClassLongPtrW(hWnd, bLargeIcon ? GCL_HICONSM : GCL_HICON); 374 375 /* If we still do not have any icon, load the default one */ 376 if (!hIcon) hIcon = LoadIconW(hInst, bLargeIcon ? MAKEINTRESOURCEW(IDI_WINDOW) : MAKEINTRESOURCEW(IDI_WINDOWSM)); 377 } 378 #undef GET_ICON 379 380 bHung = FALSE; 381 382 IsHungAppWindow = (IsHungAppWindowProc)(FARPROC)GetProcAddress(GetModuleHandleW(L"USER32.DLL"), "IsHungAppWindow"); 383 384 if (IsHungAppWindow) 385 bHung = IsHungAppWindow(hWnd); 386 387 AddOrUpdateHwnd(hWnd, szText, hIcon, bHung); 388 389 return TRUE; 390 } 391 392 void AddOrUpdateHwnd(HWND hWnd, WCHAR *szTitle, HICON hIcon, BOOL bHung) 393 { 394 LPAPPLICATION_PAGE_LIST_ITEM pAPLI = NULL; 395 HIMAGELIST hImageListLarge; 396 HIMAGELIST hImageListSmall; 397 LV_ITEM item; 398 int i; 399 BOOL bAlreadyInList = FALSE; 400 401 memset(&item, 0, sizeof(LV_ITEM)); 402 403 /* Get the image lists */ 404 hImageListLarge = ListView_GetImageList(hApplicationPageListCtrl, LVSIL_NORMAL); 405 hImageListSmall = ListView_GetImageList(hApplicationPageListCtrl, LVSIL_SMALL); 406 407 /* Check to see if it's already in our list */ 408 for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) 409 { 410 memset(&item, 0, sizeof(LV_ITEM)); 411 item.mask = LVIF_IMAGE|LVIF_PARAM; 412 item.iItem = i; 413 (void)ListView_GetItem(hApplicationPageListCtrl, &item); 414 415 pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam; 416 if (pAPLI->hWnd == hWnd) 417 { 418 bAlreadyInList = TRUE; 419 break; 420 } 421 } 422 423 /* If it is already in the list then update it if necessary */ 424 if (bAlreadyInList) 425 { 426 /* Check to see if anything needs updating */ 427 if ((pAPLI->hIcon != hIcon) || 428 (_wcsicmp(pAPLI->szTitle, szTitle) != 0) || 429 (pAPLI->bHung != bHung)) 430 { 431 /* Update the structure */ 432 pAPLI->hIcon = hIcon; 433 pAPLI->bHung = bHung; 434 wcscpy(pAPLI->szTitle, szTitle); 435 436 /* Update the image list */ 437 ImageList_ReplaceIcon(hImageListLarge, item.iItem, hIcon); 438 ImageList_ReplaceIcon(hImageListSmall, item.iItem, hIcon); 439 440 /* Update the list view */ 441 (void)ListView_RedrawItems(hApplicationPageListCtrl, 0, ListView_GetItemCount(hApplicationPageListCtrl)); 442 /* UpdateWindow(hApplicationPageListCtrl); */ 443 InvalidateRect(hApplicationPageListCtrl, NULL, 0); 444 } 445 } 446 else 447 { // It is not already in the list so add it 448 pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)HeapAlloc(GetProcessHeap(), 0, sizeof(APPLICATION_PAGE_LIST_ITEM)); 449 450 pAPLI->hWnd = hWnd; 451 pAPLI->hIcon = hIcon; 452 pAPLI->bHung = bHung; 453 wcscpy(pAPLI->szTitle, szTitle); 454 455 /* Add the item to the list */ 456 memset(&item, 0, sizeof(LV_ITEM)); 457 item.mask = LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM; 458 ImageList_AddIcon(hImageListLarge, hIcon); 459 item.iImage = ImageList_AddIcon(hImageListSmall, hIcon); 460 item.pszText = LPSTR_TEXTCALLBACK; 461 item.iItem = ListView_GetItemCount(hApplicationPageListCtrl); 462 item.lParam = (LPARAM)pAPLI; 463 (void)ListView_InsertItem(hApplicationPageListCtrl, &item); 464 } 465 466 /* Select first item if any */ 467 if ((ListView_GetNextItem(hApplicationPageListCtrl, -1, LVNI_FOCUSED | LVNI_SELECTED) == -1) && 468 (ListView_GetItemCount(hApplicationPageListCtrl) > 0) && !bApplicationPageSelectionMade) 469 { 470 ListView_SetItemState(hApplicationPageListCtrl, 0, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); 471 bApplicationPageSelectionMade = TRUE; 472 } 473 } 474 475 void ApplicationPageUpdate(void) 476 { 477 /* Enable or disable the "End Task" & "Switch To" buttons */ 478 if (ListView_GetSelectedCount(hApplicationPageListCtrl)) 479 EnableWindow(hApplicationPageEndTaskButton, TRUE); 480 else 481 EnableWindow(hApplicationPageEndTaskButton, FALSE); 482 483 /* Enable "Switch To" button only if only one app is selected */ 484 EnableWindow(hApplicationPageSwitchToButton, (ListView_GetSelectedCount(hApplicationPageListCtrl) == 1)); 485 486 /* If we are on the applications tab the windows menu will be */ 487 /* present on the menu bar so enable & disable the menu items */ 488 if (TabCtrl_GetCurSel(hTabWnd) == 0) 489 { 490 HMENU hMenu; 491 HMENU hWindowsMenu; 492 493 hMenu = GetMenu(hMainWnd); 494 hWindowsMenu = GetSubMenu(hMenu, 3); 495 496 if (ListView_GetSelectedCount(hApplicationPageListCtrl) == 1) 497 { // Only one item selected 498 EnableMenuItem(hWindowsMenu, ID_WINDOWS_TILEHORIZONTALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 499 EnableMenuItem(hWindowsMenu, ID_WINDOWS_TILEVERTICALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 500 EnableMenuItem(hWindowsMenu, ID_WINDOWS_MINIMIZE, MF_BYCOMMAND|MF_ENABLED); 501 EnableMenuItem(hWindowsMenu, ID_WINDOWS_MAXIMIZE, MF_BYCOMMAND|MF_ENABLED); 502 EnableMenuItem(hWindowsMenu, ID_WINDOWS_CASCADE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 503 EnableMenuItem(hWindowsMenu, ID_WINDOWS_BRINGTOFRONT, MF_BYCOMMAND|MF_ENABLED); 504 } 505 else if (ListView_GetSelectedCount(hApplicationPageListCtrl) > 1) 506 { // More than one item selected 507 EnableMenuItem(hWindowsMenu, ID_WINDOWS_TILEHORIZONTALLY, MF_BYCOMMAND|MF_ENABLED); 508 EnableMenuItem(hWindowsMenu, ID_WINDOWS_TILEVERTICALLY, MF_BYCOMMAND|MF_ENABLED); 509 EnableMenuItem(hWindowsMenu, ID_WINDOWS_MINIMIZE, MF_BYCOMMAND|MF_ENABLED); 510 EnableMenuItem(hWindowsMenu, ID_WINDOWS_MAXIMIZE, MF_BYCOMMAND|MF_ENABLED); 511 EnableMenuItem(hWindowsMenu, ID_WINDOWS_CASCADE, MF_BYCOMMAND|MF_ENABLED); 512 EnableMenuItem(hWindowsMenu, ID_WINDOWS_BRINGTOFRONT, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 513 } 514 else 515 { // No items selected 516 EnableMenuItem(hWindowsMenu, ID_WINDOWS_TILEHORIZONTALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 517 EnableMenuItem(hWindowsMenu, ID_WINDOWS_TILEVERTICALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 518 EnableMenuItem(hWindowsMenu, ID_WINDOWS_MINIMIZE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 519 EnableMenuItem(hWindowsMenu, ID_WINDOWS_MAXIMIZE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 520 EnableMenuItem(hWindowsMenu, ID_WINDOWS_CASCADE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 521 EnableMenuItem(hWindowsMenu, ID_WINDOWS_BRINGTOFRONT, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 522 } 523 } 524 } 525 526 void ApplicationPageOnNotify(WPARAM wParam, LPARAM lParam) 527 { 528 LPNMHDR pnmh; 529 LV_DISPINFO* pnmdi; 530 LPAPPLICATION_PAGE_LIST_ITEM pAPLI; 531 WCHAR szMsg[256]; 532 533 pnmh = (LPNMHDR) lParam; 534 pnmdi = (LV_DISPINFO*) lParam; 535 536 if (pnmh->hwndFrom == hApplicationPageListCtrl) { 537 switch (pnmh->code) { 538 case LVN_ITEMCHANGED: 539 ApplicationPageUpdate(); 540 break; 541 542 case LVN_GETDISPINFO: 543 pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)pnmdi->item.lParam; 544 545 /* Update the item text */ 546 if (pnmdi->item.iSubItem == 0) 547 wcsncpy(pnmdi->item.pszText, pAPLI->szTitle, pnmdi->item.cchTextMax); 548 549 /* Update the item status */ 550 else if (pnmdi->item.iSubItem == 1) 551 { 552 if (pAPLI->bHung) 553 LoadStringW(GetModuleHandleW(NULL), IDS_NOT_RESPONDING , szMsg, _countof(szMsg)); 554 else 555 LoadStringW(GetModuleHandleW(NULL), IDS_RUNNING, (LPWSTR) szMsg, _countof(szMsg)); 556 wcsncpy(pnmdi->item.pszText, szMsg, pnmdi->item.cchTextMax); 557 } 558 559 break; 560 561 case NM_RCLICK: 562 if (ListView_GetSelectedCount(hApplicationPageListCtrl) < 1) 563 ApplicationPageShowContextMenu1(); 564 else 565 ApplicationPageShowContextMenu2(); 566 break; 567 568 case NM_DBLCLK: 569 ApplicationPage_OnSwitchTo(); 570 break; 571 572 case LVN_KEYDOWN: 573 if (((LPNMLVKEYDOWN)lParam)->wVKey == VK_DELETE) 574 ApplicationPage_OnEndTask(); 575 break; 576 } 577 } 578 else if (pnmh->hwndFrom == ListView_GetHeader(hApplicationPageListCtrl)) 579 { 580 switch (pnmh->code) 581 { 582 case NM_RCLICK: 583 if (ListView_GetSelectedCount(hApplicationPageListCtrl) < 1) 584 ApplicationPageShowContextMenu1(); 585 else 586 ApplicationPageShowContextMenu2(); 587 break; 588 589 case HDN_ITEMCLICK: 590 (void)ListView_SortItems(hApplicationPageListCtrl, ApplicationPageCompareFunc, 0); 591 bSortAscending = !bSortAscending; 592 break; 593 } 594 } 595 } 596 597 void ApplicationPageShowContextMenu1(void) 598 { 599 HMENU hMenu; 600 HMENU hSubMenu; 601 POINT pt; 602 603 GetCursorPos(&pt); 604 605 hMenu = LoadMenuW(hInst, MAKEINTRESOURCEW(IDR_APPLICATION_PAGE_CONTEXT1)); 606 hSubMenu = GetSubMenu(hMenu, 0); 607 608 CheckMenuRadioItem(hSubMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, TaskManagerSettings.ViewMode, MF_BYCOMMAND); 609 610 TrackPopupMenu(hSubMenu, TPM_LEFTALIGN|TPM_TOPALIGN|TPM_LEFTBUTTON, pt.x, pt.y, 0, hMainWnd, NULL); 611 612 DestroyMenu(hMenu); 613 } 614 615 void ApplicationPageShowContextMenu2(void) 616 { 617 HMENU hMenu; 618 HMENU hSubMenu; 619 POINT pt; 620 621 GetCursorPos(&pt); 622 623 hMenu = LoadMenuW(hInst, MAKEINTRESOURCEW(IDR_APPLICATION_PAGE_CONTEXT2)); 624 hSubMenu = GetSubMenu(hMenu, 0); 625 626 if (ListView_GetSelectedCount(hApplicationPageListCtrl) == 1) 627 { 628 EnableMenuItem(hSubMenu, ID_APPLICATION_PAGE_SWITCHTO, MF_BYCOMMAND|MF_ENABLED); 629 EnableMenuItem(hSubMenu, ID_WINDOWS_TILEHORIZONTALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 630 EnableMenuItem(hSubMenu, ID_WINDOWS_TILEVERTICALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 631 EnableMenuItem(hSubMenu, ID_WINDOWS_MINIMIZE, MF_BYCOMMAND|MF_ENABLED); 632 EnableMenuItem(hSubMenu, ID_WINDOWS_MAXIMIZE, MF_BYCOMMAND|MF_ENABLED); 633 EnableMenuItem(hSubMenu, ID_WINDOWS_CASCADE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 634 EnableMenuItem(hSubMenu, ID_WINDOWS_BRINGTOFRONT, MF_BYCOMMAND|MF_ENABLED); 635 } 636 else if (ListView_GetSelectedCount(hApplicationPageListCtrl) > 1) 637 { 638 EnableMenuItem(hSubMenu, ID_APPLICATION_PAGE_SWITCHTO, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 639 EnableMenuItem(hSubMenu, ID_WINDOWS_TILEHORIZONTALLY, MF_BYCOMMAND|MF_ENABLED); 640 EnableMenuItem(hSubMenu, ID_WINDOWS_TILEVERTICALLY, MF_BYCOMMAND|MF_ENABLED); 641 EnableMenuItem(hSubMenu, ID_WINDOWS_MINIMIZE, MF_BYCOMMAND|MF_ENABLED); 642 EnableMenuItem(hSubMenu, ID_WINDOWS_MAXIMIZE, MF_BYCOMMAND|MF_ENABLED); 643 EnableMenuItem(hSubMenu, ID_WINDOWS_CASCADE, MF_BYCOMMAND|MF_ENABLED); 644 EnableMenuItem(hSubMenu, ID_WINDOWS_BRINGTOFRONT, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 645 } 646 else 647 { 648 EnableMenuItem(hSubMenu, ID_APPLICATION_PAGE_SWITCHTO, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 649 EnableMenuItem(hSubMenu, ID_WINDOWS_TILEHORIZONTALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 650 EnableMenuItem(hSubMenu, ID_WINDOWS_TILEVERTICALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 651 EnableMenuItem(hSubMenu, ID_WINDOWS_MINIMIZE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 652 EnableMenuItem(hSubMenu, ID_WINDOWS_MAXIMIZE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 653 EnableMenuItem(hSubMenu, ID_WINDOWS_CASCADE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 654 EnableMenuItem(hSubMenu, ID_WINDOWS_BRINGTOFRONT, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 655 } 656 657 SetMenuDefaultItem(hSubMenu, ID_APPLICATION_PAGE_SWITCHTO, MF_BYCOMMAND); 658 659 TrackPopupMenu(hSubMenu, TPM_LEFTALIGN|TPM_TOPALIGN|TPM_LEFTBUTTON, pt.x, pt.y, 0, hMainWnd, NULL); 660 661 DestroyMenu(hMenu); 662 } 663 664 void ApplicationPage_OnView(DWORD dwMode) 665 { 666 HMENU hMenu; 667 HMENU hViewMenu; 668 669 hMenu = GetMenu(hMainWnd); 670 hViewMenu = GetSubMenu(hMenu, 2); 671 672 TaskManagerSettings.ViewMode = dwMode; 673 CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, dwMode, MF_BYCOMMAND); 674 675 UpdateApplicationListControlViewSetting(); 676 } 677 678 void ApplicationPage_OnWindowsTile(DWORD dwMode) 679 { 680 LPAPPLICATION_PAGE_LIST_ITEM pAPLI = NULL; 681 LV_ITEM item; 682 int i; 683 HWND* hWndArray; 684 int nWndCount; 685 686 hWndArray = (HWND*)HeapAlloc(GetProcessHeap(), 0, sizeof(HWND) * ListView_GetItemCount(hApplicationPageListCtrl)); 687 nWndCount = 0; 688 689 for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) { 690 memset(&item, 0, sizeof(LV_ITEM)); 691 item.mask = LVIF_STATE|LVIF_PARAM; 692 item.iItem = i; 693 item.stateMask = (UINT)-1; 694 (void)ListView_GetItem(hApplicationPageListCtrl, &item); 695 696 if (item.state & LVIS_SELECTED) { 697 pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam; 698 if (pAPLI) { 699 hWndArray[nWndCount] = pAPLI->hWnd; 700 nWndCount++; 701 } 702 } 703 } 704 705 TileWindows(NULL, dwMode, NULL, nWndCount, hWndArray); 706 HeapFree(GetProcessHeap(), 0, hWndArray); 707 } 708 709 void ApplicationPage_OnWindowsMinimize(void) 710 { 711 LPAPPLICATION_PAGE_LIST_ITEM pAPLI = NULL; 712 LV_ITEM item; 713 int i; 714 715 for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) { 716 memset(&item, 0, sizeof(LV_ITEM)); 717 item.mask = LVIF_STATE|LVIF_PARAM; 718 item.iItem = i; 719 item.stateMask = (UINT)-1; 720 (void)ListView_GetItem(hApplicationPageListCtrl, &item); 721 if (item.state & LVIS_SELECTED) { 722 pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam; 723 if (pAPLI) { 724 ShowWindowAsync(pAPLI->hWnd, SW_MINIMIZE); 725 } 726 } 727 } 728 } 729 730 void ApplicationPage_OnWindowsMaximize(void) 731 { 732 LPAPPLICATION_PAGE_LIST_ITEM pAPLI = NULL; 733 LV_ITEM item; 734 int i; 735 736 for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) { 737 memset(&item, 0, sizeof(LV_ITEM)); 738 item.mask = LVIF_STATE|LVIF_PARAM; 739 item.iItem = i; 740 item.stateMask = (UINT)-1; 741 (void)ListView_GetItem(hApplicationPageListCtrl, &item); 742 if (item.state & LVIS_SELECTED) { 743 pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam; 744 if (pAPLI) { 745 ShowWindowAsync(pAPLI->hWnd, SW_MAXIMIZE); 746 } 747 } 748 } 749 } 750 751 void ApplicationPage_OnWindowsCascade(void) 752 { 753 LPAPPLICATION_PAGE_LIST_ITEM pAPLI = NULL; 754 LV_ITEM item; 755 int i; 756 HWND* hWndArray; 757 int nWndCount; 758 759 hWndArray = (HWND*)HeapAlloc(GetProcessHeap(), 0, sizeof(HWND) * ListView_GetItemCount(hApplicationPageListCtrl)); 760 nWndCount = 0; 761 762 for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) { 763 memset(&item, 0, sizeof(LV_ITEM)); 764 item.mask = LVIF_STATE|LVIF_PARAM; 765 item.iItem = i; 766 item.stateMask = (UINT)-1; 767 (void)ListView_GetItem(hApplicationPageListCtrl, &item); 768 if (item.state & LVIS_SELECTED) { 769 pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam; 770 if (pAPLI) { 771 hWndArray[nWndCount] = pAPLI->hWnd; 772 nWndCount++; 773 } 774 } 775 } 776 CascadeWindows(NULL, 0, NULL, nWndCount, hWndArray); 777 HeapFree(GetProcessHeap(), 0, hWndArray); 778 } 779 780 void ApplicationPage_OnWindowsBringToFront(void) 781 { 782 LPAPPLICATION_PAGE_LIST_ITEM pAPLI = NULL; 783 LV_ITEM item; 784 int i; 785 786 for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) { 787 memset(&item, 0, sizeof(LV_ITEM)); 788 item.mask = LVIF_STATE|LVIF_PARAM; 789 item.iItem = i; 790 item.stateMask = (UINT)-1; 791 (void)ListView_GetItem(hApplicationPageListCtrl, &item); 792 if (item.state & LVIS_SELECTED) { 793 pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam; 794 break; 795 } 796 } 797 if (pAPLI) { 798 SwitchToThisWindow(pAPLI->hWnd, TRUE); 799 } 800 } 801 802 void ApplicationPage_OnSwitchTo(void) 803 { 804 LPAPPLICATION_PAGE_LIST_ITEM pAPLI = NULL; 805 LV_ITEM item; 806 int i; 807 808 for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) { 809 memset(&item, 0, sizeof(LV_ITEM)); 810 item.mask = LVIF_STATE|LVIF_PARAM; 811 item.iItem = i; 812 item.stateMask = (UINT)-1; 813 (void)ListView_GetItem(hApplicationPageListCtrl, &item); 814 815 if (item.state & LVIS_SELECTED) { 816 pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam; 817 break; 818 } 819 } 820 if (pAPLI) { 821 SwitchToThisWindow(pAPLI->hWnd, TRUE); 822 if (TaskManagerSettings.MinimizeOnUse) 823 ShowWindowAsync(hMainWnd, SW_MINIMIZE); 824 } 825 } 826 827 void ApplicationPage_OnEndTask(void) 828 { 829 LPAPPLICATION_PAGE_LIST_ITEM pAPLI = NULL; 830 LV_ITEM item; 831 int i; 832 833 /* Trick: on Windows, pressing the CTRL key forces the task to be ended */ 834 BOOL ForceEndTask = !!(GetKeyState(VK_CONTROL) & 0x8000); 835 836 for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) { 837 memset(&item, 0, sizeof(LV_ITEM)); 838 item.mask = LVIF_STATE|LVIF_PARAM; 839 item.iItem = i; 840 item.stateMask = (UINT)-1; 841 (void)ListView_GetItem(hApplicationPageListCtrl, &item); 842 if (item.state & LVIS_SELECTED) { 843 pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam; 844 if (pAPLI) { 845 EndTask(pAPLI->hWnd, 0, ForceEndTask); 846 } 847 } 848 } 849 } 850 851 void ApplicationPage_OnGotoProcess(void) 852 { 853 LPAPPLICATION_PAGE_LIST_ITEM pAPLI = NULL; 854 LV_ITEM item; 855 int i; 856 857 for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) { 858 memset(&item, 0, sizeof(LV_ITEM)); 859 item.mask = LVIF_STATE|LVIF_PARAM; 860 item.iItem = i; 861 item.stateMask = (UINT)-1; 862 (void)ListView_GetItem(hApplicationPageListCtrl, &item); 863 if (item.state & LVIS_SELECTED) { 864 pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam; 865 break; 866 } 867 } 868 if (pAPLI) { 869 DWORD dwProcessId; 870 871 GetWindowThreadProcessId(pAPLI->hWnd, &dwProcessId); 872 /* 873 * Switch to the process tab 874 */ 875 TabCtrl_SetCurFocus(hTabWnd, 1); 876 /* 877 * Select the process item in the list 878 */ 879 i = ProcGetIndexByProcessId(dwProcessId); 880 if (i != -1) 881 { 882 ListView_SetItemState(hProcessPageListCtrl, 883 i, 884 LVIS_SELECTED | LVIS_FOCUSED, 885 LVIS_SELECTED | LVIS_FOCUSED); 886 (void)ListView_EnsureVisible(hProcessPageListCtrl, i, FALSE); 887 } 888 } 889 } 890 891 int CALLBACK ApplicationPageCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) 892 { 893 LPAPPLICATION_PAGE_LIST_ITEM Param1; 894 LPAPPLICATION_PAGE_LIST_ITEM Param2; 895 896 if (bSortAscending) { 897 Param1 = (LPAPPLICATION_PAGE_LIST_ITEM)lParam1; 898 Param2 = (LPAPPLICATION_PAGE_LIST_ITEM)lParam2; 899 } else { 900 Param1 = (LPAPPLICATION_PAGE_LIST_ITEM)lParam2; 901 Param2 = (LPAPPLICATION_PAGE_LIST_ITEM)lParam1; 902 } 903 return wcscmp(Param1->szTitle, Param2->szTitle); 904 } 905