4

可能重复:
使用类似于 Inspect 的 GDI+(或 GDI)在屏幕上绘图

我正在尝试编写一个没有窗口的蛇游戏,但会冻结前景并在其上绘制蛇。当游戏结束时,前景应该被解冻。

我已经编写了一些测试代码,应该在前景上绘制一个正方形,但它似乎所做的只是将桌面冻结一秒钟并将窗口冻结在前景中,直到我最小化、最大化、关闭它或带来另一个窗口进入前景,它不绘制任何东西。在代码中,我尝试存储桌面的位图,以便基本上可以将其重置为原始状态并将正方形绘制在不同的位置。任何人都可以发现我的代码的问题吗?

//Handle to the desktop window
HWND hDesktopWindow = GetDesktopWindow();

//Lock the window to prevent other applications drawing on it
if(!LockWindowUpdate(hDesktopWindow)){
    return 1;
}

//Calling GetDC with argument NULL retrieves the desktop's DC
HDC hdcDesktop = GetDCEx(hDesktopWindow, NULL, DCX_CACHE | DCX_LOCKWINDOWUPDATE);

//Create a compatible DC to allow us to store a bitmap of the desktop
HDC hdcCompatible;
if((hdcCompatible = CreateCompatibleDC(hdcDesktop)) == NULL){
    return 1;
}

//Create a compatible bitmap with the same dimensions as the desktop
HBITMAP hScrBitmap;
int cx = GetSystemMetrics(SM_CXSCREEN);
int cy = GetSystemMetrics(SM_CYSCREEN);
if((hScrBitmap = CreateCompatibleBitmap(hdcDesktop, cx, cy)) == NULL){
    return 1;
}

//Select the bitmap into the compatible DC
SelectObject(hdcCompatible, hScrBitmap);

//Copy the Desktop into the bitmap
if(!BitBlt(hdcCompatible, 0, 0, cx, cy, hdcDesktop, 0, 0, SRCCOPY)){
    return 1;
}

//Create a DC compatible with the bitmaps DC for drawing the rectangle
HDC hdcRectangle;
if(!CreateCompatibleDC((HDC)hScrBitmap)){
    return 1;
}

//Create a compatible bitmap for the rectangle to be drawn in
HBITMAP hRectangleBitmap;
if(!CreateCompatibleBitmap(hdcRectangle, 100, 100)){
    return 1;
}

//Fill the rectangle bitmap
if(!FloodFill(hdcRectangle, 0, 0, RGB(255,0,0))){
    return 1;
}

//Copy the rectangle onto the desktop bitmap
if(!BitBlt(hdcCompatible, 100, 100, 100, 100, hdcRectangle, 0, 0, SRCCOPY)){
    return 1;
}

//Copy the bitmap onto the actual desktop
if(!BitBlt(hdcDesktop, 0, 0, cx, cy, hdcCompatible, 0, 0, SRCCOPY)){
    return 1;
}

//Allow time to view the result
Sleep(1000);

//Allow other applications to draw on the desktop again
LockWindowUpdate(NULL);

//Cleanup
ReleaseDC(hDesktopWindow, hdcDesktop);
DeleteDC(hdcCompatible);
DeleteObject(hScrBitmap);

任何帮助将不胜感激 :)

4

2 回答 2

5

尝试直接在桌面上执行此操作会出现问题。最好拍一张桌面快照,然后创建一个与整个桌面大小相同的窗口,将快照复制到该窗口,然后在那里进行所有绘图。(这是旧屏幕保护程序中的一个常见技巧,它会执行诸如“侵蚀”桌面之类的操作。)

您不拥有桌面窗口,因此您总是会遇到失效和重绘的问题。

于 2012-11-21T17:34:37.817 回答
3
if(!CreateCompatibleDC((HDC)hScrBitmap)){
    return 1;
}

当您编写这样的 C 代码时,单点返回往往非常重要。像这样的调用将返回 FALSE,无法将 HBITMAP 投射到 HDC,并且节目结束得很糟糕。没有诊断,也没有要求再次解锁。

支持 C++ RAII 模式以确保您始终解锁:

class DesktopLocker {
public:
    DesktopLocker() { LockWindowUpdate(GetDesktopWindow()); }
    ~DesktopLocker() { LockWindowUpdate(NULL); }
};

void foo() {
   DesktopLocker lock;
   // etc...
}

直接在桌面窗口上绘画没有太多的智慧,几乎不能保证你画的任何东西都会持续下去。睡眠和锁定更新只是创可贴。看看Rainmeter 的源码,做得很好。

于 2012-11-21T12:43:10.547 回答