Sync to trunk (r46918)
[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 ProcGetIndexByProcessId(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 INT i;
240 BOOL bItemRemoved = FALSE;
241 LV_ITEM item;
242 LPAPPLICATION_PAGE_LIST_ITEM pAPLI = NULL;
243 HIMAGELIST hImageListLarge;
244 HIMAGELIST hImageListSmall;
245
246 /* Create the event */
247 hApplicationPageEvent = CreateEventW(NULL, TRUE, TRUE, NULL);
248
249 /* If we couldn't create the event then exit the thread */
250 if (!hApplicationPageEvent)
251 return 0;
252
253 while (1)
254 {
255 DWORD dwWaitVal;
256
257 /* Wait on the event */
258 dwWaitVal = WaitForSingleObject(hApplicationPageEvent, INFINITE);
259
260 /* If the wait failed then the event object must have been */
261 /* closed and the task manager is exiting so exit this thread */
262 if (dwWaitVal == WAIT_FAILED)
263 return 0;
264
265 if (dwWaitVal == WAIT_OBJECT_0)
266 {
267 /* Reset our event */
268 ResetEvent(hApplicationPageEvent);
269
270 /*
271 * FIXME:
272 *
273 * Should this be EnumDesktopWindows() instead?
274 */
275 noApps = TRUE;
276 EnumWindows(EnumWindowsProc, 0);
277 if (noApps)
278 (void)ListView_DeleteAllItems(hApplicationPageListCtrl);
279
280 /* Get the image lists */
281 hImageListLarge = ListView_GetImageList(hApplicationPageListCtrl, LVSIL_NORMAL);
282 hImageListSmall = ListView_GetImageList(hApplicationPageListCtrl, LVSIL_SMALL);
283
284 /* Check to see if we need to remove any items from the list */
285 for (i=ListView_GetItemCount(hApplicationPageListCtrl)-1; i>=0; i--)
286 {
287 memset(&item, 0, sizeof(LV_ITEM));
288 item.mask = LVIF_IMAGE|LVIF_PARAM;
289 item.iItem = i;
290 (void)ListView_GetItem(hApplicationPageListCtrl, &item);
291
292 pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
293 if (!IsWindow(pAPLI->hWnd)||
294 (wcslen(pAPLI->szTitle) <= 0) ||
295 !IsWindowVisible(pAPLI->hWnd) ||
296 (GetParent(pAPLI->hWnd) != NULL) ||
297 (GetWindow(pAPLI->hWnd, GW_OWNER) != NULL) ||
298 (GetWindowLongPtr(pAPLI->hWnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW))
299 {
300 ImageList_Remove(hImageListLarge, item.iItem);
301 ImageList_Remove(hImageListSmall, item.iItem);
302
303 (void)ListView_DeleteItem(hApplicationPageListCtrl, item.iItem);
304 HeapFree(GetProcessHeap(), 0, pAPLI);
305 bItemRemoved = TRUE;
306 }
307 }
308
309 /*
310 * If an item was removed from the list then
311 * we need to resync all the items with the
312 * image list
313 */
314 if (bItemRemoved)
315 {
316 for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++)
317 {
318 memset(&item, 0, sizeof(LV_ITEM));
319 item.mask = LVIF_IMAGE;
320 item.iItem = i;
321 item.iImage = i;
322 (void)ListView_SetItem(hApplicationPageListCtrl, &item);
323 }
324 bItemRemoved = FALSE;
325 }
326
327 ApplicationPageUpdate();
328 }
329 }
330 }
331
332 BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
333 {
334 HICON hIcon;
335 WCHAR szText[260];
336 BOOL bLargeIcon;
337 BOOL bHung = FALSE;
338 HICON* xhIcon = (HICON*)&hIcon;
339
340 typedef int (FAR __stdcall *IsHungAppWindowProc)(HWND);
341 IsHungAppWindowProc IsHungAppWindow;
342
343
344 /* Skip our window */
345 if (hWnd == hMainWnd)
346 return TRUE;
347
348 bLargeIcon = (TaskManagerSettings.ViewMode == ID_VIEW_LARGE);
349
350 GetWindowTextW(hWnd, szText, 260); /* Get the window text */
351
352 /* Check and see if this is a top-level app window */
353 if ((wcslen(szText) <= 0) ||
354 !IsWindowVisible(hWnd) ||
355 (GetParent(hWnd) != NULL) ||
356 (GetWindow(hWnd, GW_OWNER) != NULL) ||
357 (GetWindowLongPtrW(hWnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW))
358 {
359 return TRUE; /* Skip this window */
360 }
361
362 noApps = FALSE;
363 /* Get the icon for this window */
364 hIcon = NULL;
365 SendMessageTimeoutW(hWnd, WM_GETICON,bLargeIcon ? ICON_BIG /*1*/ : ICON_SMALL /*0*/, 0, 0, 1000, (PDWORD_PTR)xhIcon);
366
367 if (!hIcon)
368 {
369 hIcon = (HICON)(LONG_PTR)GetClassLongPtrW(hWnd, bLargeIcon ? GCL_HICON : GCL_HICONSM);
370 if (!hIcon) hIcon = (HICON)(LONG_PTR)GetClassLongPtrW(hWnd, bLargeIcon ? GCL_HICONSM : GCL_HICON);
371 if (!hIcon) SendMessageTimeoutW(hWnd, WM_QUERYDRAGICON, 0, 0, 0, 1000, (PDWORD_PTR)xhIcon);
372 if (!hIcon) SendMessageTimeoutW(hWnd, WM_GETICON, bLargeIcon ? ICON_SMALL /*0*/ : ICON_BIG /*1*/, 0, 0, 1000, (PDWORD_PTR)xhIcon);
373 }
374
375 if (!hIcon)
376 hIcon = LoadIconW(hInst, bLargeIcon ? MAKEINTRESOURCEW(IDI_WINDOW) : MAKEINTRESOURCEW(IDI_WINDOWSM));
377
378 bHung = FALSE;
379
380 IsHungAppWindow = (IsHungAppWindowProc)(FARPROC)GetProcAddress(GetModuleHandleW(L"USER32.DLL"), "IsHungAppWindow");
381
382 if (IsHungAppWindow)
383 bHung = IsHungAppWindow(hWnd);
384
385 AddOrUpdateHwnd(hWnd, szText, hIcon, bHung);
386
387 return TRUE;
388 }
389
390 void AddOrUpdateHwnd(HWND hWnd, WCHAR *szTitle, HICON hIcon, BOOL bHung)
391 {
392 LPAPPLICATION_PAGE_LIST_ITEM pAPLI = NULL;
393 HIMAGELIST hImageListLarge;
394 HIMAGELIST hImageListSmall;
395 LV_ITEM item;
396 int i;
397 BOOL bAlreadyInList = FALSE;
398
399 memset(&item, 0, sizeof(LV_ITEM));
400
401 /* Get the image lists */
402 hImageListLarge = ListView_GetImageList(hApplicationPageListCtrl, LVSIL_NORMAL);
403 hImageListSmall = ListView_GetImageList(hApplicationPageListCtrl, LVSIL_SMALL);
404
405 /* Check to see if it's already in our list */
406 for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++)
407 {
408 memset(&item, 0, sizeof(LV_ITEM));
409 item.mask = LVIF_IMAGE|LVIF_PARAM;
410 item.iItem = i;
411 (void)ListView_GetItem(hApplicationPageListCtrl, &item);
412
413 pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
414 if (pAPLI->hWnd == hWnd)
415 {
416 bAlreadyInList = TRUE;
417 break;
418 }
419 }
420
421 /* If it is already in the list then update it if necessary */
422 if (bAlreadyInList)
423 {
424 /* Check to see if anything needs updating */
425 if ((pAPLI->hIcon != hIcon) ||
426 (_wcsicmp(pAPLI->szTitle, szTitle) != 0) ||
427 (pAPLI->bHung != bHung))
428 {
429 /* Update the structure */
430 pAPLI->hIcon = hIcon;
431 pAPLI->bHung = bHung;
432 wcscpy(pAPLI->szTitle, szTitle);
433
434 /* Update the image list */
435 ImageList_ReplaceIcon(hImageListLarge, item.iItem, hIcon);
436 ImageList_ReplaceIcon(hImageListSmall, item.iItem, hIcon);
437
438 /* Update the list view */
439 (void)ListView_RedrawItems(hApplicationPageListCtrl, 0, ListView_GetItemCount(hApplicationPageListCtrl));
440 /* UpdateWindow(hApplicationPageListCtrl); */
441 InvalidateRect(hApplicationPageListCtrl, NULL, 0);
442 }
443 }
444 /* It is not already in the list so add it */
445 else
446 {
447 pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)HeapAlloc(GetProcessHeap(), 0, sizeof(APPLICATION_PAGE_LIST_ITEM));
448
449 pAPLI->hWnd = hWnd;
450 pAPLI->hIcon = hIcon;
451 pAPLI->bHung = bHung;
452 wcscpy(pAPLI->szTitle, szTitle);
453
454 /* Add the item to the list */
455 memset(&item, 0, sizeof(LV_ITEM));
456 item.mask = LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM;
457 ImageList_AddIcon(hImageListLarge, hIcon);
458 item.iImage = ImageList_AddIcon(hImageListSmall, hIcon);
459 item.pszText = LPSTR_TEXTCALLBACK;
460 item.iItem = ListView_GetItemCount(hApplicationPageListCtrl);
461 item.lParam = (LPARAM)pAPLI;
462 (void)ListView_InsertItem(hApplicationPageListCtrl, &item);
463 }
464 return;
465 }
466
467 void ApplicationPageUpdate(void)
468 {
469 /* Enable or disable the "End Task" & "Switch To" buttons */
470 if (ListView_GetSelectedCount(hApplicationPageListCtrl))
471 {
472 EnableWindow(hApplicationPageEndTaskButton, TRUE);
473 }
474 else
475 {
476 EnableWindow(hApplicationPageEndTaskButton, FALSE);
477 }
478 /* Enable "Switch To" button only if one app is selected */
479 if (ListView_GetSelectedCount(hApplicationPageListCtrl) == 1 )
480 {
481 EnableWindow(hApplicationPageSwitchToButton, TRUE);
482 }
483 else
484 {
485 EnableWindow(hApplicationPageSwitchToButton, FALSE);
486 }
487
488 /* If we are on the applications tab the windows menu will be */
489 /* present on the menu bar so enable & disable the menu items */
490 if (TabCtrl_GetCurSel(hTabWnd) == 0)
491 {
492 HMENU hMenu;
493 HMENU hWindowsMenu;
494
495 hMenu = GetMenu(hMainWnd);
496 hWindowsMenu = GetSubMenu(hMenu, 3);
497
498 /* Only one item selected */
499 if (ListView_GetSelectedCount(hApplicationPageListCtrl) == 1)
500 {
501 EnableMenuItem(hWindowsMenu, ID_WINDOWS_TILEHORIZONTALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
502 EnableMenuItem(hWindowsMenu, ID_WINDOWS_TILEVERTICALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
503 EnableMenuItem(hWindowsMenu, ID_WINDOWS_MINIMIZE, MF_BYCOMMAND|MF_ENABLED);
504 EnableMenuItem(hWindowsMenu, ID_WINDOWS_MAXIMIZE, MF_BYCOMMAND|MF_ENABLED);
505 EnableMenuItem(hWindowsMenu, ID_WINDOWS_CASCADE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
506 EnableMenuItem(hWindowsMenu, ID_WINDOWS_BRINGTOFRONT, MF_BYCOMMAND|MF_ENABLED);
507 }
508 /* More than one item selected */
509 else if (ListView_GetSelectedCount(hApplicationPageListCtrl) > 1)
510 {
511 EnableMenuItem(hWindowsMenu, ID_WINDOWS_TILEHORIZONTALLY, MF_BYCOMMAND|MF_ENABLED);
512 EnableMenuItem(hWindowsMenu, ID_WINDOWS_TILEVERTICALLY, MF_BYCOMMAND|MF_ENABLED);
513 EnableMenuItem(hWindowsMenu, ID_WINDOWS_MINIMIZE, MF_BYCOMMAND|MF_ENABLED);
514 EnableMenuItem(hWindowsMenu, ID_WINDOWS_MAXIMIZE, MF_BYCOMMAND|MF_ENABLED);
515 EnableMenuItem(hWindowsMenu, ID_WINDOWS_CASCADE, MF_BYCOMMAND|MF_ENABLED);
516 EnableMenuItem(hWindowsMenu, ID_WINDOWS_BRINGTOFRONT, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
517 }
518 /* No items selected */
519 else
520 {
521 EnableMenuItem(hWindowsMenu, ID_WINDOWS_TILEHORIZONTALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
522 EnableMenuItem(hWindowsMenu, ID_WINDOWS_TILEVERTICALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
523 EnableMenuItem(hWindowsMenu, ID_WINDOWS_MINIMIZE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
524 EnableMenuItem(hWindowsMenu, ID_WINDOWS_MAXIMIZE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
525 EnableMenuItem(hWindowsMenu, ID_WINDOWS_CASCADE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
526 EnableMenuItem(hWindowsMenu, ID_WINDOWS_BRINGTOFRONT, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
527 }
528 }
529 }
530
531 void ApplicationPageOnNotify(WPARAM wParam, LPARAM lParam)
532 {
533 int idctrl;
534 LPNMHDR pnmh;
535 LPNM_LISTVIEW pnmv;
536 LV_DISPINFO* pnmdi;
537 LPAPPLICATION_PAGE_LIST_ITEM pAPLI;
538 WCHAR szMsg[256];
539
540
541 idctrl = (int) wParam;
542 pnmh = (LPNMHDR) lParam;
543 pnmv = (LPNM_LISTVIEW) lParam;
544 pnmdi = (LV_DISPINFO*) lParam;
545
546 if (pnmh->hwndFrom == hApplicationPageListCtrl) {
547 switch (pnmh->code) {
548 case LVN_ITEMCHANGED:
549 ApplicationPageUpdate();
550 break;
551
552 case LVN_GETDISPINFO:
553 pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)pnmdi->item.lParam;
554
555 /* Update the item text */
556 if (pnmdi->item.iSubItem == 0)
557 {
558 wcsncpy(pnmdi->item.pszText, pAPLI->szTitle, pnmdi->item.cchTextMax);
559 }
560
561 /* Update the item status */
562 else if (pnmdi->item.iSubItem == 1)
563 {
564 if (pAPLI->bHung)
565 {
566 LoadStringW( GetModuleHandleW(NULL), IDS_Not_Responding , szMsg, sizeof(szMsg) / sizeof(szMsg[0]));
567 }
568 else
569 {
570 LoadStringW( GetModuleHandleW(NULL), IDS_Running, (LPWSTR) szMsg, sizeof(szMsg) / sizeof(szMsg[0]));
571 }
572 wcsncpy(pnmdi->item.pszText, szMsg, pnmdi->item.cchTextMax);
573 }
574
575 break;
576
577 case NM_RCLICK:
578
579 if (ListView_GetSelectedCount(hApplicationPageListCtrl) < 1)
580 {
581 ApplicationPageShowContextMenu1();
582 }
583 else
584 {
585 ApplicationPageShowContextMenu2();
586 }
587
588 break;
589
590 case NM_DBLCLK:
591
592 ApplicationPage_OnSwitchTo();
593
594 break;
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 }