我想用DirectX为Windows7制作一个动画桌面背景。我使用了C#、SlimDX和几个Windows API函数的P/Invoke导入。我对原生Windows编程不是很在行,但我已经在网上尝试过了,我认为我需要做的是:
1)找到包含dekstop壁纸的窗口的手柄,将其连接到DirectX设备上并在其中绘制。
2)创建一个新的输出窗口,并将其插入到桌面壁纸上方、桌面图标下方。
这两个我都试过了,但似乎都不管用。如果我从GetDesktopWindow()返回的句柄开始导航窗口层次结构,我可以转到Desktop -> WorkerW -> SHELLDLL_DefView -> SysListView32。如果我将一个DirectX设备连接到这个手柄上,我可以在整个桌面上绘制,但它也覆盖了图标。如果我创建一个Windows form,使用SetParent()将它的父级设置为SHELLDLL_DefView,然后使用SetWindowPos来处理它的Z顺序,我似乎只能让它位于桌面墙纸后面或桌面+图标前面。
它看起来好像桌面墙纸是包含图标的文件夹视图的背景,因此我试图做的事情无法工作。那么唯一的解决方案就是不使用桌面作为图标,或者找到一些替代方案,例如覆盖桌面,然后覆盖一个包含某个文件夹内容视图的透明窗口。
有没有人知道我应该做什么,或者我想做的事情是否可能实现?似乎你可以使用GDI绘制到桌面背景(我相信wxSnow程序就是这样),我已经看到了一些类似于我想在Windows XP的DirectX墙纸模式下使用VLC Media Player所做的事情(有趣的是,我似乎不能在我的系统上启用这个选项)。
谢谢!
发布于 2010-04-12 09:45:33
看起来这可能是不可能的。请参阅此链接:
http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/69839cec-3424-4300-9ac3-486b8c2fe492
如果您需要在桌面背景和桌面图标之间绘制一些控件,请执行以下替代步骤:
这只能在XP中完成,因为Vista不支持活动桌面。
另一篇文章建议,如果你能获得构成它的窗口的句柄,你可以在浏览器窗口的背景下做到这一点。当然,如果这是可能的,那么也有可能获得图标后面的桌面窗口的句柄。
更新:好吧,到目前为止,我发现唯一可能“工作”的事情就是创建位图文件并一遍又一遍地更换墙纸(我怀疑这会很慢,就像你提到的那样)。
全屏图像必须驻留在内存中的某个位置,但如果没有一些严重的低级内存黑客攻击,可能无法访问它。我会继续找的。
更新2:这可能行得通,但我不确定:
http://social.msdn.microsoft.com/forums/en-US/vcgeneral/thread/4af734fb-d2c1-414b-a9f1-759b76692802
它的实质是:
HWND p = FindWindow("ProgMan", NULL);
HWND s = FindWindowEx(p, NULL, "SHELLDLL_DefView", NULL);
HWND dtw = FindWindowEx(s, NULL, "SysListView32", NULL);
HDC hdc = GetDC(dtw);你基本上是从ProgMan窗口开始,然后深入到桌面墙纸(我猜是“SysListView32”)。我要试一下这个。
更新3: No go -上面的代码确实获得了桌面的DC,但它位于图标之上,所以BitBlt会将它们画在上面。不过,它不是绘制到屏幕上,因为我可以在打开的窗体下绘制,而不需要覆盖它,所以这至少是一个进步。
我猜除了图标后面的桌面"SysListView32“之外,还有一些窗口可用,或者有不止一个"SysListView32”窗口。
更新4:我非常确定使用它的东西会起作用:
http://msdn.microsoft.com/en-us/library/bb761155(v=VS.85).aspx http://msdn.microsoft.com/en-us/library/bb774742(v=VS.85).aspx
基本上,它是您调用的API方法,传入一个包含位图句柄的结构。如果调用成功,该位图将成为桌面。
DirectX是否将帧公开为位图句柄(与GDI兼容),还是仅公开DC?在我的例子中,我的动画已经是一个与GDI兼容的位图数组,所以使用这种方法不会有问题。如果这是唯一的路线,并且DirectX不公开位图句柄(我不认为它们会公开),那么对于每一帧,你都必须创建一个新的GDI位图,这将会减慢相当多的速度。
实际上,可能有一种更简单的方法,尽管我不确定它是否有效。一旦获得了墙纸实际位图的句柄,就可以使用SelectObject将其选择到设备上下文中,然后将该设备上下文用作BitBlt目的地。不过,您可能需要向桌面发送重新绘制指令,这可能会触发每次重新绘制图标。
你在这里干点活怎么样?:)
发布于 2010-04-12 08:55:15
我猜你可以通过动态生成位图并不断地将它们设置为桌面背景来获得每秒相当多的帧。然而,这听起来对CPU来说是不必要的(几乎愚蠢的)沉重。更新:现在我想了想(我写这篇文章的时候已经很晚了),这种方法的主要问题是,每次要显示新帧时,您都需要从硬盘驱动器中写入和读取位图。这是不可行的。
你真的在用桌面做图标吗?在Windows7中,开始菜单搜索功能和新的任务栏让我不再使用桌面上的图标。
只是一个想法
可以通过SendMessage(GetDesktopWindow、WM_SOME_MESSAGE、wParam、lParam)更改桌面窗口,这样您就可以实现您想要的效果。我明天可能会进一步调查这件事(目前是当地时间凌晨3点)。
发布于 2010-04-14 04:17:41
我做过的some animation of alpha blended windows总是在Z顺序的顶端。一种想法是忽略修改桌面位图的尝试,只将您的东西绘制为layered window,但以某种方式管理ZOrder,使其始终是最底部的非桌面窗口(可能通过在正确的时间有策略地调用Form.SendToBack()或其他东西)。
根据您尝试执行的操作,这可能会为您提供与桌面动画效果相同的效果。
https://stackoverflow.com/questions/2619331
复制相似问题