applpage.c 32.9 KB
Newer Older
1 2 3 4 5 6
/*
 *  ReactOS Task Manager
 *
 *  applpage.c
 *
 *  Copyright (C) 1999 - 2001  Brian Palmer  <brianp@reactos.org>
7
 *  Copyright (C) 2008  Vladimir Pankratov
8 9 10 11 12 13 14 15 16 17 18 19 20
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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 25 26 27 28 29 30
 */

#define WIN32_LEAN_AND_MEAN    /* Exclude rarely-used stuff from Windows headers */
#include <windows.h>
#include <commctrl.h>
#include <stdlib.h>
#include <memory.h>
#include <stdio.h>

31
#include "wine/unicode.h"
32 33 34 35 36
#include "taskmgr.h"

typedef struct
{
    HWND    hWnd;
37
    WCHAR   wszTitle[256];
38 39 40 41 42 43 44 45 46 47 48 49 50 51
    HICON   hIcon;
    BOOL    bHung;
} APPLICATION_PAGE_LIST_ITEM, *LPAPPLICATION_PAGE_LIST_ITEM;

HWND            hApplicationPage;               /* Application List Property Page */
HWND            hApplicationPageListCtrl;       /* Application ListCtrl Window */
HWND            hApplicationPageEndTaskButton;  /* Application End Task button */
HWND            hApplicationPageSwitchToButton; /* Application Switch To button */
HWND            hApplicationPageNewTaskButton;  /* Application New Task button */
static int      nApplicationPageWidth;
static int      nApplicationPageHeight;
static HANDLE   hApplicationPageEvent = NULL;   /* When this event becomes signaled then we refresh the app list */
static BOOL     bSortAscending = TRUE;

52
static const WCHAR    wszUser32[] = {'U','S','E','R','3','2','.','D','L','L',0};
53 54 55 56 57 58 59
#if 0
void SwitchToThisWindow (
HWND hWnd,   /* Handle to the window that should be activated */
BOOL bRestore /* Restore the window if it is minimized */
);
#endif

60
static void ApplicationPageUpdate(void)
61
{
62 63 64 65 66
    /* Enable or disable the "End Task" & "Switch To" buttons */
    if (ListView_GetSelectedCount(hApplicationPageListCtrl))
    {
        EnableWindow(hApplicationPageEndTaskButton, TRUE);
        EnableWindow(hApplicationPageSwitchToButton, TRUE);
67 68 69
    }
    else
    {
70 71
        EnableWindow(hApplicationPageEndTaskButton, FALSE);
        EnableWindow(hApplicationPageSwitchToButton, FALSE);
72 73
    }

74
    /* If we are on the applications tab, then the windows menu will */
75 76
    /* be present on the menu bar so enable & disable the menu items */
    if (TabCtrl_GetCurSel(hTabWnd) == 0)
77
    {
78 79
        HMENU   hMenu;
        HMENU   hWindowsMenu;
80

81 82
        hMenu = GetMenu(hMainWnd);
        hWindowsMenu = GetSubMenu(hMenu, 3);
83

84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
        /* Only one item selected */
        if (ListView_GetSelectedCount(hApplicationPageListCtrl) == 1)
        {
            EnableMenuItem(hWindowsMenu, ID_WINDOWS_TILEHORIZONTALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
            EnableMenuItem(hWindowsMenu, ID_WINDOWS_TILEVERTICALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
            EnableMenuItem(hWindowsMenu, ID_WINDOWS_MINIMIZE, MF_BYCOMMAND|MF_ENABLED);
            EnableMenuItem(hWindowsMenu, ID_WINDOWS_MAXIMIZE, MF_BYCOMMAND|MF_ENABLED);
            EnableMenuItem(hWindowsMenu, ID_WINDOWS_CASCADE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
            EnableMenuItem(hWindowsMenu, ID_WINDOWS_BRINGTOFRONT, MF_BYCOMMAND|MF_ENABLED);
        }
        /* More than one item selected */
        else if (ListView_GetSelectedCount(hApplicationPageListCtrl) > 1)
        {
            EnableMenuItem(hWindowsMenu, ID_WINDOWS_TILEHORIZONTALLY, MF_BYCOMMAND|MF_ENABLED);
            EnableMenuItem(hWindowsMenu, ID_WINDOWS_TILEVERTICALLY, MF_BYCOMMAND|MF_ENABLED);
            EnableMenuItem(hWindowsMenu, ID_WINDOWS_MINIMIZE, MF_BYCOMMAND|MF_ENABLED);
            EnableMenuItem(hWindowsMenu, ID_WINDOWS_MAXIMIZE, MF_BYCOMMAND|MF_ENABLED);
            EnableMenuItem(hWindowsMenu, ID_WINDOWS_CASCADE, MF_BYCOMMAND|MF_ENABLED);
            EnableMenuItem(hWindowsMenu, ID_WINDOWS_BRINGTOFRONT, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
        }
        /* No items selected */
        else
        {
            EnableMenuItem(hWindowsMenu, ID_WINDOWS_TILEHORIZONTALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
            EnableMenuItem(hWindowsMenu, ID_WINDOWS_TILEVERTICALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
            EnableMenuItem(hWindowsMenu, ID_WINDOWS_MINIMIZE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
            EnableMenuItem(hWindowsMenu, ID_WINDOWS_MAXIMIZE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
            EnableMenuItem(hWindowsMenu, ID_WINDOWS_CASCADE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
            EnableMenuItem(hWindowsMenu, ID_WINDOWS_BRINGTOFRONT, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
        }
114 115 116
    }
}

117
static void AddOrUpdateHwnd(HWND hWnd, WCHAR *wszTitle, HICON hIcon, BOOL bHung)
118 119 120 121
{
    LPAPPLICATION_PAGE_LIST_ITEM    pAPLI = NULL;
    HIMAGELIST                      hImageListLarge;
    HIMAGELIST                      hImageListSmall;
122
    LV_ITEMW                        item;
123 124 125 126
    int                             i;
    BOOL                            bAlreadyInList = FALSE;
    BOOL                            bItemRemoved = FALSE;

127
    memset(&item, 0, sizeof(LV_ITEMW));
128 129 130 131 132 133 134 135

    /* Get the image lists */
    hImageListLarge = ListView_GetImageList(hApplicationPageListCtrl, LVSIL_NORMAL);
    hImageListSmall = ListView_GetImageList(hApplicationPageListCtrl, LVSIL_SMALL);

    /* Check to see if it's already in our list */
    for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++)
    {
136
        memset(&item, 0, sizeof(LV_ITEMW));
137 138
        item.mask = LVIF_IMAGE|LVIF_PARAM;
        item.iItem = i;
139
        SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
140 141 142 143 144 145 146 147 148 149 150 151 152 153

        pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
        if (pAPLI->hWnd == hWnd)
        {
            bAlreadyInList = TRUE;
            break;
        }
    }

    /* If it is already in the list then update it if necessary */
    if (bAlreadyInList)
    {
        /* Check to see if anything needs updating */
        if ((pAPLI->hIcon != hIcon) ||
154
            (strcmpW(pAPLI->wszTitle, wszTitle) != 0) ||
155 156 157 158 159
            (pAPLI->bHung != bHung))
        {
            /* Update the structure */
            pAPLI->hIcon = hIcon;
            pAPLI->bHung = bHung;
160
            strcpyW(pAPLI->wszTitle, wszTitle);
161 162 163 164 165 166

            /* Update the image list */
            ImageList_ReplaceIcon(hImageListLarge, item.iItem, hIcon);
            ImageList_ReplaceIcon(hImageListSmall, item.iItem, hIcon);

            /* Update the list view */
167
            SendMessageW(hApplicationPageListCtrl, LVM_REDRAWITEMS, 0, ListView_GetItemCount(hApplicationPageListCtrl));
168 169 170 171 172 173 174
            /* UpdateWindow(hApplicationPageListCtrl); */
            InvalidateRect(hApplicationPageListCtrl, NULL, 0);
        }
    }
    /* It is not already in the list so add it */
    else
    {
175
        pAPLI = HeapAlloc(GetProcessHeap(), 0, sizeof(APPLICATION_PAGE_LIST_ITEM));
176 177 178 179

        pAPLI->hWnd = hWnd;
        pAPLI->hIcon = hIcon;
        pAPLI->bHung = bHung;
180
        strcpyW(pAPLI->wszTitle, wszTitle);
181 182

        /* Add the item to the list */
183
        memset(&item, 0, sizeof(LV_ITEMW));
184 185 186
        item.mask = LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM;
        ImageList_AddIcon(hImageListLarge, hIcon);
        item.iImage = ImageList_AddIcon(hImageListSmall, hIcon);
187
        item.pszText = LPSTR_TEXTCALLBACKW;
188 189
        item.iItem = ListView_GetItemCount(hApplicationPageListCtrl);
        item.lParam = (LPARAM)pAPLI;
190
        SendMessageW(hApplicationPageListCtrl, LVM_INSERTITEMW, 0, (LPARAM) &item);
191 192 193 194 195 196
    }


    /* Check to see if we need to remove any items from the list */
    for (i=ListView_GetItemCount(hApplicationPageListCtrl)-1; i>=0; i--)
    {
197
        memset(&item, 0, sizeof(LV_ITEMW));
198 199
        item.mask = LVIF_IMAGE|LVIF_PARAM;
        item.iItem = i;
200
        SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
201 202 203

        pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
        if (!IsWindow(pAPLI->hWnd)||
204
            (strlenW(pAPLI->wszTitle) <= 0) ||
205 206 207 208 209 210 211 212
            !IsWindowVisible(pAPLI->hWnd) ||
            (GetParent(pAPLI->hWnd) != NULL) ||
            (GetWindow(pAPLI->hWnd, GW_OWNER) != NULL) ||
            (GetWindowLong(hWnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW))
        {
            ImageList_Remove(hImageListLarge, item.iItem);
            ImageList_Remove(hImageListSmall, item.iItem);

213
            SendMessage(hApplicationPageListCtrl, LVM_DELETEITEM, item.iItem, 0);
214
            HeapFree(GetProcessHeap(), 0, pAPLI);
215 216 217 218 219 220 221 222 223 224 225 226 227
            bItemRemoved = TRUE;
        }
    }

    /*
     * If an item was removed from the list then
     * we need to resync all the items with the
     * image list
     */
    if (bItemRemoved)
    {
        for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++)
        {
228
            memset(&item, 0, sizeof(LV_ITEMW));
229 230 231
            item.mask = LVIF_IMAGE;
            item.iItem = i;
            item.iImage = i;
232
            SendMessageW(hApplicationPageListCtrl, LVM_SETITEMW, 0, (LPARAM) &item);
233 234 235 236 237 238
        }
    }

    ApplicationPageUpdate();
}

239
static BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
240
{
241
    HICON hIcon;
242
    WCHAR wszText[256];
243 244 245 246 247 248 249 250 251 252 253 254 255
    BOOL  bLargeIcon;
    BOOL  bHung = FALSE;
    typedef int (__stdcall *IsHungAppWindowProc)(HWND);
    IsHungAppWindowProc IsHungAppWindow;


    /* Skip our window */
    if (hWnd == hMainWnd)
        return TRUE;

    bLargeIcon = TaskManagerSettings.View_LargeIcons ? TRUE : FALSE;

    /* Check and see if this is a top-level app window */
256
    if (!GetWindowTextW(hWnd, wszText, sizeof(wszText)/sizeof(WCHAR)) ||
257 258 259 260
        !IsWindowVisible(hWnd) ||
        (GetParent(hWnd) != NULL) ||
        (GetWindow(hWnd, GW_OWNER) != NULL) ||
        (GetWindowLong(hWnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW))
261
    {
262
        return TRUE; /* Skip this window */
263
    }
264 265 266 267 268 269

    /* Get the icon for this window */
    hIcon = NULL;
    SendMessageTimeout(hWnd, WM_GETICON, bLargeIcon ? ICON_BIG /*1*/ : ICON_SMALL /*0*/, 0, 0, 1000, (PDWORD_PTR)&hIcon);

    if (!hIcon)
270
    {
271 272 273 274
        hIcon = (HICON)GetClassLongPtr(hWnd, bLargeIcon ? GCLP_HICON : GCLP_HICONSM);
        if (!hIcon) hIcon = (HICON)GetClassLongPtr(hWnd, bLargeIcon ? GCLP_HICONSM : GCLP_HICON);
        if (!hIcon) SendMessageTimeout(hWnd, WM_QUERYDRAGICON, 0, 0, 0, 1000, (PDWORD_PTR)&hIcon);
        if (!hIcon) SendMessageTimeout(hWnd, WM_GETICON, bLargeIcon ? ICON_SMALL /*0*/ : ICON_BIG /*1*/, 0, 0, 1000, (PDWORD_PTR)&hIcon);
275 276
    }

277 278 279 280 281
    if (!hIcon)
        hIcon = LoadIcon(hInst, bLargeIcon ? MAKEINTRESOURCE(IDI_WINDOW) : MAKEINTRESOURCE(IDI_WINDOWSM));

    bHung = FALSE;

282
    IsHungAppWindow = (IsHungAppWindowProc)(FARPROC)GetProcAddress(GetModuleHandleW(wszUser32), "IsHungAppWindow");
283 284 285 286

    if (IsHungAppWindow)
        bHung = IsHungAppWindow(hWnd);

287
    AddOrUpdateHwnd(hWnd, wszText, hIcon, bHung);
288 289 290 291 292 293 294 295 296 297 298 299 300 301

    return TRUE;
}

static DWORD WINAPI ApplicationPageRefreshThread(void *lpParameter)
{
    /* Create the event */
    hApplicationPageEvent = CreateEvent(NULL, TRUE, TRUE, NULL);

    /* If we couldn't create the event then exit the thread */
    if (!hApplicationPageEvent)
        return 0;

    while (1)
302
    {
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
        DWORD   dwWaitVal;

        /* Wait on the event */
        dwWaitVal = WaitForSingleObject(hApplicationPageEvent, INFINITE);

        /* If the wait failed then the event object must have been */
        /* closed and the task manager is exiting so exit this thread */
        if (dwWaitVal == WAIT_FAILED)
            return 0;

        if (dwWaitVal == WAIT_OBJECT_0)
        {
            /* Reset our event */
            ResetEvent(hApplicationPageEvent);

            /*
             * FIXME:
             *
             * Should this be EnumDesktopWindows() instead?
             */
            EnumWindows(EnumWindowsProc, 0);
        }
    }
}

static void ApplicationPageShowContextMenu1(void)
{
    HMENU   hMenu;
    HMENU   hSubMenu;
    POINT   pt;

    GetCursorPos(&pt);

    hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_APPLICATION_PAGE_CONTEXT1));
    hSubMenu = GetSubMenu(hMenu, 0);

    if (TaskManagerSettings.View_LargeIcons)
        CheckMenuRadioItem(hSubMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_LARGE, MF_BYCOMMAND);
    else if (TaskManagerSettings.View_SmallIcons)
        CheckMenuRadioItem(hSubMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_SMALL, MF_BYCOMMAND);
    else
        CheckMenuRadioItem(hSubMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_DETAILS, MF_BYCOMMAND);

    TrackPopupMenu(hSubMenu, TPM_LEFTALIGN|TPM_TOPALIGN|TPM_LEFTBUTTON, pt.x, pt.y, 0, hMainWnd, NULL);

    DestroyMenu(hMenu);
}

static void ApplicationPageShowContextMenu2(void)
{
    HMENU   hMenu;
    HMENU   hSubMenu;
    POINT   pt;

    GetCursorPos(&pt);

    hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_APPLICATION_PAGE_CONTEXT2));
    hSubMenu = GetSubMenu(hMenu, 0);

    if (ListView_GetSelectedCount(hApplicationPageListCtrl) == 1)
    {
        EnableMenuItem(hSubMenu, ID_WINDOWS_TILEHORIZONTALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
        EnableMenuItem(hSubMenu, ID_WINDOWS_TILEVERTICALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
        EnableMenuItem(hSubMenu, ID_WINDOWS_MINIMIZE, MF_BYCOMMAND|MF_ENABLED);
        EnableMenuItem(hSubMenu, ID_WINDOWS_MAXIMIZE, MF_BYCOMMAND|MF_ENABLED);
        EnableMenuItem(hSubMenu, ID_WINDOWS_CASCADE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
        EnableMenuItem(hSubMenu, ID_WINDOWS_BRINGTOFRONT, MF_BYCOMMAND|MF_ENABLED);
    }
    else if (ListView_GetSelectedCount(hApplicationPageListCtrl) > 1)
    {
        EnableMenuItem(hSubMenu, ID_WINDOWS_TILEHORIZONTALLY, MF_BYCOMMAND|MF_ENABLED);
        EnableMenuItem(hSubMenu, ID_WINDOWS_TILEVERTICALLY, MF_BYCOMMAND|MF_ENABLED);
        EnableMenuItem(hSubMenu, ID_WINDOWS_MINIMIZE, MF_BYCOMMAND|MF_ENABLED);
        EnableMenuItem(hSubMenu, ID_WINDOWS_MAXIMIZE, MF_BYCOMMAND|MF_ENABLED);
        EnableMenuItem(hSubMenu, ID_WINDOWS_CASCADE, MF_BYCOMMAND|MF_ENABLED);
        EnableMenuItem(hSubMenu, ID_WINDOWS_BRINGTOFRONT, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
    }
    else
    {
        EnableMenuItem(hSubMenu, ID_WINDOWS_TILEHORIZONTALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
        EnableMenuItem(hSubMenu, ID_WINDOWS_TILEVERTICALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
        EnableMenuItem(hSubMenu, ID_WINDOWS_MINIMIZE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
        EnableMenuItem(hSubMenu, ID_WINDOWS_MAXIMIZE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
        EnableMenuItem(hSubMenu, ID_WINDOWS_CASCADE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
        EnableMenuItem(hSubMenu, ID_WINDOWS_BRINGTOFRONT, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
    }

    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 395 396 397 398 399 400 401 402 403 404 405 406 407
    DestroyMenu(hMenu);
}

static int CALLBACK ApplicationPageCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
    LPAPPLICATION_PAGE_LIST_ITEM Param1;
    LPAPPLICATION_PAGE_LIST_ITEM Param2;

    if (bSortAscending) {
        Param1 = (LPAPPLICATION_PAGE_LIST_ITEM)lParam1;
        Param2 = (LPAPPLICATION_PAGE_LIST_ITEM)lParam2;
    } else {
        Param1 = (LPAPPLICATION_PAGE_LIST_ITEM)lParam2;
        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 415 416
{
    int             idctrl;
    LPNMHDR         pnmh;
    LPNM_LISTVIEW   pnmv;
417
    LV_DISPINFOW*   pnmdi;
418 419
    LPAPPLICATION_PAGE_LIST_ITEM pAPLI;

420 421
    WCHAR    wszNotResponding[255];
    WCHAR    wszRunning[255];
422

423 424
    LoadStringW(hInst, IDS_APPLICATION_NOT_RESPONDING, wszNotResponding, sizeof(wszNotResponding)/sizeof(WCHAR));
    LoadStringW(hInst, IDS_APPLICATION_RUNNING, wszRunning, sizeof(wszRunning)/sizeof(WCHAR));
425 426 427 428

    idctrl = (int) wParam;
    pnmh = (LPNMHDR) lParam;
    pnmv = (LPNM_LISTVIEW) lParam;
429
    pnmdi = (LV_DISPINFOW*) lParam;
430 431 432 433 434 435 436

    if (pnmh->hwndFrom == hApplicationPageListCtrl) {
        switch (pnmh->code) {
        case LVN_ITEMCHANGED:
            ApplicationPageUpdate();
            break;
            
437
        case LVN_GETDISPINFOW:
438 439 440 441 442
            pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)pnmdi->item.lParam;

            /* Update the item text */
            if (pnmdi->item.iSubItem == 0)
            {
443
                lstrcpynW(pnmdi->item.pszText, pAPLI->wszTitle, pnmdi->item.cchTextMax);
444 445 446 447 448 449
            }

            /* Update the item status */
            else if (pnmdi->item.iSubItem == 1)
            {
                if (pAPLI->bHung)
450
                    lstrcpynW(pnmdi->item.pszText, wszNotResponding, pnmdi->item.cchTextMax);
451
                else
452
                    lstrcpynW(pnmdi->item.pszText, wszRunning, pnmdi->item.cchTextMax);
453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495
            }

            break;

        case NM_RCLICK:

            if (ListView_GetSelectedCount(hApplicationPageListCtrl) < 1)
            {
                ApplicationPageShowContextMenu1();
            }
            else
            {
                ApplicationPageShowContextMenu2();
            }

            break;

        case NM_DBLCLK:

            ApplicationPage_OnSwitchTo();

            break;
        }
    }
    else if (pnmh->hwndFrom == ListView_GetHeader(hApplicationPageListCtrl))
    {
        switch (pnmh->code)
        {
        case NM_RCLICK:

            if (ListView_GetSelectedCount(hApplicationPageListCtrl) < 1)
            {
                ApplicationPageShowContextMenu1();
            }
            else
            {
                ApplicationPageShowContextMenu2();
            }

            break;

        case HDN_ITEMCLICK:

496
            SendMessageW(hApplicationPageListCtrl, LVM_SORTITEMS, 0, (LPARAM) ApplicationPageCompareFunc);
497 498 499 500 501 502 503 504
            bSortAscending = !bSortAscending;

            break;
        }
    }

}

505
void RefreshApplicationPage(void)
506
{
507 508 509 510
    /* Signal the event so that our refresh thread */
    /* will wake up and refresh the application page */
    SetEvent(hApplicationPageEvent);
}
511

512
static void UpdateApplicationListControlViewSetting(void)
513 514
{
    DWORD   dwStyle = GetWindowLong(hApplicationPageListCtrl, GWL_STYLE);
515

516 517 518 519
    dwStyle &= ~LVS_REPORT;
    dwStyle &= ~LVS_ICON;
    dwStyle &= ~LVS_LIST;
    dwStyle &= ~LVS_SMALLICON;
520

521 522 523 524
    if (TaskManagerSettings.View_LargeIcons)
        dwStyle |= LVS_ICON;
    else if (TaskManagerSettings.View_SmallIcons)
        dwStyle |= LVS_SMALLICON;
525
    else
526
        dwStyle |= LVS_REPORT;
527

528
    SetWindowLong(hApplicationPageListCtrl, GWL_STYLE, dwStyle);
529

530
    RefreshApplicationPage();
531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583
}

void ApplicationPage_OnViewLargeIcons(void)
{
    HMENU   hMenu;
    HMENU   hViewMenu;

    hMenu = GetMenu(hMainWnd);
    hViewMenu = GetSubMenu(hMenu, 2);

    TaskManagerSettings.View_LargeIcons = TRUE;
    TaskManagerSettings.View_SmallIcons = FALSE;
    TaskManagerSettings.View_Details = FALSE;
    CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_LARGE, MF_BYCOMMAND);

    UpdateApplicationListControlViewSetting();
}

void ApplicationPage_OnViewSmallIcons(void)
{
    HMENU   hMenu;
    HMENU   hViewMenu;

    hMenu = GetMenu(hMainWnd);
    hViewMenu = GetSubMenu(hMenu, 2);

    TaskManagerSettings.View_LargeIcons = FALSE;
    TaskManagerSettings.View_SmallIcons = TRUE;
    TaskManagerSettings.View_Details = FALSE;
    CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_SMALL, MF_BYCOMMAND);

    UpdateApplicationListControlViewSetting();
}

void ApplicationPage_OnViewDetails(void)
{
    HMENU   hMenu;
    HMENU   hViewMenu;

    hMenu = GetMenu(hMainWnd);
    hViewMenu = GetSubMenu(hMenu, 2);

    TaskManagerSettings.View_LargeIcons = FALSE;
    TaskManagerSettings.View_SmallIcons = FALSE;
    TaskManagerSettings.View_Details = TRUE;
    CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_DETAILS, MF_BYCOMMAND);

    UpdateApplicationListControlViewSetting();
}

void ApplicationPage_OnWindowsTileHorizontally(void)
{
    LPAPPLICATION_PAGE_LIST_ITEM    pAPLI = NULL;
584
    LV_ITEMW                        item;
585 586 587 588
    int                             i;
    HWND*                           hWndArray;
    int                             nWndCount;

589 590
    hWndArray = HeapAlloc(GetProcessHeap(), 0,
                    sizeof(HWND) * ListView_GetItemCount(hApplicationPageListCtrl));
591 592 593
    nWndCount = 0;

    for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) {
594
        memset(&item, 0, sizeof(LV_ITEMW));
595 596 597
        item.mask = LVIF_STATE|LVIF_PARAM;
        item.iItem = i;
        item.stateMask = (UINT)-1;
598
        SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
599 600 601 602 603 604 605 606 607 608 609

        if (item.state & LVIS_SELECTED) {
            pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;

            if (pAPLI) {
                hWndArray[nWndCount] = pAPLI->hWnd;
                nWndCount++;
            }
        }
    }
    TileWindows(NULL, MDITILE_HORIZONTAL, NULL, nWndCount, hWndArray);
610
    HeapFree(GetProcessHeap(), 0, hWndArray);
611 612 613 614 615
}

void ApplicationPage_OnWindowsTileVertically(void)
{
    LPAPPLICATION_PAGE_LIST_ITEM    pAPLI = NULL;
616
    LV_ITEMW                        item;
617 618 619 620
    int                             i;
    HWND*                           hWndArray;
    int                             nWndCount;

621 622
    hWndArray = HeapAlloc(GetProcessHeap(), 0,
                    sizeof(HWND) * ListView_GetItemCount(hApplicationPageListCtrl));
623 624 625
    nWndCount = 0;

    for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) {
626
        memset(&item, 0, sizeof(LV_ITEMW));
627 628 629
        item.mask = LVIF_STATE|LVIF_PARAM;
        item.iItem = i;
        item.stateMask = (UINT)-1;
630
        SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
631 632 633 634 635 636 637 638 639 640 641

        if (item.state & LVIS_SELECTED) {
            pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
            if (pAPLI) {
                hWndArray[nWndCount] = pAPLI->hWnd;
                nWndCount++;
            }
        }
    }

    TileWindows(NULL, MDITILE_VERTICAL, NULL, nWndCount, hWndArray);
642
    HeapFree(GetProcessHeap(), 0, hWndArray);
643 644 645 646 647
}

void ApplicationPage_OnWindowsMinimize(void)
{
    LPAPPLICATION_PAGE_LIST_ITEM    pAPLI = NULL;
648
    LV_ITEMW                        item;
649 650 651
    int                             i;

    for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) {
652
        memset(&item, 0, sizeof(LV_ITEMW));
653 654 655
        item.mask = LVIF_STATE|LVIF_PARAM;
        item.iItem = i;
        item.stateMask = (UINT)-1;
656
        SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
657 658 659 660 661 662 663 664 665 666 667 668
        if (item.state & LVIS_SELECTED) {
            pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
            if (pAPLI) {
                ShowWindow(pAPLI->hWnd, SW_MINIMIZE);
            }
        }
    }
}

void ApplicationPage_OnWindowsMaximize(void)
{
    LPAPPLICATION_PAGE_LIST_ITEM    pAPLI = NULL;
669
    LV_ITEMW                        item;
670 671 672
    int                             i;

    for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) {
673
        memset(&item, 0, sizeof(LV_ITEMW));
674 675 676
        item.mask = LVIF_STATE|LVIF_PARAM;
        item.iItem = i;
        item.stateMask = (UINT)-1;
677
        SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
678 679 680 681 682 683 684 685 686 687 688 689
        if (item.state & LVIS_SELECTED) {
            pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
            if (pAPLI) {
                ShowWindow(pAPLI->hWnd, SW_MAXIMIZE);
            }
        }
    }
}

void ApplicationPage_OnWindowsCascade(void)
{
    LPAPPLICATION_PAGE_LIST_ITEM    pAPLI = NULL;
690
    LV_ITEMW                        item;
691 692 693 694
    int                             i;
    HWND*                           hWndArray;
    int                             nWndCount;

695 696
    hWndArray = HeapAlloc(GetProcessHeap(), 0,
                    sizeof(HWND) * ListView_GetItemCount(hApplicationPageListCtrl));
697 698 699
    nWndCount = 0;

    for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) {
700
        memset(&item, 0, sizeof(LV_ITEMW));
701 702 703
        item.mask = LVIF_STATE|LVIF_PARAM;
        item.iItem = i;
        item.stateMask = (UINT)-1;
704
        SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
705 706 707 708 709 710 711 712 713
        if (item.state & LVIS_SELECTED) {
            pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
            if (pAPLI) {
                hWndArray[nWndCount] = pAPLI->hWnd;
                nWndCount++;
            }
        }
    }
    CascadeWindows(NULL, 0, NULL, nWndCount, hWndArray);
714
    HeapFree(GetProcessHeap(), 0, hWndArray);
715 716 717 718 719
}

void ApplicationPage_OnWindowsBringToFront(void)
{
    LPAPPLICATION_PAGE_LIST_ITEM    pAPLI = NULL;
720
    LV_ITEMW                        item;
721 722 723
    int                             i;

    for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) {
724
        memset(&item, 0, sizeof(LV_ITEMW));
725 726 727
        item.mask = LVIF_STATE|LVIF_PARAM;
        item.iItem = i;
        item.stateMask = (UINT)-1;
728
        SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
729 730 731 732 733 734 735 736 737 738 739 740 741 742 743
        if (item.state & LVIS_SELECTED) {
            pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
            break;
        }
    }
    if (pAPLI) {
        if (IsIconic(pAPLI->hWnd))
            ShowWindow(pAPLI->hWnd, SW_RESTORE);
        BringWindowToTop(pAPLI->hWnd);
    }
}

void ApplicationPage_OnSwitchTo(void)
{
    LPAPPLICATION_PAGE_LIST_ITEM    pAPLI = NULL;
744
    LV_ITEMW                        item;
745 746 747
    int                             i;

    for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) {
748
        memset(&item, 0, sizeof(LV_ITEMW));
749 750 751
        item.mask = LVIF_STATE|LVIF_PARAM;
        item.iItem = i;
        item.stateMask = (UINT)-1;
752
        SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
753 754 755 756 757 758 759 760 761 762

        if (item.state & LVIS_SELECTED) {
            pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
            break;
        }
    }
    if (pAPLI) {
        typedef void (WINAPI *PROCSWITCHTOTHISWINDOW) (HWND, BOOL);
        PROCSWITCHTOTHISWINDOW SwitchToThisWindow;

763
        HMODULE hUser32 = GetModuleHandleW(wszUser32);
764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780
        SwitchToThisWindow = (PROCSWITCHTOTHISWINDOW)GetProcAddress(hUser32, "SwitchToThisWindow");
        if (SwitchToThisWindow) {
            SwitchToThisWindow(pAPLI->hWnd, TRUE);
        } else {
            if (IsIconic(pAPLI->hWnd))
                ShowWindow(pAPLI->hWnd, SW_RESTORE);
            BringWindowToTop(pAPLI->hWnd);
            SetForegroundWindow(pAPLI->hWnd);
        }
        if (TaskManagerSettings.MinimizeOnUse)
            ShowWindow(hMainWnd, SW_MINIMIZE);
    }
}

void ApplicationPage_OnEndTask(void)
{
    LPAPPLICATION_PAGE_LIST_ITEM    pAPLI = NULL;
781
    LV_ITEMW                        item;
782 783 784
    int                             i;

    for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) {
785
        memset(&item, 0, sizeof(LV_ITEMW));
786 787 788
        item.mask = LVIF_STATE|LVIF_PARAM;
        item.iItem = i;
        item.stateMask = (UINT)-1;
789
        SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
790 791 792 793 794 795 796 797 798 799 800 801
        if (item.state & LVIS_SELECTED) {
            pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
            if (pAPLI) {
                PostMessage(pAPLI->hWnd, WM_CLOSE, 0, 0);
            }
        }
    }
}

void ApplicationPage_OnGotoProcess(void)
{
    LPAPPLICATION_PAGE_LIST_ITEM pAPLI = NULL;
802
    LV_ITEMW item;
803 804 805 806
    int i;
    /* NMHDR nmhdr; */

    for (i=0; i<ListView_GetItemCount(hApplicationPageListCtrl); i++) {
807
        memset(&item, 0, sizeof(LV_ITEMW));
808 809 810
        item.mask = LVIF_STATE|LVIF_PARAM;
        item.iItem = i;
        item.stateMask = (UINT)-1;
811
        SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831
        if (item.state & LVIS_SELECTED) {
            pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
            break;
        }
    }
    if (pAPLI) {
        DWORD   dwProcessId;

        GetWindowThreadProcessId(pAPLI->hWnd, &dwProcessId);
        /*
         * Switch to the process tab
         */
        TabCtrl_SetCurFocus(hTabWnd, 1);
        /*
         * FIXME: Select the process item in the list
         */
        for (i=0; i<ListView_GetItemCount(hProcessPage); i++) {
        }
    }
}
832 833 834 835 836 837 838 839 840 841

INT_PTR CALLBACK
ApplicationPageWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    RECT        rc;
    int         nXDifference;
    int         nYDifference;
    int         cx, cy;
    LVCOLUMNW   column;

842 843 844 845 846
    WCHAR wszTask[255];
    WCHAR wszStatus[255];

    LoadStringW(hInst, IDS_APPLICATION_TASK, wszTask, sizeof(wszTask)/sizeof(WCHAR));
    LoadStringW(hInst, IDS_APPLICATION_STATUS, wszStatus, sizeof(wszStatus)/sizeof(WCHAR));
847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961

    switch (message) {
    case WM_INITDIALOG:

        /* Save the width and height */
        GetClientRect(hDlg, &rc);
        nApplicationPageWidth = rc.right;
        nApplicationPageHeight = rc.bottom;

        /* Update window position */
        SetWindowPos(hDlg, NULL, 15, 30, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER);

        /* Get handles to the controls */
        hApplicationPageListCtrl = GetDlgItem(hDlg, IDC_APPLIST);
        hApplicationPageEndTaskButton = GetDlgItem(hDlg, IDC_ENDTASK);
        hApplicationPageSwitchToButton = GetDlgItem(hDlg, IDC_SWITCHTO);
        hApplicationPageNewTaskButton = GetDlgItem(hDlg, IDC_NEWTASK);

        /* Initialize the application page's controls */
        column.mask = LVCF_TEXT|LVCF_WIDTH;
        column.pszText = wszTask;
        column.cx = 250;
        /* Add the "Task" column */
        SendMessageW(hApplicationPageListCtrl, LVM_INSERTCOLUMNW, 0, (LPARAM) &column);
        column.mask = LVCF_TEXT|LVCF_WIDTH;
        column.pszText = wszStatus;
        column.cx = 95;
        /* Add the "Status" column */
        SendMessageW(hApplicationPageListCtrl, LVM_INSERTCOLUMNW, 1, (LPARAM) &column);

        SendMessageW(hApplicationPageListCtrl, LVM_SETIMAGELIST, LVSIL_SMALL,
                    (LPARAM) ImageList_Create(16, 16, ILC_COLOR8|ILC_MASK, 0, 1));
        SendMessageW(hApplicationPageListCtrl, LVM_SETIMAGELIST, LVSIL_NORMAL,
                    (LPARAM) ImageList_Create(32, 32, ILC_COLOR8|ILC_MASK, 0, 1));

        UpdateApplicationListControlViewSetting();

        /* Start our refresh thread */
        CreateThread(NULL, 0, ApplicationPageRefreshThread, NULL, 0, NULL);

        return TRUE;

    case WM_DESTROY:
        /* Close the event handle, this will make the */
        /* refresh thread exit when the wait fails */
        CloseHandle(hApplicationPageEvent);
        break;

    case WM_COMMAND:

        /* Handle the button clicks */
        switch (LOWORD(wParam))
        {
        case IDC_ENDTASK:
            ApplicationPage_OnEndTask();
            break;
        case IDC_SWITCHTO:
            ApplicationPage_OnSwitchTo();
            break;
        case IDC_NEWTASK:
            SendMessageW(hMainWnd, WM_COMMAND, MAKEWPARAM(ID_FILE_NEW, 0), 0);
            break;
        }

        break;

    case WM_SIZE:
        if (wParam == SIZE_MINIMIZED)
            return 0;

        cx = LOWORD(lParam);
        cy = HIWORD(lParam);
        nXDifference = cx - nApplicationPageWidth;
        nYDifference = cy - nApplicationPageHeight;
        nApplicationPageWidth = cx;
        nApplicationPageHeight = cy;

        /* Reposition the application page's controls */
        GetWindowRect(hApplicationPageListCtrl, &rc);
        cx = (rc.right - rc.left) + nXDifference;
        cy = (rc.bottom - rc.top) + nYDifference;
        SetWindowPos(hApplicationPageListCtrl, NULL, 0, 0, cx, cy, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOMOVE|SWP_NOZORDER);
        InvalidateRect(hApplicationPageListCtrl, NULL, TRUE);

        GetClientRect(hApplicationPageEndTaskButton, &rc);
        MapWindowPoints(hApplicationPageEndTaskButton, hDlg, (LPPOINT)(&rc), (sizeof(RECT)/sizeof(POINT)) );
        cx = rc.left + nXDifference;
        cy = rc.top + nYDifference;
        SetWindowPos(hApplicationPageEndTaskButton, NULL, cx, cy, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER);
        InvalidateRect(hApplicationPageEndTaskButton, NULL, TRUE);

        GetClientRect(hApplicationPageSwitchToButton, &rc);
        MapWindowPoints(hApplicationPageSwitchToButton, hDlg, (LPPOINT)(&rc), (sizeof(RECT)/sizeof(POINT)) );
        cx = rc.left + nXDifference;
        cy = rc.top + nYDifference;
        SetWindowPos(hApplicationPageSwitchToButton, NULL, cx, cy, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER);
        InvalidateRect(hApplicationPageSwitchToButton, NULL, TRUE);

        GetClientRect(hApplicationPageNewTaskButton, &rc);
        MapWindowPoints(hApplicationPageNewTaskButton, hDlg, (LPPOINT)(&rc), (sizeof(RECT)/sizeof(POINT)) );
        cx = rc.left + nXDifference;
        cy = rc.top + nYDifference;
        SetWindowPos(hApplicationPageNewTaskButton, NULL, cx, cy, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER);
        InvalidateRect(hApplicationPageNewTaskButton, NULL, TRUE);

        break;

    case WM_NOTIFY:
        ApplicationPageOnNotify(wParam, lParam);
        break;

    }

  return 0;
}