windows DirectX 桌面
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2619331/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
DirectX Desktop
提问by Jonathan
I'd like to make an animated desktop background for Windows 7 using DirectX. I'm using C#, SlimDX and a couple of P/Invoke imports of Windows API functions. I'm not brilliant with native Windows programming, but I've had a poke around online and I believe what I need to do is either:
我想使用 DirectX 为 Windows 7 制作动画桌面背景。我正在使用 C#、SlimDX 和几个 P/Invoke 导入的 Windows API 函数。我对原生 Windows 编程并不擅长,但我在网上闲逛了一下,我相信我需要做的是:
1) Find the handle of the window containing the dekstop wallpaper, hook it up to a DirectX device and draw into it.
1) 找到包含桌面壁纸的窗口句柄,将其连接到 DirectX 设备并绘制到其中。
2) Make a new output window, and insert it above the desktop wallpaper but below the desktop icons.
2) 创建一个新的输出窗口,并将其插入桌面壁纸上方但桌面图标下方。
I've tried both these, but neither seems to work. If I navigate the Window heirarchy starting from the handle returned by GetDesktopWindow(), I can go Desktop -> WorkerW -> SHELLDLL_DefView -> SysListView32. If I hook up a DirectX device to this handle, I can draw over the entire desktop, but it also covers the icons. If I create a Windows form, set its parent to SHELLDLL_DefView using SetParent() and then use SetWindowPos to play with its Z-order I can only seem to get it to go either behind the desktop wallpaper or in front of the desktop + icons.
我已经尝试了这两种方法,但似乎都不起作用。如果我从 GetDesktopWindow() 返回的句柄开始导航 Window 层次结构,我可以去桌面 -> WorkerW -> SHELLDLL_DefView -> SysListView32。如果我将 DirectX 设备连接到这个手柄,我可以在整个桌面上绘制,但它也覆盖了图标。如果我创建一个 Windows 窗体,使用 SetParent() 将其父级设置为 SHELLDLL_DefView,然后使用 SetWindowPos 来处理它的 Z 顺序,我似乎只能让它在桌面墙纸后面或桌面 + 图标前面。
It looks as though the desktop wallpaper is background to the folder view containing the icons, and therefore what I am trying to do cannot work. The only solution then would be to not use the desktop for icons, or to find some alternative, e.g. overwriting the desktop then overlaying a transparent window containing a view of the contents of some folder.
看起来桌面墙纸是包含图标的文件夹视图的背景,因此我尝试做的事情无法正常工作。唯一的解决方案是不使用桌面作为图标,或者寻找一些替代方法,例如覆盖桌面然后覆盖包含某个文件夹内容视图的透明窗口。
Does anyone have any idea of what I should be doing, or even whether what I want to do is possible? It seems you can draw to the desktop background using the GDI (as I believe the wxSnow program does), and I've seen something similar to what I want done by VLC Media Player under Windows XP with its DirectX wallpaper mode (interestingly, I can't seem to get this option enabled on my system).
有没有人知道我应该做什么,甚至我想做的事情是否可行?似乎您可以使用 GDI 绘制到桌面背景(正如我相信 wxSnow 程序所做的那样),并且我已经看到了类似于我想要在 Windows XP 下使用 DirectX 墙纸模式通过 VLC Media Player 完成的事情(有趣的是,我似乎无法在我的系统上启用此选项)。
Thanks!
谢谢!
回答by MusiGenesis
Looks like this might not be possible. See this link:
看起来这可能是不可能的。请参阅此链接:
http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/69839cec-3424-4300-9ac3-486b8c2fe492
http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/69839cec-3424-4300-9ac3-486b8c2fe492
If you need to draw some controls between the desktop background and desktop icons, an alternative step is below:
- Create your user control in a windows control library.
- Embed the user control in an ActiveX control.
- Embed the ActiveX control in a web page.
- Enable active desktop and set the web page to be your desktop background.
This can only be done in XP since Vista doesn't support active desktop.
如果你需要在桌面背景和桌面图标之间绘制一些控件,下面是一个替代步骤:
- 在 Windows 控件库中创建您的用户控件。
- 将用户控件嵌入到 ActiveX 控件中。
- 在网页中嵌入 ActiveX 控件。
- 启用活动桌面并将网页设置为您的桌面背景。
这只能在 XP 中完成,因为 Vista 不支持活动桌面。
Another post there suggests that you could possibly do this with the background of an explorer window - if you could get the handle of the window that constitutes it. Of course, if that's possible then it may be possible also to get the handle of the desktop window behind the icons.
那里的另一篇文章建议您可以使用资源管理器窗口的背景来执行此操作 - 如果您可以获得构成它的窗口的句柄。当然,如果可能的话,也可以在图标后面获取桌面窗口的句柄。
Update:Well, so far the only thing I've found that could possibly "work" is just creating Bitmap files and changing the wallpaper over and over again (I suspect this would be slow, as you mentioned).
更新:嗯,到目前为止,我发现唯一可能“有效”的方法就是创建位图文件并一遍又一遍地更改墙纸(我怀疑这会很慢,正如你所提到的)。
That full screen image must be resident in memory somewhere, but there may be no way to access it without some serious low-level memory hacking. I'm going to keep looking.
该全屏图像必须驻留在内存中的某处,但如果没有严重的低级内存黑客攻击,则可能无法访问它。我会继续寻找。
Update 2:This might work, but I'm not sure:
更新 2:这可能有效,但我不确定:
http://social.msdn.microsoft.com/forums/en-US/vcgeneral/thread/4af734fb-d2c1-414b-a9f1-759b76692802
http://social.msdn.microsoft.com/forums/en-US/vcgeneral/thread/4af734fb-d2c1-414b-a9f1-759b76692802
The meat of it is this:
它的肉是这样的:
HWND p = FindWindow("ProgMan", NULL);
HWND s = FindWindowEx(p, NULL, "SHELLDLL_DefView", NULL);
HWND dtw = FindWindowEx(s, NULL, "SysListView32", NULL);
HDC hdc = GetDC(dtw);
You're basically starting with the ProgMan window and drilling down from there to the desktop wallpaper ("SysListView32", I guess). I'm going to try this out.
您基本上是从 ProgMan 窗口开始,然后从那里深入到桌面墙纸(我猜是“SysListView32”)。我要试试这个。
Update 3:No go - the above code does get the desktop's DC, but it's above the icons so BitBlt draws over them. It's not drawing to the Screen, though, because I can draw underneath an open form without covering it, so that's progress at least.
更新 3:不行 - 上面的代码确实获得了桌面的 DC,但它位于图标上方,所以 BitBlt 会在它们上方绘制。但是,它并没有绘制到屏幕上,因为我可以在不覆盖它的情况下在打开的表单下绘制,所以至少这是一个进步。
I'm guessing that there's some window available other than "SysListView32" that is the desktop behind the icons, or there's more than one "SysListView32" window.
我猜除了图标后面的桌面“SysListView32”之外还有一些可用的窗口,或者有不止一个“SysListView32”窗口。
Update 4:I'm pretty sure something using this would work:
更新 4:我很确定使用它的东西会起作用:
http://msdn.microsoft.com/en-us/library/bb761155(v=VS.85).aspxhttp://msdn.microsoft.com/en-us/library/bb774742(v=VS.85).aspx
http://msdn.microsoft.com/en-us/library/bb761155(v=VS.85).aspx http://msdn.microsoft.com/en-us/library/bb774742(v=VS.85) .aspx
Basically, it's an API method that you call, passing in a structure which include a bitmap handle. If the call is successful, that bitmap becomes the desktop.
基本上,它是您调用的 API 方法,传入包含位图句柄的结构。如果调用成功,该位图将成为桌面。
Does DirectX expose frames as bitmap handles (GDI-compatible), or does it only expose the DC? In my case, my animation is already an array of GDI-compatible bitmaps, so I would have no trouble using this approach. If this is the only route, and DirectX doesn't expose the bitmap handles (and I don't think they would), then for each frame you would have to create a new GDI bitmap, which would slow things down quite a bit.
DirectX 是否将帧公开为位图句柄(GDI 兼容),还是仅公开 DC?就我而言,我的动画已经是一组与 GDI 兼容的位图,因此使用这种方法不会有任何问题。如果这是唯一的途径,并且 DirectX 不公开位图句柄(我认为他们不会),那么对于每一帧,您都必须创建一个新的 GDI 位图,这会大大减慢速度。
Actually, there might be an easier way, although I'm not sure it would work. Once you get the handle to the actual bitmap of the wallpaper, you can select it into a device context using SelectObject
, and then just use that device context as the BitBlt destination. You might have to send a repaint instruction to the desktop, though, which might trigger the icons to be repainted every time.
实际上,可能有更简单的方法,尽管我不确定它是否可行。一旦获得墙纸实际位图的句柄,就可以使用 将其选择到设备上下文中SelectObject
,然后将该设备上下文用作 BitBlt 目标。但是,您可能必须向桌面发送重绘指令,这可能会触发每次重绘图标。
How about you do some work here? :)
你来这里工作怎么样?:)
回答by dkackman
I've done some animation of alpha blended windowsthat are always on the top of the Z-Order. One idea would be to ignore trying to modify the desktop bitmap and just draw your stuff as a layered windowbut manage the ZOrder somehow so it is always the bottom-most, non-desktop window (perhaps by strategically calling Form.SendToBack()
or something at the right times).
我已经做了一些总是在 Z 顺序顶部的alpha 混合窗口的动画。一个想法是忽略尝试修改桌面位图,只是将您的东西绘制为分层窗口,但以某种方式管理 ZOrder,因此它始终是最底部的非桌面窗口(可能通过战略性调用Form.SendToBack()
或在正确的时间进行某些操作)。
Depending on what you are trying to do this may give you the same effect of animating the desktop.
根据您尝试执行的操作,这可能会给您带来与桌面动画相同的效果。
回答by Andreas Rejbrand
I guess you could get quite a few frames per second by dynamically generating bitmaps and constantly setting these as the desktop background. However, this sounds unnecessarily (almost stupidly) heavy for the CPU. Update: Now that I think about it (it was late when I wrote this), the main problem with such an approach is that you need to write and read bitmaps from the hard drive every time a new frame is to be displayed. This is not feasible.
我想你可以通过动态生成位图并不断将它们设置为桌面背景来每秒获得相当多的帧。然而,这对 CPU 来说听起来不必要(几乎是愚蠢的)沉重。更新:现在我想起来了(我写这个的时候已经晚了),这种方法的主要问题是每次要显示新帧时都需要从硬盘驱动器写入和读取位图。这是不可行的。
Are you really using the desktop for icons? In Windows 7 the start menu search function and the new taskbar has made me not use the desktop for icons.
你真的在用桌面做图标吗?在 Windows 7 中,开始菜单搜索功能和新的任务栏让我不再使用桌面图标。
Just an idea
只是一个想法
It mightbe possible to alter the desktop window, by means of SendMessage(GetDesktopWindow, WM_SOME_MESSAGE, wParam, lParam), so that you can achieve what you want. I might investigate this further tomorrow (currently 3 am, local time).
这也许是可以改变桌面窗口,通过SendMessage函数(GetDesktopWindow,WM_SOME_MESSAGE话,wParam,lParam的)的方式,这样就可以达到你想要的。我明天可能会对此进行进一步调查(目前是当地时间凌晨 3 点)。