⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 taskswnd.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 5 页
字号:
            NewBtnSize = (rcClient.right - (uiBtnsPerLine * tbm.cxButtonSpacing)) / uiBtnsPerLine;

            /* Determine the minimum and maximum width of a button */
            if (Horizontal)
                uiMax = GetSystemMetrics(SM_CXMINIMIZED);
            else
                uiMax = rcClient.right;

            uiMin = GetSystemMetrics(SM_CXSIZE) + (2 * GetSystemMetrics(SM_CXEDGE));

            if (NewBtnSize < uiMin)
                NewBtnSize = uiMin;
            if (NewBtnSize > uiMax)
                NewBtnSize = uiMax;

            This->ButtonSize.cx = NewBtnSize;

            /* Recalculate how many buttons actually fit into one line */
            uiBtnsPerLine = rcClient.right / (NewBtnSize + tbm.cxButtonSpacing);
            if (uiBtnsPerLine == 0)
                uiBtnsPerLine++;
            This->TbButtonsPerLine = uiBtnsPerLine;

            tbbi.cbSize = sizeof(tbbi);
            tbbi.dwMask = TBIF_BYINDEX | TBIF_SIZE | TBIF_STATE;
            tbbi.cx = (INT)NewBtnSize;

            for (ui = 0; ui != This->ToolbarBtnCount; ui++)
            {
                tbbi.fsState = TBSTATE_ENABLED;

                /* Check if we're updating a button that is the last one in the
                   line. If so, we need to set the TBSTATE_WRAP flag! */
                if ((ui + 1) % uiBtnsPerLine == 0)
                    tbbi.fsState |= TBSTATE_WRAP;

                if (This->ActiveTaskItem != NULL &&
                    This->ActiveTaskItem->Index == ui)
                {
                    tbbi.fsState |= TBSTATE_CHECKED;
                }

                SendMessage(This->hWndToolbar,
                            TB_SETBUTTONINFO,
                            (WPARAM)ui,
                            (LPARAM)&tbbi);
            }

#if 0
            /* FIXME: Force the window to the correct position in case some idiot
                      did something to us */
            SetWindowPos(This->hWndToolbar,
                         NULL,
                         0,
                         0,
                         rcClient.right, /* FIXME */
                         rcClient.bottom, /* FIXME */
                         SWP_NOACTIVATE | SWP_NOZORDER);
#endif
        }
        else
        {
            This->TbButtonsPerLine = 0;
            This->ButtonSize.cx = 0;
        }
    }

    TaskSwitchWnd_EndUpdate(This);
}

static BOOL CALLBACK
TaskSwitchWnd_EnumWindowsProc(IN HWND hWnd,
                              IN LPARAM lParam)
{
    PTASK_SWITCH_WND This = (PTASK_SWITCH_WND)lParam;

    /* Only show windows that still exist and are visible and none of explorer's
       special windows (such as the desktop or the tray window) */
    if (IsWindow(hWnd) && IsWindowVisible(hWnd) &&
        !ITrayWindow_IsSpecialHWND(This->Tray,
                                   hWnd))
    {
        /* Don't list popup windows and also no tool windows */
        if (GetWindow(hWnd,
                      GW_OWNER) == NULL &&
            !(GetWindowLong(hWnd,
                            GWL_EXSTYLE) & WS_EX_TOOLWINDOW))
        {
            TaskSwitchWnd_AddTask(This,
                                  hWnd);
        }
    }

    return TRUE;
}

static LRESULT CALLBACK
TaskSwichWnd_ToolbarSubclassedProc(IN HWND hWnd,
                                   IN UINT msg,
                                   IN WPARAM wParam,
                                   IN LPARAM lParam,
                                   IN UINT_PTR uIdSubclass,
                                   IN DWORD_PTR dwRefData)
{
    LRESULT Ret;

    Ret = DefSubclassProc(hWnd,
                          msg,
                          wParam,
                          lParam);

    if (msg == WM_NCHITTEST && Ret == HTCLIENT)
    {
        POINT pt;

        /* See if the mouse is on a button */
        pt.x = (SHORT)LOWORD(lParam);
        pt.y = (SHORT)HIWORD(lParam);

        if (MapWindowPoints(HWND_DESKTOP,
                            hWnd,
                            &pt,
                            1) != 0 &&
            (INT)SendMessage(hWnd,
                             TB_HITTEST,
                             0,
                             (LPARAM)&pt) < 0)
        {
            /* Make the control appear to be transparent outside of any buttons */
            Ret = HTTRANSPARENT;
        }
    }

    return Ret;
}

static VOID
TaskSwitchWnd_Create(IN OUT PTASK_SWITCH_WND This)
{
    This->hWndToolbar = CreateWindowEx(0,
                                       TOOLBARCLASSNAME,
                                       szRunningApps,
                                       WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN |
                                           TBSTYLE_TOOLTIPS | TBSTYLE_WRAPABLE | TBSTYLE_LIST |
                                           TBSTYLE_TRANSPARENT |
                                           CCS_TOP | CCS_NORESIZE | CCS_NODIVIDER,
                                       0,
                                       0,
                                       0,
                                       0,
                                       This->hWnd,
                                       NULL,
                                       hExplorerInstance,
                                       NULL);

    if (This->hWndToolbar != NULL)
    {
        SIZE BtnSize;

        /* Identify the version we're using */
        SendMessage(This->hWndToolbar,
                    TB_BUTTONSTRUCTSIZE,
                    sizeof(TBBUTTON),
                    0);

        /* Calculate the default button size. Don't save this in This->ButtonSize.cx so that
           the actual button width gets updated correctly on the first recalculation */
        BtnSize.cx = GetSystemMetrics(SM_CXMINIMIZED);
        This->ButtonSize.cy = BtnSize.cy = GetSystemMetrics(SM_CYSIZE) + (2 * GetSystemMetrics(SM_CYEDGE));
        SendMessage(This->hWndToolbar,
                    TB_SETBUTTONSIZE,
                    0,
                    (LPARAM)MAKELONG(BtnSize.cx,
                                     BtnSize.cy));

        /* We don't want to see partially clipped buttons...not that we could see them... */
#if 1
        SendMessage(This->hWndToolbar,
                    TB_SETEXTENDEDSTYLE,
                    0,
                    TBSTYLE_EX_HIDECLIPPEDBUTTONS);
#endif

        /* Set proper spacing between buttons */
        TaskSwitchWnd_UpdateTbButtonSpacing(This,
                                            ITrayWindow_IsHorizontal(This->Tray),
                                            0);

        /* Register the shell hook */
        This->ShellHookMsg = RegisterWindowMessage(TEXT("SHELLHOOK"));
        RegisterShellHook(This->hWnd,
                          3); /* 1 if not NT! We're targeting NT so we don't care! */

        /* Add all windows to the toolbar */
        EnumWindows(TaskSwitchWnd_EnumWindowsProc,
                    (LPARAM)This);

        /* Recalculate the button size */
        TaskSwitchWnd_UpdateButtonsSize(This,
                                        FALSE);

        /* Subclass the toolbar control because it doesn't provide a
           NM_NCHITTEST notification */
        This->IsToolbarSubclassed = SetWindowSubclass(This->hWndToolbar,
                                                      TaskSwichWnd_ToolbarSubclassedProc,
                                                      TSW_TOOLBAR_SUBCLASS_ID,
                                                      (DWORD_PTR)This);
    }
}

static VOID
TaskSwitchWnd_NCDestroy(IN OUT PTASK_SWITCH_WND This)
{
    This->IsDestroying = TRUE;

    /* Unregister the shell hook */
    RegisterShellHook(This->hWnd,
                      FALSE);

    TaskSwitchWnd_DeleteAllTasks(This);
}

static BOOL
TaskSwitchWnd_HandleAppCommand(IN OUT PTASK_SWITCH_WND This,
                               IN WPARAM wParam,
                               IN LPARAM lParam)
{
    BOOL Ret = FALSE;

    switch (GET_APPCOMMAND_LPARAM(lParam))
    {
        case APPCOMMAND_BROWSER_SEARCH:
            Ret = SHFindFiles(NULL,
                              NULL);
            break;

        case APPCOMMAND_BROWSER_HOME:
        case APPCOMMAND_LAUNCH_MAIL:
        default:
            DbgPrint("Shell app command %d unhandled!\n", (INT)GET_APPCOMMAND_LPARAM(lParam));
            break;
    }

    return Ret;
}


static LRESULT
TaskSwitchWnd_HandleShellHookMsg(IN OUT PTASK_SWITCH_WND This,
                                 IN WPARAM wParam,
                                 IN LPARAM lParam)
{
    BOOL Ret = FALSE;

    switch ((INT)wParam)
    {
        case HSHELL_APPCOMMAND:
            TaskSwitchWnd_HandleAppCommand(This,
                                           wParam,
                                           lParam);
            Ret = TRUE;
            break;

        case HSHELL_WINDOWCREATED:
            TaskSwitchWnd_AddTask(This,
                                  (HWND)lParam);
            Ret = TRUE;
            break;

        case HSHELL_WINDOWDESTROYED:
            /* The window still exists! Delay destroying it a bit */
            TaskSwitchWnd_DeleteTask(This,
                                     (HWND)lParam);
            Ret = TRUE;
            break;

        case HSHELL_ACTIVATESHELLWINDOW:
            goto UnhandledShellMessage;

        case HSHELL_RUDEAPPACTIVATED:
            goto UnhandledShellMessage;

        case HSHELL_WINDOWACTIVATED:
            TaskSwitchWnd_ActivateTask(This,
                                       (HWND)lParam);
            Ret = TRUE;
            break;

        case HSHELL_GETMINRECT:
            goto UnhandledShellMessage;

        case HSHELL_FLASH:
            TaskSwitchWnd_FlashTask(This,
                                    (HWND)lParam);
            Ret = TRUE;
            break;

        case HSHELL_REDRAW:
            TaskSwitchWnd_RedrawTask(This,
                                     (HWND)lParam);
            Ret = TRUE;
            break;

        case HSHELL_TASKMAN:
        case HSHELL_LANGUAGE:
        case HSHELL_SYSMENU:
        case HSHELL_ENDTASK:
        case HSHELL_ACCESSIBILITYSTATE:
        case HSHELL_WINDOWREPLACED:
        case HSHELL_WINDOWREPLACING:
        default:
        {
            static const struct {
                INT msg;
                LPCWSTR msg_name;
            } hshell_msg[] = {
                {HSHELL_WINDOWCREATED, L"HSHELL_WINDOWCREATED"},
                {HSHELL_WINDOWDESTROYED, L"HSHELL_WINDOWDESTROYED"},
                {HSHELL_ACTIVATESHELLWINDOW, L"HSHELL_ACTIVATESHELLWINDOW"},
                {HSHELL_WINDOWACTIVATED, L"HSHELL_WINDOWACTIVATED"},
                {HSHELL_GETMINRECT, L"HSHELL_GETMINRECT"},
                {HSHELL_REDRAW, L"HSHELL_REDRAW"},
                {HSHELL_TASKMAN, L"HSHELL_TASKMAN"},
                {HSHELL_LANGUAGE, L"HSHELL_LANGUAGE"},
                {HSHELL_SYSMENU, L"HSHELL_SYSMENU"},
                {HSHELL_ENDTASK, L"HSHELL_ENDTASK"},
                {HSHELL_ACCESSIBILITYSTATE, L"HSHELL_ACCESSIBILITYSTATE"},
                {HSHELL_APPCOMMAND, L"HSHELL_APPCOMMAND"},
                {HSHELL_WINDOWREPLACED, L"HSHELL_WINDOWREPLACED"},
                {HSHELL_WINDOWREPLACING, L"HSHELL_WINDOWREPLACING"},
                {HSHELL_RUDEAPPACTIVATED, L"HSHELL_RUDEAPPACTIVATED"},
            };
            int i, found;
UnhandledShellMessage:
            for (i = 0, found = 0; i != sizeof(hshell_msg) / sizeof(hshell_msg[0]); i++)
            {
                if (hshell_msg[i].msg == (INT)wParam)
                {
                    DbgPrint("Shell message %ws unhandled (lParam = 0x%p)!\n", hshell_msg[i].msg_name, lParam);
                    found = 1;
                    break;
                }
            }
            if (!found)
            {
                DbgPrint("Shell message %d unhandled (lParam = 0x%p)!\n", (INT)wParam, lParam);
            }
            break;
        }
    }

    return Ret;
}

static VOID
TaskSwitchWnd_EnableGrouping(IN OUT PTASK_SWITCH_WND This,
                             IN BOOL bEnable)
{
    This->IsGroupingEnabled = bEnable;

    /* Collapse or expand groups if neccessary */
    TaskSwitchWnd_UpdateButtonsSize(This,
                                    FALSE);
}

static LRESULT
TaskSwichWnd_HandleItemPaint(IN OUT PTASK_SWITCH_WND This,
                             IN OUT NMTBCUSTOMDRAW *nmtbcd)
{
    HFONT hCaptionFont, hBoldCaptionFont;
    LRESULT Ret = CDRF_DODEFAULT;

#if TASK_USE_DRAWCAPTIONTEMP != 0

    UINT uidctFlags = DC_TEXT | DC_ICON | DC_NOSENDMSG;

#endif

    if (!IS_TASKGROUP_PTR(nmtbcd->nmcd.lItemlParam))
    {
        PTASK_ITEM TaskItem = GET_TASKITEM_PTR(nmtbcd->nmcd.lItemlParam);

        if (TaskItem != NULL && IsWindow(TaskItem->hWnd))
        {
            hCaptionFont = ITrayWindow_GetCaptionFonts(This->Tray,
                                                       &hBoldCaptionFont);
            if (nmtbcd->nmcd.uItemState & CDIS_CHECKED)
                hCaptionFont = hBoldCaptionFont;

#if TASK_USE_DRAWCAPTIONTEMP != 0

            /* Make sure we don't draw on the button edges */
            InflateRect(&nmtbcd->nmcd.rc,
                        -GetSystemMetrics(SM_CXEDGE),
                        -GetSystemMetrics(SM_CYEDGE));

            if ((nmtbcd->nmcd.uItemState & CDIS_MARKED) && TaskItem->RenderFlashed)
            {
                /* This is a slight glitch. We have to move the rectangle so that
                   the button content appears to be pressed. However, when flashing
                   is enabled, we can see a light line at the top and left inner

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -