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