在DirectX 全屏独占 方式下显示对话框和任意窗口

DirectX SDK
在全屏方式(full-screen mode)中显示一个窗口 [语言: C++ ]
用全屏方式,DirectDraw 拥有对显示的完全控制权。因此,通过GDI 建立的对话框和其他窗子是不能正常显示的。 不过,通过使用特别的技术你能合并一个 Windows 对话框,HTML 帮助,或者其它任何一种窗口 到你的应用程序当中。

FSWindow 例子描述了一个对话框如何在全屏模式的应用程序中显示并更新, 以及鼠标的点击和键盘的输入工作的如同这个对话框由 GDI 显示一样。

在 FSWindow 里,对话框被建立和"显示" 如同一个普通的对话框窗口:

hWndDlg = CreateDialog(g_hInstance,
        MAKEINTRESOURCE(IDD_DIALOG_SAMPLE),
        hWnd, (DLGPROC) SampleDlgProc);
ShowWindow(hWndDlg, SW_SHOWNORMAL);

当然,在这点对话框只在被隐藏的 GDI 表面上被显示。它不在由 DirectDraw 控制的主要表面(primary surface)上出现。

如果你的显卡硬件加速能力包括 DDCAPS2 _ CANRENDERWINDOWED ( 参考 DDCAPS 结构),显示和更新对话框是非常简单的事情。程序只需调用 IDirectDraw7:FlipToGDISurface 方法,使 GDI 表面为主要表面。今后,对对话框的全部更新将被自动显示,因为 GDI 现在将直接对前台缓冲区进行重画更新。应用程序还是继续对后备缓冲区进行重画更新,并且通过每次的更新 DirectDraw  都将后备缓冲区的被赋值到前台缓冲区。 对话框并没有被覆盖是因为对于应用程序的窗口来说前台缓冲区已经被裁剪(clipped )了一部分,对话框就正好裁剪了被省略的部分。

下列代码,在 FSWindow_Init 函数中,建立裁剪器,把它与应用程序窗口关联起来,并且把 GDI 表面(surface )带到前台:

if (ddObject->CreateClipper(0, &ddClipper, NULL) == DD_OK)
    ddClipper->SetHWnd(0, hwndAppWindow);
ddObject->FlipToGDISurface();

然后,在 FSWindow_Update 函数中,下列代码 复制后备缓冲区重画的内容 到裁剪区域。

ddFrontBuffer->SetClipper(ddClipper);
ddFrontBuffer->Blt(NULL, ddBackBuffer, NULL, DDBLT_WAIT, NULL);

请注意,因为 GDI 表面就是主要表面,Windows 继续显示鼠标。 (如果应用程序使用独占级别的 DirectInput 来控制鼠标设备的话,这将不会发生。)

对于没有 DDCAPS2_CANRENDERWINDOWED 支持的硬件来说,在全屏方式下显示并且更新一个窗口就显得有些错综复杂了。这样的话,应用程序应该负责获得由 GDI 创建的窗口的全部图像并且在全屏重画更新完成后将它们复制到后备缓冲区。之后全部后备缓冲区会和平常一样被替换到前台。

FSWindow 范例提供两种不同的方法为操作窗口的显存,这取决于内容是静止还是动态的(小猫:这里是指对话框的内容)。 静止的内容的这种方法更迅速因为它从记忆设备上下文而不是屏幕设备上下文中进行相关复制。这种方法应该用于不改变的窗口,例如信息的对话框的窗子。 (不过记住那个,除非在需要回应事件的时候你手工不断更新位图,否则哪怕如同按按钮这样基础的动画效果用户也是不能看见的。)

如果内容是静止的,当窗子初始化时,FSWindow 调用 CreateBMPFromWindow 函数。 此函数创建一个位图并且将窗口的内容复制进去。位图的句柄被存储在全局变量 hwndFSWindowBMP 中。 每当主要表面正要被更新时,这个位图将被复制到后备缓冲区,如下:

if (FSWindow_IsStatic)
{
    hdcMemory = CreateCompatibleDC(NULL);
    SelectObject(hdcMemory, hwndFSWindowBMP);
    BitBlt(hdcBackBuffer, x, y, cx, cy, hdcMemory, 0, 0, SRCCOPY);
    DeleteDC(hdcMemory);
}

如果, 另一方面,窗口的内容是动态的,下列代码被执行。 直接从 GDI 表面(以hdcScreen 设备上下文描述)复制图像到后备缓冲区。

BitBlt(hdcBackBuffer,x,y,cx,cy,hdcScreen,x,y,SRCCOPY);
坐标系相对于 GDI 表面上窗体的位置和尺寸,经由对 GetWindowRect 函数的调用得到。

当FSWindow 应用正在没有 DDCAPS2_CANRENDERWINDOWED 支持的硬件上运转时,它不使用 GDI 表面,因此 Windows 不能显示鼠标。 应用程序接管这项任务,通过获得关于光标的信息并且在页面转换前在背面缓冲区上显示它。

 

----------------------------------------------------------------------------

用下面的代码就可以为主表面挂接上Clipper:

 // 首先创建一个Clipper:
 LPDIRECTDRAWCLIPPER clipper;
 lpDD->CreateClipper(0, &clipper, 0);

 // 将clipper与主窗口进行关联:
 clipper->SetHWnd(0, hMainWnd);

 // 将clipper挂入主表面:
 lpDDSMain->SetClipper(clipper);

 // 删除clipper
 clipper->Release();
}

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/yushenrui/archive/2005/12/26/562117.aspx

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值