2

我正在尝试使用原始 DirectDraw 接口编写单个缓冲的窗口应用程序。

这纯粹是出于教育目的和公正的态度。我在玩IDirectDraw界面(我强调这是原始版本,就像在 DirectX 1.0 中一样)。

现在,该文档包含一组关于创建后缓冲和在主表面和后缓冲表面之间翻转的教程。

但是,它没有描述如何编写一个窗口化的单缓冲区应用程序。事实上,我几乎找不到任何关于这个想法的参考。没有任何迹象表明它不可能。

DDSCL_NORMAL通过设置与应用程序在一个窗口内的行为的合作级别。

hr = IDirectDraw_SetCooperativeLevel(lpDirectDraw, hWnd_, DDSCL_NORMAL);
if (hr != DD_OK)
    return -1;

成功后创建主曲面。

ZeroMemory(&ddSurfaceDesc, sizeof ddSurfaceDesc);
ddSurfaceDesc.dwSize            = sizeof ddSurfaceDesc;
ddSurfaceDesc.dwFlags           = DDSD_CAPS;
ddSurfaceDesc.ddsCaps.dwCaps    = DDSCAPS_PRIMARYSURFACE;

hr = IDirectDraw_CreateSurface(lpDirectDraw, &ddSurfaceDesc, &lpDirectDrawPrimarySurface, (IUnknown *) NULL);
if (hr != DD_OK)
    return -1;

这个函数也成功了。请注意,我没有创建后台缓冲区。

但是,在我的主循环中:

while (fIterateLoop)
{
    for (ZeroMemory(&msg, sizeof msg); PeekMessage(&msg, (HWND) NULL, 0, 0, PM_REMOVE); DispatchMessage(&msg))
        fIterateLoop = msg.message == WM_QUIT ? FALSE : TRUE;

    if (fDraw && lpDirectDrawPrimarySurface != (LPDIRECTDRAWSURFACE) NULL)
    {
        HDC hdc;

        hr = IDirectDrawSurface_GetDC(lpDirectDrawPrimarySurface, &hdc);
        if (hr == DD_OK)
        {
            SetBkColor(hdc, RGB(0, 0, 0));
            SetTextColor(hdc, RGB(255, 255, 255));
            TextOut(hdc, 15, 15, "hello, world!", sizeof "hello, world!" - 1);

            hr = IDirectDrawSurface_ReleaseDC(lpDirectDrawPrimarySurface, hdc);
        }
    }
}

根本没有任何东西被吸引到窗口上。我的原始代码(全屏缓冲应用程序)正确显示“你好,世界!” 在屏幕的左上角,唯一的修改是微小的编辑以停止后台缓冲区的创建,并直接写入主表面。

如果我CreateSurface在调用后使用后备缓冲区的选项调用SetCooperativeLevelDDSCL_NORMAL那么它会返回并出错。我理解这一点,因为文档指出:

如果您使用 IDirectDraw::SetCooperativeLevel 将模式设置为 DDSCL_NORMAL,则只能创建在曲面之间闪烁的曲面。

我错过了什么吗?我是否从根本上误解了 DirectDraw?我的印象是使用缓冲区是为了:

  • 性能优势,以及
  • 防止屏幕撕裂。

我不在乎这两个对不对。我能做些什么?

4

2 回答 2

0

这是完全可以实现的。所需的是要写入的主表面和修剪器以将表面修剪到窗口。

创建一个类型的裁剪器IDirectDrawClipper并使用它IDirectDrawClipper_SetHWnd来匹配裁剪器到窗口。接下来,然后使用IDirectDrawSurface_SetClipper将裁剪器附加到由主表面控制的内存。

如果您没有锁定窗口大小,请确保在每次窗口更改大小时重新调用然后恢复表面。 IDirectDraw_SetDisplayMode

还请记住,您需要在表面上进行 blit,而不是像有后缓冲区一样翻转。

这篇博文中有几个优点。

于 2013-06-15T13:55:01.800 回答
0

技术上没有问题。这些命令实际上是在屏幕上绘制文本。然而,问题是命令是相对于整个显示而不是客户区绘制的。

我在尝试集成对客户区大小实时更改的支持时发现了这一点,并且不小心将应用程序设置为SIZE_MAXIMIZED并通过IDirectDrawSurface_Restore. 事后看来,我应该多花点力气画到屏幕的中央,而不是左上角。

我还没有弄清楚如何修改程序以相对于客户区域进行绘制,但这个问题的核心是关于使用单个缓冲区和窗口进行绘制,这就是我已经解决的问题。

于 2013-06-03T22:06:12.270 回答