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