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
GetSystemColorDepth(VOID)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
AppPageCleanup(void)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
ApplicationPageWndProc(HWND hDlg,UINT message,WPARAM wParam,LPARAM lParam)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
RefreshApplicationPage(void)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
UpdateApplicationListControlViewSetting(void)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
ApplicationPageRefreshThread(void * lpParameter)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
EnumWindowsProc(HWND hWnd,LPARAM lParam)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
AddOrUpdateHwnd(HWND hWnd,WCHAR * szTitle,HICON hIcon,BOOL bHung)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
ApplicationPageUpdate(void)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
ApplicationPageOnNotify(WPARAM wParam,LPARAM lParam)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
ApplicationPageShowContextMenu1(void)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
ApplicationPageShowContextMenu2(void)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
ApplicationPage_OnView(DWORD dwMode)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
ApplicationPage_OnWindowsTile(DWORD dwMode)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
ApplicationPage_OnWindowsMinimize(void)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
ApplicationPage_OnWindowsMaximize(void)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
ApplicationPage_OnWindowsCascade(void)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
ApplicationPage_OnWindowsBringToFront(void)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
ApplicationPage_OnSwitchTo(void)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
ApplicationPage_OnEndTask(void)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
ApplicationPage_OnGotoProcess(void)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
ApplicationPageCompareFunc(LPARAM lParam1,LPARAM lParam2,LPARAM lParamSort)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