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