今天在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

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

  1. 在Windows Server 2012中如何快速开关桌面上经典的“计算机、我的文档”等通用图标

    我们都知道,在Windows Server 2012系列的服务器版本中都已经引入了Modern的现代界面作为默认的用户交互界面,同时满足视觉一致化,新版的服务器管理程序也做成了扁平化.因此传统的计算机 ...

  2. Windows Server 2012 R2在桌面上顯示我的電腦等圖示

    Windows Server 2012 R2在桌面上顯示我的電腦等圖示   從Windows2012開始,微軟取消了服務器桌面個性化選項,如何重新調出配置界面,可以使用微軟命令調出.方法如下: 同時按 ...

  3. Windows Server 2012 R2在桌面上显示计算机/网络图标

    原文 Windows Server 2012 R2在桌面上显示计算机/网络图标 从Windows2012开始,微软取消了服务器桌面个性化选项,如何重新调出配置界面,可以使用微软命令调出.具体方法如下: ...

  4. c# Windows Service 桌面上显示UI

    介绍 本文的目的是说明如何从Windows Vista中的服务正确启动交互式进程,以及演示如何以完全管理员权限启动该进程.交互式过程是能够在桌面上显示UI的过程. 本文介绍如何创建一个名为Loader ...

  5. Win10删除桌面上的回收站、计算机、网络等图标

    解决方案: 桌面上鼠标右键,选择个性化 个性化窗口左边侧栏选择主题 移动至最下方点击"桌面图标设置"即可看到系统中的五个桌面图标

  6. Windows 10 如何在桌面上显示“此电脑”和“控制面板”

    新电脑安装好 Windows 10 系统,默认在桌面上是不显示 "此电脑" 和 "控制面板" 图标的. 如果是 Windows 10 家庭版,桌面一般只显示&q ...

  7. 通过Rancher Desktop在桌面上运行K8s

    Rancher 发行的操作系统新选择:Rancher Desktop for Windows,它可以帮助你在Windows桌面上管理Kubernetes和容器.当然他当然会支持Linux,Mac的. ...

  8. win7 桌面上的网络邻居不见了

    win7 桌面上的网络邻居不见了,可能是以前在桌面上直接删除了.现右击桌面--个性化--更改桌面图标,也找不到网上邻居了.怎么找回来啊? 网上邻居已经改名叫网络了.可以右键桌面选择“个性化”,然后更改 ...

  9. 在WINDOWS SERVER 上或远程桌面中使用 MUTEX

    引用: http://www.cnblogs.com/fg0711/archive/2012/05/03/2480502.html 使用Mutex需要注意的两个细节 可能你已经注意到了,例子中在给Mu ...

随机推荐

  1. uva 10859 - Placing Lampposts dp

    题意: 有n个节点,m条边,无向无环图,求最少点覆盖,并且在同样点数下保证被覆盖两次的变最多 分析: 1.统一化目标,本题需要优化目标有两个,一个最小灯数a,一个最大双覆盖边数b,一大一小,应该归一成 ...

  2. Neighbour table overflow --- arp表溢出

    [root@jiangyi01.sqa.zmf /home/ahao.mah] #grep . /proc/sys/net/ipv4/neigh/default/gc_thresh* /proc/sy ...

  3. Adobe Photoshop CC 2015安装激活

    分享一下Adobe Photoshop CC 2015 安装激活步骤 工具/原料   xf-adobecc2015.exe Adobe Photoshop CC 2015官方原版 方法/步骤   1 ...

  4. yii 笔记

    Yii1.1: $_GET 可以表示为 Yii::app()->request->getQuery() $_POST 可以表示为 Yii::app()->request->po ...

  5. (转)在Android的webview中定制js的alert,confirm和prompt对话框的方法

    1.首先继承android.webkit.WebChromeClient实现MyWebChromeClient. 2.在MyWebChromeClient.java中覆盖onJsAlert,onJsC ...

  6. localStrorage、 sessionStorage 、cookie

          HTML5中增加了两种全新数据存储方式:Web Storage和Web SQL Database. 前者可用于临时或永久保存客户端的少量数据:后者是客户端本地化的一套数据库系统,可将大量数 ...

  7. 关闭钩子(shutdown hook)的作用

    DK1.3介绍了java.lang.Runtime class的addShutdownHook()方法.如果你需要在你的程序关闭前采取什么措施,那么关闭钩子(shutdown hook)是很有用的. ...

  8. String 和 InputStream 互转方式

    /** * 利用BufferedReader实现Inputstream转换成String <功能详细描述> * * @param in * @return String */ public ...

  9. 类型转换操作符static_cast、const_cast、dynamic_cast、reinterpret_cast

    一.static_cast 对于类型转换,我们常常这么做: (type) expression 引进了static_cast类型转换操作符后,我们只需这样做: static_cast<type& ...

  10. Foreach语法

    先看例子: Random rand = new Random(47); float f[] = new float[10]; for(int i = 0; i < 10; i++){ f[i] ...