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