DirectDraw - IDirectDraw.CreateSurface%
Post by Michael Hutton on Dec 28th, 2009, 08:27am
I know this is tedious but could some kind soul take a glance at the code below and see why I can't get IDirectDraw.CreateSurface% to work?
Code:
MODE 8
DDSCL_NORMAL = &8
DDSD_CAPS = 1
DDSCAPS_PRIMARYSURFACE = &200
SYS "GetSystemMetrics", 0 TO xscreen%
SYS "GetSystemMetrics", 1 TO yscreen%
SYS "LoadLibrary", "DDRAW.DLL" TO ddraw%
IF ddraw%=0 THEN ERROR 100, "Direct Draw not available"
SYS "GetProcAddress", ddraw%, "DirectDrawCreateEx" TO `DirectDrawCreateEx`
DIM IID_IDirectDraw7{a%, b%, c%, d%}
IID_IDirectDraw7.a% = &15E65EC0
IID_IDirectDraw7.b% = &11D23B9C
IID_IDirectDraw7.c% = &60002FB9
IID_IDirectDraw7.d% = &5BEA9797
DIM IDirectDraw{QueryInterface%, AddRef%, Release%, Compact%, CreateClipper%, \
\ CreatePalette%, CreateSurface%, DuplicateSurface%, \
\ EnumDisplayModes%, EnumSurfaces%, FlipToGDISurface%, \
\ GetCaps%, GetDisplayMode%, GetFourCCCodes%, GetGDISurface%, \
\ GetMonitorFrequency%, GetScanLine%, GetVerticalBlankStatus%, \
\ Initialize%, RestoreDisplayMode%, SetCooperativeLevel%, \
\ SetDisplayMode%, WaitForVerticalBlank%}
SYS `DirectDrawCreateEx`, 0, ^IDirectDraw%, IID_IDirectDraw7{}, 0
!(^IDirectDraw{}+4) = !IDirectDraw%
ON CLOSE PROC0 : QUIT
ON ERROR PROC0 : SYS "MessageBox", @hwnd%, REPORT$, 0, 48 : QUIT
REM Establish how DirectDraw will cooperate with GDI
SYS IDirectDraw.SetCooperativeLevel%, IDirectDraw%, 0, DDSCL_NORMAL TO R%
IF R% THEN ERROR 100,"Cannot set Cooperative Level "+STR$~R%
DIM DDPIXELFORMAT{dwSize%, \
\ dwFlags%, \
\ dwFourCC%, \
\ dwRGBBitCount%, \ Union!
\ dwRBitMask%, \ Union!
\ dwGBitMask%, \ Union!
\ dwBBitMask%, \ Union!
\ dwRGBAlphaBitMask% } :REM Union!
DIM DDCAPS{dwSize%, \
\ dwCKeyCaps%, \
\ dwPalCaps%, \
\ dwBltCaps%, \
\ dwAlphaCaps%, \
\ dwOverlayCaps%, \
\ dwVidMemTotal%, \
\ dwVidMemFree%, \
\ dwVidMemStride%, \
\ dwMaxVisibleOverlays%, \
\ dwCurrVisibleOverlays%, \
\ dwNumFourCCCodes%, \
\ dwAlignBoundarySrc%, \
\ dwAlignSizeSrc%, \
\ dwAlignBoundaryDest%, \
\ dwAlignSizeDest%, \
\ dwRops%, \ Possible error?
\ dwMinOverlayStretch%, \
\ dwMaxOverlayStretch%, \
\ dwMiscCaps% }
DIM ddsd{ dwSize%, \
\ dwFlags%, \
\ dwHeight%, \
\ dwWidth%, \
\ lPitch%, \
\ lXPitch%, \
\ dwBackBufferCount%, \
\ dwRefreshRate%, \
\ lpSurface%, \
\ ddckCKDestOverlay{l%,h%}, \
\ ddckCKDestBlt{l%,h%}, \
\ ddckCKSrcOverlay{l%,h%}, \
\ ddckCKSrcBlt{l%,h%}, \
\ pixelformat{} = DDPIXELFORMAT{}, \ possible error?
\ dwCaps%, \
\ dwSurfaceSize% }
ddsd.dwSize% = DIM(ddsd{})
ddsd.dwFlags% = DDSD_CAPS
ddsd.dwCaps% = DDSCAPS_PRIMARYSURFACE
SYS IDirectDraw.CreateSurface%, IDirectDraw%, ddsd{}, ^spSurface%, 0 TO R%
IF R% THEN ERROR 100,"Cannot CreateSurface "+STR$~R%
PROC0
END
DEF PROC0
SYS IDirectDraw.Release%, IDirectDraw%
SYS "FreeLibrary", ddraw%
ENDPROC
I think the problem is related to my definition of the structures, but was wondering if anyone already has these definitions somewhere?
I am trying to translate http://www.codeproject.com/KB/mobile/CeScreenGrabber.aspx
"DirectDraw Screen Capture" - half way down the page.
Thank you,
Michael
Re: DirectDraw - IDirectDraw.CreateSurface%
Post by admin on Dec 28th, 2009, 09:39am
Quote:I know this is tedious but could some kind soul take a glance at the code below and see why I can't get IDirectDraw.CreateSurface% to work? |
|
The prototype for IDirectDraw7::CreateSurface is:
Code:HRESULT CreateSurface(
LPDDSURFACEDESC2 lpDDSurfaceDesc,
LPDIRECTDRAWSURFACE7 FAR *lplpDDSurface,
IUnknown FAR *pUnkOuter
);
Note in particular that the first parameter is a pointer to a DDSURFACEDESC2 structure. As far as I can see, you're passing a DDSURFACEDESC structure (Windows Mobile and Windows CE only) instead.
I assume you realise that the IDirectDraw interface is obsolete? It isn't supported in DirectX8 or later and is available only for backwards compatibility with DirectX7. Strictly speaking you shouldn't be using it in 'new' projects.
Richard.
Re: DirectDraw - IDirectDraw.CreateSurface%
Post by Michael Hutton on Dec 29th, 2009, 01:24am
Quote:Note in particular that the first parameter is a pointer to a DDSURFACEDESC2 structure. As far as I can see, you're passing a DDSURFACEDESC structure (Windows Mobile and Windows CE only) instead. |
|
Well, that would explain a bit..doh.
Quote:I assume you realise that the IDirectDraw interface is obsolete? It isn't supported in DirectX8 or later and is available only for backwards compatibility with DirectX7. Strictly speaking you shouldn't be using it in 'new' projects. |
|
Yes, I did realise but it was the only example I could find of capturing the Desktop. I was trying to get this to work and then was thinking of updating the code as and when I could. I am obviously intrested in speed... GetPixel is just way too slow..
I'll see where I get. Thanks for the reply.
Michael
Re: DirectDraw - IDirectDraw.CreateSurface%
Post by Michael Hutton on Dec 29th, 2009, 02:30am
I seem to have got it working...
Code:
MODE 8
DDSCL_NORMAL = &8
DDSD_CAPS = 1
DDSCAPS_PRIMARYSURFACE = &200
SYS "GetSystemMetrics", 0 TO xscreen%
SYS "GetSystemMetrics", 1 TO yscreen%
SYS "LoadLibrary", "DDRAW.DLL" TO ddraw%
IF ddraw%=0 THEN ERROR 100, "Direct Draw not available"
SYS "GetProcAddress", ddraw%, "DirectDrawCreateEx" TO `DirectDrawCreateEx`
DIM IID_IDirectDraw7{a%, b%, c%, d%}
IID_IDirectDraw7.a% = &15E65EC0
IID_IDirectDraw7.b% = &11D23B9C
IID_IDirectDraw7.c% = &60002FB9
IID_IDirectDraw7.d% = &5BEA9797
DIM IDirectDraw{QueryInterface%, AddRef%, Release%, Compact%, CreateClipper%, \
\ CreatePalette%, CreateSurface%, DuplicateSurface%, \
\ EnumDisplayModes%, EnumSurfaces%, FlipToGDISurface%, \
\ GetCaps%, GetDisplayMode%, GetFourCCCodes%, GetGDISurface%, \
\ GetMonitorFrequency%, GetScanLine%, GetVerticalBlankStatus%, \
\ Initialize%, RestoreDisplayMode%, SetCooperativeLevel%, \
\ SetDisplayMode%, WaitForVerticalBlank%}
SYS `DirectDrawCreateEx`, 0, ^IDirectDraw%, IID_IDirectDraw7{}, 0
!(^IDirectDraw{}+4) = !IDirectDraw%
REM Apparently should give a pointer to the Primary Surface...
REM PRINT IDirectDraw%
REM PRINT !(IDirectDraw%+4)
REM PRINT !(!(IDirectDraw%+4)+44)
ON CLOSE PROC0 : QUIT
ON ERROR PROC0 : SYS "MessageBox", @hwnd%, REPORT$, 0, 48 : QUIT
REM Establish how DirectDraw will cooperate with GDI
SYS IDirectDraw.SetCooperativeLevel%, IDirectDraw%, 0, DDSCL_NORMAL TO R%
IF R% THEN ERROR 100,"Cannot set Cooperative Level "+STR$~R%
DIM DDPIXELFORMAT{dwSize%, \
\ dwFlags%, \
\ dwFourCC%, \
\ dwRGBBitCount%, \ Union!
\ dwRBitMask%, \ Union!
\ dwGBitMask%, \ Union!
\ dwBBitMask%, \ Union!
\ dwRGBAlphaBitMask% } :REM Union!
DIM DDSCAPS2{ \
\ dwCaps%, \
\ dwCaps2%, \
\ dwCaps3%, \
\ dwCaps4% }
DIM DDCAPS{dwSize%, \
\ dwCKeyCaps%, \
\ dwPalCaps%, \
\ dwBltCaps%, \
\ dwAlphaCaps%, \
\ dwOverlayCaps%, \
\ dwVidMemTotal%, \
\ dwVidMemFree%, \
\ dwVidMemStride%, \
\ dwMaxVisibleOverlays%, \
\ dwCurrVisibleOverlays%, \
\ dwNumFourCCCodes%, \
\ dwAlignBoundarySrc%, \
\ dwAlignSizeSrc%, \
\ dwAlignBoundaryDest%, \
\ dwAlignSizeDest%, \
\ dwRops%, \
\ dwMinOverlayStretch%, \
\ dwMaxOverlayStretch%, \
\ dwMiscCaps% }
DIM ddsd{ \
\ dwSize%, \
\ dwFlags%, \
\ dwHeight%, \
\ dwWidth%, \
\ dwPitchOrLinearSize%, \
\ dwBackBufferCount%, \
\ dwMipMapCount%, \
\ dwAlphaBitDepth%, \
\ dwReserved%, \
\ lpSurface%, \
\ ddckCKDestOverlay{l%,h%}, \
\ ddckCKDestBlt{l%,h%}, \
\ ddckCKSrcOverlay{l%,h%}, \
\ ddckCKSrcBlt{l%,h%}, \
\ ddpfPixelFormat{} = DDPIXELFORMAT{}, \
\ ddsCaps{} = DDSCAPS2{}, \
\ dwTextureStage% }
ddsd.dwSize% = DIM(ddsd{})
ddsd.dwFlags% = DDSD_CAPS
ddsd.ddsCaps.dwCaps% = DDSCAPS_PRIMARYSURFACE
SYS IDirectDraw.CreateSurface%, IDirectDraw%, ddsd{}, ^spSurface%, 0 TO R%
IF R% THEN ERROR 100,"Cannot CreateSurface "+STR$~R%
PROC0
END
DEF PROC0
SYS IDirectDraw.Release%, IDirectDraw%
SYS "FreeLibrary", ddraw%
ENDPROC
I'll keep people posted (if they are interested!)
Re: DirectDraw - IDirectDraw.CreateSurface%
Post by admin on Dec 29th, 2009, 09:02am
Quote:Yes, I did realise but it was the only example I could find of capturing the Desktop.... GetPixel is just way too slow. |
|
What exactly are you trying to do? If you want to read pixels from the desktop quickly, why not simply BitBlt the entire desktop DC into a DIBSection? No need for anything complicated like DirectDraw or DirectX!
Richard.
Re: DirectDraw - IDirectDraw.CreateSurface%
Post by Michael Hutton on Jan 2nd, 2010, 03:25am
Quote:What exactly are you trying to do? If you want to read pixels from the desktop quickly, why not simply BitBlt the entire desktop DC into a DIBSection? No need for anything complicated like DirectDraw or DirectX! |
|
My aim was to capture the desktop, modify it, and then BitBlt it back, many frames a second. I will do some 'speed tests' on BitBlt. I have been away for the new year. I suppose I was slightly enamoured by the potential of directly accessing the primary surface (monitor) through DDRAW. I realise it is depreciated.
Michael
Re: DirectDraw - IDirectDraw.CreateSurface%
Post by admin on Jan 2nd, 2010, 09:46am
Quote:My aim was to capture the desktop, modify it, and then BitBlt it back, many frames a second. |
|
Write to the desktop DC? Can you even do that on Vista/Windows 7? I would have anticipated you would hit security restrictions in attempting that (unless running as an administrator) but I've not tried it.
Can't you achieve what you want by overlaying a transparent (layered) window on the desktop, and drawing to that? There have been several previous examples of doing that in BB4W.
Richard.
Re: DirectDraw - IDirectDraw.CreateSurface%
Post by Michael Hutton on Jan 4th, 2010, 02:47am
Quote:Write to the desktop DC? Can you even do that on Vista/Windows 7? |
|
Code:
MODE 8
SYS "GetSystemMetrics", 0 TO xscreen%
SYS "GetSystemMetrics", 1 TO yscreen%
SYS "CreateDC", "DISPLAY", 0, 0, 0 TO hdcScreen%
SYS "CreateCompatibleDC", hdcScreen% TO hdcCompatible%
SYS "CreateCompatibleBitmap", hdcScreen%, xscreen%, yscreen% TO hbitmap%
SYS "SelectObject", hdcCompatible%, hbitmap% TO oldbm%
REPEAT
SYS "BitBlt", hdcCompatible%, 0, 0, xscreen%, yscreen%, hdcScreen%, 0, 0, &CC0020 TO R%
IF R% = 0 THEN ERROR 100, "Failed to BitBlt"
CIRCLE FILL RND(1280), RND(1024), RND(100)
SYS "BitBlt", hdcScreen%, 0,0, 640, 512, @memhdc%, 0, 0, &CC0020 TO R%
IF R% = 0 THEN ERROR 100, "Failed to BitBlt"
UNTIL FALSE
(Obviously - no cleanup code)
Works on my Vista Ultimate x64 edition. Which did rather surprise me, and you can draw to the desktop DC with SYS "LineTo" @desktopDC%, X%, Y%. So access seems pretty free. I am interested to see if DirectX/DDRAW provides a faster way of interacting with it.
Michael
Re: DirectDraw - IDirectDraw.CreateSurface%
Post by Michael Hutton on Jul 28th, 2015, 7:41pm
Oh! ...and this also works with Windows 8 (v6).
Forgot about this.
Michael