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

📄 desktop.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 3 页
字号:
                                                       IN REFIID riid,
                                                       OUT PVOID *ppv)
{
    /* FIXME - handle guidService */
    return IDesktopShellBrowserImpl_IServiceProvider_QueryInterface(iface,
                                                                    riid,
                                                                    ppv);
}

static const IServiceProviderVtbl IDesktopShellBrowserImpl_IServiceProvider_Vtbl =
{
    /* IUnknown */
    IDesktopShellBrowserImpl_IServiceProvider_QueryInterface,
    IDesktopShellBrowserImpl_IServiceProvider_AddRef,
    IDesktopShellBrowserImpl_IServiceProvider_Release,
    /* IServiceProvider */
    IDesktopShellBrowserImpl_IServiceProvider_QueryService
};

/*
 * IShellFolderViewCB
 */

static HRESULT STDMETHODCALLTYPE
IDesktopShellBrowserImpl_IShellFolderViewCB_QueryInterface(IN OUT IShellFolderViewCB *iface,
                                                           IN REFIID riid,
                                                           OUT LPVOID *ppvObj)
{
    IDesktopShellBrowserImpl *This = impl_from_IShellFolderViewCB(iface);
    IShellBrowser *ShellBrowser = IShellBrowser_from_impl(This);

    return IDesktopShellBrowserImpl_QueryInterface(ShellBrowser,
                                                   riid,
                                                   ppvObj);
}

static ULONG STDMETHODCALLTYPE
IDesktopShellBrowserImpl_IShellFolderViewCB_Release(IN OUT IShellFolderViewCB *iface)
{
    IDesktopShellBrowserImpl *This = impl_from_IShellFolderViewCB(iface);
    IShellBrowser *ShellBrowser = IShellBrowser_from_impl(This);

    return IDesktopShellBrowserImpl_Release(ShellBrowser);
}

static ULONG STDMETHODCALLTYPE
IDesktopShellBrowserImpl_IShellFolderViewCB_AddRef(IN OUT IShellFolderViewCB *iface)
{
    IDesktopShellBrowserImpl *This = impl_from_IShellFolderViewCB(iface);
    IShellBrowser *ShellBrowser = IShellBrowser_from_impl(This);

    return IDesktopShellBrowserImpl_AddRef(ShellBrowser);
}

static HRESULT STDMETHODCALLTYPE
IDesktopShellBrowserImpl_IShellFolderViewCB_MessageSFVCB(IN OUT IShellFolderViewCB *iface,
                                                         IN UINT uMsg,
                                                         IN WPARAM wParam,
                                                         IN LPARAM lParam)
{
    IDesktopShellBrowserImpl *This = impl_from_IShellFolderViewCB(iface);
    HRESULT hr = S_OK;
    switch (uMsg)
    {
        case SFVM_GETNOTIFY:
            hr = IDesktopShellBrowserImpl_GetNotify(This,
                                                    (LPITEMIDLIST *)wParam,
                                                    (LONG *)lParam);
            break;

        case SFVM_FSNOTIFY:
            hr = S_OK;
            break;

        default:
            hr = E_NOTIMPL;
            break;
    }

    return hr;
}

static const IShellFolderViewCBVtbl IDesktopShellBrowserImpl_IShellFolderViewCB_Vtbl =
{
    /* IUnknown */
    IDesktopShellBrowserImpl_IShellFolderViewCB_QueryInterface,
    IDesktopShellBrowserImpl_IShellFolderViewCB_AddRef,
    IDesktopShellBrowserImpl_IShellFolderViewCB_Release,
    /* IShellFolderViewCB */
    IDesktopShellBrowserImpl_IShellFolderViewCB_MessageSFVCB
};

/*****************************************************************************/

static const TCHAR szProgmanClassName[] = TEXT("Progman");
static const TCHAR szProgmanWindowName[] = TEXT("Program Manager");

static VOID
PositionIcons(IN OUT IDesktopShellBrowserImpl *This,
              IN const RECT *prcDesktopRect)
{
    /* FIXME - Move all icons and align them on the destop. Before moving, we should
               check if we're moving an icon above an existing one. If so, we should
               let the list view control arrange the icons */
    return;
}

static VOID
UpdateWorkArea(IN OUT IDesktopShellBrowserImpl *This,
               IN const RECT *prcDesktopRect)
{
    RECT rcDesktopRect;
    LONG Style;

    Style = GetWindowLong(This->hWndDesktopListView,
                          GWL_STYLE);

    if (!(Style & LVS_AUTOARRANGE ) &&
        GetWindowRect(This->hWnd,
                      &rcDesktopRect))
    {
        /* Only resize the desktop if it was resized to something other
           than the virtual screen size/position! */
        if (!EqualRect(prcDesktopRect,
                       &rcDesktopRect))
        {
            SetWindowPos(This->hWnd,
                         NULL,
                         prcDesktopRect->left,
                         prcDesktopRect->top,
                         prcDesktopRect->right - prcDesktopRect->left,
                         prcDesktopRect->bottom - prcDesktopRect->top,
                         SWP_NOZORDER | SWP_NOACTIVATE);

            /* Let's try to rearrange the icons on the desktop. This is
               especially neccessary when switching screen resolutions... */
            PositionIcons(This,
                          prcDesktopRect);
        }
    }
}

static LRESULT CALLBACK
ProgmanWindowProc(IN HWND hwnd,
                  IN UINT uMsg,
                  IN WPARAM wParam,
                  IN LPARAM lParam)
{
    IDesktopShellBrowserImpl *This = NULL;
    LRESULT Ret = FALSE;

    if (uMsg != WM_NCCREATE)
    {
        This = (IDesktopShellBrowserImpl*)GetWindowLongPtr(hwnd,
                                                           0);
    }

    if (This != NULL || uMsg == WM_NCCREATE)
    {
        switch (uMsg)
        {
            case WM_ERASEBKGND:
                PaintDesktop((HDC)wParam);
                break;

            case WM_GETISHELLBROWSER:
                Ret = (LRESULT)IShellBrowser_from_impl(This);
                break;

            case WM_SHELL_ADDDRIVENOTIFY:
            {
                HANDLE hLock;
                LPITEMIDLIST *ppidl;
                LONG lEventId;

                hLock = SHChangeNotification_Lock((HANDLE)wParam,
                                                  (DWORD)lParam,
                                                  &ppidl,
                                                  &lEventId);
                if (hLock != NULL)
                {
                    /* FIXME */
                    SHChangeNotification_Unlock(hLock);
                }
                break;
            }

            case WM_SIZE:
                if (wParam == SIZE_MINIMIZED)
                {
                    /* Hey, we're the desktop!!! */
                    ShowWindow(hwnd,
                               SW_RESTORE);
                }
                else
                {
                    RECT rcDesktop;

                    rcDesktop.left = GetSystemMetrics(SM_XVIRTUALSCREEN);
                    rcDesktop.top = GetSystemMetrics(SM_YVIRTUALSCREEN);
                    rcDesktop.right = GetSystemMetrics(SM_CXVIRTUALSCREEN);
                    rcDesktop.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN);

                    UpdateWorkArea(This,
                                   &rcDesktop);
                }
                break;

            case WM_SYSCOLORCHANGE:
            {
                InvalidateRect(This->hWnd,
                               NULL,
                               TRUE);

                if (This->hWndShellView != NULL)
                {
                    /* Forward the message */
                    SendMessage(This->hWndShellView,
                                WM_SYSCOLORCHANGE,
                                wParam,
                                lParam);
                }
                break;
            }

            case WM_NCCREATE:
            {
                LPCREATESTRUCT CreateStruct = (LPCREATESTRUCT)lParam;
                This = IDesktopShellBrowserImpl_Construct(hwnd,
                                                          CreateStruct);
                if (This == NULL)
                    break;

                SetWindowLongPtr(hwnd,
                                 0,
                                 (LONG_PTR)This);

                if (This->hWndShellView != NULL)
                    SetShellWindowEx(This->hWnd,
                                     This->hWndDesktopListView);
                else
                    SetShellWindow(This->hWnd);

                Ret = TRUE;
                break;
            }

            case WM_DESTROY:
            {
                IDesktopShellBrowserImpl_Destroy(This);
                break;
            }

            case WM_NCDESTROY:
            {
                IDesktopShellBrowserImpl_Release(IShellBrowser_from_impl(This));

                PostQuitMessage(0);
                break;
            }

            default:
                Ret = DefWindowProc(hwnd, uMsg, wParam, lParam);
                break;
        }
    }

    return Ret;
}

static BOOL
RegisterProgmanWindowClass(VOID)
{
    WNDCLASS wcProgman;

    wcProgman.style = CS_DBLCLKS;
    wcProgman.lpfnWndProc = ProgmanWindowProc;
    wcProgman.cbClsExtra = 0;
    wcProgman.cbWndExtra = sizeof(IDesktopShellBrowserImpl *);
    wcProgman.hInstance = hExplorerInstance;
    wcProgman.hIcon = NULL;
    wcProgman.hCursor = LoadCursor(NULL,
                                   IDC_ARROW);
    wcProgman.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1);
    wcProgman.lpszMenuName = NULL;
    wcProgman.lpszClassName = szProgmanClassName;

    return RegisterClass(&wcProgman) != 0;
}

static VOID
UnregisterProgmanWindowClass(VOID)
{
    UnregisterClass(szProgmanClassName,
                    hExplorerInstance);
}

typedef struct _DESKCREATEINFO
{
    HANDLE hEvent;
    HWND hWndDesktop;
    IDesktopShellBrowserImpl *pDesktop;
} DESKCREATEINFO, *PDESKCREATEINFO;

static DWORD CALLBACK
DesktopThreadProc(IN OUT LPVOID lpParameter)
{
    volatile DESKCREATEINFO *DeskCreateInfo = (volatile DESKCREATEINFO *)lpParameter;
    HWND hwndDesktop;
    IDesktopShellBrowserImpl *pDesktop;
    IShellDesktopTray *pSdt;
    MSG Msg;
    BOOL Ret;

    OleInitialize(NULL);
    hwndDesktop = CreateWindowEx(WS_EX_TOOLWINDOW,
                                 szProgmanClassName,
                                 szProgmanWindowName,
                                 WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
                                 0,
                                 0,
                                 GetSystemMetrics(SM_CXVIRTUALSCREEN),
                                 GetSystemMetrics(SM_CYVIRTUALSCREEN),
                                 NULL,
                                 NULL,
                                 hExplorerInstance,
                                 NULL);

    DeskCreateInfo->hWndDesktop = hWndDesktop;
    if (hwndDesktop == NULL)
        return 1;

    pDesktop = (IDesktopShellBrowserImpl*)GetWindowLongPtr(hwndDesktop,
                                                           0);
    (void)InterlockedExchangePointer(&DeskCreateInfo->pDesktop,
                                     pDesktop);

    if (!SetEvent(DeskCreateInfo->hEvent))
    {
        /* Failed to notify that we initialized successfully, kill ourselves
           to make the main thread wake up! */
        return 1;
    }

    while (1)
    {
        Ret = (GetMessage(&Msg,
                          NULL,
                          0,
                          0) != 0);

        if (Ret != -1)
        {
            if (!Ret)
                break;

            TranslateMessage(&Msg);
            DispatchMessage(&Msg);
        }
    }

    OleUninitialize();

    /* FIXME: Properly rundown the main thread! */
    ExitProcess(0);

    return 0;
}

HANDLE
DesktopCreateWindow(IN OUT ITrayWindow *Tray)
{
    HANDLE hThread;
    HANDLE hEvent;
    DWORD DesktopThreadId;
    IDesktopShellBrowserImpl *pDesktop = NULL;
    HANDLE Handles[2];
    DWORD WaitResult;
    HWND hWndDesktop = NULL;
    IShellDesktopTray *pSdt;
    HRESULT hRet;

    if (!RegisterProgmanWindowClass())
        return NULL;

    if (!RegisterTrayWindowClass())
    {
        UnregisterProgmanWindowClass();
        return NULL;
    }

    if (!RegisterTaskSwitchWndClass())
    {
        UnregisterProgmanWindowClass();
        UnregisterTrayWindowClass();
        return NULL;
    }

    hEvent = CreateEvent(NULL,
                         FALSE,
                         FALSE,
                         NULL);
    if (hEvent != NULL)
    {
        volatile DESKCREATEINFO DeskCreateInfo;

        DeskCreateInfo.hEvent = hEvent;
        DeskCreateInfo.pDesktop = NULL;

        hThread = CreateThread(NULL,
                               0,
                               DesktopThreadProc,
                               (PVOID)&DeskCreateInfo,
                               0,
                               &DesktopThreadId);
        if (hThread != NULL)
        {
            Handles[0] = hThread;
            Handles[1] = hEvent;

            WaitResult = WaitForMultipleObjects(sizeof(Handles) / sizeof(Handles[0]),
                                                Handles,
                                                FALSE,
                                                INFINITE);
            if (WaitResult != WAIT_FAILED && WaitResult != WAIT_OBJECT_0)
            {
                pDesktop = DeskCreateInfo.pDesktop;
                hWndDesktop = DeskCreateInfo.hWndDesktop;
            }

            CloseHandle(hThread);
        }

        CloseHandle(hEvent);
    }

    if (pDesktop != NULL)
    {
        hRet = ITrayWindow_QueryInterface(Tray,
                                          &IID_IShellDesktopTray,
                                          (PVOID*)&pSdt);
        if (SUCCEEDED(hRet))
        {
            IShellDesktopTray_RegisterDesktopWindow(pSdt,
                                                    hWndDesktop);
            IShellDesktopTray_Release(pSdt);
        }
    }
    else
    {
        UnregisterProgmanWindowClass();
        UnregisterTrayWindowClass();
        UnregisterTaskSwitchWndClass();
    }

    return (HANDLE)pDesktop;
}

VOID
DesktopDestroyShellWindow(IN HANDLE hDesktop)
{
    //IDesktopShellBrowserImpl *pDesktop = (IDesktopShellBrowserImpl *)hDesktop;

    /* FIXME - Destroy window (don't use DestroyWindow() as
               the window belongs to another thread!) */

    UnregisterProgmanWindowClass();
    UnregisterTrayWindowClass();
}

#endif /* USE_API_SHCREATEDESKTOP */

⌨️ 快捷键说明

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