4

重複の可能性:
Inspect に似た GDI+ (または GDI) を使用して画面に描画する

ウィンドウのないスネーク ゲームを作成しようとしていますが、前景がフリーズし、その上にスネークが描画されます。ゲームが終了すると、フォアグラウンドは凍結解除されます。

前景に正方形を描画することになっているテストコードをいくつか書きましたが、デスクトップを1秒間フリーズし、最小化、最大化、閉じる、または別のウィンドウを表示するまで、ウィンドウを前景でフリーズするだけのようですフォアグラウンドに移動し、何も描画しません。コードでは、デスクトップのビットマップを保存して、基本的に元の状態にリセットし、正方形を別の位置にペイントできるようにしています。誰でも私のコードの問題を見つけることができますか?

//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 に答える