wnaspi32: Make winaspi.dll into a stand-alone 16-bit module.
[wine] / programs / taskmgr / applpage.c
1 /*
2  *  ReactOS Task Manager
3  *
4  *  applpage.c
5  *
6  *  Copyright (C) 1999 - 2001  Brian Palmer  <brianp@reactos.org>
7  *  Copyright (C) 2008  Vladimir Pankratov
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 St, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23
24 #define WIN32_LEAN_AND_MEAN    /* Exclude rarely-used stuff from Windows headers */
25 #include <windows.h>
26 #include <commctrl.h>
27 #include <stdlib.h>
28 #include <memory.h>
29 #include <stdio.h>
30
31 #include "wine/unicode.h"
32 #include "taskmgr.h"
33
34 typedef struct
35 {
36     HWND    hWnd;
37     WCHAR   wszTitle[256];
38     HICON   hIcon;
39     BOOL    bHung;
40 } APPLICATION_PAGE_LIST_ITEM, *LPAPPLICATION_PAGE_LIST_ITEM;
41
42 HWND            hApplicationPage;               /* Application List Property Page */
43 HWND            hApplicationPageListCtrl;       /* Application ListCtrl Window */
44 HWND            hApplicationPageEndTaskButton;  /* Application End Task button */
45 HWND            hApplicationPageSwitchToButton; /* Application Switch To button */
46 HWND            hApplicationPageNewTaskButton;  /* Application New Task button */
47 static int      nApplicationPageWidth;
48 static int      nApplicationPageHeight;
49 static HANDLE   hApplicationPageEvent = NULL;   /* When this event becomes signaled then we refresh the app list */
50 static BOOL     bSortAscending = TRUE;
51
52 static const WCHAR    wszUser32[] = {'U','S','E','R','3','2','.','D','L','L',0};
53 #if 0
54 void SwitchToThisWindow (
55 HWND hWnd,   /* Handle to the window that should be activated */
56 BOOL bRestore /* Restore the window if it is minimized */
57 );
58 #endif
59
60 static void ApplicationPageUpdate(void)
61 {
62     /* Enable or disable the "End Task" & "Switch To" buttons */
63     if (ListView_GetSelectedCount(hApplicationPageListCtrl))
64     {
65         EnableWindow(hApplicationPageEndTaskButton, TRUE);
66         EnableWindow(hApplicationPageSwitchToButton, TRUE);
67     }
68     else
69     {
70         EnableWindow(hApplicationPageEndTaskButton, FALSE);
71         EnableWindow(hApplicationPageSwitchToButton, FALSE);
72     }
73
74     /* If we are on the applications tab, then the windows menu will */
75     /* be present on the menu bar so enable & disable the menu items */
76     if (TabCtrl_GetCurSel(hTabWnd) == 0)
77     {
78         HMENU   hMenu;
79         HMENU   hWindowsMenu;
80
81         hMenu = GetMenu(hMainWnd);
82         hWindowsMenu = GetSubMenu(hMenu, 3);
83
84         /* Only one item selected */
85         if (ListView_GetSelectedCount(hApplicationPageListCtrl) == 1)
86         {
87             EnableMenuItem(hWindowsMenu, ID_WINDOWS_TILEHORIZONTALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
88             EnableMenuItem(hWindowsMenu, ID_WINDOWS_TILEVERTICALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
89             EnableMenuItem(hWindowsMenu, ID_WINDOWS_MINIMIZE, MF_BYCOMMAND|MF_ENABLED);
90             EnableMenuItem(hWindowsMenu, ID_WINDOWS_MAXIMIZE, MF_BYCOMMAND|MF_ENABLED);
91             EnableMenuItem(hWindowsMenu, ID_WINDOWS_CASCADE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
92             EnableMenuItem(hWindowsMenu, ID_WINDOWS_BRINGTOFRONT, MF_BYCOMMAND|MF_ENABLED);
93         }
94         /* More than one item selected */
95         else if (ListView_GetSelectedCount(hApplicationPageListCtrl) > 1)
96         {
97             EnableMenuItem(hWindowsMenu, ID_WINDOWS_TILEHORIZONTALLY, MF_BYCOMMAND|MF_ENABLED);
98             EnableMenuItem(hWindowsMenu, ID_WINDOWS_TILEVERTICALLY, MF_BYCOMMAND|MF_ENABLED);
99             EnableMenuItem(hWindowsMenu, ID_WINDOWS_MINIMIZE, MF_BYCOMMAND|MF_ENABLED);
100             EnableMenuItem(hWindowsMenu, ID_WINDOWS_MAXIMIZE, MF_BYCOMMAND|MF_ENABLED);
101             EnableMenuItem(hWindowsMenu, ID_WINDOWS_CASCADE, MF_BYCOMMAND|MF_ENABLED);
102             EnableMenuItem(hWindowsMenu, ID_WINDOWS_BRINGTOFRONT, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
103         }
104         /* No items selected */
105         else
106         {
107             EnableMenuItem(hWindowsMenu, ID_WINDOWS_TILEHORIZONTALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
108             EnableMenuItem(hWindowsMenu, ID_WINDOWS_TILEVERTICALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
109             EnableMenuItem(hWindowsMenu, ID_WINDOWS_MINIMIZE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
110             EnableMenuItem(hWindowsMenu, ID_WINDOWS_MAXIMIZE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
111             EnableMenuItem(hWindowsMenu, ID_WINDOWS_CASCADE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
112             EnableMenuItem(hWindowsMenu, ID_WINDOWS_BRINGTOFRONT, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
113         }
114     }
115 }
116
117 static void AddOrUpdateHwnd(HWND hWnd, WCHAR *wszTitle, HICON hIcon, BOOL bHung)
118 {
119     LPAPPLICATION_PAGE_LIST_ITEM    pAPLI = NULL;
120     HIMAGELIST                      hImageListLarge;
121     HIMAGELIST                      hImageListSmall;
122     LV_ITEMW                        item;
123     int                             i;
124     BOOL                            bAlreadyInList = FALSE;
125     BOOL                            bItemRemoved = FALSE;
126
127     memset(&item, 0, sizeof(LV_ITEMW));
128
129     /* Get the image lists */
130     hImageListLarge = ListView_GetImageList(hApplicationPageListCtrl, LVSIL_NORMAL);
131     hImageListSmall = ListView_GetImageList(hApplicationPageListCtrl, LVSIL_SMALL);
132
133     /* Check to see if it's already in our list */
134     for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++)
135     {
136         memset(&item, 0, sizeof(LV_ITEMW));
137         item.mask = LVIF_IMAGE|LVIF_PARAM;
138         item.iItem = i;
139         SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
140
141         pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
142         if (pAPLI->hWnd == hWnd)
143         {
144             bAlreadyInList = TRUE;
145             break;
146         }
147     }
148
149     /* If it is already in the list then update it if necessary */
150     if (bAlreadyInList)
151     {
152         /* Check to see if anything needs updating */
153         if ((pAPLI->hIcon != hIcon) ||
154             (strcmpW(pAPLI->wszTitle, wszTitle) != 0) ||
155             (pAPLI->bHung != bHung))
156         {
157             /* Update the structure */
158             pAPLI->hIcon = hIcon;
159             pAPLI->bHung = bHung;
160             strcpyW(pAPLI->wszTitle, wszTitle);
161
162             /* Update the image list */
163             ImageList_ReplaceIcon(hImageListLarge, item.iItem, hIcon);
164             ImageList_ReplaceIcon(hImageListSmall, item.iItem, hIcon);
165
166             /* Update the list view */
167             SendMessageW(hApplicationPageListCtrl, LVM_REDRAWITEMS, 0, ListView_GetItemCount(hApplicationPageListCtrl));
168             /* UpdateWindow(hApplicationPageListCtrl); */
169             InvalidateRect(hApplicationPageListCtrl, NULL, 0);
170         }
171     }
172     /* It is not already in the list so add it */
173     else
174     {
175         pAPLI = HeapAlloc(GetProcessHeap(), 0, sizeof(APPLICATION_PAGE_LIST_ITEM));
176
177         pAPLI->hWnd = hWnd;
178         pAPLI->hIcon = hIcon;
179         pAPLI->bHung = bHung;
180         strcpyW(pAPLI->wszTitle, wszTitle);
181
182         /* Add the item to the list */
183         memset(&item, 0, sizeof(LV_ITEMW));
184         item.mask = LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM;
185         ImageList_AddIcon(hImageListLarge, hIcon);
186         item.iImage = ImageList_AddIcon(hImageListSmall, hIcon);
187         item.pszText = LPSTR_TEXTCALLBACKW;
188         item.iItem = ListView_GetItemCount(hApplicationPageListCtrl);
189         item.lParam = (LPARAM)pAPLI;
190         SendMessageW(hApplicationPageListCtrl, LVM_INSERTITEMW, 0, (LPARAM) &item);
191     }
192
193
194     /* Check to see if we need to remove any items from the list */
195     for (i=ListView_GetItemCount(hApplicationPageListCtrl)-1; i>=0; i--)
196     {
197         memset(&item, 0, sizeof(LV_ITEMW));
198         item.mask = LVIF_IMAGE|LVIF_PARAM;
199         item.iItem = i;
200         SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
201
202         pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
203         if (!IsWindow(pAPLI->hWnd)||
204             (strlenW(pAPLI->wszTitle) <= 0) ||
205             !IsWindowVisible(pAPLI->hWnd) ||
206             (GetParent(pAPLI->hWnd) != NULL) ||
207             (GetWindow(pAPLI->hWnd, GW_OWNER) != NULL) ||
208             (GetWindowLong(hWnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW))
209         {
210             ImageList_Remove(hImageListLarge, item.iItem);
211             ImageList_Remove(hImageListSmall, item.iItem);
212
213             SendMessage(hApplicationPageListCtrl, LVM_DELETEITEM, item.iItem, 0);
214             HeapFree(GetProcessHeap(), 0, pAPLI);
215             bItemRemoved = TRUE;
216         }
217     }
218
219     /*
220      * If an item was removed from the list then
221      * we need to resync all the items with the
222      * image list
223      */
224     if (bItemRemoved)
225     {
226         for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++)
227         {
228             memset(&item, 0, sizeof(LV_ITEMW));
229             item.mask = LVIF_IMAGE;
230             item.iItem = i;
231             item.iImage = i;
232             SendMessageW(hApplicationPageListCtrl, LVM_SETITEMW, 0, (LPARAM) &item);
233         }
234     }
235
236     ApplicationPageUpdate();
237 }
238
239 static BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
240 {
241     HICON hIcon;
242     WCHAR wszText[256];
243     BOOL  bLargeIcon;
244     BOOL  bHung = FALSE;
245     typedef int (__stdcall *IsHungAppWindowProc)(HWND);
246     IsHungAppWindowProc IsHungAppWindow;
247
248
249     /* Skip our window */
250     if (hWnd == hMainWnd)
251         return TRUE;
252
253     bLargeIcon = TaskManagerSettings.View_LargeIcons ? TRUE : FALSE;
254
255     /* Check and see if this is a top-level app window */
256     if (!GetWindowTextW(hWnd, wszText, sizeof(wszText)/sizeof(WCHAR)) ||
257         !IsWindowVisible(hWnd) ||
258         (GetParent(hWnd) != NULL) ||
259         (GetWindow(hWnd, GW_OWNER) != NULL) ||
260         (GetWindowLong(hWnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW))
261     {
262         return TRUE; /* Skip this window */
263     }
264
265     /* Get the icon for this window */
266     hIcon = NULL;
267     SendMessageTimeout(hWnd, WM_GETICON, bLargeIcon ? ICON_BIG /*1*/ : ICON_SMALL /*0*/, 0, 0, 1000, (PDWORD_PTR)&hIcon);
268
269     if (!hIcon)
270     {
271         hIcon = (HICON)GetClassLongPtr(hWnd, bLargeIcon ? GCLP_HICON : GCLP_HICONSM);
272         if (!hIcon) hIcon = (HICON)GetClassLongPtr(hWnd, bLargeIcon ? GCLP_HICONSM : GCLP_HICON);
273         if (!hIcon) SendMessageTimeout(hWnd, WM_QUERYDRAGICON, 0, 0, 0, 1000, (PDWORD_PTR)&hIcon);
274         if (!hIcon) SendMessageTimeout(hWnd, WM_GETICON, bLargeIcon ? ICON_SMALL /*0*/ : ICON_BIG /*1*/, 0, 0, 1000, (PDWORD_PTR)&hIcon);
275     }
276
277     if (!hIcon)
278         hIcon = LoadIcon(hInst, bLargeIcon ? MAKEINTRESOURCE(IDI_WINDOW) : MAKEINTRESOURCE(IDI_WINDOWSM));
279
280     bHung = FALSE;
281
282     IsHungAppWindow = (IsHungAppWindowProc)(FARPROC)GetProcAddress(GetModuleHandleW(wszUser32), "IsHungAppWindow");
283
284     if (IsHungAppWindow)
285         bHung = IsHungAppWindow(hWnd);
286
287     AddOrUpdateHwnd(hWnd, wszText, hIcon, bHung);
288
289     return TRUE;
290 }
291
292 static DWORD WINAPI ApplicationPageRefreshThread(void *lpParameter)
293 {
294     /* Create the event */
295     hApplicationPageEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
296
297     /* If we couldn't create the event then exit the thread */
298     if (!hApplicationPageEvent)
299         return 0;
300
301     while (1)
302     {
303         DWORD   dwWaitVal;
304
305         /* Wait on the event */
306         dwWaitVal = WaitForSingleObject(hApplicationPageEvent, INFINITE);
307
308         /* If the wait failed then the event object must have been */
309         /* closed and the task manager is exiting so exit this thread */
310         if (dwWaitVal == WAIT_FAILED)
311             return 0;
312
313         if (dwWaitVal == WAIT_OBJECT_0)
314         {
315             /* Reset our event */
316             ResetEvent(hApplicationPageEvent);
317
318             /*
319              * FIXME:
320              *
321              * Should this be EnumDesktopWindows() instead?
322              */
323             EnumWindows(EnumWindowsProc, 0);
324         }
325     }
326 }
327
328 static void ApplicationPageShowContextMenu1(void)
329 {
330     HMENU   hMenu;
331     HMENU   hSubMenu;
332     POINT   pt;
333
334     GetCursorPos(&pt);
335
336     hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_APPLICATION_PAGE_CONTEXT1));
337     hSubMenu = GetSubMenu(hMenu, 0);
338
339     if (TaskManagerSettings.View_LargeIcons)
340         CheckMenuRadioItem(hSubMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_LARGE, MF_BYCOMMAND);
341     else if (TaskManagerSettings.View_SmallIcons)
342         CheckMenuRadioItem(hSubMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_SMALL, MF_BYCOMMAND);
343     else
344         CheckMenuRadioItem(hSubMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_DETAILS, MF_BYCOMMAND);
345
346     TrackPopupMenu(hSubMenu, TPM_LEFTALIGN|TPM_TOPALIGN|TPM_LEFTBUTTON, pt.x, pt.y, 0, hMainWnd, NULL);
347
348     DestroyMenu(hMenu);
349 }
350
351 static void ApplicationPageShowContextMenu2(void)
352 {
353     HMENU   hMenu;
354     HMENU   hSubMenu;
355     POINT   pt;
356
357     GetCursorPos(&pt);
358
359     hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_APPLICATION_PAGE_CONTEXT2));
360     hSubMenu = GetSubMenu(hMenu, 0);
361
362     if (ListView_GetSelectedCount(hApplicationPageListCtrl) == 1)
363     {
364         EnableMenuItem(hSubMenu, ID_WINDOWS_TILEHORIZONTALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
365         EnableMenuItem(hSubMenu, ID_WINDOWS_TILEVERTICALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
366         EnableMenuItem(hSubMenu, ID_WINDOWS_MINIMIZE, MF_BYCOMMAND|MF_ENABLED);
367         EnableMenuItem(hSubMenu, ID_WINDOWS_MAXIMIZE, MF_BYCOMMAND|MF_ENABLED);
368         EnableMenuItem(hSubMenu, ID_WINDOWS_CASCADE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
369         EnableMenuItem(hSubMenu, ID_WINDOWS_BRINGTOFRONT, MF_BYCOMMAND|MF_ENABLED);
370     }
371     else if (ListView_GetSelectedCount(hApplicationPageListCtrl) > 1)
372     {
373         EnableMenuItem(hSubMenu, ID_WINDOWS_TILEHORIZONTALLY, MF_BYCOMMAND|MF_ENABLED);
374         EnableMenuItem(hSubMenu, ID_WINDOWS_TILEVERTICALLY, MF_BYCOMMAND|MF_ENABLED);
375         EnableMenuItem(hSubMenu, ID_WINDOWS_MINIMIZE, MF_BYCOMMAND|MF_ENABLED);
376         EnableMenuItem(hSubMenu, ID_WINDOWS_MAXIMIZE, MF_BYCOMMAND|MF_ENABLED);
377         EnableMenuItem(hSubMenu, ID_WINDOWS_CASCADE, MF_BYCOMMAND|MF_ENABLED);
378         EnableMenuItem(hSubMenu, ID_WINDOWS_BRINGTOFRONT, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
379     }
380     else
381     {
382         EnableMenuItem(hSubMenu, ID_WINDOWS_TILEHORIZONTALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
383         EnableMenuItem(hSubMenu, ID_WINDOWS_TILEVERTICALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
384         EnableMenuItem(hSubMenu, ID_WINDOWS_MINIMIZE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
385         EnableMenuItem(hSubMenu, ID_WINDOWS_MAXIMIZE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
386         EnableMenuItem(hSubMenu, ID_WINDOWS_CASCADE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
387         EnableMenuItem(hSubMenu, ID_WINDOWS_BRINGTOFRONT, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
388     }
389
390     SetMenuDefaultItem(hSubMenu, ID_APPLICATION_PAGE_SWITCHTO, MF_BYCOMMAND);
391
392     TrackPopupMenu(hSubMenu, TPM_LEFTALIGN|TPM_TOPALIGN|TPM_LEFTBUTTON, pt.x, pt.y, 0, hMainWnd, NULL);
393
394     DestroyMenu(hMenu);
395 }
396
397 static int CALLBACK ApplicationPageCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
398 {
399     LPAPPLICATION_PAGE_LIST_ITEM Param1;
400     LPAPPLICATION_PAGE_LIST_ITEM Param2;
401
402     if (bSortAscending) {
403         Param1 = (LPAPPLICATION_PAGE_LIST_ITEM)lParam1;
404         Param2 = (LPAPPLICATION_PAGE_LIST_ITEM)lParam2;
405     } else {
406         Param1 = (LPAPPLICATION_PAGE_LIST_ITEM)lParam2;
407         Param2 = (LPAPPLICATION_PAGE_LIST_ITEM)lParam1;
408     }
409     return strcmpW(Param1->wszTitle, Param2->wszTitle);
410 }
411
412 static void ApplicationPageOnNotify(WPARAM wParam, LPARAM lParam)
413 {
414     int             idctrl;
415     LPNMHDR         pnmh;
416     LPNM_LISTVIEW   pnmv;
417     LV_DISPINFOW*   pnmdi;
418     LPAPPLICATION_PAGE_LIST_ITEM pAPLI;
419
420     static const WCHAR    wszNotResponding[] = {'N','o','t',' ','R','e','s','p','o','n','d','i','n','g',0};
421     static const WCHAR    wszRunning[] = {'R','u','n','n','i','n','g',0};
422
423
424     idctrl = (int) wParam;
425     pnmh = (LPNMHDR) lParam;
426     pnmv = (LPNM_LISTVIEW) lParam;
427     pnmdi = (LV_DISPINFOW*) lParam;
428
429     if (pnmh->hwndFrom == hApplicationPageListCtrl) {
430         switch (pnmh->code) {
431         case LVN_ITEMCHANGED:
432             ApplicationPageUpdate();
433             break;
434             
435         case LVN_GETDISPINFOW:
436             pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)pnmdi->item.lParam;
437
438             /* Update the item text */
439             if (pnmdi->item.iSubItem == 0)
440             {
441                 lstrcpynW(pnmdi->item.pszText, pAPLI->wszTitle, pnmdi->item.cchTextMax);
442             }
443
444             /* Update the item status */
445             else if (pnmdi->item.iSubItem == 1)
446             {
447                 if (pAPLI->bHung)
448                     lstrcpynW(pnmdi->item.pszText, wszNotResponding, pnmdi->item.cchTextMax);
449                 else
450                     lstrcpynW(pnmdi->item.pszText, wszRunning, pnmdi->item.cchTextMax);
451             }
452
453             break;
454
455         case NM_RCLICK:
456
457             if (ListView_GetSelectedCount(hApplicationPageListCtrl) < 1)
458             {
459                 ApplicationPageShowContextMenu1();
460             }
461             else
462             {
463                 ApplicationPageShowContextMenu2();
464             }
465
466             break;
467
468         case NM_DBLCLK:
469
470             ApplicationPage_OnSwitchTo();
471
472             break;
473         }
474     }
475     else if (pnmh->hwndFrom == ListView_GetHeader(hApplicationPageListCtrl))
476     {
477         switch (pnmh->code)
478         {
479         case NM_RCLICK:
480
481             if (ListView_GetSelectedCount(hApplicationPageListCtrl) < 1)
482             {
483                 ApplicationPageShowContextMenu1();
484             }
485             else
486             {
487                 ApplicationPageShowContextMenu2();
488             }
489
490             break;
491
492         case HDN_ITEMCLICK:
493
494             SendMessageW(hApplicationPageListCtrl, LVM_SORTITEMS, 0, (LPARAM) ApplicationPageCompareFunc);
495             bSortAscending = !bSortAscending;
496
497             break;
498         }
499     }
500
501 }
502
503 void RefreshApplicationPage(void)
504 {
505     /* Signal the event so that our refresh thread */
506     /* will wake up and refresh the application page */
507     SetEvent(hApplicationPageEvent);
508 }
509
510 static void UpdateApplicationListControlViewSetting(void)
511 {
512     DWORD   dwStyle = GetWindowLong(hApplicationPageListCtrl, GWL_STYLE);
513
514     dwStyle &= ~LVS_REPORT;
515     dwStyle &= ~LVS_ICON;
516     dwStyle &= ~LVS_LIST;
517     dwStyle &= ~LVS_SMALLICON;
518
519     if (TaskManagerSettings.View_LargeIcons)
520         dwStyle |= LVS_ICON;
521     else if (TaskManagerSettings.View_SmallIcons)
522         dwStyle |= LVS_SMALLICON;
523     else
524         dwStyle |= LVS_REPORT;
525
526     SetWindowLong(hApplicationPageListCtrl, GWL_STYLE, dwStyle);
527
528     RefreshApplicationPage();
529 }
530
531 void ApplicationPage_OnViewLargeIcons(void)
532 {
533     HMENU   hMenu;
534     HMENU   hViewMenu;
535
536     hMenu = GetMenu(hMainWnd);
537     hViewMenu = GetSubMenu(hMenu, 2);
538
539     TaskManagerSettings.View_LargeIcons = TRUE;
540     TaskManagerSettings.View_SmallIcons = FALSE;
541     TaskManagerSettings.View_Details = FALSE;
542     CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_LARGE, MF_BYCOMMAND);
543
544     UpdateApplicationListControlViewSetting();
545 }
546
547 void ApplicationPage_OnViewSmallIcons(void)
548 {
549     HMENU   hMenu;
550     HMENU   hViewMenu;
551
552     hMenu = GetMenu(hMainWnd);
553     hViewMenu = GetSubMenu(hMenu, 2);
554
555     TaskManagerSettings.View_LargeIcons = FALSE;
556     TaskManagerSettings.View_SmallIcons = TRUE;
557     TaskManagerSettings.View_Details = FALSE;
558     CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_SMALL, MF_BYCOMMAND);
559
560     UpdateApplicationListControlViewSetting();
561 }
562
563 void ApplicationPage_OnViewDetails(void)
564 {
565     HMENU   hMenu;
566     HMENU   hViewMenu;
567
568     hMenu = GetMenu(hMainWnd);
569     hViewMenu = GetSubMenu(hMenu, 2);
570
571     TaskManagerSettings.View_LargeIcons = FALSE;
572     TaskManagerSettings.View_SmallIcons = FALSE;
573     TaskManagerSettings.View_Details = TRUE;
574     CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_DETAILS, MF_BYCOMMAND);
575
576     UpdateApplicationListControlViewSetting();
577 }
578
579 void ApplicationPage_OnWindowsTileHorizontally(void)
580 {
581     LPAPPLICATION_PAGE_LIST_ITEM    pAPLI = NULL;
582     LV_ITEMW                        item;
583     int                             i;
584     HWND*                           hWndArray;
585     int                             nWndCount;
586
587     hWndArray = HeapAlloc(GetProcessHeap(), 0,
588                     sizeof(HWND) * ListView_GetItemCount(hApplicationPageListCtrl));
589     nWndCount = 0;
590
591     for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) {
592         memset(&item, 0, sizeof(LV_ITEMW));
593         item.mask = LVIF_STATE|LVIF_PARAM;
594         item.iItem = i;
595         item.stateMask = (UINT)-1;
596         SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
597
598         if (item.state & LVIS_SELECTED) {
599             pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
600
601             if (pAPLI) {
602                 hWndArray[nWndCount] = pAPLI->hWnd;
603                 nWndCount++;
604             }
605         }
606     }
607     TileWindows(NULL, MDITILE_HORIZONTAL, NULL, nWndCount, hWndArray);
608     HeapFree(GetProcessHeap(), 0, hWndArray);
609 }
610
611 void ApplicationPage_OnWindowsTileVertically(void)
612 {
613     LPAPPLICATION_PAGE_LIST_ITEM    pAPLI = NULL;
614     LV_ITEMW                        item;
615     int                             i;
616     HWND*                           hWndArray;
617     int                             nWndCount;
618
619     hWndArray = HeapAlloc(GetProcessHeap(), 0,
620                     sizeof(HWND) * ListView_GetItemCount(hApplicationPageListCtrl));
621     nWndCount = 0;
622
623     for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) {
624         memset(&item, 0, sizeof(LV_ITEMW));
625         item.mask = LVIF_STATE|LVIF_PARAM;
626         item.iItem = i;
627         item.stateMask = (UINT)-1;
628         SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
629
630         if (item.state & LVIS_SELECTED) {
631             pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
632             if (pAPLI) {
633                 hWndArray[nWndCount] = pAPLI->hWnd;
634                 nWndCount++;
635             }
636         }
637     }
638
639     TileWindows(NULL, MDITILE_VERTICAL, NULL, nWndCount, hWndArray);
640     HeapFree(GetProcessHeap(), 0, hWndArray);
641 }
642
643 void ApplicationPage_OnWindowsMinimize(void)
644 {
645     LPAPPLICATION_PAGE_LIST_ITEM    pAPLI = NULL;
646     LV_ITEMW                        item;
647     int                             i;
648
649     for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) {
650         memset(&item, 0, sizeof(LV_ITEMW));
651         item.mask = LVIF_STATE|LVIF_PARAM;
652         item.iItem = i;
653         item.stateMask = (UINT)-1;
654         SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
655         if (item.state & LVIS_SELECTED) {
656             pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
657             if (pAPLI) {
658                 ShowWindow(pAPLI->hWnd, SW_MINIMIZE);
659             }
660         }
661     }
662 }
663
664 void ApplicationPage_OnWindowsMaximize(void)
665 {
666     LPAPPLICATION_PAGE_LIST_ITEM    pAPLI = NULL;
667     LV_ITEMW                        item;
668     int                             i;
669
670     for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) {
671         memset(&item, 0, sizeof(LV_ITEMW));
672         item.mask = LVIF_STATE|LVIF_PARAM;
673         item.iItem = i;
674         item.stateMask = (UINT)-1;
675         SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
676         if (item.state & LVIS_SELECTED) {
677             pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
678             if (pAPLI) {
679                 ShowWindow(pAPLI->hWnd, SW_MAXIMIZE);
680             }
681         }
682     }
683 }
684
685 void ApplicationPage_OnWindowsCascade(void)
686 {
687     LPAPPLICATION_PAGE_LIST_ITEM    pAPLI = NULL;
688     LV_ITEMW                        item;
689     int                             i;
690     HWND*                           hWndArray;
691     int                             nWndCount;
692
693     hWndArray = HeapAlloc(GetProcessHeap(), 0,
694                     sizeof(HWND) * ListView_GetItemCount(hApplicationPageListCtrl));
695     nWndCount = 0;
696
697     for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) {
698         memset(&item, 0, sizeof(LV_ITEMW));
699         item.mask = LVIF_STATE|LVIF_PARAM;
700         item.iItem = i;
701         item.stateMask = (UINT)-1;
702         SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
703         if (item.state & LVIS_SELECTED) {
704             pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
705             if (pAPLI) {
706                 hWndArray[nWndCount] = pAPLI->hWnd;
707                 nWndCount++;
708             }
709         }
710     }
711     CascadeWindows(NULL, 0, NULL, nWndCount, hWndArray);
712     HeapFree(GetProcessHeap(), 0, hWndArray);
713 }
714
715 void ApplicationPage_OnWindowsBringToFront(void)
716 {
717     LPAPPLICATION_PAGE_LIST_ITEM    pAPLI = NULL;
718     LV_ITEMW                        item;
719     int                             i;
720
721     for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) {
722         memset(&item, 0, sizeof(LV_ITEMW));
723         item.mask = LVIF_STATE|LVIF_PARAM;
724         item.iItem = i;
725         item.stateMask = (UINT)-1;
726         SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
727         if (item.state & LVIS_SELECTED) {
728             pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
729             break;
730         }
731     }
732     if (pAPLI) {
733         if (IsIconic(pAPLI->hWnd))
734             ShowWindow(pAPLI->hWnd, SW_RESTORE);
735         BringWindowToTop(pAPLI->hWnd);
736     }
737 }
738
739 void ApplicationPage_OnSwitchTo(void)
740 {
741     LPAPPLICATION_PAGE_LIST_ITEM    pAPLI = NULL;
742     LV_ITEMW                        item;
743     int                             i;
744
745     for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) {
746         memset(&item, 0, sizeof(LV_ITEMW));
747         item.mask = LVIF_STATE|LVIF_PARAM;
748         item.iItem = i;
749         item.stateMask = (UINT)-1;
750         SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
751
752         if (item.state & LVIS_SELECTED) {
753             pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
754             break;
755         }
756     }
757     if (pAPLI) {
758         typedef void (WINAPI *PROCSWITCHTOTHISWINDOW) (HWND, BOOL);
759         PROCSWITCHTOTHISWINDOW SwitchToThisWindow;
760
761         HMODULE hUser32 = GetModuleHandleW(wszUser32);
762         SwitchToThisWindow = (PROCSWITCHTOTHISWINDOW)GetProcAddress(hUser32, "SwitchToThisWindow");
763         if (SwitchToThisWindow) {
764             SwitchToThisWindow(pAPLI->hWnd, TRUE);
765         } else {
766             if (IsIconic(pAPLI->hWnd))
767                 ShowWindow(pAPLI->hWnd, SW_RESTORE);
768             BringWindowToTop(pAPLI->hWnd);
769             SetForegroundWindow(pAPLI->hWnd);
770         }
771         if (TaskManagerSettings.MinimizeOnUse)
772             ShowWindow(hMainWnd, SW_MINIMIZE);
773     }
774 }
775
776 void ApplicationPage_OnEndTask(void)
777 {
778     LPAPPLICATION_PAGE_LIST_ITEM    pAPLI = NULL;
779     LV_ITEMW                        item;
780     int                             i;
781
782     for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) {
783         memset(&item, 0, sizeof(LV_ITEMW));
784         item.mask = LVIF_STATE|LVIF_PARAM;
785         item.iItem = i;
786         item.stateMask = (UINT)-1;
787         SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
788         if (item.state & LVIS_SELECTED) {
789             pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
790             if (pAPLI) {
791                 PostMessage(pAPLI->hWnd, WM_CLOSE, 0, 0);
792             }
793         }
794     }
795 }
796
797 void ApplicationPage_OnGotoProcess(void)
798 {
799     LPAPPLICATION_PAGE_LIST_ITEM pAPLI = NULL;
800     LV_ITEMW item;
801     int i;
802     /* NMHDR nmhdr; */
803
804     for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) {
805         memset(&item, 0, sizeof(LV_ITEMW));
806         item.mask = LVIF_STATE|LVIF_PARAM;
807         item.iItem = i;
808         item.stateMask = (UINT)-1;
809         SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
810         if (item.state & LVIS_SELECTED) {
811             pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
812             break;
813         }
814     }
815     if (pAPLI) {
816         DWORD   dwProcessId;
817
818         GetWindowThreadProcessId(pAPLI->hWnd, &dwProcessId);
819         /*
820          * Switch to the process tab
821          */
822         TabCtrl_SetCurFocus(hTabWnd, 1);
823         /*
824          * FIXME: Select the process item in the list
825          */
826         for (i=0; i<ListView_GetItemCount(hProcessPage); i++) {
827         }
828     }
829 }
830
831 INT_PTR CALLBACK
832 ApplicationPageWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
833 {
834     RECT        rc;
835     int         nXDifference;
836     int         nYDifference;
837     int         cx, cy;
838     LVCOLUMNW   column;
839
840     static const WCHAR wszTasks[] = {'T','a','s','k','s',0};
841     static WCHAR wszTask[] = {'T','a','s','k',0};
842     static WCHAR wszStatus[] = {'S','t','a','t','u','s',0};
843
844     switch (message) {
845     case WM_INITDIALOG:
846
847         /* Save the width and height */
848         GetClientRect(hDlg, &rc);
849         nApplicationPageWidth = rc.right;
850         nApplicationPageHeight = rc.bottom;
851
852         /* Update window position */
853         SetWindowPos(hDlg, NULL, 15, 30, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER);
854
855         /* Get handles to the controls */
856         hApplicationPageListCtrl = GetDlgItem(hDlg, IDC_APPLIST);
857         hApplicationPageEndTaskButton = GetDlgItem(hDlg, IDC_ENDTASK);
858         hApplicationPageSwitchToButton = GetDlgItem(hDlg, IDC_SWITCHTO);
859         hApplicationPageNewTaskButton = GetDlgItem(hDlg, IDC_NEWTASK);
860
861         SetWindowTextW(hApplicationPageListCtrl, wszTasks);
862
863         /* Initialize the application page's controls */
864         column.mask = LVCF_TEXT|LVCF_WIDTH;
865         column.pszText = wszTask;
866         column.cx = 250;
867         /* Add the "Task" column */
868         SendMessageW(hApplicationPageListCtrl, LVM_INSERTCOLUMNW, 0, (LPARAM) &column);
869         column.mask = LVCF_TEXT|LVCF_WIDTH;
870         column.pszText = wszStatus;
871         column.cx = 95;
872         /* Add the "Status" column */
873         SendMessageW(hApplicationPageListCtrl, LVM_INSERTCOLUMNW, 1, (LPARAM) &column);
874
875         SendMessageW(hApplicationPageListCtrl, LVM_SETIMAGELIST, LVSIL_SMALL,
876                     (LPARAM) ImageList_Create(16, 16, ILC_COLOR8|ILC_MASK, 0, 1));
877         SendMessageW(hApplicationPageListCtrl, LVM_SETIMAGELIST, LVSIL_NORMAL,
878                     (LPARAM) ImageList_Create(32, 32, ILC_COLOR8|ILC_MASK, 0, 1));
879
880         UpdateApplicationListControlViewSetting();
881
882         /* Start our refresh thread */
883         CreateThread(NULL, 0, ApplicationPageRefreshThread, NULL, 0, NULL);
884
885         return TRUE;
886
887     case WM_DESTROY:
888         /* Close the event handle, this will make the */
889         /* refresh thread exit when the wait fails */
890         CloseHandle(hApplicationPageEvent);
891         break;
892
893     case WM_COMMAND:
894
895         /* Handle the button clicks */
896         switch (LOWORD(wParam))
897         {
898         case IDC_ENDTASK:
899             ApplicationPage_OnEndTask();
900             break;
901         case IDC_SWITCHTO:
902             ApplicationPage_OnSwitchTo();
903             break;
904         case IDC_NEWTASK:
905             SendMessageW(hMainWnd, WM_COMMAND, MAKEWPARAM(ID_FILE_NEW, 0), 0);
906             break;
907         }
908
909         break;
910
911     case WM_SIZE:
912         if (wParam == SIZE_MINIMIZED)
913             return 0;
914
915         cx = LOWORD(lParam);
916         cy = HIWORD(lParam);
917         nXDifference = cx - nApplicationPageWidth;
918         nYDifference = cy - nApplicationPageHeight;
919         nApplicationPageWidth = cx;
920         nApplicationPageHeight = cy;
921
922         /* Reposition the application page's controls */
923         GetWindowRect(hApplicationPageListCtrl, &rc);
924         cx = (rc.right - rc.left) + nXDifference;
925         cy = (rc.bottom - rc.top) + nYDifference;
926         SetWindowPos(hApplicationPageListCtrl, NULL, 0, 0, cx, cy, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOMOVE|SWP_NOZORDER);
927         InvalidateRect(hApplicationPageListCtrl, NULL, TRUE);
928
929         GetClientRect(hApplicationPageEndTaskButton, &rc);
930         MapWindowPoints(hApplicationPageEndTaskButton, hDlg, (LPPOINT)(&rc), (sizeof(RECT)/sizeof(POINT)) );
931         cx = rc.left + nXDifference;
932         cy = rc.top + nYDifference;
933         SetWindowPos(hApplicationPageEndTaskButton, NULL, cx, cy, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER);
934         InvalidateRect(hApplicationPageEndTaskButton, NULL, TRUE);
935
936         GetClientRect(hApplicationPageSwitchToButton, &rc);
937         MapWindowPoints(hApplicationPageSwitchToButton, hDlg, (LPPOINT)(&rc), (sizeof(RECT)/sizeof(POINT)) );
938         cx = rc.left + nXDifference;
939         cy = rc.top + nYDifference;
940         SetWindowPos(hApplicationPageSwitchToButton, NULL, cx, cy, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER);
941         InvalidateRect(hApplicationPageSwitchToButton, NULL, TRUE);
942
943         GetClientRect(hApplicationPageNewTaskButton, &rc);
944         MapWindowPoints(hApplicationPageNewTaskButton, hDlg, (LPPOINT)(&rc), (sizeof(RECT)/sizeof(POINT)) );
945         cx = rc.left + nXDifference;
946         cy = rc.top + nYDifference;
947         SetWindowPos(hApplicationPageNewTaskButton, NULL, cx, cy, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER);
948         InvalidateRect(hApplicationPageNewTaskButton, NULL, TRUE);
949
950         break;
951
952     case WM_NOTIFY:
953         ApplicationPageOnNotify(wParam, lParam);
954         break;
955
956     }
957
958   return 0;
959 }