今天在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. BZOJ3397: [Usaco2009 Feb]Surround the Islands 环岛篱笆

    3397: [Usaco2009 Feb]Surround the Islands 环岛篱笆 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 11  So ...

  2. mongodb sort limit和skip用法

    > db.mediaCollection.find().skip().toArray() [ { "_id" : ObjectId("5353463193efef0 ...

  3. POJ_3009——冰球,IDS迭代加深搜索

    Description On Planet MM-21, after their Olympic games this year, curling is getting popular. But th ...

  4. HDU_2025——查找最大的字母

    Problem Description 对于输入的每个字符串,查找其中的最大字母,在该字母后面插入字符串“(max)”.   Input 输入数据包括多个测试实例,每个实例由一行长度不超过100的字符 ...

  5. 金错刀对话口袋购物王珂:找到痛点,确认卖点,制造爆点! - 资讯 - i黑马网

    金错刀对话口袋购物王珂:找到痛点,确认卖点,制造爆点! - 资讯 - i黑马网 金错刀对话口袋购物王珂:找到痛点,确认卖点,制造爆点!

  6. C#系列教程——switch定义及使用

    代码如下: using System; class Switch_Test { static void Main() { Console.WriteLine("box sizes: 1=Sm ...

  7. [置顶] 白话最小边覆盖总结--附加 hdu1151结题报告

    刚开始看到这个题目的时候就觉得想法很明了,就是不知道如何去匹配... 去网上看了不少人的解题报告,但是对于刚接触“最小边覆盖”的我来说....还是很困难滴....于是自己又开始一如以往学习“最大独立集 ...

  8. 利用TreeSet给纯数字字符串排序

    import java.util.Iterator;import java.util.TreeSet; /* * 给字符串中的数字排序 * String str = "10,2,11,1,3 ...

  9. redis 源代码分析(一) 内存管理

    一,redis内存管理介绍 redis是一个基于内存的key-value的数据库,其内存管理是很重要的,为了屏蔽不同平台之间的差异,以及统计内存占用量等,redis对内存分配函数进行了一层封装,程序中 ...

  10. mvc之验证IEnumerable<T> 类型

    假设我们有这么一种需求,我们要同时添加年级和年级下面的多个班级,我们一般会像下面这种做法. Action中我们这样接收: [HttpPost] public ActionResult CreateGr ...