Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Direct Draw in einem geschlossenen Bereich (https://www.delphipraxis.net/27649-direct-draw-einem-geschlossenen-bereich.html)

Dannyboy 13. Aug 2004 14:29


Direct Draw in einem geschlossenen Bereich
 
Hallo Graphik-Freaks,
ich bin, wie in den letzten Tagen bereits erwähnt, dabei
einen Leveleditor für 2D Spiele zu generieren.
Dazu brauche ich in meinem Fenster ein rechteckigen Bereich, der
DirectX (Direct Draw) fähig ist, um dort das aktuelle Level an der
aktuellen Position darzustellen. Es darf NICHT die ganze Form einnehmen,
da noch Platz für Buttons etc. da sein muss.
Also, was verwende ich da am besten? :gruebel:
Besten Dank im Voraus.
DANNY

memphis 13. Aug 2004 15:04

Re: Direct Draw in einem geschlossenen Bereich
 
hallo

du kannst DirectDraw auch in einem Panel laufen lassen.
Hierzu musst du nur anstelle des Handles der Form, jenes des Panels benutzten.

Wenn ich mich nicht ganz irre wird im Funktionsaufruf SetCooperativeLevel das Handle übergeben. Ersetzt form1.handle einfach durch panel1.handle und es müsst dann funktionieren. Weiters befindet sich in dieser Funktion auch noch ein Flag für den Fullscreen-Modus, dieses musst du auch entfernen.

Ich habe leider grad keine Möglichkeit dies zu testen.

MfG
Luki

Dannyboy 23. Aug 2004 10:54

Re: Direct Draw in einem geschlossenen Bereich
 
Sicher, dass eine TPanel-Komonente dafür geeignet ist? :gruebel:
Ich hab' meine Init-Funktion so gelassen, wie sie
bei der Form funktionierte, habe bloß dass Fullscreen-Flag
rausgehauen: Irgendwie mag's keine Panels, denn bei der
Form geht's. :pale:

Vjay 23. Aug 2004 14:09

Re: Direct Draw in einem geschlossenen Bereich
 
Also ich habe zwar keine Ahnung von DirectX, aber so wie es ausschaut braucht die funktion das Handle zu einem Fenster.

Das TPanel.Handle referenziert ebenfalls eines und daher müsste das eigentlich gehen.

Dannyboy 23. Aug 2004 14:28

Re: Direct Draw in einem geschlossenen Bereich
 
Zitat:

Zitat von Vjay
Also ich habe zwar keine Ahnung von DirectX, aber so wie es ausschaut braucht die funktion das Handle zu einem Fenster.

Das TPanel.Handle referenziert ebenfalls eines und daher müsste das eigentlich gehen.

Nicht zwangsläufig. Buttons haben auch Handles und können logischwerweise
nicht als Display verwendet werden.

dizzy 23. Aug 2004 16:06

Re: Direct Draw in einem geschlossenen Bereich
 
Und wie sie das können :!:

Nimm mal nen TMediaPlayer und nen Button. Dann wähle den Button als Display, und ab dafür. --> GEHT!
Ein Button ist nämlich ein WinControl, genau so wie ein Fenster, genau so wie ein Panel!

memphis 23. Aug 2004 16:20

Re: Direct Draw in einem geschlossenen Bereich
 
hallo

Ich hab jetzt leider keine Möglichkeit es zu testen und meine DirectDraw Zeit ist auch schon lange her. Aber mit dem Panel funkioniert es sicher, das wieso und warum hat dizzy bereits erklärt und mit Direct3D funktioniert es so bei mir einwandfrei.

Mal guckn ob ich heute Abend noch ein bißchen Delphi-Quellcode auf ner Backup-CD finde ansonsten kann ich dir nur Auszüge aus meiner alte C++ 2d-Engine anbieten, die unter anderem auch af einem Panel einwandfrei funktionierte.

Spiele mal ein bißchen mit den anderen Flags herum, vieleicht funktionierts ja..
Ansonsten poste mal deinen Initialisierungs-Code, dann guck ichs mir mal an..


MfG
Luki

memphis 23. Aug 2004 16:33

Re: Direct Draw in einem geschlossenen Bereich
 
hallo

mir fällt gerade noch was ein? hast du das Flag für den exclusiven Modus gesetzt? Heißt glaub ich DDSCL_EXCLUSIVE oder so in der Art. Wenn ja, lösch es einfach mal... man kann nämlich wenn ich mich nicht ganz iree DirectDraw nur bei Fullscreen in den exclusiven Modus setzte.

Vieleicht hilfts...

MfG
Luki

Dannyboy 24. Aug 2004 08:14

Re: Direct Draw in einem geschlossenen Bereich
 
Zitat:

Zitat von dizzy
Und wie sie das können :!:

Nimm mal nen TMediaPlayer und nen Button. Dann wähle den Button als Display, und ab dafür. --> GEHT!
Ein Button ist nämlich ein WinControl, genau so wie ein Fenster, genau so wie ein Panel!

Oh, wow, das habe ich gar nicht gewusst. :shock: :shock: :shock:
Zitat:

Zitat von memphis
mir fällt gerade noch was ein? hast du das Flag für den exclusiven Modus gesetzt? Heißt glaub ich DDSCL_EXCLUSIVE oder so in der Art. Wenn ja, lösch es einfach mal... man kann nämlich wenn ich mich nicht ganz iree DirectDraw nur bei Fullscreen in den exclusiven Modus setzte.

Vieleicht hilfts...

Yo, <DDSLC_EXCLUSIVE> und <DDSCL_FULLSCREEN> müssen immer zusammen verwendet werden. Ich habe Euch jetzt mal die wichtigen Passagen meines Sourcecodes gepostet. Die Methode <init_DirectX> schlägt bei <SetCooperativeLevel> jedes Mal fehl. Übergeben wird in <display> ein TPanel-Objekt. Wie ihr sehen könnt, habe ich mit den Flags bereits herumgespielt, aber irgendwie komm' ich nicht auf die richtige Kombination. :gruebel: Der Fullscreen-Modus soll NICHT gesetzt werden, ergo darf auch das <DDSCL_EXCLUSIVE>-Flag nicht gesetzt sein. Sorry, ich dokumentiere meinen Source immer in englisch. So, wie unten gepostet, funktioniert es leider NICHT.
Seht's Euch mal bitte an.
Delphi-Quellcode:
type
  TLevelMap = class
  private
  // Display (panel, form, whatever) to be used as canvas for level
    display : HWND;
  // Direct Draw Object
    IDD     : IDirectDraw;
  // front buffer surface for Direct-X
    Primary : IDirectDrawSurface;
  // back buffer for Direct-X
    Back    : IDirectDrawSurface;
  public
    constructor create(const display : THandle);
    function Init_DirectX : boolean;
  end;

implementation

constructor TLevelMap.create;
begin
  inherited create;
  self.display:= display;
  IDD:= NIL;
  Primary:= NIL;
  Back:= NIL;
end;

function TLevelMap.Init_DirectX;
var ddsd:   TDDSurfaceDesc;
    ddscaps: TDDSCaps;
begin
  result:=false;
// Try to initialize direct draw object
  if not (DirectDrawCreate(nil,IDD,nil)=DD_OK) then exit;
// Set Cooperative Level to flags mentioned below
{  if not (IDD.SetCooperativeLevel(Display,DDSCL_ALLOWREBOOT or
                                          DDSCL_EXCLUSIVE or
                                          DDSCL_FULLSCREEN or
                                          DDSCL_ALLOWMODEX)=DD_OK) then exit;
}
if not (IDD.SetCooperativeLevel(Display, //DDSCL_ALLOWREBOOT or
                                      //   DDSCL_EXCLUSIVE or
                                       //  DDSCL_FULLSCREEN { or
                                       DDSCL_NORMAL or
                                       DDSCL_NOWINDOWCHANGES or
                                         DDSCL_ALLOWMODEX)=DD_OK) then exit;
// initialize surfaceDesc
  with ddsd do
  begin
    dwSize:=sizeof(ddsd);
    dwFlags:=DDSD_CAPS or DDSD_BACKBUFFERCOUNT;
    ddsCaps.dwCaps:=DDSCAPS_PRIMARYSURFACE or DDSCAPS_FLIP or DDSCAPS_COMPLEX;
    dwBackBufferCount:=1;
  end;
// create front suface and attach back surface to it
  if not (IDD.CreateSurface(ddsd,Primary,nil)=DD_OK) then exit;
  ddscaps.dwCaps:=DDSCAPS_BACKBUFFER or DDSCAPS_VIDEOMEMORY;
  if not (Primary.GetAttachedSurface(ddscaps,Back)=DD_OK) then exit;
  result:=true;
end;

Dannyboy 6. Sep 2004 10:06

Re: Direct Draw in einem geschlossenen Bereich
 
Hi Leutz,
wollt' mich noch mal explizit bei Euch für Eure Hilfe bei diesem Thema bedanken. Es funktiniert jetzt ohne Probleme. :thumb:

Bissi doof ist, dass DirectX im Fenstermodus scheinbar immer direkt auf den Desktop zeichnet
und zwar uabhängig davon, ob man das Handle eines Panels übergibt, das Handle des Fenters
oder einfach das Handle 0 (Null). Habe nun 2 Methoden: Zum Ereugen von Front - und
Backsurface.

Hier der Quelltext:
Delphi-Quellcode:
function TGraphicInterface.Init_DirectX;
var DDSurfaceDesc :   TDDSurfaceDesc2;
    Clipper      : IDirectDrawClipper;
    res : HRESULT;
begin
  result:=false;
  res:= DirectDrawCreateEx(nil, DD7, IID_IDirectDraw7, nil);
  if res <> DD_OK then
  begin
    self.SetLastError(DDErrorString(res));
    exit;
  end;
  res:= DD7.SetCooperativeLevel(0, DDSCL_NORMAL );
  if res <> DD_OK then
  begin
    self.SetLastError(DDErrorString(res));
    exit;
  end;
  fillchar(DDSurfaceDesc, sizeof(DDSurfaceDesc), 0);
  with DDSurfaceDesc do
  begin
    dwSize:=sizeof(DDSurfaceDesc);
    dwFlags:= DDSD_CAPS;
    ddsCaps.dwCaps:=DDSCAPS_PRIMARYSURFACE;
  end;
  res:= DD7.CreateSurface( DDSurfaceDesc,Primary,nil);
  if res <> DD_OK then
  begin
    self.SetLastError(DDErrorString(res));
    exit;
  end;
  if not self.CreateBackgroundSurface(self.Back, width, height) then
  begin
    self.SetLastError('<CreateSurface> returned FALSE');
    exit;
  end;
  res:= DD7.CreateClipper(0, Clipper, nil);
  if res <> DD_OK then
  begin
    self.SetLastError('<Create Clipper> returned FALSE');
    exit;
  end;
  result:= res = DD_OK
end;

Function TGraphicInterface.CreateBackgroundSurface;
Var Desc : TDDSurfaceDesc2;
Begin
  ZeroMemory(@Desc,SizeOf(Desc));
  Desc.dwSize:= SizeOf(Desc);
  Desc.dwFlags := DDSD_CAPS OR DDSD_WIDTH OR DDSD_HEIGHT;
  Desc.dwWidth := width;
  Desc.dwHeight:= height;
  Desc.ddsCaps.dwCaps:= DDSCAPS_OFFSCREENPLAIN;
  Result:= DD7.CreateSurface(Desc, Surface, nil) = DD_OK;
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:54 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz