Win32:如何在窗外画画?

Ian*_*oyd 4 winapi layered-windows ws-ex-layered dropshadow

看一下Windows tooltips类提示窗口,我看到它在提示窗口的实际矩形之外绘制了它的阴影.

使用SpyXX - 我可以获得工具提示的窗口rect和类样式:

Rectangle:     (440, 229)-(544, 249), 104x20
Restored Rect: (440, 229)-(544, 249), 104x20
Client Rect:   (0, 0)-(104, 20), 104x20
Run Code Online (Sandbox Code Playgroud)

您会注意到,您看到的投影实际上位于正在绘制的窗口之外.我怎么能画外一个影子在我的窗口,而被外界我的窗口?

注意:阴影不是使用标准CS_DROPSHADOW类样式绘制的.我已通过实验证实了这一点,并且还可以在SpyXX中看到窗口的类样式; 它不使用CS_DROPSHADOW:

Windows Styles:     94000001

    WS_POPUP        80000000
    WS_VISIBLE      10000000
    WS_CLIPSIBLINGS  4000000
    TTS_ALWAYSTIP          1

Extended Styles:    00080088

    WS_EX_LAYERED      80000
    WS_EX_TOOLWIN         80
    WS_EX_TOPMOST          8
Run Code Online (Sandbox Code Playgroud)

那我怎么能在窗外画画?

注意:尝试在桌面上绘制DC已经完成.来自Greg Schechter的重定向GDI,DirectX和WPF应用程序:

从屏幕上绘图和阅读 - Baaaad!

最后,由于我们处于重定向主题,一个特别危险的做法是写入屏幕,通过使用GetDC(NULL)并写入,或尝试执行XOR橡皮带线等.有两个写入屏幕的重要原因很糟糕:

它很昂贵...写入屏幕本身并不昂贵,但它几乎总是伴随着从屏幕读取,因为在写入屏幕时,通常会执行读取 - 修改 - 写入操作,如XOR.从视频内存表面读取非常昂贵,需要与DWM同步,并停止整个GPU管道以及DWM应用程序管道.
这是不可预测的......如果你以某种方式设法到达实际的主要部分并写入它,那么你写入主数据库的内容将保留在屏幕上的时间就不可预测.由于UCE不知道它,它可能在下一帧刷新中被清除,或者它可能持续很长时间,这取决于屏幕上需要更新的其他内容.(我们实际上不允许直接写入主数据库,因为这个原因......例如,如果您尝试访问DirectDraw主数据库,DWM将关闭,直到访问应用程序退出)

小智 5

你不能以你描述的方式在窗外画画.

如果您右键单击桌面,然后转到属性/外观/效果并取消选中"在菜单下显示阴影"...您将不再拥有阴影.

底线是,这是窗口管理器的产品,而不是您的程序.

  • 窗口管理器只是将CS_DROPSHADOW样式添加到窗口中.在上面的帖子中,您没有枚举类样式,只列举了窗口样式.如果您在工具提示窗口中实际枚举类样式,并选中"在菜单下显示阴影"选项,您将看到CS_DROPSHADOW类样式.如果未选中该选项,您将看不到它.类样式与窗口样式不同.为什么不写一个示例程序来测试呢?我没有时间来播放它. (2认同)