Embedding Window Media Player in mfc - c++

I am embedding a window media player activex control in a dialog based mfc application. Now all play/pause button is getting disabled. I want to enable them.
As I have put put_uiMode(_T("mini"));
and when writingthese lines
hr = m_spWMPPlayer->put_fullScreen(VARIANT_TRUE)
hr = m_spWMPPlayer->get_fullScreen(&b); // returned b = VARIANT_FALSE
value of b is coming FALSE.
What could be the error? Any one knows this?
Thank You
BOOL CLuminPlayerDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
CComPtr<IWMPPlayer> m_spWMPPlayer;
CComPtr<IWMPRemoteMediaServices> m_spServices;
CComPtr<IWMPControls> m_spControls;
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
HRESULT hr = NULL;
if(SUCCEEDED(hr))
{
hr = CoCreateInstance(__uuidof(WindowsMediaPlayer), 0, CLSCTX_INPROC_SERVER, IID_IOleObject, (void**)&m_spServices);
if(SUCCEEDED(hr))
{
BSTR str = NULL;
VARIANT_BOOL b ;
hr = m_spServices->QueryInterface(__uuidof(IWMPPlayer), (void**)&m_spWMPPlayer);
if(SUCCEEDED(hr))
{
hr = m_spWMPPlayer->get_enabled(&b); // returned b= VARIANT_TRUE
hr = m_spWMPPlayer->get_enableContextMenu(&b); //returned b = VARIANT_TRUE
hr = m_spWMPPlayer->get_uiMode(&str); // returned str = L"full"
hr = m_spWMPPlayer->put_uiMode(_T("mini")); //hr = S_OK
hr = m_spWMPPlayer->get_uiMode(&str); // str = L"mini"
hr = m_spWMPPlayer->put_fullScreen(VARIANT_TRUE);
hr = m_spWMPPlayer->get_fullScreen(&b); // returned b = VARIANT_FALSE
hr = m_spWMPPlayer->put_URL(_T("C:\\Visual Studio 2012\\Projects\\Lumin-Player\\Debug\\abc.mp4")); //returned hr = S_OK
hr = m_spServices->QueryInterface(__uuidof(IWMPControls), (void**)&m_spControls); // returned hr = S_OK
if(SUCCEEDED(hr))
{
hr = m_spControls->play(); //returned hr = S_OK
}
}
}
}
return TRUE; // return TRUE unless you set the focus to a control
}

MSDN says:
For full-screen mode to work properly when embedding the Windows Media Player control, the video display area must have a height and width of at least one pixel. If the BSTR specified in IWMPPlayer::put_uiMode is set to "mini" or "full", the height of the control itself must be 65 pixels or greater to accommodate the video display area in addition to the user interface.
This assumes that the player is already properly initialized as ActiveX control. In your code, you simply create a COM object without doing any ActiveX Control initialization. Presumably the player detects this and reports error.
Your hr in respective put_fullScreen call should have 0xC00D0FD2 NS_E_WMPOCX_NO_ACTIVE_CORE "The requested method or property is not available because the Windows Media Player ActiveX control has not been properly activated." to indicate the problem.

Related

C++ - Open Control Panel item in the same window

I have a Windows-based application. I'm trying to open a Control Panel item the following way:
EnumWindows(EnumWindowsProcMy, ppid);
IOpenControlPanel *pPanel = NULL;
CoInitialize(nullptr);
HRESULT hr = CoCreateInstance(CLSID_OpenControlPanel, NULL,
CLSCTX_INPROC_SERVER, IID_IOpenControlPanel,
(void**)&pPanel);
if (FAILED(hr)) {
return -1;
}
pPanel->Open(CUSTOM_GUID, NULL, NULL);
This however opens the Control Panel Item in a new Window. Is there any way to navigate to the Control Panel item in an already Open Window? I have the Handle to the Window.
If you already have a running instance of control panel you can do somewhat like.
Retrieves a pointer to a running object that has been registered.
Sample code
IUnknown *puk = NULL;
HRESULT hr = GetActiveObject(CLSID_OpenControlPanel, 0, &puk);
return (hr == S_OK);

Can not reuse brush to draw both text and rectangle

INTRODUCTION AND RELEVANT INFORMATION:
I am trying to learn to print with XPS Document API.
For a simple start, I have decided to draw a rectangle, and some text below it.
After going through the official examples I was able to achieve my goal.
PROBLEM:
Basically, I have concatenated 2 code examples provided from the above link. Now I wanted to polish the code, mainly to use single brush to draw both rectangle and the text.
After rewriting the code, I get the following error:
First-chance exception at 0x7555D3CF in XPS printing.exe: Microsoft C++ exception: SplException::THResultException at memory location 0x002CEF9C.
If there is a handler for this exception, the program may be safely continued.
SSCCEE:
Below is the function I rewrote. I have marked the crashing point with the appropriate comments.
void XPS_TEST()
{
IXpsOMObjectFactory *xpsFactory;
HRESULT hr = S_OK;
// Init COM for this thread if it hasn't
// been initialized, yet.
hr = CoInitializeEx(0, COINIT_MULTITHREADED);
hr = CoCreateInstance(
__uuidof(XpsOMObjectFactory),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IXpsOMObjectFactory),
reinterpret_cast<LPVOID*>(&xpsFactory));
if (SUCCEEDED(hr))
{
// Declare the variables used in this section.
IOpcPartUri *opcPartUri = NULL;
IXpsOMPackage *xpsPackage = NULL;
IXpsOMDocumentSequence *xpsFDS = NULL;
IXpsOMDocumentCollection *fixedDocuments = NULL;
IXpsOMDocument *xpsFD = NULL;
IXpsOMPage *xpsPage = NULL;
IXpsOMPageReferenceCollection *pageRefs = NULL;
IXpsOMPageReference *xpsPageRef = NULL;
// test size of the document
XPS_SIZE pageSize = { 200, 200 };
// Create the package.
hr = xpsFactory->CreatePackage(&xpsPackage);
// Create the URI for the fixed document sequence part and then
// create the fixed document sequence
hr = xpsFactory->CreatePartUri(
L"/FixedDocumentSequence.fdseq", &opcPartUri);
hr = xpsFactory->CreateDocumentSequence(opcPartUri, &xpsFDS);
// Release this URI to reuse the interface pointer.
if (NULL != opcPartUri) { opcPartUri->Release(); opcPartUri = NULL; }
// Create the URI for the document part and then create the document.
hr = xpsFactory->CreatePartUri(
L"/Documents/1/FixedDocument.fdoc", &opcPartUri);
hr = xpsFactory->CreateDocument(opcPartUri, &xpsFD);
// Release this URI to reuse the interface pointer.
if (NULL != opcPartUri) { opcPartUri->Release(); opcPartUri = NULL; }
// Create a blank page.
hr = xpsFactory->CreatePartUri(
L"/Documents/1/Pages/1.fpage", &opcPartUri);
hr = xpsFactory->CreatePage(
&pageSize, // Page size
L"en-US", // Page language
opcPartUri, // Page part name
&xpsPage);
// Release this URI to reuse the interface pointer.
if (NULL != opcPartUri) { opcPartUri->Release(); opcPartUri = NULL; }
// Create a page reference for the page.
hr = xpsFactory->CreatePageReference(&pageSize, &xpsPageRef);
// Add the fixed document sequence to the package.
hr = xpsPackage->SetDocumentSequence(xpsFDS);
// Get the document collection of the fixed document sequence
// and then add the document to the collection.
hr = xpsFDS->GetDocuments(&fixedDocuments);
hr = fixedDocuments->Append(xpsFD);
// Get the page reference collection from the document
// and add the page reference and blank page.
hr = xpsFD->GetPageReferences(&pageRefs);
hr = pageRefs->Append(xpsPageRef);
hr = xpsPageRef->SetPage(xpsPage);
//======================== draw rectangle ====================//
XPS_COLOR xpsColor;
IXpsOMSolidColorBrush *xpsFillBrush = NULL;
// the brush I want to reuse !!
IXpsOMSolidColorBrush *xpsStrokeBrush = NULL;
// Set the fill brush color to RED.
xpsColor.colorType = XPS_COLOR_TYPE_SRGB;
xpsColor.value.sRGB.alpha = 0xFF;
xpsColor.value.sRGB.red = 0xFF;
xpsColor.value.sRGB.green = 0x00;
xpsColor.value.sRGB.blue = 0x00;
// Use the object factory to create the brush.
hr = xpsFactory->CreateSolidColorBrush(
&xpsColor,
NULL, // color profile resource
&xpsFillBrush);
// The color profile resource parameter is NULL because
// this color type does not use a color profile resource.
// Set the stroke brush color to BLACK.
xpsColor.colorType = XPS_COLOR_TYPE_SRGB;
xpsColor.value.sRGB.alpha = 0xFF;
xpsColor.value.sRGB.red = 0x00;
xpsColor.value.sRGB.green = 0x00;
xpsColor.value.sRGB.blue = 0x00;
// Use the object factory to create the brush.
hr = xpsFactory->CreateSolidColorBrush(
&xpsColor,
NULL, // This color type does not use a color profile resource.
&xpsStrokeBrush);
// test rectangle
XPS_RECT rect = { 0, 0, 200, 20 };
IXpsOMGeometryFigure *rectFigure;
IXpsOMGeometry *imageRectGeometry;
IXpsOMGeometryFigureCollection *geomFigureCollection;
// Define the start point and create an empty figure.
XPS_POINT origin = { rect.x, rect.y };
hr = xpsFactory->CreateGeometryFigure(&origin, &rectFigure);
// Define the segments of the geometry figure.
// First, define the type of each segment.
XPS_SEGMENT_TYPE segmentTypes[3] =
{
XPS_SEGMENT_TYPE_LINE, // each segment is a straight line
XPS_SEGMENT_TYPE_LINE,
XPS_SEGMENT_TYPE_LINE
};
// Define the x and y coordinates of each corner of the figure
// the start point has already been defined so only the
// remaining three corners need to be defined.
FLOAT segmentData[6] =
{
rect.x, (rect.y + rect.height),
(rect.x + rect.width), (rect.y + rect.height),
(rect.x + rect.width), rect.y
};
// Describe if the segments are stroked (that is if the segment lines
// should be drawn as a line).
BOOL segmentStrokes[3] =
{
TRUE, TRUE, TRUE // Yes, draw each of the segment lines.
};
// Add the segment data to the figure.
hr = rectFigure->SetSegments(
3,
6,
segmentTypes,
segmentData,
segmentStrokes);
// Set the closed and filled properties of the figure.
hr = rectFigure->SetIsClosed(TRUE);
hr = rectFigure->SetIsFilled(TRUE);
// Create the geometry object.
hr = xpsFactory->CreateGeometry(&imageRectGeometry);
// Get a pointer to the figure collection interface of the geometry...
hr = imageRectGeometry->GetFigures(&geomFigureCollection);
// ...and then add the figure created above to this geometry.
hr = geomFigureCollection->Append(rectFigure);
// If not needed for anything else, release the rectangle figure.
rectFigure->Release();
// when done adding figures, release the figure collection.
geomFigureCollection->Release();
IXpsOMPath *rectPath = NULL;
IXpsOMVisualCollection *pageVisuals = NULL;
// Create the new path object.
hr = xpsFactory->CreatePath(&rectPath);
// Add the geometry to the path.
// imageRectGeometry is initialized outside of this example.
hr = rectPath->SetGeometryLocal(imageRectGeometry);
// Set the short description of the path to provide
// a textual description of the object for accessibility.
hr = rectPath->SetAccessibilityShortDescription(L"Red Rectangle");
// Set the fill and stroke brushes to use the brushes
// created in the first section.
hr = rectPath->SetFillBrushLocal(xpsFillBrush);
hr = rectPath->SetStrokeBrushLocal(xpsStrokeBrush);
// Get the visual collection of this page and add this path to it.
hr = xpsPage->GetVisuals(&pageVisuals);
hr = pageVisuals->Append(rectPath);
// If not needed for anything else, release the rectangle path.
rectPath->Release();
// When finished with the brushes, release the interface pointers.
if (NULL != xpsFillBrush) xpsFillBrush->Release();
//******************** I have commented out below code, ****************//
//******************** because I plan to use the brush to draw text ****//
//if (NULL != xpsStrokeBrush) xpsStrokeBrush->Release();
// When done with the geometry interface, release it.
imageRectGeometry->Release();
//========================= draw text =====================//
GUID fontNameGuid;
WCHAR guidString[128] = { 0 };
WCHAR uriString[256] = { 0 };
IStream *fontStream = NULL;
IOpcPartUri *fontUri = NULL;
IXpsOMFontResource *fontResource = NULL;
// Create font stream.
hr = xpsFactory->CreateReadOnlyStreamOnFile(
// I have hardcoded Arial here, just for testing
L"C:\\Windows\\Fonts\\Arial.ttf",
&fontStream);
// Create new obfuscated part name for this resource using a GUID.
hr = CoCreateGuid(&fontNameGuid);
hr = StringFromGUID2(
fontNameGuid,
guidString,
ARRAYSIZE(guidString));
// Create a URI string for this font resource that will place
// the font part in the /Resources/Fonts folder of the package.
wcscpy_s(uriString, ARRAYSIZE(uriString), L"/Resources/Fonts/");
// Create the part name using the GUID string as the name and
// ".odttf" as the extension GUID string start and ends with
// curly braces so they are removed.
wcsncat_s(uriString, ARRAYSIZE(uriString),
guidString + 1, wcslen(guidString) - 2);
wcscat_s(uriString, ARRAYSIZE(uriString), L".odttf");
// Create the font URI interface.
hr = xpsFactory->CreatePartUri(
uriString,
&fontUri);
// Create the font resource.
hr = xpsFactory->CreateFontResource(
fontStream,
XPS_FONT_EMBEDDING_OBFUSCATED,
fontUri,
FALSE, // isObfSourceStream
&fontResource);
if (NULL != fontUri) fontUri->Release();
LPCWSTR unicodeString = L"Test string";
// move test string below our rectangle
origin.y += 30.0f;
FLOAT fontEmSize = 7.56f;
IXpsOMGlyphsEditor *glyphsEditor = NULL;
IXpsOMGlyphs *xpsGlyphs = NULL;
// Create a new Glyphs object and set its properties.
hr = xpsFactory->CreateGlyphs(fontResource, &xpsGlyphs);
hr = xpsGlyphs->SetOrigin(&origin);
hr = xpsGlyphs->SetFontRenderingEmSize(fontEmSize);
//*************** I GET A CRASH BELOW !!!! ***************//
hr = xpsGlyphs->SetFillBrushLocal(xpsStrokeBrush); // <<---
// Some properties are inter-dependent so they
// must be changed by using a GlyphsEditor.
hr = xpsGlyphs->GetGlyphsEditor(&glyphsEditor);
hr = glyphsEditor->SetUnicodeString(unicodeString);
hr = glyphsEditor->ApplyEdits();
// Add the new Glyphs object to the page
hr = pageVisuals->Append(xpsGlyphs);
// Release interface pointers.
if (NULL != xpsGlyphs) xpsGlyphs->Release();
if (NULL != glyphsEditor) glyphsEditor->Release();
if (NULL != pageVisuals) pageVisuals->Release();
//******************** Releasing the brush here *******//
if (NULL != xpsStrokeBrush) xpsStrokeBrush->Release();
//========================= write to file ====================//
hr = xpsPackage->WriteToFile(
L"C:\\Users\\Smiljkovic\\Desktop\\xpsTest.xps",
NULL, // LPSECURITY_ATTRIBUTES
FILE_ATTRIBUTE_NORMAL,
FALSE); // Optimize Markup Size
//========================== cleanup ==================//
// Release interface pointer
if (NULL != xpsPage) xpsPage->Release();
if (NULL != pageRefs) pageRefs->Release();
if (NULL != fixedDocuments) fixedDocuments->Release();
if (NULL != xpsPageRef) xpsPageRef->Release();
if (NULL != xpsFD) xpsFD->Release();
if (NULL != xpsFDS) xpsFDS->Release();
if (NULL != xpsPackage) xpsPackage->Release();
xpsFactory->Release();
}
// Uninitialize COM when finished
CoUninitialize();
}
QUESTION:
How can I use the same brush ( xpsStrokeBrush from the above example ) for drawing both the text and the rectangle outline?
per SetStrokeBrushLocal documentation:
After you call SetStrokeBrushLocal, the stroke brush lookup key is released and GetStrokeBrushLookup returns a NULL pointer in the lookup parameter.
You could use Clone on the brush before using it.
But, if you plan on re-using brushes, then use the CreateDictionary, SetDictionaryLocal and then Append your brush there; which will let you use SetFillBrushLookup.

Problems using IFileDialog on Windows 7

I'm facing some weird (at least for me) behavior on using the Common Item Dialogs in my MFC Windows application running on Windows 7 or Vista.
According to the MSDN http://msdn.microsoft.com/en-us/library/windows/desktop/bb776913(v=vs.85).aspx I'm using the new interfaces to display file open and save dialogs:
bool OpenFileDialog(CString& strFile, CString strTitle, CStringArray& astrFilter, CStringArray& astrFilterExtension, ULONG nFlags, HWND hParentWnd)
{
USES_CONVERSION;
INT_PTR nResult = 0;
INT_PTR nFilterCount = astrFilter.GetCount();
IFileDialog* pfod = 0;
HRESULT hr = ::CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfod));
if(SUCCEEDED(hr))
{
// New dialog starting with Vista/Windows 7
COMDLG_FILTERSPEC* pOpenTypes = 0;
if((nFilterCount > 0) && (nFilterCount == astrFilterExtension.GetCount()))
{
pOpenTypes = new COMDLG_FILTERSPEC[nFilterCount];
for(int nIdx = 0; nIdx < nFilterCount; nIdx++)
{
pOpenTypes[nIdx].pszName = astrFilter[nIdx].GetBuffer();
pOpenTypes[nIdx].pszSpec = astrFilterExtension[nIdx].GetBuffer();
}
}
// Set the file types to display.
if(pOpenTypes)
{
hr = pfod->SetFileTypes(nFilterCount, pOpenTypes);
if(SUCCEEDED(hr))
hr = pfod->SetFileTypeIndex(0);
}
if(!strFile.IsEmpty())
pfod->SetFileName(strFile);
if(!strTitle.IsEmpty())
pfod->SetTitle(strTitle);
if(SUCCEEDED(hr))
{
// Ensure the dialog only returns file system paths.
DWORD dwFlags;
hr = pfod->GetOptions(&dwFlags);
if(SUCCEEDED(hr))
{
dwFlags |= FOS_FORCEFILESYSTEM;
if(nFlags & OFN_FILEMUSTEXIST)
dwFlags |= FOS_FILEMUSTEXIST;
if(nFlags & OFN_PATHMUSTEXIST)
dwFlags |= FOS_PATHMUSTEXIST;
hr = pfod->SetOptions(dwFlags);
if(SUCCEEDED(hr))
{
// Create an event handling object, and hook it up to the dialog.
IFileDialogEvents* pfde = NULL;
DWORD dwCookie;
// Actually only added for debugging purposes
/*hr = CDialogEventHandler_CreateInstance(IID_PPV_ARGS(&pfde));
if(SUCCEEDED(hr))
{
// Hook up the event handler.
hr = pfod->Advise(pfde, &dwCookie);
if(!SUCCEEDED(hr))
{
pfde->Release();
pfde = 0;
}
}*/
// Now show the dialog. Usually called with hParent == 0
if(hParentWnd)
hr = pfod->Show(::GetWindow(hParentWnd, GW_OWNER));
else
hr = pfod->Show(0);
// do something with the path when the dialog was closed...
So the dialog appears and works fine if I want to select a file from a normal drive. I can navigate through the folders and select any file I want. On leaving the dialog I also get the correct file information.
But it doesn't work for one of the Libraries in the navigation pane on the left side. Whenever I try to select a Library like Documents, Videos or Pictures the dialog doesn't update the right pane which shows the folder/library content.
What I noticed is that on clicking a Library in the file open/save dialog the OnFolderChanging() event of the IFileDialogEvents interface is fired but the OnFolderChange() and OnSelectionChange() are not. Those events are fired if I click and navigate on a "normal" drive like C.
I also tried to call the dialogs early in my InitInstance method to avoid possible side-effects with my other code but this didn't help either.
Is there someone who had the same behavior and was able to resolve this?
Thanks a lot!
So I finally found the answer to this issue. Creating the new MFC project for the application was the actual hint to solve this. The reason was that the "Stack reserve size" was too big. The settings in the old VS6.0 project had the stack size increased to more than 100MB. Apparently the IFileDialog based dialogs do not work properly when the reserved stack size is simply too large (other thing might don't work also as expected). So I had to set it back to 15MB in my case.

IMovieControl::Run fails on Windows XP?

Actually, it only fails the second time it's called. I'm using a windowless control to play video content, where the video being played could change while the control is still on screen. Once the graph is built the first time, we switch media by stopping playback, replacing the SOURCE filter, and running the graph again. This works fine under Vista, but when running on XP, the second call to Run() returns E_UNEXPECTED.
The initialization goes something like this:
// Get the interface for DirectShow's GraphBuilder
mGB.CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER);
// Create the Video Mixing Renderer and add it to the graph
ATL::CComPtr<IBaseFilter> pVmr;
pVmr.CoCreateInstance(CLSID_VideoMixingRenderer9, NULL, CLSCTX_INPROC);
mGB->AddFilter(pVmr, L"Video Mixing Renderer 9");
// Set the rendering mode and number of streams
ATL::CComPtr<IVMRFilterConfig9> pConfig;
pVmr->QueryInterface(IID_IVMRFilterConfig9, (void**)&pConfig);
pConfig->SetRenderingMode(VMR9Mode_Windowless);
pVmr->QueryInterface(IID_IVMRWindowlessControl9, (void**)&mWC);
And here's what we do when we decide to play a movie. RenderFileToVideoRenderer is borrowed from dshowutil.h in the DirectShow samples area.
// Release the source filter, if it exists, so we can replace it.
IBaseFilter *pSource = NULL;
if (SUCCEEDED(mpGB->FindFilterByName(L"SOURCE", &pSource)) && pSource)
{
mpGB->RemoveFilter(pSource);
pSource->Release();
pSource = NULL;
}
// Render the file.
hr = RenderFileToVideoRenderer(mpGB, mPlayPath.c_str(), FALSE);
// QueryInterface for DirectShow interfaces
hr = mpGB->QueryInterface(&mMC);
hr = mpGB->QueryInterface(&mME);
hr = mpGB->QueryInterface(&mMS);
// Read the default video size
hr = mpWC->GetNativeVideoSize(&lWidth, &lHeight, NULL, NULL);
if (hr != E_NOINTERFACE)
{
if (FAILED(hr))
{
return hr;
}
// Play video at native resolution, anchored at top-left corner.
RECT r;
r.left = 0;
r.top = 0;
r.right = lWidth;
r.bottom = lHeight;
hr = mpWC->SetVideoPosition(NULL, &r);
}
// Run the graph to play the media file
if (mMC)
{
hr = mMC->Run();
if (FAILED(hr))
{
// We get here the second time this code is executed.
return hr;
}
mState = Running;
}
if (mME)
{
mME->SetNotifyWindow((OAHWND)m_hWnd, WM_GRAPHNOTIFY, 0);
}
Anybody know what's going on here?
Try calling IMediaControl::StopWhenReady before removing the source filter.
When are you calling QueryInterface directly? you can use CComQIPtr<> to warp the QI for you. This way you won't have to call Release as it will be called automatically.
The syntax look like this: CComPtr<IMediaControl> mediaControl = pGraph;
In FindFilterByName() instead of passing live pointer pass a CComPtr, again so you won't have to call release explicitly.
Never got a resolution on this. The production solution was to just call IGraphBuilder::Release and rebuild the entire graph from scratch. There's a CPU spike and a slight redraw delay when switching videos, but it's less pronounced than we'd feared.

DirectDraw question - running the application as a regular Windows application

I am developing an application for video recording and I want to overlay the video preview with a logo and recording timer.
I tried to run the full-screen application and everything worked fine. Then I tried to run the application as a regular Windows application and it returned an error.
Could anyone take a look at the code below if there's a way to modify it to run the application as a regular Windows app?
HRESULT CViewfinderRenderer::OnStartStreaming()
{
HRESULT hr = S_OK;
DDSURFACEDESC ddsd;
m_pDD = NULL;
//full screen settings
hr = DirectDrawCreate(NULL, &m_pDD, NULL);
hr = m_pDD->SetCooperativeLevel(m_hWnd, DDSCL_FULLSCREEN);
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE;
ddsd.dwBackBufferCount = 1;
//end full screen settings
//normal settings
/*hr = DirectDrawCreate(NULL, &m_pDD, NULL);
hr = m_pDD->SetCooperativeLevel(m_hWnd, DDSCL_NORMAL);
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_BACKBUFFERCOUNT;
ddsd.dwBackBufferCount = 1;*/
//end normal settings
hr = m_pDD->CreateSurface(&ddsd, &m_pSurface, NULL);
if (hr != DD_OK) {
return hr;
}
// Get backsurface
hr = m_pSurface->EnumAttachedSurfaces(&m_pBackSurface, EnumFunction);
return S_OK;
}
Even when running windowed, you need to create a primary surface, only it is not a flippable surface.
//full screen settings
hr = DirectDrawCreate(NULL, &m_pDD, NULL);
hr = m_pDD->SetCooperativeLevel(m_hWnd, DDSCL_NORMAL);
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
Besides of creating a surface, most likely you will want to create a clipper for the window. For a complete sample see paragraph Running windowed in this GameDev article.
What error did it return?
Also try this instead:
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;