游戏开发论坛

 找回密码
 立即注册
搜索
查看: 6313|回复: 8

DirectX 全屏问题

[复制链接]

2

主题

12

帖子

12

积分

新手上路

Rank: 1

积分
12
发表于 2011-11-13 21:32:00 | 显示全部楼层 |阅读模式
    我自己做的DirectX练习程序,如果设置全屏的话,进去没问题,但是进去后将屏幕切换出来,就只能显示一个原始窗口了,而且也进不去那个全屏界面了,有什么方法能解决这个问题吗。
    我是跟着DirectX9.0 3D 游戏开发编程基础学的,那上面的例子也是这个情况,DirectX自带的倒没有,但是翻看DXUT源代码是一个艰巨的工作,我估计将所有都放下专心看这个,也不是一天二天能搞定的,就上来请教各位大哥了,希望哪位能指点一下,谢谢。

1万

主题

1万

帖子

2万

积分

管理员

中级会员

Rank: 9Rank: 9Rank: 9

积分
20515
发表于 2011-11-14 11:08:00 | 显示全部楼层

Re:DirectX 全屏问题

应该是在切换回去的时候设备没恢复好。

1万

主题

1万

帖子

2万

积分

管理员

中级会员

Rank: 9Rank: 9Rank: 9

积分
20515
发表于 2011-11-14 11:08:00 | 显示全部楼层

Re:DirectX 全屏问题

可以看下DX的文档,里面有段专门讲这个问题的部分。

50

主题

236

帖子

454

积分

中级会员

Rank: 3Rank: 3

积分
454
发表于 2011-11-14 18:51:00 | 显示全部楼层

Re: DirectX 全屏问题

下面这代码是我测试程序专用的,相当精简。


  1. // 切换窗口/全屏模式
  2. void CRender::ToggleScreen(BOOL bWindow)
  3. {
  4.         if (m_D3DParam.Windowed == bWindow)        return;

  5.         m_D3DParam.Windowed = bWindow;
  6.         OnLostDevice();
  7.         OnResetDevice();

  8.         DWORD wndStyle = GetWindowLong(m_hWnd, GWL_STYLE);

  9.         // 窗口模式
  10.         if (bWindow)
  11.         {
  12.                 RECT rcWnd = { 0, 0, m_ScreenWidth, m_ScreenHeight };
  13.                 AdjustWindowRect( &rcWnd, wndStyle, FALSE);
  14.                 SetWindowLong(m_hWnd, GWL_STYLE, wndStyle);
  15.                 SetWindowPos(m_hWnd, HWND_NOTOPMOST,
  16.                         (GetSystemMetrics(SM_CXSCREEN)-m_ScreenWidth)/2,
  17.                         (GetSystemMetrics(SM_CYSCREEN)-m_ScreenHeight)/2,
  18.                         (rcWnd.right - rcWnd.left), (rcWnd.bottom-rcWnd.top),
  19.                         SWP_SHOWWINDOW);
  20.         }
  21.         // 全屏模式
  22.         else
  23.         {
  24.                 // 改变指定窗口的属性
  25.                 SetWindowLong(m_hWnd, GWL_STYLE, wndStyle);
  26.                 // 设置窗口位置
  27.                 SetWindowPos(m_hWnd, HWND_TOPMOST,
  28.                         0,
  29.                         0,
  30.                         GetSystemMetrics(SM_CXSCREEN),
  31.                         GetSystemMetrics(SM_CYSCREEN),
  32.                         SWP_SHOWWINDOW);   // 窗口不能被移动和改变大小
  33.         }
  34. }

  35. void CRender::OnLostDevice()
  36. {
  37.         if (CGameFont::s_pGameFont != NULL)
  38.         {
  39.                 CGameFont::s_pGameFont->OnLostDevice();
  40.         }
  41. }


  42. void CRender::OnResetDevice()
  43. {
  44.         if (FAILED(m_pD3DDevice->Reset(&m_D3DParam)))
  45.         {
  46.                 return;
  47.         }

  48.         if (CGameFont::s_pGameFont != NULL)
  49.         {
  50.                 CGameFont::s_pGameFont->OnResetDevice();
  51.         }

  52.         SetRenderState();
  53. }

  54. void CRender::SetRenderState()
  55. {
  56.         m_pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
  57.         m_pD3DDevice->SetFVF(D3DFVF_VERTEX2D);

  58.         // 启用融合运算
  59.         m_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
  60.         m_pD3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  61.         m_pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

  62.         m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
  63. }
复制代码


主要函数都在这了。
直接调用ToggleScreen()就OK
其中m_D3DParam是D3DPRESENT_PARAMETERS类型的变量,D3D初始化的时候,保存下来就行,
还有字体对象,最终会调用ID3DXFont::OnLostDevice()和ID3DXFont::OnResetDevice(),你若不用这东西,就不用管了。

2

主题

12

帖子

12

积分

新手上路

Rank: 1

积分
12
 楼主| 发表于 2011-11-16 12:26:00 | 显示全部楼层

Re:DirectX 全屏问题

谢谢二位大哥 我试试你那代码 按上面知道说的 是因为设备丢失的原因 在网上找到很多资料 但是一时还没弄明白 呵呵

50

主题

236

帖子

454

积分

中级会员

Rank: 3Rank: 3

积分
454
发表于 2011-11-17 09:27:00 | 显示全部楼层

Re: Re:DirectX 全屏问题

sb55154634: ReirectX 全屏问题

谢谢二位大哥 我试试你那代码 按上面知道说的 是因为设备丢失的原因 在网上找到很多资料 但是一时还没弄明白 呵呵


你没弄明白,其实我也不是很明白。
我也仅仅知道如何处理,如何保证没有问题。

主要就是通过手动制造设备丢失来处理窗口/全屏切换,而且不仅仅可以处理这个变换,稍微改一改的话,还可以支持窗口的任意拉伸,这也是我唯一所知道的方式。

一般的设备丢失往往是在全屏模式下,用户按了系统键或其他什么键把程序切到了桌面或其他窗口中,这会造成设备丢失,即Present()函数执行之后,它会返回一个D3DERR_DEVICELOST值,此时就可能需要重置设备,恢复资源,处理方式像下面这样:


  1. HRESULT hr;
  2.         hr = m_pD3DDevice->Present(NULL, NULL, NULL, NULL);

  3.         if (hr == D3DERR_DEVICELOST)
  4.         {
  5.                 if (m_pD3DDevice->TestCooperativeLevel() == D3DERR_DEVICENOTRESET)
  6.                 {
  7.                         OnLostDevice();
  8.                         OnResetDevice();
  9.                 }
  10.         }
复制代码

0

主题

398

帖子

577

积分

高级会员

Rank: 4

积分
577
发表于 2011-11-17 09:36:00 | 显示全部楼层

Re:DirectX 全屏问题

当初设计DX的时候,微软对于一些特殊情况下了断言,认为你的DX程序不会显示在屏幕上时,为了保证系统的响应,就强制清理了显存,但是应用程序保留的指针无法清理,所以要搞出一个状态来靠应用程序主动检测和自己去处理.这些特殊情况包括:全屏下切出;全屏和窗口模式下锁定工作站(就是Win+L)或者调出了"Windows 安全"(Ctrl+Alt+Del)等等,现在DX10已经把这个去掉了...

2

主题

12

帖子

12

积分

新手上路

Rank: 1

积分
12
 楼主| 发表于 2011-11-20 13:56:00 | 显示全部楼层

Re:DirectX 全屏问题

呵呵 没有完全搞明白 但是能调试通过了 在OnLostDevice() 中将调用directX的那些create创建的资源中全部销毁,除了device, 然后在OnResetDevice()中将这些销毁的所有资源全部重建 以及重新设置device的那些状态。至少我试了好几种方法  都能够在退出全屏后还能恢复全屏  不过貌似在退出全屏后图像第一屏有点割裂

2

主题

12

帖子

12

积分

新手上路

Rank: 1

积分
12
 楼主| 发表于 2011-11-20 14:01:00 | 显示全部楼层

Re:DirectX 全屏问题

退出全屏后恢复全屏刚进去时候有一点图像割裂
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-6-9 14:25

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表