• 桌面上嵌入窗口(桌面日历)原理探索(将该窗口的Owner设置成桌面的Shell 窗口,可使用SetWindowLong更改窗口的GWL_HWNDPARENT,还要使用SetWindowPos设置Z-Order)


    今天在QQ群里有人问怎样实现将自己的窗口嵌入桌面,让它和桌面融为一体,就像很多桌面日历软件那样。

    我当时想到的就是建立一个Child  Window,将他的父窗口设置成桌面Shell窗口就可以了。但是后来想想觉得不对,因为很多桌面日历窗口都有半透明和阴影效果,明显是用Layered Window实现的,而大家知道Layered Window一定要用Pop Up Window才能实现的。

    那么如何用Pop up Window实现这种效果呢? 这里关键的一点就是要将该窗口的Owner设置成桌面的Shell 窗口。

    很多以为Pop Up Window的Owner窗口只能在Create时关联, 建立后没法动态修改,实际上微软是有接口让我们改的,只是他们不建议我们动态改,因为这样会影响窗口的层次关系,尤其是对于Modal Dialog。

    我们将窗口Owner改成桌面Shell窗口的代码如下:

    BOOL CheckParent(HWND hWnd)
    {
        static HWND s_hWndOldParent = NULL;

       HWND hWndProgram = NULL;
       HWND hWndShellDLL = NULL;
       hWndProgram = FindWindow(_T("Progman"), _T("Program Manager"));
       if(hWndProgram != NULL)
       {
           hWndShellDLL = FindWindowEx(hWndProgram, NULL, _T("SHELLDLL_DefView"), NULL);
       }

       if(hWndShellDLL != NULL
           && hWndShellDLL != s_hWndOldParent)
       {
            SetWindowLong(hWnd, GWL_HWNDPARENT, (LONG)hWndShellDLL);
            s_hWndOldParent = hWndShellDLL;
            return TRUE;
       }

       return FALSE;
    }


    另外还有一个问题是一般Pop up窗口在Show出来时会显示在最上面,而我们是要让它显示在最下面, 所以要设置下Z-Order:

       hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
          CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);


        CheckParent(hWnd);

       SetWindowPos(hWnd, HWND_BOTTOM, 0, 0, 0, 0,
           SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_SHOWWINDOW);


    这样上面的代码就实现了的窗口永远在桌面上,即使你点“显示桌面”或是WIN+D,也不受影响。

    另外,如果你要让你的窗口在激活时也不会跑到其他窗口上面,只要创建时设置WS_EX_NOACTIVATE属性就可以了。

    还有个问题是桌面Shell有可能重启,比如我们Kill掉Explorer.exe进程,所以我们最好一开始就启一个定时器,然后不停调用CheckParent(HWND hWnd)。

    测试代码下载: source code

    http://www.cppblog.com/weiym/archive/2012/05/03/173608.html

    在Win7的Aero模式下因为桌面的窗口层次有变化, 上面的代码会找不到窗口"SHELLDLL_DefView"窗口

    简单改了下,未完全测试:
    HWND GetShellDLLForWin7()
    {
    HWND hWndShell = NULL;
    HWND hWndDesktop = GetDesktopWindow();
    if(hWndDesktop == NULL) return NULL;

    HWND hWndWorkerW = NULL;
    while(TRUE)
    {
    hWndWorkerW = FindWindowEx(hWndDesktop, hWndWorkerW, _T("WorkerW"), NULL);
    if(hWndWorkerW == NULL) break;

    if(::GetWindowLong(hWndWorkerW, GWL_STYLE) & WS_VISIBLE)
    {
    break;
    }
    else
    {
    continue;
    }
    }

    if(hWndWorkerW != NULL)
    {
    hWndShell = FindWindowEx(hWndWorkerW, NULL, _T("SHELLDLL_DefView"), NULL);
    }

    return hWndShell;
    }

    BOOL CheckParent(HWND hWnd)
    {
    static HWND s_hWndOldParent = NULL;

    HWND hWndProgram = NULL;
    HWND hWndShellDLL = NULL;
    hWndProgram = FindWindow(_T("Progman"), _T("Program Manager"));
    if(hWndProgram != NULL)
    {
    hWndShellDLL = FindWindowEx(hWndProgram, NULL, _T("SHELLDLL_DefView"), NULL);

    //Win7
    if(hWndShellDLL == NULL)
    {
    hWndShellDLL = GetShellDLLForWin7();
    }
    }

    if(hWndShellDLL != NULL
    && hWndShellDLL != s_hWndOldParent)
    {
    SetWindowLong(hWnd, GWL_HWNDPARENT, (LONG)hWndShellDLL);
    s_hWndOldParent = hWndShellDLL;
    return TRUE;
    }

    return FALSE;
    }

    http://www.cppblog.com/weiym/archive/2012/05/03/173608.html

  • 相关阅读:
    Silverlight学习(五)图形标绘
    Silverlight学习(四) domainservice动态多条件查询
    MySQL之单表查询
    mysql外键的三种关系
    mysql之完整性约束
    接口类和抽象类的区别
    mysql中的sql_mode
    html5本地存储技术 localstorage
    mysql数值类型
    mysql
  • 原文地址:https://www.cnblogs.com/findumars/p/5786057.html
Copyright © 2020-2023  润新知