游戏开发论坛

 找回密码
 立即注册
搜索
查看: 9376|回复: 16

编DIRECTX截图,到LOCK时出错,请帮忙~

[复制链接]

5

主题

16

帖子

16

积分

新手上路

Rank: 1

积分
16
发表于 2004-4-5 12:08:00 | 显示全部楼层 |阅读模式
先运行我编写的程序,然后打开DIRECTX游戏,用定时器启动截图程序,但在LOCK时出错,代码如下:
.
.
.
LPDIRECTDRAWSURFACE lpSurface;
WORD* lpBuffer;// 表面指针
FILE* fp;// 打开文件s
if( (fp=fopen("d:\\Model.bmp", "wb")) != NULL )
{
// 锁定表面
DDSURFACEDESC ddsd;
ddsd.dwSize = sizeof(ddsd);
HRESULT ddrval = lpSurface->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL );
if( ddrval == DD_OK )
{
.
.
.

"0x00401d68"指令引用的"0xcccccccc"内存。该内存不能为"read"

黄箭头停留在HRESULT ddrval = lpSurface->Lock( NULL, &ddsd,DDLOCK_WAIT, NULL );

调试看结果:
ddraval     -85893460
&ddsd       0x0012fa34
   dwsize   108
   dwflags  3435973836
   dwHeight 3435973836
   lPitch   -858993460
   dwLinearSize 3435973836
   dwBackBufferCount 3435973836
   dwMipMapCount 3435973836
   .
   .
   .
ddsd {...}
   ddsd.dwSize 108
lpSurface  0xcccccccc

.
.
.





1万

主题

1万

帖子

2万

积分

管理员

中级会员

Rank: 9Rank: 9Rank: 9

积分
20527
发表于 2004-4-5 13:42:00 | 显示全部楼层

Re:编DIRECTX截图,到LOCK时出错,请帮忙~

错误的起因:
lpSurface  0xcccccccc

你对一个错误的指针进行访问,这个是很致命的错误。

粗略看了一下你的代码,你没有对lpSurface进行初始化创建,也就是lpSurface不存在,你对一个不存在的指针内容进行操作,那……必然……

4

主题

19

帖子

19

积分

新手上路

Rank: 1

积分
19
发表于 2004-4-5 14:05:00 | 显示全部楼层

Re:编DIRECTX截图,到LOCK时出错,请帮忙~

超出LOCK范围,确定该页面是啥格式的,24还是16

5

主题

16

帖子

16

积分

新手上路

Rank: 1

积分
16
 楼主| 发表于 2004-4-5 20:00:00 | 显示全部楼层

Re:编DIRECTX截图,到LOCK时出错,请帮忙~

感谢楼上两位高手!

2楼说的“lpSurface不存在”,在程序第一行不是“LPDIRECTDRAWSURFACE lpSurface; “了吗?

该程序是在本站的http://www.gameres.com/Articles/Program/Visual/2D/jietu.htm
上。
它说功能是:将一个16位的DirectDraw表面,存为一张24位BMP位图 (传入主表面即截屏)



0

主题

10

帖子

10

积分

新手上路

Rank: 1

积分
10
发表于 2004-4-6 09:41:00 | 显示全部楼层

Re:编DIRECTX截图,到LOCK时出错,请帮忙~

第一,你用到了定时器!

第二,你用DIRECTX创建表面;

以上两者,存在着“顺序的关系”,在你还没有设定时器开关前(SetTimer),必须创建你要保存的表面才行(lpSurface),象你提供的函数
bool SaveToBitmapFile(LPDIRECTDRAWSURFACE lpSurface, char* ilename)
这个函数在调用前,lpSurface必须存在!

如果你的程式按照下面的写法!一定会错的!
WinMain(........)
{
     。。。。
   你的代码(code)
     。。。
   SetTimer(...);   //启用定时器   (1)
   。。。
   g_pDD->CreateSurface(...);    //创建你要保存的表面  (2)
   。。。
   其它代码(Code)
}
回调函数
HRESULT CALLBACK WinProc(...)
{
     。。。
   switch(msg)
    {
        其它消息:
                    ....
         WM_TIMER:
                   SaveToBitmapFile(你要保存的表面,文件名);
                   return;

    }
    return DefWindowProc(....)   
}
上面的写法,会出问题的,因为你还没有没有创建表面之前,就会启动定时器,这样一来!当定时器消息(WM_TIMER)被触发,表面(lpSurface)还没有创建!所以得把上面的(1)放到(2)后面!

5

主题

16

帖子

16

积分

新手上路

Rank: 1

积分
16
 楼主| 发表于 2004-4-7 22:21:00 | 显示全部楼层

Re: Re:编DIRECTX截图,到LOCK时出错,请帮忙~

游戏人生: Re:编DIRECTX截图,到LOCK时出错,请帮忙~

第一,你用到了定时器!

第二,你用DIRECTX创建表面;

以上两者,存在着“顺序的关系”,在你还没有设...


十分感谢5楼的意见 ~~

我按照您的意见对程序进行了修改,但依然是老地方出错。

我用MFC创建一个对话框的程序,用一个BUTTON启动计时器和CREATESURFACE:
void CXxxDlg::OnButton1()
{
DirectDrawCreateEx(NULL,(void**)&lpdd,IID_IDirectDraw7,NULL);
DDSURFACEDESC2 ddsd;
memset(&ddsd,0,sizeof(ddsd));
ddsd.dwSize=sizeof(ddsd);
ddsd.dwFlags=DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
if (FAILED(lpdd->CreateSurface(&ddsd,&lpddsprimary,NULL))){}
SetTimer(1,4000,NULL);       
}

触发后:
void CXxxDlg::OnTimer(UINT nIDEvent)
{
LPDIRECTDRAWSURFACE lpddsprimary = NULL;
if  (SaveToBitmapFile(lpddsprimary,"d:\\t.bmp"))         MessageBeep(MB_OK);
KillTimer(1);
MessageBeep(MB_OK);       
CDialog::OnTimer(nIDEvent);
}

其中的 SaveToBitmapFile 照抄不变:
bool SaveToBitmapFile(LPDIRECTDRAWSURFACE lpSurface, char* filename)
{
    WORD* lpBuffer; // 表面指针
    int nPitch; // 表面跨距
    int nWidth, nHeight; // 表面宽高

    // 打开文件s
    FILE* fp;
    if( (fp=fopen(filename, "wb")) != NULL )
    {
        // 锁定表面
        DDSURFACEDESC ddsd;
        ddsd.dwSize = sizeof(ddsd);

        HRESULT ddrval = lpSurface->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL );
        if( ddrval == DD_OK )
        {
            lpBuffer = (WORD *)ddsd.lpSurface;
            nWidth = ddsd.dwWidth;
            nHeight = ddsd.dwHeight;
            nPitch = ddsd.lPitch >> 1; //lPitch以Byte为单位,GraphPitch以WORD为单位。所以GraphPitch = lPitch / 2;
        }

运行该程序后,运行一DIRECTX程序,用ALT+TAB切换回来,按BUTTON,后ALT+TAB回游戏,等待4秒后SaveToBitmapFile(),但出错提示依然同我发的第一贴。该怎么办?

0

主题

10

帖子

10

积分

新手上路

Rank: 1

积分
10
发表于 2004-4-8 10:01:00 | 显示全部楼层

Re:编DIRECTX截图,到LOCK时出错,请帮忙~

void CXxxDlg::OnTimer(UINT nIDEvent)
{
LPDIRECTDRAWSURFACE lpddsprimary = NULL;    //把这一项除掉,应该就可以了
if  (SaveToBitmapFile(lpddsprimary,"d:\\t.bmp"))  MessageBeep(MB_OK);
KillTimer(1);
MessageBeep(MB_OK);
CDialog::OnTimer(nIDEvent);
}

0

主题

10

帖子

10

积分

新手上路

Rank: 1

积分
10
发表于 2004-4-8 10:10:00 | 显示全部楼层

Re:编DIRECTX截图,到LOCK时出错,请帮忙~

你这上面还存在一个问题,这样写会为消耗大量的内存(显存)!

你每次按“按钮”时,都要去分配!而过去分配的,你没有释放!这样一样,时间长了,就可死机了!

这种作法,会崩溃的!

5

主题

16

帖子

16

积分

新手上路

Rank: 1

积分
16
 楼主| 发表于 2004-4-8 12:14:00 | 显示全部楼层

Re: Re:编DIRECTX截图,到LOCK时出错,请帮忙~

游戏人生: Re:编DIRECTX截图,到LOCK时出错,请帮忙~

void CXxxDlg::OnTimer(UINT nIDEvent)
{
LPDIRECTDRAWSURFACE lpddsprimary = NULL;    //把这一项除掉...


恩,我按照你的提示,将该语句注释掉:
void CXxxDlg::OnTimer(UINT nIDEvent)
{
//LPDIRECTDRAWSURFACE lpddsprimary = NULL;
if  (SaveToBitmapFile(lpddsprimary,"d:\\t.bmp"))         MessageBeep(MB_OK);

结果编译是出错提示:
E:\xxx\xxxDlg.cpp(286) : error C2664: 'SaveToBitmapFile' : cannot convert parameter 1 from 'struct IDirectDrawSurface7 *' to 'struct IDirectDrawSurface *'
        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

该如何处理?是不是参数没传递下去呢?

谢谢你的第二个提示,我觉得先把最难的这个抓图搞掂了,再慢慢优化程序,呵呵

0

主题

10

帖子

10

积分

新手上路

Rank: 1

积分
10
发表于 2004-4-8 16:54:00 | 显示全部楼层

Re:编DIRECTX截图,到LOCK时出错,请帮忙~

//首先,把lpddsprimary 为一个CXxxDlg类的一个变量
//定义为
LPDIRECTDRAWSURFACE7    lpddsprimary;

下面的函数要注意参数定义
void SaveToBitmapFile(LPDIRECTDRAWSURFACE7 lpSurf,char *filename);

//也就是说如果你用LPDIRECTDRAWSURFACE7 来定义的,最好所有关变量都是7版的,如果用LPDIRECTDRAWSURFACE 定义的,最好变量也按相应的版来定义
同一性,比较好!
//directx程式比较难调试,慢慢试吧!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-6-30 03:31

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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