How to reposition/resize the resource on the screen? - c++

I want to embed the native camera application into custom form.
The RECT r properties where I want to embed the camera are the following:
r.top = 26;
r.bottom = 220;
r.left = 0;
r.right = 320;
and this is the method which runs the native camera application:
HRESULT CPhotoCapture::CameraCapture(HWND hwndOwner, LPTSTR pszFilename)
{
HRESULT hResult;
SHCAMERACAPTURE shcc;
//Set the SHCAMERACAPTURE structure
ZeroMemory(&shcc, sizeof(shcc));
shcc.cbSize = sizeof(shcc);
shcc.hwndOwner = hwndOwner;
shcc.pszInitialDir = _T("\\My Documents");
shcc.pszDefaultFileName = _T("test.jpg");
shcc.pszTitle = _T("Camera Demo");
shcc.StillQuality = CAMERACAPTURE_STILLQUALITY_HIGH;
shcc.VideoTypes = CAMERACAPTURE_VIDEOTYPE_MESSAGING;
shcc.nResolutionWidth = 1024;
shcc.nResolutionHeight = 768;
shcc.nVideoTimeLimit = 15;
shcc.Mode = CAMERACAPTURE_MODE_STILL;
//display the camera capture dialog
hResult = SHCameraCapture(&shcc);
if(hResult == S_OK)
{
//TODO:: Write to log
}
return hResult;
}
The method above is called from the window which dimensions are equal to r:
HRESULT hr = S_OK;
hr = m_PhotoCapture.CameraCapture(this->m_hWnd, L"test");
Does anyone know how to modify the above function (hwndOwner) the way to display the embedded resource in the rectangle r?

I think you need to put a picture box (sized to your desired dimensions) on your custom form, and then pass the windows handle of the picture box instead of the handle of the form itself.

You're not too clear on what hwndOwner points to. My **guess* on how this probably works is that you need to create a Window that is a child of your main display Window whose location matches your rect (and is visible), then pass it's handle in and that the capture API then uses DShow to pipe the output of the frame grabs from the camera to that Window that the handle represents.

Related

Creating Swap Chain causes Window Handle to become Invalid

I'm trying to work with both Direct2D and Direct3D. Right now, I'm having Direct2D draw content to a separate Device Context (with an HDC) and then copy the contents of that Device Context into my window. I could show the code I use to set that up in an edit to this post if requested, but before Direct3D gets involved, that part works.
Here is a simplified version of the Window Drawing code I use.
if (d3dEngine.Get()) // Object used to hold Direct3D Resources (.Get() returns a pointer for a null check)
{
// d3dEngine->PrepareScene(D2D1::ColorF(D2D1::ColorF::Wheat));
}
// Drawing Board holds the Direct 2D Render Target
drawingBoard->GetRenderer()->BeginDraw();
drawingBoard->GetRenderer()->Clear(D2D1::ColorF(1.0f,1.0f,1.0f,1.0f));
mainPage->Draw(); // Main Page Holds various objects that draw to Direct2D
if (d3dEngine.Get())
d3dEngine->FinalizeScene();
drawingBoard->GetRenderer()->EndDraw();
// Get the Secondary Device Context that Direct2D draws to
HDC dc = drawingBoard->GetDc();
RECT r{ 0,0,0,0 };
int err = 0;
// Retrieve the Rectangle for the window (currentWindow is the window handle used)
if(!GetClientRect(currentWindow, &r))
err = GetLastError();
// Use the BitBlt function to copy Direct2D content into a window
if (!BitBlt(GetDC(currentWindow), r.left, r.top, r.right - r.left, r.bottom - r.top, dc, 0, 0, SRCCOPY))
err = GetLastError();
Before any Direct3D resources are created (and the d3dEngine.Get() call returns null), this code runs to my satisfaction.
However, following the creation of Direct3D resources, the code fails:
RECT r{ 0,0,0,0 };
int err = 0;
// Retrieve the Rectangle for the window (currentWindow is the window handle used)
if(!GetClientRect(currentWindow, &r))
err = GetLastError();
The window handle currentWindow becomes invalid as GetLastError() returns 1400 after the call to GetClientRect. I suspect that the Swap Chain in Direct3D 11 may play a role due to the following code used to activate Direct3D.
GetClientRect(window, &Location);
unsigned int width = Location.right - Location.left,
height = Location.bottom - Location.top;
D3D_DRIVER_TYPE dTypes[] =
{
D3D_DRIVER_TYPE_HARDWARE//, D3D_DRIVER_TYPE_WARP
};
int tTypes = ARRAYSIZE(dTypes);
D3D_FEATURE_LEVEL dLevels[] =
{
D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0
};
int tLevels = ARRAYSIZE(dLevels);
DXGI_SWAP_CHAIN_DESC swapChainDescription;
// Initialize the swap cahin
swapChainDescription.BufferCount = 2;
swapChainDescription.BufferDesc.Width = Location.right - Location.left;
swapChainDescription.BufferDesc.Height = Location.bottom - Location.top;
swapChainDescription.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
swapChainDescription.BufferDesc.RefreshRate.Numerator = 30;
swapChainDescription.BufferDesc.RefreshRate.Denominator = 1;
swapChainDescription.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDescription.OutputWindow = window;
swapChainDescription.Windowed = true;
swapChainDescription.SampleDesc.Count = 1;
swapChainDescription.SampleDesc.Quality = 0;
swapChainDescription.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
swapChainDescription.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
swapChainDescription.Flags = DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE;
swapChainDescription.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;// DXGI_SWAP_EFFECT_DISCARD;
unsigned int flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
/// Other initialization Code
HRESULT results = 0;
// Initialize ID3D11Device "graphicsDevice"
IDXGISwapChain* sc = nullptr;
results = dxFact->CreateSwapChain(graphicsDevice, &swapChainDescription, &sc);
This code is in a different class than the Window drawing code towards the beginning.
The window variable in the Direct3D code holds the same value that currentWindow holds in the Window Code.
Is there anyone who could provide insight as to what is going on and why the window handle stops working? And perhaps suggest a workaround?
While I'm still unsure why the window handle seemed to be useless when I checked, I was able to develop a workaround.
Basically, I have my Window class hold a RECT indicating the size of the Window and I use that instead of getting the RECT from the Window every time.
RECT r{ 0,0,0,0 };
int err = 0;
// Retrieve the Rectangle for the window (currentWindow is the window handle used)
if(!GetClientRect(currentWindow, &r))
err = GetLastError();
// Use the BitBlt function to copy Direct2D content into a window
if (!BitBlt(GetDC(currentWindow), r.left, r.top, r.right - r.left, r.bottom - r.top, dc, 0, 0, SRCCOPY))
err = GetLastError();
// Now, it uses a 'size' attribute
int err = 0;
if (!BitBlt(GetTWindowDc(), size.left, size.top, size.right - size.left, size.bottom - size.top, dc, 0, 0, SRCCOPY))
err = GetLastError();
When it comes to getting the Window Device Context, the new GetTWindowDc() method takes care of that:
if (d3dEngine.Get())
return d3dEngine->GetDC();
return GetDC(currentWindow);
Basically, if Direct3D is activated, the 3D manager object (which holds a DXGISurface) retrieves the HDC from Direct3D to use.
HDC TWindowEngine::GetDC()
{
if (!surface.Get()) // My Unique Smart pointer to a DXGISurface1 object
return 0;
HDC dc;
assert(SUCCEEDED(surface->GetDC(FALSE, &dc)));
return dc;
}
According to Surface-GetDc Documentation, you need to call the corresponding ReleaseDc on the DXGISurface1 object. So this is how I do it.
In the Window Draw code:
if (!BitBlt(GetTWindowDc(), size.left, size.top, size.right - size.left, size.bottom - size.top, dc, 0, 0, SRCCOPY))
err = GetLastError();
FlushDc();
Here is the FlushDc method:
void TWindow::FlushDc()
{
if (d3dEngine.Get())
d3dEngine->ClearDC();
}
And the ClearDC method is impelented.
void TWindowEngine::ClearDC()
{
if (surface.Get())
surface->ReleaseDC(nullptr);
}

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.

Embedding Window Media Player in mfc

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.

how to attach scrollbar to a dialog

I have to find the correct way to attach a scrollbar to a set of images that are created dynamically by the application.
In my code I create the scrollbar but it is not working properly. The main window does not scroll to view all the images.
int currentLength = iImage * (WIDTH + SPACER);
picName.Format(_T("Image %d"),iImage);
CPoint topLeft(currentLength,0);
CPoint bottomRigth(currentLength + (WIDTH), HEIGHT);
CRect miniCRect(topLeft, bottomRigth);
Miniature[iImage] = new CStatic();
Miniature[iImage]->Create(picName, WS_CHILD|WS_VISIBLE|SS_BITMAP, miniCRect, this);
if((bottomRigth.x > 500) && (currentLength <= 500))
{
//creo la scrool bar
CPoint ptnrigin(0,210);
CPoint endptn(bottomRigth.x,230);
CRect workingArea(ptnrigin,endptn);
cs.Create(WS_VISIBLE,workingArea,this,0);
cs.EnableScrollBar(ESB_ENABLE_BOTH);
SCROLLINFO info;
info.cbSize = sizeof(SCROLLINFO);
info.fMask = SIF_ALL;
info.nMin = 1;
info.nMax = 10;
info.nPage = 2;
info.nPos = 5;
info.nTrackPos = 5;
cs.SetScrollInfo(&info);
}
HDC hDCScreen_mini = ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
HDC hDCMem_mini = ::CreateCompatibleDC(hDCScreen_mini);
// create a compatible bitmap and select it in the memory DC
HBITMAP hBitmap_mini = ::CreateCompatibleBitmap(hDCScreen_mini, miniCRect.Width(), miniCRect.Height());
HBITMAP hBmpOld_mini = (HBITMAP)::SelectObject(hDCMem_mini, hBitmap_mini);
BitBlt(hDCMem_mini, 0, 0, desktopRect.Width(), desktopRect.Height(), hDCScreen_mini, desktopRect.left, desktopRect.top, dwRop);
Miniature[iImage]->SetBitmap(hBitmap_mini);
Invalidate();
// restore the memory DC and perform cleanup
SelectObject(hDCMem_mini, hBmpOld_mini);
DeleteDC(hDCMem_mini);
DeleteDC(hDCScreen_mini);
//end capture
Can someone help me?
A scrollbar does not scroll your window or its contents. It only provides input from the user to code that you must write to reposition the images. Such code typically uses ScrollWindow to move the visible portion, followed by adding the newly-visible portion in WM_PAINT.
A different approach (that does do the scrolling for you) would be to put the images in an owner-drawn list box.

CreateDIBSection in MFC and rendering using picture control

I'm creating a DIB Section in MFC using the call CreateDIBSection. I get a HBITMAP from the call which I pass onto another dialog in my MFC Project. In the other dialog I'm using CStatic::SetBitmap(HBITMAP) call to render the bitmap. But for some reason I'm not able to see anything. This works perfectly fine if this is done in same dialog, but I want to create bitmap in one dialog and display in another.
The code for creating the DIBSection is
//-----------------BEGINNING OF FIRST DIALOG--------------------------------------------------
LPVOID pViewBitmapBits = NULL;
BITMAPINFOHEADER BMHeaderInfo;
memset(&BMHeaderInfo, 0, sizeof(BITMAPINFOHEADER));
BMHeaderInfo.biSize = sizeof(BITMAPINFOHEADER);
BMHeaderInfo.biWidth = 800;
BMHeaderInfo.biHeight = 400;
BMHeaderInfo.biPlanes = 1;
BMHeaderInfo.biBitCount = 8;
BMHeaderInfo.biCompression = BI_RGB;
BMHeaderInfo.biSizeImage = 0;
BMHeaderInfo.biClrUsed = 0;
BMHeaderInfo.biClrImportant= 0;
BITMAPINFO BMInfo;
memset(&BMInfo, 0, sizeof(BMInfo));
BMInfo.bmiHeader = BMHeaderInfo;
BMInfo.bmiColors[0].rgbBlue=255;
HBITMAP hGlobalBitMap = CreateDIBSection(m_pParentSheet->test.m_hDC, &BMInfo, DIB_RGB_COLORS, &pViewBitmapBits, NULL, NULL);
SelectObject(m_pParentSheet->test.m_hDC, hGlobalBitMap);
//--------------------------END OF FIRST DIALOG----------------------------------
//-----------------------------BEGINNING OF SECOND DIALOG----------------------------------------
void CreateViewDlg::OnBnClickedButton2()
{
m_pic.SetBitmap(hGlobalBitMap );
}
//------------------------------------END OF SECOND DIALOG---------------------------------
Please help me with this. Is there any limitation to the usage of HBITMAP Handles?
HBITMAP hGlobalBitMap = ...
Looks like local variable hiding the global variable.