C++ MFC Bitmap displays incorrectly - c++

I am trying to get a background picture working in a MFC Dialog.
protected:
CBitmap m_Background;
CBrush m_BrushHold;
CSize m_BitmapSize;
BOOL CNameDlg::OnInitDialog()
{
//[...]
int i = m_Background.LoadBitmapW (30996);
//int y = GetLastError();
BITMAP bm;
m_Background.GetBitmap (&bm);
m_BitmapSize = CSize (bm.bmWidth, bm.bmHeight);
Invalidate(1);
//[...]
return TRUE; // return TRUE unless you set the focus to a control
}
m_BitmapSize is WAY to low. (e.g. 33, 11 while the real size is 428, 368)
BOOL CLotteryDlg::OnEraseBkgnd(CDC* pDC)
{
CDC dcMemory;
dcMemory.CreateCompatibleDC (pDC);
CBitmap* pOldbitmap = dcMemory.SelectObject (&m_Background);
CRect rcClient;
GetClientRect (&rcClient);
const CSize &sbitmap = m_BitmapSize;
pDC->BitBlt (0, 0, sbitmap.cx, sbitmap.cy, &dcMemory, 0, 0, SRCCOPY);
dcMemory.SelectObject (pOldbitmap);
return TRUE;
}
After painting it I will get either a small square in the top left corner or it displays
How can I get it to display correctly ?

Related

Redraw shapes in MFC

I'm trying to develop a painter app using MFC with C++.
So I set up a view in which I do the actual painting. However, when I open the color button I get "leftovers" of the menu on my canvas view.. I have no idea how to erase them.. I tried using SaveDC and RestoreDC to restore it to the previous state but no luck there. As I understand it is meant to restore properties of the device context such as pen & brush but it has no use for me...
I also need this feature so when I put up a rectangle, I could present a preview for it, but the "previews` are again presented like leftovers.
My view's OnEraseBkgbd;
BOOL CanvasView::OnEraseBkgnd(CDC* pDC)
{
if (!isBackgroundInit)
{
CRect rect;
GetClientRect(&rect);
CBrush myBrush(RGB(255, 255, 255)); // dialog background color
CBrush* pOld = pDC->SelectObject(&myBrush);
BOOL bRes = pDC->PatBlt(0, 0, rect.Width(), rect.Height(), PATCOPY);
pDC->SelectObject(pOld); // restore old brush
isBackgroundInit = true;
return bRes;
}
return 0;
}
My OnPaint:
void CanvasView::OnPaint()
{
CDialogEx::OnPaint();
//UpdateData(true);
CRect rect;
GetClientRect(&rect);
if (dc == nullptr)
{
dc = new CClientDC(this);
//dc->CreateCompatibleDC(dc);
HDC hdc = CreateCompatibleDC(*dc);
this->hdc = &hdc;
} else
{
BitBlt(*dc, 0, 0, (int)rect.Width(), (int)rect.Height(), *hdc, 0, 0, SRCCOPY);
}
}
How it looked at first:
How it looks when opening a color button:
How it looks after closing the color button menu(leftovers marked with red arrows):
When trying to put up a rectangle:
Any idea how to fix this and really restore drawing?
I am not sure I understand what you are trying to do.
CView has a virtual method called OnDraw. This is the method you must override:
void CMyView::OnDraw(CDC* pDC)
{
CMyDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// first erase the entire client rectangle
CRect cr;
GetClientRect( &cr );
pDC->FillSolidRect( cr, RGB( 255, 255, 255 ) );
// your actual drawing goes here
pDC->Rectangle( 0, 0, 100, 100 );
}
You will also have to write OnEraseBkgnd:
BOOL CMyView::OnEraseBkgnd( CDC* /*pDC*/ )
{
return TRUE; // we fill the client rectangle in OnDraw
}
Also, it looks like you are trying to implement an ad-hoc memory DC. There is already one: CMemDC.

An Aero caption title bar issue using DWM API on the windows 10

In order to draw the icon on the caption title bar, I have refereed this MSDN article and used DWM API to create my customize client area by calling DwmExtendFrameIntoClientArea.
my code:
CMainFrame::CMainFrame()
{
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
BOOL fDwmEnabled = FALSE;
if (SUCCEEDED(DwmIsCompositionEnabled(&fDwmEnabled)))
TRACE0("DWM is enabled\n");
TCHAR szLogoPath[MAX_PATH];
GetModuleFileName ( GetModuleHandle(NULL), szLogoPath, _countof(szLogoPath) );
PathRemoveFileSpec ( szLogoPath );
PathAppend ( szLogoPath, _T("lena.bmp") );
m_pLogoImage = m_pLogoImage->FromFile ( CT2CW(szLogoPath) );
if(NULL == m_pLogoImage)
TRACE0("load image fail\n");
}
void CMainFrame::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp)
{
int xFrame = 2;
int yFrame = 2;
int nTHight = 30;
NCCALCSIZE_PARAMS * p;
RECT * rc;
RECT aRect;
RECT bRect;
RECT acRect;
p = (NCCALCSIZE_PARAMS *)lpncsp;
CopyRect(&bRect,&p->rgrc[1]);
CopyRect(&aRect,&p->rgrc[0]);
acRect.left = aRect.left + xFrame;
acRect.top = aRect.top - nTHight;
acRect.right = aRect.right - xFrame;
acRect.bottom = aRect.bottom - yFrame;
CopyRect(&p->rgrc[0],&acRect);
CopyRect(&p->rgrc[1],&aRect);
CopyRect(&p->rgrc[2],&bRect);
CFrameWnd::OnNcCalcSize(TRUE, lpncsp);
}
LRESULT CMainFrame::OnNcHitTest(CPoint p)
{
BOOL dwm_enabled = FALSE;
if (SUCCEEDED(DwmIsCompositionEnabled(&dwm_enabled)))
{
LRESULT result = 0;
if (!DwmDefWindowProc(m_hWnd, WM_NCHITTEST, 0, MAKELPARAM(p.x, p.y), &result))
result = HitTestNCA(m_hWnd, p);
if (result == HTNOWHERE && GetForegroundWindow() != this)
{
return HTCAPTION;
}
return result;
}
return CWnd::OnNcHitTest(p);
}
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if(cs.hMenu!=NULL)
{
::DestroyMenu(cs.hMenu);
cs.hMenu = NULL ;
}
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
cs.style = WS_CAPTION | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_OVERLAPPED| WS_SYSMENU | WS_THICKFRAME;
cs.dwExStyle &= ~WS_EX_CLIENTEDGE;
cs.lpszClass = AfxRegisterWndClass(0);
return TRUE;
}
void CMainFrame::OnActivate(UINT nState,CWnd* pWndOther,BOOL bMinimized )
{
CFrameWnd::OnActivate(nState,pWndOther,bMinimized);
BOOL fDwmEnabled = FALSE;
if (SUCCEEDED(DwmIsCompositionEnabled(&fDwmEnabled)))
{
if(nState == WA_ACTIVE )
{
MARGINS margins = {-1};
/*margins.cyTopHeight = 30;
margins.cxLeftWidth = 0;
margins.cxRightWidth = 0;
margins.cyBottomHeight = 0;*/
HRESULT hr = DwmExtendFrameIntoClientArea(m_hWnd, &margins);
if (!SUCCEEDED(hr))
TRACE0("Failed in DwmExtendFrameIntoClientArea\n");
}
}
}
void CMainFrame::OnNcPaint()
{
CFrameWnd::OnPaint();
CDC* dc = GetWindowDC();
RECT rcClient;
GetWindowRect(&rcClient);
dc->FillSolidRect(0,0,RECTWIDTH(rcClient),RECTHEIGHT(rcClient),RGB(255,0,0));
CPaintDC gdc(this); // device context for painting
Graphics gr(gdc.m_hDC);
gr.DrawImage ( m_pLogoImage, 0, 0 );
ReleaseDC(dc);
}
The result under Windows 7 is fine.
However, my window appears another unknown caption title bar under Windows 10.
I found out the unknown caption is caused by WS_THICKFRAME in the cs.style.
If I remove WS_THICKFRAME, the unknown cation bar will disappear, but I cannot resizing the border of my window. Furthermore, my program cannot capture the minimum, maximum and the close button message on my custom caption bar anymore.
I want to remove the unknown title bar without any side effect.
Does anyone could provide me a good solution or suggestion?
Best Regards,
When using DwmExtendFrameIntoClientArea, it means frame is extended in to client area. It is no longer in non-client area. So there is no need to override OnNcPaint, you can do all of the painting in OnPaint
void CMainFrame::OnPaint()
{
CPaintDC dc(this);
//paint titlebar area (this used to be the non-client area)
CRect rc;
GetClientRect(&rc);
rc.bottom = titlebar_height;
CDC memdc;
memdc.CreateCompatibleDC(&dc);
BITMAPINFOHEADER bmpInfoHeader = {
sizeof(BITMAPINFOHEADER), rc.Width(), -rc.Height(), 1, 32 };
HBITMAP hbitmap = CreateDIBSection(
dc, (BITMAPINFO*)(&bmpInfoHeader), DIB_RGB_COLORS, NULL, NULL, 0);
auto oldbitmap = memdc.SelectObject(hbitmap);
dc.BitBlt(0, 0, rc.Width(), rc.Height(), &memdc, 0, 0, SRCCOPY);
memdc.SelectObject(oldbitmap);
DeleteObject(hbitmap);
//begin normal paint
//The new client area begins below titlebar_height which we define earlier
GetClientRect(&rc);
rc.top = titlebar_height;
dc.FillSolidRect(&rc, RGB(0, 0, 255));
Gdiplus::Image *image = Gdiplus::Image::FromFile(L"file.jpg");
Gdiplus::Graphics gr(dc);
gr.DrawImage(image, 0, 0);
delete image;
}
Use a member variable CRect m_border to keep track of border's thickness. You can use AdjustWindowRectEx to find the thickness of the borders.
void CMainFrame::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
{
CFrameWnd::OnActivate(nState, pWndOther, bMinimized);
titlebar_height = 100;
//find border thickness
if (GetWindowLongPtr(m_hWnd, GWL_STYLE) & WS_THICKFRAME)
{
m_border = { 0,0,0,0 };
AdjustWindowRectEx(&m_border, GetWindowLongPtr(m_hWnd,
GWL_STYLE) & ~WS_CAPTION, FALSE, NULL);
m_border.left = abs(m_border.left);
m_border.top = abs(m_border.top);
}
else if (GetWindowLongPtr(m_hWnd, GWL_STYLE) & WS_BORDER)
{
m_border = { 1,1,1,1 };
}
else
{
m_border = { 0,0,0,0 };
}
//Extend frame in to client area
MARGINS margins = { 0 };
margins.cyTopHeight = titlebar_height; //<<=== *** edited
DwmExtendFrameIntoClientArea(m_hWnd, &margins);
SetWindowPos(NULL, 0, 0, 0, 0,
SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
}
m_border will be for example {7,7,7,7};
Allow Windows to do the painting on left, right, bottom border. The top border is the only one changed
void CMainFrame::OnNcCalcSize(BOOL validate, NCCALCSIZE_PARAMS FAR* lpncsp)
{
if (validate)
{
lpncsp->rgrc[0].left += m_border.left;
lpncsp->rgrc[0].right -= m_border.right;
lpncsp->rgrc[0].bottom -= m_border.bottom;
}
else
{
CFrameWnd::OnNcCalcSize(validate, lpncsp);
}
}
see also How to glow the minimum. maximum and close button?

How to glow the minimum. maximum and close button?

I followed below guide to create a custom Aero Frame using DWM API.
Custom Window Frame Using DWM
My work:
void CMainFrame::OnActivate(UINT nState,CWnd* pWndOther,BOOL bMinimized )
{
CFrameWnd::OnActivate(nState,pWndOther,bMinimized);
BOOL fDwmEnabled = FALSE;
if (SUCCEEDED(DwmIsCompositionEnabled(&fDwmEnabled)))
{
if(nState == WA_ACTIVE )
{
MARGINS margins ={-1};
HRESULT hr = DwmExtendFrameIntoClientArea(m_hWnd, &margins);
if (!SUCCEEDED(hr));
}
}
}
void CMainFrame::OnNcPaint(){
RECT rcClient;
GetWindowRect(&rcClient);
// Inform the application of the frame change.
SetWindowPos(
NULL,
rcClient.left, rcClient.top,
RECTWIDTH(rcClient), RECTHEIGHT(rcClient),
SWP_FRAMECHANGED);
CFrameWnd::OnNcPaint();
CDC* dc = GetWindowDC();
dc->FillSolidRect(0,0,RECTWIDTH(rcClient),RECTHEIGHT(rcClient),RGB(0,0,0));
}
LRESULT CMainFrame::OnNcHitTest(CPoint p)
{
LRESULT r ;
r = CFrameWnd::OnNcHitTest( p);
if(r == HTMINBUTTON || r == HTMAXBUTTON || r == HTCLOSE)
return r;
else
r = HitTestNCA(m_hWnd,p); // this function is direct copied from above link.
return r;
}
Result:
I found out the minimum, maximum and close button that will not be glowed when I move the mouse on these buttons.
General situation:
How to fix this problem?
Best Regards,
DwmDefWindowProc is required to handle caption buttons. From msdn:
For caption button hit testing, DWM provides the DwmDefWindowProc
function. To properly hit test the caption buttons in custom frame
scenarios, messages should first be passed to DwmDefWindowProc for
handling. DwmDefWindowProc returns TRUE if a message is handled and
FALSE if it is not. If the message is not handled by DwmDefWindowProc,
your application should handle the message itself or pass the message
onto DefWindowProc.
In MFC it can work out as follows:
LRESULT cframeWnd::OnNcHitTest(CPoint p)
{
BOOL dwm_enabled = FALSE;
if (SUCCEEDED(DwmIsCompositionEnabled(&dwm_enabled)))
{
LRESULT result = 0;
if (!DwmDefWindowProc(m_hWnd, WM_NCHITTEST, 0, MAKELPARAM(p.x, p.y), &result))
result = HitTestNCA(m_hWnd, p);
if (result == HTNOWHERE && GetForegroundWindow() != this)
{
return HTCAPTION;
}
return result;
}
return CWnd::OnNcHitTest(p);
}
I added a fix with GetForegroundWindow(), because the HitTestNCA function from MSDN example is wrong, it doesn't return HTCLIENT when it should. So when another window has focus, it won't switch windows upon mouse click in client area.
Also, there is a leak in OnNcPaint:
CDC* dc = GetWindowDC();
Whenever GetWindowDC() is called it should be followed by ReleaseDC. Or just use CWindowDC which has automatic cleanup. You don't actually need to override OnNcPaint because frame has been extended to "client area".
Here is a full example:
class cglassWnd : public CWnd
{
void OnNcCalcSize(BOOL, NCCALCSIZE_PARAMS FAR*);
LRESULT OnNcHitTest(CPoint p);
void OnNcMouseLeave();
int OnCreate(LPCREATESTRUCT lpCreateStruct);
void OnActivate(UINT state, CWnd* otherWnd, BOOL minimized);
void OnPaint();
CRect borders;
int titlebar_height;
DECLARE_MESSAGE_MAP()
public:
cglassWnd();
};
BEGIN_MESSAGE_MAP(cglassWnd, CWnd)
ON_WM_NCHITTEST()
ON_WM_NCCALCSIZE()
ON_WM_NCMOUSELEAVE()
ON_WM_ACTIVATE()
ON_WM_CREATE()
ON_WM_PAINT()
END_MESSAGE_MAP()
cglassWnd::cglassWnd()
{
BOOL dwm_enabled = FALSE;
DwmIsCompositionEnabled(&dwm_enabled);
if (!dwm_enabled)
TRACE("Error: don't use this class, add error handling...");
//modified height for the new title bar
titlebar_height = 60;
}
int cglassWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
int res = CWnd::OnCreate(lpCreateStruct);
//find border thickness
borders = { 0,0,0,0 };
if (GetWindowLongPtr(m_hWnd, GWL_STYLE) & WS_THICKFRAME)
{
AdjustWindowRectEx(&borders,
GetWindowLongPtr(m_hWnd, GWL_STYLE) & ~WS_CAPTION, FALSE, NULL);
borders.left = abs(borders.left);
borders.top = abs(borders.top);
}
else if (GetWindowLongPtr(m_hWnd, GWL_STYLE) & WS_BORDER)
{
borders = { 1,1,1,1 };
}
//Extend caption in to client area
MARGINS margins = { 0 };
margins.cyTopHeight = titlebar_height;
DwmExtendFrameIntoClientArea(m_hWnd, &margins);
SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
return res;
}
void cglassWnd::OnPaint()
{
CPaintDC dc(this);
//paint titlebar area (this used to be the non-client area)
CRect rc;
GetClientRect(&rc);
rc.bottom = titlebar_height;
//see MSDN reference for explanation of this code
//upside-down bitmap is for the sake of DrawThemeTextEx
CDC memdc;
memdc.CreateCompatibleDC(&dc);
BITMAPINFOHEADER infhdr = { sizeof(infhdr), rc.right, -rc.bottom, 1, 32 };
HBITMAP hbitmap = CreateDIBSection(dc,(BITMAPINFO*)(&infhdr),DIB_RGB_COLORS,0,0,0);
auto oldbitmap = memdc.SelectObject(hbitmap);
//do extra titlebar painting here
//for example put DrawThemeTextEx for window's name
dc.BitBlt(0, 0, rc.Width(), rc.Height(), &memdc, 0, 0, SRCCOPY);
memdc.SelectObject(oldbitmap);
DeleteObject(hbitmap);
//begin normal paint
//The new client area begins below titlebar_height which we define earlier
GetClientRect(&rc);
rc.top = titlebar_height;
dc.FillSolidRect(&rc, RGB(128, 128, 255));
}
void cglassWnd::OnNcCalcSize(BOOL validate, NCCALCSIZE_PARAMS FAR* sz)
{
if (validate)
{
sz->rgrc[0].left += borders.left;
sz->rgrc[0].right -= borders.right;
sz->rgrc[0].bottom -= borders.bottom;
}
else
{
CWnd::OnNcCalcSize(validate, sz);
}
}
LRESULT cglassWnd::OnNcHitTest(CPoint pt)
{
LRESULT result = 0;
//handle close/minimize/maximize button
if (DwmDefWindowProc(m_hWnd, WM_NCHITTEST, 0, MAKELPARAM(pt.x, pt.y), &result))
return result;
//cursor is over the frame or client area:
result = CWnd::OnNcHitTest(pt);
if (result == HTCLIENT)
{
ScreenToClient(&pt);
if (pt.y < borders.top) return HTTOP;
if (pt.y < titlebar_height) return HTCAPTION;
}
return result;
}
void cglassWnd::OnNcMouseLeave()
{
//This is for close/minimize/maximize/help buttons
LRESULT result;
DwmDefWindowProc(m_hWnd, WM_NCMOUSELEAVE, 0, 0, &result);
CWnd::OnNcMouseLeave();
}
void cglassWnd::OnActivate(UINT state, CWnd* otherWnd, BOOL minimized)
{
CWnd::OnActivate(state, otherWnd, minimized);
Invalidate(FALSE);
}

MFC how to save and reuse the current device context CDC

Well simply what I need to do is to create a grid of rectangle and fill any selected case of that grid at the user click. thus I save the parameters (color, position..). The problem is when I try to fill the case at the click event I can't any changes maybe because the device context is changed even if I use GetDC() method. So is there any way to save the current created on OnDraw() method for exmaple and use it somewhere in another function, I tried to use SaveDC() and RestoreDC() but in vain.
Here's some of my code:
void CXThiefManView::OnDraw(CDC* pDC)
{
CXThiefManDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
CRect rcClient;
GetClientRect(&rcClient);
// Get the background color of the board
COLORREF clr = pDoc->GetBoardSpace(-1, -1);
// Draw the background first
pDC->FillSolidRect(&rcClient, clr);
// Create the brush for drawing
CBrush br;
br.CreateStockObject(HOLLOW_BRUSH);
CBrush* pbrOld = pDC->SelectObject(&br);
// Draw the squares
for (int row = 0; row < pDoc->GetRows(); row++)
{
for (int col = 0; col < pDoc->GetColumns(); col++)
{
// Get the color for this board space
clr = pDoc->GetBoardSpace(row, col);
// Calculate the size and position of this space
CRect rcBlock;
rcBlock.top = row * pDoc->GetHeight();
rcBlock.left = col * pDoc->GetWidth();
rcBlock.right = rcBlock.left + pDoc->GetWidth();
rcBlock.bottom = rcBlock.top + pDoc->GetHeight();
// Fill in the block with the correct color
pDC->FillSolidRect(&rcBlock, clr);
// Draw the block outline
pDC->Rectangle(&rcBlock);
}
}
saveState = pDC->SaveDC();
DrawItem(pDC, pDoc->GetThiefRow(), pDoc->GetThiefCol(), pDoc->GetThiefColor());
}
void CXThiefManView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CView::OnLButtonDown(nFlags, point);
CXThiefManDoc* pDoc = GetDocument();
// the draw item here to fill the case
DrawItem(GetDC(), 5, 5, RGB(0, 0, 0));
}
Underneath all those MFC function, the WINAPI functions of the same name are being called. In WINAPI, GetDC returns a new device context. SaveDC & RestoreDC allow you to save and restore the state (brush, font etc...) of a specific DC handle, but that doesn't cross to other handles.
There's nothing MFC can do about it, nor can you. You have to reconfigure the new DC handle for your needs.
Handle from GetDC has to be released by ReleaseDC. Please see GetDC
Or use CClientDC dc(this) which has automatic cleanup, it's usage is similar, for example Draw(&dc,...);.
As to your main question, you can save the drawing on a bitmap. The bitmap can be saved.
define:
CBitmap m_bitmap;
CDC m_memdc;
initialize the bitmap and dc:
CClientDC dc(this);
m_bitmap.CreateCompatibleBitmap(&dc, 2000, 1200);
//this creates a bitmap as big as the screen...
m_memdc.CreateCompatibleDC(&dc);
m_memdc.SelectObject(m_bitmap);
m_memdc.FillSolidRect(0, 0, 2000, 1200, RGB(255, 255, 255));
//draw on m_memdc, then draw memdc on to dc
Usage:
void CMyWindow::OnPaint()
{
CWnd::OnPaint();
CClientDC dc(this);
CRect rc;
GetClientRect(&rc);
dc.BitBlt(0, 0, rc.Width(), rc.Height(), &m_memdc, 0, 0, SRCCOPY);
}
void CMyWindow::OnMouseMove(UINT k, CPoint p)
{
CClientDC dc(this);
CRect rc;
GetClientRect(&rc);
if (k & MK_LBUTTON)
{
//draw on m_memdc, (instead of drawing on dc)
m_memdc.SetPixel(p.x, p.y, RGB(0,0,0));
m_memdc.SetPixel(p.x, p.y+1, RGB(0,0,255));
//when finished drawing, draw m_memdc on to dc
dc.BitBlt(0, 0, rc.Width(), rc.Height(), &m_memdc, 0, 0, SRCCOPY);
}
}

MFC C++ Screenshot

I have an application that has drawn a grid using CDC (it has text, rectangle, and bitmaps). I want to take a screenshot of that finished grid when it is saved and use that screenshot as a "preview" for the file.
How can I take a screenshot of my application and save it?
Thank you,
Answer is here
void CScreenShotDlg::OnPaint()
{
// device context for painting
CPaintDC dc(this);
// Get the window handle of calculator application.
HWND hWnd = ::FindWindow( 0, _T( "Calculator" ));
// Take screenshot.
PrintWindow( hWnd,
dc.GetSafeHdc(),
0 );
}
Ultimately I ended up doing it this way because I wanted to capture even the hidden parts of the window (since the content extends beyond the screen and requires scrolling):
CDC* WindowToCaptureDC = AfxGetMainWnd()->GetWindowDC();
CDC CaptureDC;
CDC MemDC;
MemDC.CreateCompatibleDC(WindowToCaptureDC);
CaptureDC.CreateCompatibleDC(WindowToCaptureDC);
CBitmap CaptureBmp;
CBitmap ResizeBmp;
int pWidth = grid.tableWidth + grid.marginLeft*2;
int pHeight = grid.tableHeight + grid.marginBottom;
CaptureBmp.CreateCompatibleBitmap( WindowToCaptureDC, pWidth, pHeight);
CaptureDC.SelectObject(&CaptureBmp);
CBrush brush(RGB(255, 255, 255));
CaptureDC.SelectObject(&brush);
CaptureDC.Rectangle(0, 0, pWidth, pHeight);
///Drew items into CaptureDC like I did for OnDraw HERE///
double width = //desired width;
double height = //desired width;
//maintain aspect ratio
if(pWidth!=width || pHeight!=height)
{
double w = width/pWidth;
double h = height/pHeight;
if(w < h)
height = height*w;
else
width = width*h;
}
ResizeBmp.CreateCompatibleBitmap(WindowToCaptureDC, width, height);
MemDC.SelectObject(&ResizeBmp);
MemDC.StretchBlt(0, 0, width, height, &CaptureDC, 0, 0, pWidth, pHeight, SRCCOPY);
CImage TempImageObj;
TempImageObj.Attach((HBITMAP)ResizeBmp.Detach());
CString filePath = _T("LOCATION\\image.bmp");
TempImageObj.Save(filePath);