游戏开发论坛

 找回密码
 立即注册
搜索
查看: 4935|回复: 5

我用DELPHI+DIRECTX7 SDK方式编了一个程序,可是退出的时候总

[复制链接]

9

主题

31

帖子

31

积分

注册会员

Rank: 2

积分
31
发表于 2005-11-2 10:22:00 | 显示全部楼层 |阅读模式
我用DELPHI+DIRECTX7 SDK方式编了一个程序,可是退出的时候总是内存出错.高手来看一下!
我发现如果在退出时不释放DIRECTDRAW对象,就不会出错。。。可是不释放又有点不安全吧。。
我找了好久都找不到原因。。有这方面经验的高手请帮忙呀  

64

主题

855

帖子

856

积分

高级会员

Rank: 4

积分
856
QQ
发表于 2005-11-2 14:25:00 | 显示全部楼层

Re:我用DELPHI+DIRECTX7 SDK方式编了一个程序,可是退出的时候

正确释放DDraw对象绝不会导致内存出错,可能是你别的地方内存引用错误,释放DDraw的时候导致连锁错误,内存出错是大问题,好好检查一下代码比较好。

64

主题

855

帖子

856

积分

高级会员

Rank: 4

积分
856
QQ
发表于 2005-11-2 14:27:00 | 显示全部楼层

Re:我用DELPHI+DIRECTX7 SDK方式编了一个程序,可是退出的时候

不行的话做个最简单的验证,整个程序就是新建一个DDraw对象,然后释放它。看看有什么问题

9

主题

31

帖子

31

积分

注册会员

Rank: 2

积分
31
 楼主| 发表于 2005-11-2 15:53:00 | 显示全部楼层

Re:我用DELPHI+DIRECTX7 SDK方式编了一个程序,可是退出的时候

最简单的没问题,但是我建了一个离屏表面和一个键盘控制以后,就出问题了..
我把全部代码贴出来..大家帮我看一下...同样的代码,我用C就没问题..怪事..

program KS;

//-----------------------------------------------------------------------------
// Include files
//-----------------------------------------------------------------------------
uses
  Windows,
  Messages,
  DirectDraw,
  DIRECTINPUT,
  SysUtils,
  DDUtil ;

{$R *.res}

const
  //---------------------------------------------------------------------------
  // Local definitions
  //---------------------------------------------------------------------------
  NAME  : PChar = 'DDExample2';
  TITLE : PChar = 'Direct Draw Example 2';

  //---------------------------------------------------------------------------
  // Default settings
  //---------------------------------------------------------------------------
  TIMER_ID   = 1;
  TIMER_RATE = 500;

var
  //---------------------------------------------------------------------------
  // Global data
  //---------------------------------------------------------------------------
  PDD        : IDirectDraw7;                // DirectDraw 对象
  DDSPrimary : IDirectDrawSurface7;         // DirectDraw 主表面
  DDSBack    : IDirectDrawSurface7;         // DirectDraw 后台表面
  DDSBuff    : IDirectDrawSurface7;         // DirectDraw 离屏表面
  DDSWORK    : IDirectDrawSurface7;         // DirectDraw 工作表面
  DDINPUT    : IDIRECTINPUT7;
  DDDEV      : IDIRECTINPUTDEVICE;
//  DDPal      : IDIRECTDRAWPALETTE;          // The primary surface palette
  g_bActive     : Boolean = False;             // Is application active?
  DDBLTFX : TDDBLTFX;
  KeyBuf:Array[0..255] Of Byte;
    h_Wnd : HWND;
  X,Y:INTEGER;
  //---------------------------------------------------------------------------
  // Local data
  //---------------------------------------------------------------------------
  szBackground : PChar = 'ZJ.bmp';
  szMsg        : PChar = 'Page Flipping Test: Press F12 to exit';
  szFrontMsg   : PChar = 'Front buffer (F12 to quit)';
  szBackMsg    : PChar = 'Back buffer (F12 to quit)';

//-----------------------------------------------------------------------------
// Name: ReleaseAllObjects
// Desc: Finished with all objects we use; release them
//-----------------------------------------------------------------------------
procedure ReleaseAllObjects;
begin
  if Assigned(pDD) then
    begin
    if Assigned(DDSBack) then
        begin
          DDSBack := nil;
        end;
      if Assigned(DDSPrimary) then
        begin
         DDSPrimary := nil;
        end;
      if Assigned(DDSBUFF) then
        begin
          DDSBUFF := nil;
        end;
      if Assigned(DDSWORK) then
        begin
          DDSWORK := nil;
        end;  

      PDD:=NIL;
      if assigned(ddinput) then
      begin
      dddev.Unacquire ;
      end;

    end;
end;

//-----------------------------------------------------------------------------
// Name: InitFail
// Desc: This function is called if an initialization function fails
//-----------------------------------------------------------------------------
function InitFail(h_Wnd : HWND; hRet : HRESULT; Text : string) : HRESULT;
begin
  ReleaseAllObjects;
  MessageBox(h_Wnd, PChar(Text + ': ' + DDErrorString(hRet)), TITLE, MB_OK);
  DestroyWindow(h_Wnd);
  Result := hRet;
end;

//-----------------------------------------------------------------------------
// Name: UpdateFrame
// Desc: Displays the proper text for the page
//-----------------------------------------------------------------------------
var
  phase : Boolean = False;
  
procedure UpdateFrame(h_Wnd : HWND);
var
  h_DC    : HDC;
  rc      : TRect;
  size    : TSize;
begin
  // The back buffer already has a loaded bitmap, so don't clear it
  if DDSBack.GetDC(h_DC) = DD_OK then
    begin
      SetBkColor(h_DC, RGB(0, 0, 255));
      SetTextColor(h_DC, RGB(255, 255, 0));
      if phase then
        begin
          GetClientRect(h_Wnd, rc);
          GetTextExtentPoint(h_DC, szMsg, StrLen(szMsg), size);
          TextOut(h_DC, (rc.right - size.cx) div 2, (rc.bottom - size.cy) div 2, szMsg, StrLen(szMsg));
          TextOut(h_DC, 0, 0, szFrontMsg, StrLen(szFrontMsg));
          phase := False;
        end
      else
        begin
          TextOut(h_DC, 0, 0, szBackMsg, StrLen(szBackMsg));
          phase := True;
        end;
      DDSBack.ReleaseDC(h_DC);
    end;
end;

//-----------------------------------------------------------------------------
// Name: WindowProc
// Desc: The Main Window Procedure
//-----------------------------------------------------------------------------
function WindowProc(h_Wnd: HWND; aMSG: Cardinal; wParam: Cardinal; lParam: Integer) : Integer; stdcall;
var
  hRet : HRESULT;
begin
  case aMSG of
    // Pause if minimized
    WM_ACTIVATE:
      begin
        if HIWORD(wParam) = 0 then
          g_bActive := True
        else
          g_bActive := False;
        Result := 0;
        Exit;
      end;
    // Clean up and close the app
    WM_DESTROY:
      begin
        ReleaseAllObjects;
        PostQuitMessage(0);
        Result := 0;
        Exit;
      end;
    WM_CLOSE:
      BEGIN
       destroywindow(h_Wnd);
       exit;
      end;
    // Handle any non-accelerated key commands
    WM_KEYDOWN:
      begin
        case wParam of
          VK_ESCAPE,
          VK_F12:
            begin
              PostMessage(h_Wnd, WM_CLOSE, 0, 0);
              Result := 0;
              Exit;
            end;
        end;
      end;
    // Turn off the cursor since this is a full-screen app
    WM_SETCURSOR:
      begin
        SetCursor(0);
        Result := 1;
        Exit;
      end;
    end;

  Result := DefWindowProc(h_Wnd, aMSG, wParam, lParam);
end;

//-----------------------------------------------------------------------------
// Name: InitApp
// Desc: Do work required for every instance of the application:
//          Create the window, initialize data
//-----------------------------------------------------------------------------
function InitApp(hInst : THANDLE; nCmdShow : Integer) : HRESULT;
var

  wc : WNDCLASS;
  ddsd : TDDSurfaceDesc2;
  ddscaps : TDDSCaps2;
  hRet : HRESULT;
  tycl: TDIDataFormat;
begin
  // Set up and register window class
  wc.style := CS_HREDRAW or CS_VREDRAW;
  wc.lpfnWndProc := @WindowProc;
  wc.cbClsExtra := 0;
  wc.cbWndExtra := 0;
  wc.hInstance := hInst;
  wc.hIcon := LoadIcon(hInst, 'MAINICON');
  wc.hCursor := LoadCursor(0, IDC_ARROW);
  wc.hbrBackground := GetStockObject(BLACK_BRUSH);
  wc.lpszMenuName := NAME;
  wc.lpszClassName := NAME;
  RegisterClass(wc);

  // Create a window
  h_Wnd := CreateWindowEx(WS_EX_TOPMOST,
                          NAME,
                          TITLE,
                          WS_POPUP,
                          0,
                          0,
                         300,200,
//                          GetSystemMetrics(SM_CXSCREEN),
//                          GetSystemMetrics(SM_CYSCREEN),
                          0,
                          0,
                          hInst,
                          nil);

  if h_Wnd = 0 then
    begin
      Result := 0;
      Exit;
    end;

  ShowWindow(h_Wnd, nCmdShow);
  UpdateWindow(h_Wnd);
  SetFocus(h_Wnd);

  ///////////////////////////////////////////////////////////////////////////
  // Create the main DirectDraw object
  ///////////////////////////////////////////////////////////////////////////
  hRet := DirectDrawCreateEx(nil, pDD, IDirectDraw7, nil);
  if hRet <> DD_OK then
    begin
      Result := InitFail(h_Wnd, hRet, 'DirectDrawCreateEx FAILED');
      Exit;
    end;

  // Get exclusive mode
  hRet := pDD.SetCooperativeLevel(h_Wnd, DDSCL_EXCLUSIVE or DDSCL_FULLSCREEN);
  if hRet <> DD_OK then
    begin
      Result := InitFail(h_Wnd, hRet, 'SetCooperativeLevel FAILED');
      Exit;
    end;

  // Set the video mode to 640x480x8
  hRet := pDD.SetDisplayMode(1024, 768,32, 0, 0);
  if hRet <> DD_OK then
    begin
      Result := InitFail(h_Wnd, hRet, 'SetDisplayMode FAILED');
      Exit;
    end;

  // Create the primary surface with 1 back buffer
  FillChar(ddsd, SizeOf(ddsd), 0);
  ddsd.dwSize := SizeOf(ddsd);
  ddsd.dwFlags := DDSD_CAPS or DDSD_BACKBUFFERCOUNT;
  ddsd.ddsCaps.dwCaps := DDSCAPS_PRIMARYSURFACE or DDSCAPS_FLIP or DDSCAPS_COMPLEX;
  ddsd.dwBackBufferCount := 1;
  hRet := pDD.CreateSurface(ddsd, DDSPrimary, nil);
  if hRet <> DD_OK then
    begin
      Result := InitFail(h_Wnd, hRet, 'CreateSurface FAILED');
      Exit;
    end;
  // Get a pointer to the back buffer
  FillChar(ddscaps, SizeOf(ddscaps), 0);
  ddscaps.dwCaps := DDSCAPS_BACKBUFFER;
  hRet := DDSPrimary.GetAttachedSurface(ddscaps, DDSBack);
  if hRet <> DD_OK then
    begin
      Result := InitFail(h_Wnd, hRet, 'GetAttachedSurface FAILED');
      Exit;
    end;

//开始创建离屏页面,先清空页面描述
//填充页面描述
ddsd.dwFlags := DDSD_CAPS or DDSD_HEIGHT or DDSD_WIDTH;
ddsd.ddsCaps.dwCaps :=DDSCAPS_OFFSCREENPLAIN or DDSCAPS_SYSTEMMEMORY ; //这是离屏页面
ddsd.dwHeight:=193; //高
ddsd.dwWidth:=384; //宽
hRet:=pDD.CreateSurface(ddsd, DDSBuff, nil ) ;
  if hRet <> DD_OK then
    begin
      Result := InitFail(h_Wnd, hRet, 'GetAttachedSurface FAILED');
      Exit;
    end;

//创建键盘设备
tycl:=c_dfDIKeyboard ;
hret:=DirectInputCreateEX(getmodulehandle(nil),DIRECTINPUT_VERSION,IID_IDIRECTINPUT7,ddinput,nil);
  if hRet <> DD_OK then
    begin
      Result := InitFail(h_Wnd, hRet, 'GetAttachedSurface FAILED');
      Exit;
    end;
IF ddinput.CreateDevice(GUID_SYSKEYBOARD,dddev,nil)=DI_OK THEN
if dddev.SetDataFormat(tycl)=DI_OK then
//IF dddev.SetCooperativeLevel(h_Wnd,DISCL_EXCLUSIVE OR DISCL_FOREGROUND)=DI_OK THEN
IF dddev.SetCooperativeLevel(h_Wnd, DISCL_FOREGROUND)=DI_OK THEN
DDDEV.Acquire ;

  // 调入位图到离屏表面
//     DDSBuff :=DDLoadBitmap(PDD,szBackground,0,0);
  hRet := DDReLoadBitmap(DDSBuff, szBackground);
    if hRet <> DD_OK then
    begin
      Result := InitFail(h_Wnd, hRet, 'DDReLoadBitmap FAILED');
      Exit;
    end;
    ddsetcolorkey(DDSBuff,rgb(255,0,255));
    ddBltFx.dwSize:=sizeof(DDBLTFX);
  ddBltFx.dwFillColor:=0; //如是纯红则为dwRBitMask,
  Result := DD_OK;

end;

function game() : HRESULT;
var
hRet : HRESULT;
pic:integer;
rect,rect1:trect;
begin
FillChar(KeyBuf, SizeOf(KeyBuf), 0);
//hret:=dddev.GetDeviceState(sizeof(keybuf),@keybuf);

if failed(dddev.GetDeviceState(sizeof(keybuf),@keybuf)) then
   begin
   hret:=dddev.Acquire ;
   while (hret= DIERR_INPUTLOST) OR (HRET=DIERR_OTHERAPPHASPRIO)
     DO hret:=dddev.Acquire ;
   end;
pic:=0;   
if keybuf[DIK_LEFT] AND $80<>0 then
  BEGIN
   IF X>0 THEN DEC(X);
   pic:=1;
  END;
if keybuf[DIK_RIGHT] AND $80<>0 then
  BEGIN
   IF X<800-64 THEN INC(X);
   pic:=2;
  END;
if keybuf[DIK_UP] AND $80<>0 then
  BEGIN
   IF Y>0 THEN DEC(y);
  END;
if keybuf[DIK_DOWN] AND $80<>0 then
  BEGIN
   IF Y<600-64 THEN INC(Y);
  END;
  RECT.Left:=pic*64;
  RECT.Top:=0;
  RECT.Right :=pic*64+63;
  RECT.Bottom :=63;
  RECT1.Left:=0;
  RECT1.Top:=0;
  RECT1.Right :=1024;
  RECT1.Bottom :=768;
  DDSBack.blt(@rect1,NIL,@rect1,DDBLT_WAIT or DDBLT_COLORFILL,@DDBLTFX);
  DDSBack.BltFast(X,Y,DDSBuff,@RECT,DDBLTFAST_SRCCOLORKEY OR DDBLTFAST_WAIT);

  DDSPrimary.Flip(nil, 0);
  Result := DD_OK;
end;

//-----------------------------------------------------------------------------
// Name: WinMain
// Desc: Initialization, message loop
//-----------------------------------------------------------------------------
var
  aMSG : MSG;
begin
  if InitApp(GetModuleHandle(nil), SW_SHOW) <> DD_OK then
    begin
      Exit;
    end;
  X:=400;Y:=300;
  while (true) do
    begin
     if peekmessage(amsg,0,0,0,PM_REMOVE) THEN
     BEGIN
      IF (AMSG.message=WM_QUIT) then break;
      TranslateMessage(aMSG);
      DispatchMessage(aMSG);
      END;
    IF g_bActive THEN GAME;
    end;


end.

9

主题

31

帖子

31

积分

注册会员

Rank: 2

积分
31
 楼主| 发表于 2005-11-2 15:55:00 | 显示全部楼层

Re: 我用DELPHI+DIRECTX7 SDK方式编了一个程序,可是退出的时候

这是这个工程用到的所有文件,请高手帮我调试看看.那一部分引起的内存问题.

sf_2005112155512.rar

87.43 KB, 下载次数:

9

主题

31

帖子

31

积分

注册会员

Rank: 2

积分
31
 楼主| 发表于 2005-11-4 14:52:00 | 显示全部楼层

Re:我用DELPHI+DIRECTX7 SDK方式编了一个程序,可是退出的时候

高手帮帮忙呀。。。期待中~~
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-22 12:07

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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