Failed to GetDC for overlays surface

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



Hello,

I am trying to generate a overlays surface and then do some drawing to it. More specifically I want to draw some lines and also enlange a piece of the screen and draw to my overlay.

So far I suceeded in generating the overlays surface and drawing a black square using IDirectDrawSurface.Blt without a source surface.

Now I would like to get a DC to use drawing operations, or do anything else that allows me to draw lines and do other basic operations on my overlay, but IDirectDrawSurface.GetDC fails with 88760249 "Cannot create DC"

Does anyone know what factors cause IDirectDrawSurface.GetDC to fail? I read the reference on MSDN but there are no details about that.

Bellow is my full code. On the WM_PAINT event of the main window I draw a black square on the overlay. Bellow it is code to get a DC and draw a square using windows GDI instead, but that fails.

Thanks

program overlay;

{$ifdef fpc}
{$mode delphi}{$H+}
{$endif}

uses
Classes, SysUtils,
Windows, DirectDraw;

{ Global Variables }
var
{ DirectX variables }
g_lpdd: IDirectDraw7 = nil;
g_lpddsPrimary: IDirectDrawSurface7 = nil;
g_lpddsOverlay: IDirectDrawSurface7 = nil;
g_lpClipper: IDirectDrawClipper = nil;

{ Debug variables }
DebugLoc, DebugInfo: Cardinal;

ddrval: HRESULT;

{ prototypes }

function InitOverlays: Boolean; forward;
function WndProc(ahWnd: HWND; amessage: UINT; awParam: WPARAM; alParam: LPARAM): LResult; stdcall; forward;
procedure CreateMainWindow; forward;
procedure ShowError; forward;

{*******************************************************************
* InitOverlays ()
*
* Initializes DirectX and creates a overlay surface
*******************************************************************}
function InitOverlays: Boolean;
var
ddsd, ddsdOverlay: DDSURFACEDESC2;
capsDrv: TDDCaps;
pixelFormats: array[0..3] of DDPIXELFORMAT;
begin
Result := False;
DebugInfo := 0;
DebugLoc := 0;

{ Init DirectDraw }

ddrval := DirectDrawCreateEx(nil, g_lpdd, IID_IDirectDraw7, nil);
if ddrval <> DD_OK then
begin
DebugLoc := $1;
Exit;
end;

{ For NORMAL cooperative level we no longer need to provide an HWND }

ddrval := g_lpdd.SetCooperativeLevel(0, DDSCL_NORMAL);
if ddrval <> DD_OK then
begin
DebugLoc := $2;
Exit;
end;

if g_lpdd = nil then
begin
DebugLoc := $3;
Exit;
end;

{ Create the primary surface }

FillChar(ddsd, sizeof(ddsd), #0);
ddsd.dwSize := sizeof(ddsd);
ddsd.dwFlags := DDSD_CAPS;
ddsd.ddsCaps.dwCaps := DDSCAPS_PRIMARYSURFACE;
ddrval := g_lpdd.CreateSurface(ddsd, g_lpddsPrimary, nil);

if ddrval <> DD_OK then
begin
DebugLoc := $4;
Exit;
end;

{ Get driver capabilities to determine Overlay support }

FillChar(capsDrv, sizeof(capsDrv), #0);
capsDrv.dwSize := sizeof(capsDrv);
ddrval := g_lpdd.GetCaps(@capsDrv, nil);

if ddrval <> DD_OK then
begin
DebugLoc := $5;
Exit;
end;

{*******************************************************************
Does the driver support overlays in the current mode?
(Currently the DirectDraw emulation layer does not support overlays.
Overlay related APIs will fail without hardware support)
*******************************************************************}

if (capsDrv.dwCaps and DDCAPS_OVERLAY) = 0 then
begin
DebugLoc := $B;
Exit;
end;

{ Setup the overlay surface }

{ Init Direct3D }

FillChar(ddsdOverlay, sizeof(ddsdOverlay), #0);
ddsdOverlay.dwSize := sizeof(ddsdOverlay);
ddsdOverlay.dwFlags := DDSD_CAPS or DDSD_HEIGHT or DDSD_WIDTH or DDSD_PIXELFORMAT;
ddsdOverlay.dwBackBufferCount := 0;
ddsdOverlay.dwWidth := 800;
ddsdOverlay.dwHeight := 720;
ddsdOverlay.ddsCaps.dwCaps := DDSCAPS_OVERLAY or DDSCAPS_VIDEOMEMORY;

{*******************************************************************
Fills many possible pixel formats to be utilized.
The most widely supported seams to be YUV, so that one is
utilized by default
*******************************************************************}

{ Generic YUV }
pixelFormats[0].dwSize := SizeOf(DDPIXELFORMAT);
pixelFormats[0].dwFlags := DDPF_FOURCC;
pixelFormats[0].dwFourCC := DWORD(Byte('U') or (Byte('Y') shl 8) or (Byte('V') shl 16) or (Byte('Y') shl 24));
pixelFormats[0].dwYUVBitCount := 16;

{ RGB 16 bits depth 5-5-5 }
pixelFormats[1].dwSize := SizeOf(DDPIXELFORMAT);
pixelFormats[1].dwFlags := DDPF_RGB;
pixelFormats[1].dwFourCC := 0;
pixelFormats[1].dwRGBBitCount := 16;
pixelFormats[1].dwRBitMask := $7C00;
pixelFormats[1].dwGBitMask := $03E0;
pixelFormats[1].dwBBitMask := $001F;

{ RGB 16 bits depth 5-6-5 }
pixelFormats[2].dwSize := SizeOf(DDPIXELFORMAT);
pixelFormats[2].dwFlags := DDPF_RGB;
pixelFormats[2].dwFourCC := 0;
pixelFormats[2].dwRgbBitCount := 16;
pixelFormats[2].dwRBitMask := $F800;
pixelFormats[2].dwGBitMask := $07E0;
pixelFormats[2].dwBBitMask := $001F;

{ RGB 32 bits depth }
pixelFormats[3].dwSize := SizeOf(DDPIXELFORMAT);
pixelFormats[3].dwFlags := DDPF_RGB;
pixelFormats[3].dwFourCC := 0;
pixelFormats[3].dwRGBBitCount := 32;
pixelFormats[3].dwRBitMask := $00FF0000;
pixelFormats[3].dwGBitMask := $0000FF00;
pixelFormats[3].dwBBitMask := $000000FF;

ddsdOverlay.ddpfPixelFormat := pixelFormats[0];

ddrval := g_lpdd.CreateSurface(ddsdOverlay, g_lpddsOverlay, nil);

if ddrval <> DD_OK then
begin
DebugLoc := $C;
DebugInfo := ddrval;
Exit;
end;

if (g_lpddsOverlay = nil) then
begin
DebugLoc := $D;
Exit;
end;

{ Create a clipper for our window }
ddrval := g_lpdd.CreateClipper(0, g_lpClipper, nil);
if ddrval <> DD_OK then
begin
DebugLoc := $E;
Exit;
end;

Result := True;
end;

{*******************************************************************
* WndProc ()
*
* Message handling routine for the main window
*******************************************************************}
function WndProc(ahWnd: HWND; amessage: UINT; awParam: WPARAM; alParam: LPARAM): LResult; stdcall;
var
wmId, wmEvent: Integer;
ps: PAINTSTRUCT;
MyDC: HDC;
ptClient: POINT;
rectBlt: RECT;
addbfx: DDBltFX;
begin
Result := 0;

case amessage of
WM_PAINT:
begin
{ Attach the clipper to the primary surface for this operation }

// ddrval := g_lpddsPrimary.SetClipper(g_lpClipper);

MyDC := BeginPaint(ahWnd, @ps);

{ Fill the client area with colour key }

ptClient.x := ps.rcPaint.left;
ptClient.y := ps.rcPaint.top;
ClientToScreen(GetDesktopWindow, @ptClient);
rectBlt.left := ptClient.x;
rectBlt.top := ptClient.y;

ptClient.x := ps.rcPaint.right;
ptClient.y := ps.rcPaint.bottom;
ClientToScreen(GetDesktopWindow, @ptClient);
rectBlt.right := ptClient.x;
rectBlt.bottom := ptClient.y;

addbfx.dwSize := sizeof(DDBLTFX);
addbfx.dwFillColor := 0;

g_lpddsPrimary.Blt(
@rectBlt, nil, @rectBlt, DDBLT_COLORFILL or DDBLT_WAIT, @addbfx);


{ Get the DC from the overlay surface }
{ MyDC := 0;
ddrval := g_lpddsOverlay.GetDC(MyDC);

if ddrval <> DD_OK then
begin
DebugInfo := ddrval;
ShowError;
Exit;
end;

Windows.Rectangle(MyDC, 0, 0, 200, 200);}

EndPaint(ahWnd, @ps);

// ddrval := g_lpddsPrimary.SetClipper(nil);
end;

WM_DESTROY:
PostQuitMessage(0);
else
Result := DefWindowProc(ahWnd, amessage, awParam, alParam);
end;
end;

{*******************************************************************
* CreateMainWindow ()
*
* Creates the main window
*******************************************************************}
procedure CreateMainWindow;
var
wcex: WNDCLASSEX;
ahwnd: HWND;
MainWindowClassName: PChar;
begin
MainWindowClassName := 'OVERLAYS';

FillChar(wcex, sizeof(wcex), #0);
wcex.cbSize := sizeof(WNDCLASSEX);

wcex.style := CS_HREDRAW or CS_VREDRAW;
wcex.lpfnWndProc := @WndProc;
wcex.cbClsExtra := 0;
wcex.cbWndExtra := 0;
wcex.hInstance := hInstance;
wcex.hCursor := LoadCursor(0, IDC_ARROW);
wcex.hbrBackground := (COLOR_WINDOW+1);
wcex.lpszClassName := MainWindowClassName;

RegisterClassEx(@wcex);

ahWnd := CreateWindow(MainWindowClassName, 'Overlays Example', WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 100, 100, 0, 0, hInstance, nil);

ShowWindow(ahWnd, SW_SHOWNORMAL);

UpdateWindow(ahWnd);
end;

{*******************************************************************
* WndProc ()
*
* Message handling routine for the main window
*******************************************************************}
procedure ShowError;
begin
Windows.MessageBox(0, PChar('Loc: ' + IntToHex(DebugLoc, 8) + ' Info: ' + IntToHex(DebugInfo, 8)), 'Titulo', MB_ICONEXCLAMATION + MB_OK);
end;

{*******************************************************************
* Main program block
*******************************************************************}
var
Msg: TMsg;
begin
if not InitOverlays() then ShowError;

CreateMainWindow();

while Windows.GetMessage(@Msg, 0, 0, 0) do
begin
Windows.TranslateMessage(@msg);
Windows.DispatchMessage(@msg);
end;
end.
.



Relevant Pages

  • Re: DirectDraw YUV display
    ... DirectShow does not use the same type of color key as Mosquito. ... uses Source Color Keys (which use colors in the overlay to determine overlay ... whereas the video renderer in DirectShow uses Destination ... The overlay surface must support the appropriate ...
    (microsoft.public.windowsce.platbuilder)
  • Re: Transparent Direct3D
    ... > I would like to have a windowed Direct3D app maximized to fit the entire ... > through where I don't render. ... - If it's OK to use DDraw, you can use DDraw7 overlay surfaces. ... substitutes data from the overlay surface for the corresponding pixel, ...
    (microsoft.public.win32.programmer.directx.graphics)
  • Re: directdraw - updateoverlay - how to overlay the same content on multiple windows ?
    ... i have to draw the same video image sequence on multiple windows ... I first tried with 1 overlay surface. ... // update overlay in window 1 ...
    (microsoft.public.win32.programmer.directx.graphics)
  • Re: How to capture screen with overlay surface?
    ... >> to capture the overlay screen on my PC. ... > A regular SnagIt 7.2 region or window capture gets the overlay surface on ... I've seen in some cases a movie player don't use overlay surface by ...
    (microsoft.public.win32.programmer.directx.video)
  • Re: 2D overlay on top of 3D
    ... I prefer you draw the GUI _after_ the 3D scene. ... draw the 2D overlay on top. ...
    (microsoft.public.win32.programmer.directx.graphics)