如何获得DirectX窗口的位置与大小?

像QQ游戏那样的窗口,用Windows的API能否搞定?
我的意思是,用GetWindowRect函数得不到DirectX窗口的信息,有什么解决办法

的痛苦是不能使用换页操作(Flip). 但是有许多人还是喜欢在窗口模式下进行游戏.
首先, 窗口模式下创建一个 IDirectDraw 接口对象和全屏模式下是一样的, 不同的是, 在选择协作模式和不能改变屏幕分辨率. (当然你坚决要改变, 一定要有礼貌的改变.)

// 设置协作级别,窗口化下使用 DDSCL_NORMAL 标志.
if (FAILED(m_x2d_lpDDraw->SetCooperativeLevel(m_x2d_hWnd, DDSCL_NORMAL)))
return (E_FAIL);

// 使用 DirectDraw 接口对象创建 DirectDrawSurface 主页面对象.
DDSURFACEDESC2 ddsd;
INIT_DXSTRUCT(ddsd);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
if (FAILED(m_x2d_lpDDraw->CreateSurface(&ddsd, &m_x2d_lpDDrawPrimarySurface, NULL)))
return (E_FAIL);

// 创建一个离屏页面
INIT_DXSTRUCT(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
ddsd.dwWidth = width;
ddsd.dwHeight = height;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;

if (FAILED(m_x2d_lpDDraw->CreateSurface(&ddsd, &m_x2d_lpDDrawBackSurface, NULL)))
return (E_FAIL);

/* 在这里省略掉给这个离屏页面附属上裁剪器,
下面使用到这个离屏页面的是已经附属上裁减器的. */

LPDIRECTDRAWCLIPPER lpDDClipper = NULL;
// 创建裁剪器.
if (FAILED(m_x2d_lpDDraw->CreateClipper(0, &lpDDClipper, NULL)))
return (E_FAIL);

// 与窗口工作区关联.
if (FAILED(lpDDClipper->SetHWnd(0, m_x2d_hWnd)))
{
SAFE_RELEASE(lpDDClipper);
return (E_FAIL);
}

if (FAILED(m_x2d_lpDDrawPrimarySurface->SetClipper(lpDDClipper)))
{
SAFE_RELEASE(lpDDClipper);
return (E_FAIL);
}
SAFE_RELEASE(lpDDClipper);

给主页面设置裁剪器, 是为了窗口在超出(超出屏幕的显示部分)桌面时能正常工作.实际上主页面就是你的桌面.

现在桌面上有许多窗口在运行, 我们不能胡乱的在桌面上乱画, 否则其他的窗口可能抱怨. 我们要知道我们的窗口工作区位置, 然后我们在这个工作区内工作.

GetClientRect(m_x2d_hWnd, &m_x2d_ClientRect);
ClientToScreen(m_x2d_hWnd, (LPPOINT)&m_x2d_ClientRect);
ClientToScreen(m_x2d_hWnd, (LPPOINT)&m_x2d_ClientRect+1);

m_x2d_ClientRect 保存的是我们的窗口工作区(客户区)位置.

然后我们可能这样用:
m_x2d_lpDDrawPrimarySurface->Blt(&m_x2d_ClientRect, m_x2d_lpDDrawBackSurface, NULL, DDBLT_WAIT, NULL));

这个位转换目标位置就是我们的工作区. 因为我们给主页面附属了裁剪器, 所以不能再用BltFast来位转换了.

如果我们像这样用, 可能看到一个杂乱的桌面.
RECT rct = ;
m_x2d_lpDDrawPrimarySurface->Blt(&rct, surface, NULL, DDBLT_WAIT, NULL));
这样的后果是:
在桌面的 X = 0, Y = 0 位置, 画上 宽 = 300, 高 = 123 的 surface 图形.

在窗口模式下, 一定要正确获得自己的工作区, 当窗口移动或者改变大小, 我们因该有所行动.

case WM_MOVE:
case WM_SIZE:
GetClientRect(m_x2d_hWnd, &m_x2d_ClientRect);
ClientToScreen(m_x2d_hWnd, (LPPOINT)&m_x2d_ClientRect);
ClientToScreen(m_x2d_hWnd, (LPPOINT)&m_x2d_ClientRect+1);
break;

还有, 当窗口失去焦点(活动), 应该停止在继续向主页面绘画. 否则, 你画的将覆盖掉在窗口上的其他窗口的内容.

case WM_ACTIVATE:
{
switch((LOWORD(wParam)))
{
case WA_ACTIVE:
case WA_CLICKACTIVE:
// 活动, 可以继续向主页面绘画了.
Active(true);
break;
case WA_INACTIVE:
// 不活动, 停止向主页面绘画.
Active(false);
break;
default:
break;
}
}
温馨提示:答案为网友推荐,仅供参考
第1个回答  2011-03-25
窗口模式的DirextX程序,并且要求显示内容不随窗口的变化而变化,是这个意思吗?
我的想法是,先将要显示的内容通过“渲染到纹理”的技术渲染到一张固定大小的纹理上,然后创建一个与窗体等大并且随着窗体的大小变化而变化的2D显示体;然后,当窗体大小改变的时候,计算当前窗体大小和上面说的那个“固定大小的纹理”在尺寸上的比例关系,根据这个比例关系调整2D显示体的纹理坐标值,最后将固定大小的纹理交付给那个2D显示体显示就可以了。

拖动滚动条的时候,也只要根据窗体大小、纹理大小和滚动条位置计算纹理坐标就可以了。
第2个回答  2011-04-08
得不到,QQ游戏是经过特殊处理的,截图自己分析吧本回答被提问者采纳