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