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 LRESULT bAlive; 357 358 typedef int (FAR __stdcall *IsHungAppWindowProc)(HWND); 359 IsHungAppWindowProc IsHungAppWindow; 360 361 /* Skip our window */ 362 if (hWnd == hMainWnd) 363 return TRUE; 364 365 bLargeIcon = (TaskManagerSettings.ViewMode == ID_VIEW_LARGE); 366 367 GetWindowTextW(hWnd, szText, 260); /* Get the window text */ 368 369 /* Check and see if this is a top-level app window */ 370 if ((wcslen(szText) <= 0) || 371 !IsWindowVisible(hWnd) || 372 (GetParent(hWnd) != NULL) || 373 (GetWindow(hWnd, GW_OWNER) != NULL) || 374 (GetWindowLongPtrW(hWnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW)) 375 { 376 return TRUE; /* Skip this window */ 377 } 378 379 noApps = FALSE; 380 381 #define GET_ICON(type) \ 382 SendMessageTimeoutW(hWnd, WM_GETICON, (type), 0, SMTO_ABORTIFHUNG, 100, (PDWORD_PTR)&hIcon) 383 384 /* Get the icon for this window */ 385 hIcon = NULL; 386 bAlive = GET_ICON(bLargeIcon ? ICON_BIG : ICON_SMALL); 387 if (!hIcon) 388 { 389 /* We failed, try to retrieve other icons... */ 390 if (!hIcon && bAlive) 391 GET_ICON(bLargeIcon ? ICON_SMALL : ICON_BIG); 392 if (!hIcon) 393 hIcon = (HICON)(LONG_PTR)GetClassLongPtrW(hWnd, bLargeIcon ? GCL_HICON : GCL_HICONSM); 394 if (!hIcon) 395 hIcon = (HICON)(LONG_PTR)GetClassLongPtrW(hWnd, bLargeIcon ? GCL_HICONSM : GCL_HICON); 396 397 /* If we still do not have any icon, load the default one */ 398 if (!hIcon) hIcon = LoadIconW(hInst, bLargeIcon ? MAKEINTRESOURCEW(IDI_WINDOW) : MAKEINTRESOURCEW(IDI_WINDOWSM)); 399 } 400 #undef GET_ICON 401 402 bHung = FALSE; 403 404 IsHungAppWindow = (IsHungAppWindowProc)(FARPROC)GetProcAddress(GetModuleHandleW(L"USER32.DLL"), "IsHungAppWindow"); 405 406 if (IsHungAppWindow) 407 bHung = IsHungAppWindow(hWnd); 408 409 AddOrUpdateHwnd(hWnd, szText, hIcon, bHung); 410 411 return TRUE; 412 } 413 414 void AddOrUpdateHwnd(HWND hWnd, WCHAR *szTitle, HICON hIcon, BOOL bHung) 415 { 416 LPAPPLICATION_PAGE_LIST_ITEM pAPLI = NULL; 417 HIMAGELIST hImageListLarge; 418 HIMAGELIST hImageListSmall; 419 LV_ITEM item; 420 int i; 421 BOOL bAlreadyInList = FALSE; 422 423 memset(&item, 0, sizeof(LV_ITEM)); 424 425 /* Get the image lists */ 426 hImageListLarge = ListView_GetImageList(hApplicationPageListCtrl, LVSIL_NORMAL); 427 hImageListSmall = ListView_GetImageList(hApplicationPageListCtrl, LVSIL_SMALL); 428 429 /* Check to see if it's already in our list */ 430 for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) 431 { 432 memset(&item, 0, sizeof(LV_ITEM)); 433 item.mask = LVIF_IMAGE|LVIF_PARAM; 434 item.iItem = i; 435 (void)ListView_GetItem(hApplicationPageListCtrl, &item); 436 437 pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam; 438 if (pAPLI->hWnd == hWnd) 439 { 440 bAlreadyInList = TRUE; 441 break; 442 } 443 } 444 445 /* If it is already in the list then update it if necessary */ 446 if (bAlreadyInList) 447 { 448 /* Check to see if anything needs updating */ 449 if ((pAPLI->hIcon != hIcon) || 450 (_wcsicmp(pAPLI->szTitle, szTitle) != 0) || 451 (pAPLI->bHung != bHung)) 452 { 453 /* Update the structure */ 454 pAPLI->hIcon = hIcon; 455 pAPLI->bHung = bHung; 456 wcscpy(pAPLI->szTitle, szTitle); 457 458 /* Update the image list */ 459 ImageList_ReplaceIcon(hImageListLarge, item.iItem, hIcon); 460 ImageList_ReplaceIcon(hImageListSmall, item.iItem, hIcon); 461 462 /* Update the list view */ 463 (void)ListView_RedrawItems(hApplicationPageListCtrl, 0, ListView_GetItemCount(hApplicationPageListCtrl)); 464 /* UpdateWindow(hApplicationPageListCtrl); */ 465 InvalidateRect(hApplicationPageListCtrl, NULL, 0); 466 } 467 } 468 /* It is not already in the list so add it */ 469 else 470 { 471 pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)HeapAlloc(GetProcessHeap(), 0, sizeof(APPLICATION_PAGE_LIST_ITEM)); 472 473 pAPLI->hWnd = hWnd; 474 pAPLI->hIcon = hIcon; 475 pAPLI->bHung = bHung; 476 wcscpy(pAPLI->szTitle, szTitle); 477 478 /* Add the item to the list */ 479 memset(&item, 0, sizeof(LV_ITEM)); 480 item.mask = LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM; 481 ImageList_AddIcon(hImageListLarge, hIcon); 482 item.iImage = ImageList_AddIcon(hImageListSmall, hIcon); 483 item.pszText = LPSTR_TEXTCALLBACK; 484 item.iItem = ListView_GetItemCount(hApplicationPageListCtrl); 485 item.lParam = (LPARAM)pAPLI; 486 (void)ListView_InsertItem(hApplicationPageListCtrl, &item); 487 } 488 489 /* Select first item if any */ 490 if ((ListView_GetNextItem(hApplicationPageListCtrl, -1, LVNI_FOCUSED | LVNI_SELECTED) == -1) && 491 (ListView_GetItemCount(hApplicationPageListCtrl) > 0) && !bApplicationPageSelectionMade) 492 { 493 ListView_SetItemState(hApplicationPageListCtrl, 0, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); 494 bApplicationPageSelectionMade = TRUE; 495 } 496 /* 497 else 498 { 499 bApplicationPageSelectionMade = FALSE; 500 } 501 */ 502 } 503 504 void ApplicationPageUpdate(void) 505 { 506 /* Enable or disable the "End Task" & "Switch To" buttons */ 507 if (ListView_GetSelectedCount(hApplicationPageListCtrl)) 508 { 509 EnableWindow(hApplicationPageEndTaskButton, TRUE); 510 } 511 else 512 { 513 EnableWindow(hApplicationPageEndTaskButton, FALSE); 514 } 515 /* Enable "Switch To" button only if only one app is selected */ 516 EnableWindow(hApplicationPageSwitchToButton, (ListView_GetSelectedCount(hApplicationPageListCtrl) == 1)); 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_APPLICATION_PAGE_SWITCHTO, MF_BYCOMMAND|MF_ENABLED); 690 EnableMenuItem(hSubMenu, ID_WINDOWS_TILEHORIZONTALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 691 EnableMenuItem(hSubMenu, ID_WINDOWS_TILEVERTICALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 692 EnableMenuItem(hSubMenu, ID_WINDOWS_MINIMIZE, MF_BYCOMMAND|MF_ENABLED); 693 EnableMenuItem(hSubMenu, ID_WINDOWS_MAXIMIZE, MF_BYCOMMAND|MF_ENABLED); 694 EnableMenuItem(hSubMenu, ID_WINDOWS_CASCADE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 695 EnableMenuItem(hSubMenu, ID_WINDOWS_BRINGTOFRONT, MF_BYCOMMAND|MF_ENABLED); 696 } 697 else if (ListView_GetSelectedCount(hApplicationPageListCtrl) > 1) 698 { 699 EnableMenuItem(hSubMenu, ID_APPLICATION_PAGE_SWITCHTO, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 700 EnableMenuItem(hSubMenu, ID_WINDOWS_TILEHORIZONTALLY, MF_BYCOMMAND|MF_ENABLED); 701 EnableMenuItem(hSubMenu, ID_WINDOWS_TILEVERTICALLY, MF_BYCOMMAND|MF_ENABLED); 702 EnableMenuItem(hSubMenu, ID_WINDOWS_MINIMIZE, MF_BYCOMMAND|MF_ENABLED); 703 EnableMenuItem(hSubMenu, ID_WINDOWS_MAXIMIZE, MF_BYCOMMAND|MF_ENABLED); 704 EnableMenuItem(hSubMenu, ID_WINDOWS_CASCADE, MF_BYCOMMAND|MF_ENABLED); 705 EnableMenuItem(hSubMenu, ID_WINDOWS_BRINGTOFRONT, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 706 } 707 else 708 { 709 EnableMenuItem(hSubMenu, ID_APPLICATION_PAGE_SWITCHTO, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 710 EnableMenuItem(hSubMenu, ID_WINDOWS_TILEHORIZONTALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 711 EnableMenuItem(hSubMenu, ID_WINDOWS_TILEVERTICALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 712 EnableMenuItem(hSubMenu, ID_WINDOWS_MINIMIZE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 713 EnableMenuItem(hSubMenu, ID_WINDOWS_MAXIMIZE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 714 EnableMenuItem(hSubMenu, ID_WINDOWS_CASCADE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 715 EnableMenuItem(hSubMenu, ID_WINDOWS_BRINGTOFRONT, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 716 } 717 718 SetMenuDefaultItem(hSubMenu, ID_APPLICATION_PAGE_SWITCHTO, MF_BYCOMMAND); 719 720 TrackPopupMenu(hSubMenu, TPM_LEFTALIGN|TPM_TOPALIGN|TPM_LEFTBUTTON, pt.x, pt.y, 0, hMainWnd, NULL); 721 722 DestroyMenu(hMenu); 723 } 724 725 void ApplicationPage_OnView(DWORD dwMode) 726 { 727 HMENU hMenu; 728 HMENU hViewMenu; 729 730 hMenu = GetMenu(hMainWnd); 731 hViewMenu = GetSubMenu(hMenu, 2); 732 733 TaskManagerSettings.ViewMode = dwMode; 734 CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, dwMode, MF_BYCOMMAND); 735 736 UpdateApplicationListControlViewSetting(); 737 } 738 739 void ApplicationPage_OnWindowsTile(DWORD dwMode) 740 { 741 LPAPPLICATION_PAGE_LIST_ITEM pAPLI = NULL; 742 LV_ITEM item; 743 int i; 744 HWND* hWndArray; 745 int nWndCount; 746 747 hWndArray = (HWND*)HeapAlloc(GetProcessHeap(), 0, sizeof(HWND) * ListView_GetItemCount(hApplicationPageListCtrl)); 748 nWndCount = 0; 749 750 for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) { 751 memset(&item, 0, sizeof(LV_ITEM)); 752 item.mask = LVIF_STATE|LVIF_PARAM; 753 item.iItem = i; 754 item.stateMask = (UINT)-1; 755 (void)ListView_GetItem(hApplicationPageListCtrl, &item); 756 757 if (item.state & LVIS_SELECTED) { 758 pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam; 759 if (pAPLI) { 760 hWndArray[nWndCount] = pAPLI->hWnd; 761 nWndCount++; 762 } 763 } 764 } 765 766 TileWindows(NULL, dwMode, NULL, nWndCount, hWndArray); 767 HeapFree(GetProcessHeap(), 0, hWndArray); 768 } 769 770 void ApplicationPage_OnWindowsMinimize(void) 771 { 772 LPAPPLICATION_PAGE_LIST_ITEM pAPLI = NULL; 773 LV_ITEM item; 774 int i; 775 776 for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) { 777 memset(&item, 0, sizeof(LV_ITEM)); 778 item.mask = LVIF_STATE|LVIF_PARAM; 779 item.iItem = i; 780 item.stateMask = (UINT)-1; 781 (void)ListView_GetItem(hApplicationPageListCtrl, &item); 782 if (item.state & LVIS_SELECTED) { 783 pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam; 784 if (pAPLI) { 785 ShowWindowAsync(pAPLI->hWnd, SW_MINIMIZE); 786 } 787 } 788 } 789 } 790 791 void ApplicationPage_OnWindowsMaximize(void) 792 { 793 LPAPPLICATION_PAGE_LIST_ITEM pAPLI = NULL; 794 LV_ITEM item; 795 int i; 796 797 for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) { 798 memset(&item, 0, sizeof(LV_ITEM)); 799 item.mask = LVIF_STATE|LVIF_PARAM; 800 item.iItem = i; 801 item.stateMask = (UINT)-1; 802 (void)ListView_GetItem(hApplicationPageListCtrl, &item); 803 if (item.state & LVIS_SELECTED) { 804 pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam; 805 if (pAPLI) { 806 ShowWindowAsync(pAPLI->hWnd, SW_MAXIMIZE); 807 } 808 } 809 } 810 } 811 812 void ApplicationPage_OnWindowsCascade(void) 813 { 814 LPAPPLICATION_PAGE_LIST_ITEM pAPLI = NULL; 815 LV_ITEM item; 816 int i; 817 HWND* hWndArray; 818 int nWndCount; 819 820 hWndArray = (HWND*)HeapAlloc(GetProcessHeap(), 0, sizeof(HWND) * ListView_GetItemCount(hApplicationPageListCtrl)); 821 nWndCount = 0; 822 823 for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) { 824 memset(&item, 0, sizeof(LV_ITEM)); 825 item.mask = LVIF_STATE|LVIF_PARAM; 826 item.iItem = i; 827 item.stateMask = (UINT)-1; 828 (void)ListView_GetItem(hApplicationPageListCtrl, &item); 829 if (item.state & LVIS_SELECTED) { 830 pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam; 831 if (pAPLI) { 832 hWndArray[nWndCount] = pAPLI->hWnd; 833 nWndCount++; 834 } 835 } 836 } 837 CascadeWindows(NULL, 0, NULL, nWndCount, hWndArray); 838 HeapFree(GetProcessHeap(), 0, hWndArray); 839 } 840 841 void ApplicationPage_OnWindowsBringToFront(void) 842 { 843 LPAPPLICATION_PAGE_LIST_ITEM pAPLI = NULL; 844 LV_ITEM item; 845 int i; 846 847 for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) { 848 memset(&item, 0, sizeof(LV_ITEM)); 849 item.mask = LVIF_STATE|LVIF_PARAM; 850 item.iItem = i; 851 item.stateMask = (UINT)-1; 852 (void)ListView_GetItem(hApplicationPageListCtrl, &item); 853 if (item.state & LVIS_SELECTED) { 854 pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam; 855 break; 856 } 857 } 858 if (pAPLI) { 859 SwitchToThisWindow(pAPLI->hWnd, TRUE); 860 } 861 } 862 863 void ApplicationPage_OnSwitchTo(void) 864 { 865 LPAPPLICATION_PAGE_LIST_ITEM pAPLI = NULL; 866 LV_ITEM item; 867 int i; 868 869 for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) { 870 memset(&item, 0, sizeof(LV_ITEM)); 871 item.mask = LVIF_STATE|LVIF_PARAM; 872 item.iItem = i; 873 item.stateMask = (UINT)-1; 874 (void)ListView_GetItem(hApplicationPageListCtrl, &item); 875 876 if (item.state & LVIS_SELECTED) { 877 pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam; 878 break; 879 } 880 } 881 if (pAPLI) { 882 SwitchToThisWindow(pAPLI->hWnd, TRUE); 883 if (TaskManagerSettings.MinimizeOnUse) 884 ShowWindowAsync(hMainWnd, SW_MINIMIZE); 885 } 886 } 887 888 void ApplicationPage_OnEndTask(void) 889 { 890 LPAPPLICATION_PAGE_LIST_ITEM pAPLI = NULL; 891 LV_ITEM item; 892 int i; 893 894 /* Trick: on Windows, pressing the CTRL key forces the task to be ended */ 895 BOOL ForceEndTask = !!(GetKeyState(VK_CONTROL) & 0x8000); 896 897 for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) { 898 memset(&item, 0, sizeof(LV_ITEM)); 899 item.mask = LVIF_STATE|LVIF_PARAM; 900 item.iItem = i; 901 item.stateMask = (UINT)-1; 902 (void)ListView_GetItem(hApplicationPageListCtrl, &item); 903 if (item.state & LVIS_SELECTED) { 904 pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam; 905 if (pAPLI) { 906 EndTask(pAPLI->hWnd, 0, ForceEndTask); 907 } 908 } 909 } 910 } 911 912 void ApplicationPage_OnGotoProcess(void) 913 { 914 LPAPPLICATION_PAGE_LIST_ITEM pAPLI = NULL; 915 LV_ITEM item; 916 int i; 917 918 for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) { 919 memset(&item, 0, sizeof(LV_ITEM)); 920 item.mask = LVIF_STATE|LVIF_PARAM; 921 item.iItem = i; 922 item.stateMask = (UINT)-1; 923 (void)ListView_GetItem(hApplicationPageListCtrl, &item); 924 if (item.state & LVIS_SELECTED) { 925 pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam; 926 break; 927 } 928 } 929 if (pAPLI) { 930 DWORD dwProcessId; 931 932 GetWindowThreadProcessId(pAPLI->hWnd, &dwProcessId); 933 /* 934 * Switch to the process tab 935 */ 936 TabCtrl_SetCurFocus(hTabWnd, 1); 937 /* 938 * Select the process item in the list 939 */ 940 i = ProcGetIndexByProcessId(dwProcessId); 941 if (i != -1) 942 { 943 ListView_SetItemState(hProcessPageListCtrl, 944 i, 945 LVIS_SELECTED | LVIS_FOCUSED, 946 LVIS_SELECTED | LVIS_FOCUSED); 947 (void)ListView_EnsureVisible(hProcessPageListCtrl, 948 i, 949 FALSE); 950 } 951 } 952 } 953 954 int CALLBACK ApplicationPageCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) 955 { 956 LPAPPLICATION_PAGE_LIST_ITEM Param1; 957 LPAPPLICATION_PAGE_LIST_ITEM Param2; 958 959 if (bSortAscending) { 960 Param1 = (LPAPPLICATION_PAGE_LIST_ITEM)lParam1; 961 Param2 = (LPAPPLICATION_PAGE_LIST_ITEM)lParam2; 962 } else { 963 Param1 = (LPAPPLICATION_PAGE_LIST_ITEM)lParam2; 964 Param2 = (LPAPPLICATION_PAGE_LIST_ITEM)lParam1; 965 } 966 return wcscmp(Param1->szTitle, Param2->szTitle); 967 } 968