用Delphi绘制和清除桌面画布

用Delphi绘制和清除桌面画布,delphi,graphics,canvas,desktop,Delphi,Graphics,Canvas,Desktop,我试图通过使用桌面画布直接绘制整个屏幕。问题是我无法清除桌面画布。我曾尝试将canvas.pen.style设置为psNotXOR并绘制旧图像,但不幸的是,这不够可靠,在某些情况下仍存在一些遗留问题 我需要的是在鼠标悬停在窗口/控件上时,在其周围绘制一个选择矩形。我以前做过类似的事情,但我从来没有想出一个可接受的解决方案 想一想,尽管你可以发送一个无效命令给桌面 因为桌面是一个修改过的listview控件,所以您应该能够使用 procedure InvalidateDesktop; begin

我试图通过使用桌面画布直接绘制整个屏幕。问题是我无法清除桌面画布。我曾尝试将canvas.pen.style设置为psNotXOR并绘制旧图像,但不幸的是,这不够可靠,在某些情况下仍存在一些遗留问题


我需要的是在鼠标悬停在窗口/控件上时,在其周围绘制一个选择矩形。

我以前做过类似的事情,但我从来没有想出一个可接受的解决方案

想一想,尽管你可以发送一个无效命令给桌面

因为桌面是一个修改过的listview控件,所以您应该能够使用

procedure InvalidateDesktop;
begin
  RedrawWindow(GetDesktopWindow, 0, 0, RDW_INVALIDATE);

  //if that doesn't work then try this:
  //Sendmessage(GetDesktopWindow, wm_setredraw, 1, 0);
end;

这可能会满足您的需要,我还没有测试它,因为我只是将其作为示例进行了改进。

您没有在什么操作系统上编写您在清除这些人工制品后遇到的问题

至少在桌面合成激活的情况下,直接绘制到桌面并进行XOR绘制是一个非常糟糕的主意(请参阅中的“绘制到屏幕并从屏幕读取——Baaad!”)。除了负面的性能影响之外,您无法确定同时会发生哪些其他绘画,以及哪些效果和动画会改变显示的内容,因此简单的XOR可能不足以完全擦除所有内容

一种可能的实现方法是桌面大小的透明覆盖窗口,并在上面画橡皮筋选择器。如果大小更改足够,则使整个窗口无效,无需删除旧的选择行。如果覆盖层被移除,线条也将消失。桌面合成将确保不会出现闪烁。但是,在选择区域时切换应用程序会有问题,您需要捕捉到这一点并立即取消选择

编辑:

我刚刚用Delphi 2009和以下测试应用程序对其进行了测试:

  • FormStyle
    设置为
    fsstationtop
    AlphaBlend
    设置为
    True
  • 使用重写的
    CreateParams()
    方法添加
    WS_EX_TRANSPARENT
    扩展样式标志

我可以将所有鼠标点击传递到底层窗口,同时可以在它们上面画一个窗口。这应该让你开始了。

这是我们在应用程序中的做法:

    FBitmap.Canvas.Brush.Color := clWhite;
    FBitmap.Canvas.FillRect(FBitmap.Canvas.ClipRect);
问题是Windows不会将鼠标后的控件返回给我

我认为您需要为此钩住鼠标事件消息-钩住的消息然后给您鼠标结束的窗口句柄


查看SetWindowsHookEx(WH_MOUSE,,,,)和MOUSEHOOKSTRUCT。

可见列表视图只是
GetDesktopWindow()
返回的
HWND
的子视图,因此可能无法正常工作。我说过我没有测试它。正如mghie预期的那样,不幸的是,这不起作用。谢谢你的回答,Ryan。我考虑过了,但问题是Windows不会将鼠标后的控件返回给我。还是会?仔细想想,如果画布是透明的,这可能会奏效。我试试看。谢谢你提供了非常详细和有用的答案。嗯,选择不起作用,顶层窗口总是在鼠标后面。对不起,我不明白。您是否只需在桌面上单击鼠标左键并开始拖动鼠标即可开始选择?如果是这样的话,你如何用一个全局(低级)鼠标钩子抓住它?或者创建覆盖(在特殊选择模式下)并用鼠标单击开始选择?也许你可以用更多的细节来展开你的问题。请注意,你可以使透明的窗口“点击通过”,这可能是你需要做的。谷歌,几年前有一篇关于它的DiLascia文章,这正是我需要的。谢谢你提供了非常有用的答案。-1这不是OP要求的“清除”。相反,它只是绘制一个白色矩形。我已经在使用全局鼠标钩子检索窗口句柄,但当我创建顶层窗口时,即使它是透明的,窗口也始终选择其句柄:(