Mismatch between print preview and real print output - visual-c++

I want to print a bitmap. To avoid printing small bitmap I set CScrollView mode as MM_LOMETRIC with sizes 3830 x 1995. I have created the bitmap and made the bitblt to the screen. There were everythig just like I want on the screen and on the print preview but when I printed the document I've got very bad result.
The same picture on print preview.
It seems to me that printer does not see a bitmap the same way as print preview does.
Pay attantion that the first ractangle puts directly on the DC and memDC puts into it.
Are there any ideas how to fix this mismatch between print previw and the real printing?
Project files
void OnDraw()
{
CPen pen;
pen.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
CPen* OldPen = pDC->SelectObject(&pen);
CRect rcView;
GetClientRect(rcView);
int iClientWidth = rcView.right;
int iClientHeight = rcView.bottom;
int iMemWidth = 1900;
int iMemHeight = 950;
CDC memDC;
CBitmap memBitmap;
memDC.CreateCompatibleDC(pDC);
memBitmap.CreateCompatibleBitmap(pDC, iMemWidth, iMemHeight);
memDC.SelectObject(&memBitmap);
memDC.SetMapMode(MM_LOMETRIC);
CPen pen1;
pen1.CreatePen(PS_SOLID, 3, RGB(0, 0, 0));
memDC.SelectObject(&pen1);
CBrush brBK;
brBK.CreateSolidBrush(RGB(255, 255, 255));
memDC.SelectObject(&brBK);
RECT rc;
rc.left = 0;
rc.top = 0;
rc.right = iMemWidth;
rc.bottom = iMemHeight;
memDC.FillRect(&rc, &brBK);
memDC.Rectangle(rc.left, rc.top, rc.right, -rc.bottom);
memDC.MoveTo(0, 0);
memDC.LineTo(1900, -950);
memDC.MoveTo(0, -950);
memDC.LineTo(200, -750);
CFont font;
font.CreateFont(
50, // nHeight
0, // nWidth
0, // nEscapement
0, // nOrientation
FW_NORMAL, // nWeight
FALSE, // bItalic
FALSE, // bUnderline
0, // cStrikeOut
ANSI_CHARSET, // nCharSet
OUT_DEFAULT_PRECIS, // nOutPrecision
CLIP_DEFAULT_PRECIS, // nClipPrecision
DEFAULT_QUALITY, // nQuality
DEFAULT_PITCH | FF_SWISS, // nPitchAndFamily
_T("Arial"));
memDC.SelectObject(&font);
memDC.TextOut(100, -100, _T("Hello"));
pDC->BitBlt(10, -10, iMemWidth, -iMemHeight, &memDC, 0, 0, SRCCOPY);
font.DeleteObject();
brBK.DeleteObject();
memDC.DeleteDC();
memBitmap.DeleteObject();
pen.DeleteObject();
pen1.DeleteObject();
}
void OnInitialUpdate()
{
CScrollView::OnInitialUpdate();
CSize sizeTotal;
sizeTotal.cx = 3830;
sizeTotal.cy = 1995;
SetScrollSizes(MM_LOMETRIC, sizeTotal);
}

Related

Why is my stretchblt images losing colours?

I am having some difficulties in correctly populating a CListCtrl with thumbnails of monitor displays.
On the right of my CDialog I have a static control and I render the image on a white canvas like this:
void CCenterCursorOnScreenDlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
{
if (nIDCtl == IDC_STATIC_MONITOR && !m_imgPreview.IsNull())
{
// Set the mode
SetStretchBltMode(lpDrawItemStruct->hDC, HALFTONE);
// Wipe the canvas
FillRect(lpDrawItemStruct->hDC, &lpDrawItemStruct->rcItem, static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)));
// Get canvas rectangle
const CRect rectCanvas(lpDrawItemStruct->rcItem);
// Calculate ratio factors
const float nRatioImage = m_imgPreview.GetWidth() / static_cast<float>(m_imgPreview.GetHeight());
const float nRatioCanvas = rectCanvas.Width() / static_cast<float>(rectCanvas.Height());
// Calculate new rectangle size
// Account for portrait images (negative values)
CRect rectDraw = rectCanvas;
if (nRatioImage > nRatioCanvas)
rectDraw.SetRect(0, 0, rectDraw.right, static_cast<int>(rectDraw.right / nRatioImage));
else if (nRatioImage < nRatioCanvas)
rectDraw.SetRect(0, 0, static_cast<int>((rectDraw.bottom * nRatioImage)), rectDraw.bottom);
// Add a margin
rectDraw.DeflateRect(5, 5);
// Move to center
const CSize ptOffset = rectCanvas.CenterPoint() - rectDraw.CenterPoint();
rectDraw.OffsetRect(ptOffset);
// Add a black frame
FrameRect(lpDrawItemStruct->hDC, &lpDrawItemStruct->rcItem, static_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)));
// Draw
m_imgPreview.Draw(lpDrawItemStruct->hDC, rectDraw);
return;
}
CDialogEx::OnDrawItem(nIDCtl, lpDrawItemStruct);
}
The above works beautifully:
But I have problems with the CListCtrl versions of the images. For instance, I am losing the colouring as you can see.
My CImageList is created like this:
m_ImageListThumb.Create(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, ILC_COLOR32, 0, 1);
m_ListThumbnail.SetImageList(&m_ImageListThumb, LVSIL_NORMAL);
I then create all the thumbnails by calling DrawThumbnails() in OnInitDialog:
void CCenterCursorOnScreenDlg::DrawThumbnails()
{
int monitorIndex = 0;
m_ListThumbnail.SetRedraw(FALSE);
for (auto& strMonitor : m_monitors.strMonitorNames)
{
CImage img;
CreateMonitorThumbnail(monitorIndex, img, true);
CBitmap* pImage = new CBitmap();
pImage->Attach((HBITMAP)img);
m_ImageListThumb.Add(pImage, nullptr);
CString strMonitorDesc = m_monitors.strMonitorNames.at(monitorIndex);
strMonitorDesc.AppendFormat(L" (Screen %d)", monitorIndex + 1);
m_ListThumbnail.InsertItem(monitorIndex, strMonitorDesc, monitorIndex);
monitorIndex++;
delete pImage;
}
m_ListThumbnail.SetRedraw(TRUE);
}
The CreateMonitorThumbnail function:
BOOL CCenterCursorOnScreenDlg::CreateMonitorThumbnail(const int iMonitorIndex, CImage &rImage, bool bSmall)
{
const CRect rcCapture = m_monitors.rcMonitors.at(iMonitorIndex);
// destroy the currently contained bitmap to create a new one
rImage.Destroy();
auto nWidth = rcCapture.Width();
auto nHeight = rcCapture.Height();
if (bSmall)
{
nWidth = THUMBNAIL_WIDTH;
nHeight = THUMBNAIL_HEIGHT;
}
// create bitmap and attach it to this object
if (!rImage.Create(nWidth, nHeight, 32, 0))
{
AfxMessageBox(L"Cannot create image!", MB_ICONERROR);
return FALSE;
}
// create virtual screen DC
CDC dcScreen;
dcScreen.CreateDC(_T("DISPLAY"), nullptr, nullptr, nullptr);
// copy the contents from the virtual screen DC
BOOL bRet = FALSE;
if (bSmall)
{
CRect rt(0, 0, nWidth, nHeight);
//::FillRect(rImage.GetDC(), rt, static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)));
bRet = ::StretchBlt(rImage.GetDC(), 0, 0,
nWidth,
nHeight,
dcScreen.m_hDC,
rcCapture.left,
rcCapture.top,
rcCapture.Width(),
rcCapture.Height(), SRCCOPY | CAPTUREBLT);
}
else
{
bRet = ::BitBlt(rImage.GetDC(), 0, 0,
rcCapture.Width(),
rcCapture.Height(),
dcScreen.m_hDC,
rcCapture.left,
rcCapture.top, SRCCOPY | CAPTUREBLT);
}
// do cleanup and return
dcScreen.DeleteDC();
rImage.ReleaseDC();
return bRet;
}
Ideally I want to have exactly the same kind of visual image as on the right, but obviously resized down. How do I fix this?
I simplified the converting from CImage to CBitmap but it made no difference:
void CCenterCursorOnScreenDlg::DrawThumbnails()
{
int monitorIndex = 0;
// Stop redrawing the CListCtrl
m_ListThumbnail.SetRedraw(FALSE);
// Loop monitor info
for (auto& strMonitor : m_monitors.strMonitorNames)
{
// Create the thumbnail image
CImage monitorThumbnail;
CreateMonitorThumbnail(monitorIndex, monitorThumbnail, true);
// Convert it to a CBitmap
CBitmap* pMonitorThumbnailBitmap = CBitmap::FromHandle(monitorThumbnail);
// Add the CBitmap to the CImageList
m_ImageListThumb.Add(pMonitorThumbnailBitmap, nullptr);
// Build the caption description
CString strMonitorDesc = m_monitors.strMonitorNames.at(monitorIndex);
strMonitorDesc.AppendFormat(L" (Screen %d)", monitorIndex + 1);
// Add the item to the CListCtrl
m_ListThumbnail.InsertItem(monitorIndex, strMonitorDesc, monitorIndex);
monitorIndex++;
}
// Start redrawiung the CListCtrl again
m_ListThumbnail.SetRedraw(TRUE);
}
If I change my code to pass false for the last parameter, so that it uses the original captured images without scaling down:
The colours are god there, so it is when I do:
if (bSmall)
{
CRect rt(0, 0, nWidth, nHeight);
//::FillRect(rImage.GetDC(), rt, static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)));
bRet = ::StretchBlt(rImage.GetDC(), 0, 0,
nWidth,
nHeight,
dcScreen.m_hDC,
rcCapture.left,
rcCapture.top,
rcCapture.Width(),
rcCapture.Height(), SRCCOPY | CAPTUREBLT);
}
that it messes up.
My issue was did not have anything to do with OnDrawItem. I simply included that to indicate how the image on the right was being rendered. I thought it may helped as background information. But it has probably confused the question and I may take it out in the long run!
Based on the comments I was reminded about SetStretchBltMode which was missing from CreateMonitorThumbnail. So, I now have this function:
BOOL CCenterCursorOnScreenDlg::CreateMonitorThumbnail(const int iMonitorIndex, CImage &rImage, bool bResizeAsThumbnail)
{
const CRect rcCapture = m_monitors.rcMonitors.at(iMonitorIndex);
// Destroy the currently contained bitmap to create a new one
rImage.Destroy();
// Massage the dimensions as we want a thumbnail
auto nWidth = rcCapture.Width();
auto nHeight = rcCapture.Height();
if (bResizeAsThumbnail)
{
nWidth = m_iThumbnailWidth;
auto dRatio = rcCapture.Width() / nWidth;
//nHeight = m_iThumbnailHeight;
nHeight = static_cast<int>(rcCapture.Height() / dRatio);
if (nHeight > m_iThumbnailHeight)
{
AfxMessageBox(L"Need to investigate!");
}
}
// Create bitmap and attach it to this object
if (!rImage.Create(nWidth, nHeight, 32, 0))
{
AfxMessageBox(L"Cannot create image!", MB_ICONERROR);
return FALSE;
}
// Create virtual screen DC
CDC dcScreen;
dcScreen.CreateDC(L"DISPLAY", nullptr, nullptr, nullptr);
// Copy (or resize) the contents from the virtual screen DC
BOOL bRet = FALSE;
auto dcImage = rImage.GetDC();
if (bResizeAsThumbnail)
{
// Set the mode first!
SetStretchBltMode(dcImage, COLORONCOLOR);
CPen penBlack;
penBlack.CreatePen(PS_SOLID, 3, RGB(0, 0, 0));
::Rectangle(dcImage, 0, 0, m_iThumbnailWidth, m_iThumbnailHeight);
int iTop = (m_iThumbnailHeight - nHeight) / 2;
// Copy (and resize)
bRet = ::StretchBlt(dcImage, 0, iTop,
nWidth,
nHeight,
dcScreen.m_hDC,
rcCapture.left,
rcCapture.top,
rcCapture.Width(),
rcCapture.Height(), SRCCOPY | CAPTUREBLT);
}
else
{
// Copy
bRet = ::BitBlt(dcImage, 0, 0,
rcCapture.Width(),
rcCapture.Height(),
dcScreen.m_hDC,
rcCapture.left,
rcCapture.top, SRCCOPY | CAPTUREBLT);
}
// Do cleanup and return
dcScreen.DeleteDC();
rImage.ReleaseDC();
return bRet;
}
That was the key to getting the thumbnail showing with the right colours:

Printing text and bitmap using MFC

I need to print some text (using font specified), than print a bitmap, using MFC. I can draw text on bitmap, than print this bitmap, using code below - but I need to print text, and than print bitmap in the bottom. The bitmap must be loaded from file.
CFont j1;
j1.CreateFont(
120, // nHeight
120, // nWidth
0, // nEscapement
0, // nOrientation
FW_NORMAL, // nWeight
FALSE, // bItalic
FALSE, // bUnderline
0, // cStrikeOut
RUSSIAN_CHARSET, // nCharSet
OUT_DEFAULT_PRECIS, // nOutPrecision
CLIP_DEFAULT_PRECIS, // nClipPrecision
DEFAULT_QUALITY, // nQuality
DEFAULT_PITCH | FF_SWISS, // nPitchAndFamily
"Arial"); // lpszFacename // lpszFacename
int w = 600, h = 400;
CClientDC dc(this);
CBitmap bmp;
CDC memdc;
memdc.CreateCompatibleDC(&dc);
bmp.CreateCompatibleBitmap(&dc, w, h);
if (!bmp.Attach(::LoadImage(
::GetModuleHandle(NULL), "D:\\UPM\\BMP\\Login.bmp", IMAGE_BITMAP, 0, 0,
LR_LOADFROMFILE | LR_CREATEDIBSECTION | LR_DEFAULTSIZE))) {
AfxMessageBox(_T("Error loading bitmap!")); return;
}
BITMAP bm;
bmp.GetBitmap(&bm);
auto oldbmp = memdc.SelectObject(bmp);
CFont* pOldFont = memdc.SelectObject(&j1);
//draw on bitmap
///memdc.FillSolidRect(0, 0, w, h, RGB(200, 200, 200));
memdc.SetTextColor(RGB(255, 0, 0));
CRect rc(0, 0, w, h);
memdc.DrawText("qwerty\nrtrtrt\nttttt", &rc, DT_WORDBREAK | DT_EXPANDTABS | DT_CENTER);
///pDC->DrawText(dpu, strRect, DT_WORDBREAK | DT_EXPANDTABS | DT_CENTER);
//dc.BitBlt(0, 0, w, h, &memdc, 0, 0, SRCCOPY);//optional: draw the bitmap on dialog
CPrintDialog pd(false);
if (pd.DoModal() == IDOK)
{
CDC PrintDC;
HDC hdc = pd.GetPrinterDC();
PrintDC.Attach(hdc);
DOCINFO docinfo = { sizeof(docinfo) };
docinfo.lpszDocName = "Print test";
PrintDC.StartDoc(&docinfo);
PrintDC.StartPage();
PrintDC.BitBlt(0, 0, w, h, &memdc, 0, 0, SRCCOPY);
PrintDC.EndPage();
PrintDC.EndDoc();
}
dc.SelectObject(oldbmp);
CClientDC dc(this);
dc.DrawText(...);
...
PrintDC.BitBlt(0, 0, w, h, &memdc, 0, 0, SRCCOPY);
You are drawing text on display's "client DC", then drawing a bitmap on a "printer DC".
Use instead a paint function for everything, and a paint_bitmap function to make things easier.
void paint_bitmap(CDC& dc, CBitmap &bmp, CRect rc)
{
CDC memdc;
memdc.CreateCompatibleDC(&dc);
auto oldbmp = memdc.SelectObject(&bmp);
dc.BitBlt(rc.left, rc.top, rc.Width(), rc.Height(), &memdc, 0, 0, SRCCOPY);
memdc.SelectObject(oldbmp);
}
void paint(CDC& dc)
{
CBitmap bmp;
if (!bmp.Attach(...))...
dc.DrawText(L"text", &rc, ...);
rc.OffsetRect(0, 200);
paint_bitmap(dc, bmp, rc);
}
...
CPrintDialog pd(false);
if (pd.DoModal() == IDOK)
{
HDC hdc = pd.GetPrinterDC();
if (hdc)
{
...
dc.StartPage();
paint(dc); //<- use this for printer or display
dc.EndPage();
}
To print directly to default printer:
CPrintDialog pd(false);
if (pd.GetDefaults() && pd.m_pd.hDC)
{
CDC dc;
dc.Attach(pd.m_pd.hDC);
DOCINFO docinfo = { sizeof(docinfo) };
docinfo.lpszDocName = L"Print test";
dc.StartDoc(&docinfo);
dc.StartPage();
paint(dc);
dc.EndPage();
dc.EndDoc();
}
else
{
MessageBox(L"no default printer...");
}
or if you want a particular printer which you are sure is there, use
HDC hdc = CreateDC(L"WINSPOOL", L"Microsoft Print to PDF", NULL, NULL);
if (hdc)
{
CDC dc;
dc.Attach(hdc);
...
//DeleteDC(hdc); CDC will take care of delete
}

How do I draw a pixmap to root window with xcb?

I'm trying to write a window manager with a wallpaper switcher:
void smoke_change_background(smoke_wm_state_t *config, char *desktop) {
struct smoke_desktop_list_element_t *node = smoke_desktop_list_node(config->tree, desktop);
if (node->background != 0) {
xcb_intern_atom_reply_t *xpmap = xcb_intern_atom_reply(config->connection,
xcb_intern_atom(config->connection,
false,
strlen("_X_ROOTPMAP_ID"),
"_X_ROOTPMAP_ID"),
NULL);
xcb_intern_atom_reply_t *esetr = xcb_intern_atom_reply(config->connection,
xcb_intern_atom(config->connection,
false,
strlen("ESETROOT_PMAP_ID"),
"ESETROOT_PMAP_ID"),
NULL);
xcb_get_property_reply_t *xrepl = xcb_get_property_reply(config->connection,
xcb_get_property(config->connection,
0,
config->screen->root,
xpmap->atom,
XCB_ATOM_PIXMAP,
0,
32),
NULL);
uint32_t *xp = (uint32_t*) xcb_get_property_value(xrepl);
xcb_get_property_reply_t *erepl = xcb_get_property_reply(config->connection,
xcb_get_property(config->connection,
0,
config->screen->root,
esetr->atom,
XCB_ATOM_PIXMAP,
0, 32),
NULL);
uint32_t *ep = (uint32_t*) xcb_get_property_value(erepl);
xcb_change_property(config->connection,
XCB_PROP_MODE_REPLACE,
config->screen->root,
xpmap->atom,
XCB_ATOM_PIXMAP,
32, 1,
(void*) &node->background);
xcb_change_property(config->connection,
XCB_PROP_MODE_REPLACE,
config->screen->root,
esetr->atom,
XCB_ATOM_PIXMAP,
32, 1,
(void*) &node->background);
xcb_free_pixmap(config->connection, *xp);
xcb_free_pixmap(config->connection, *ep);
uint32_t values[1];
values[0] = node->background;
xcb_change_window_attributes(config->connection, config->screen->root, XCB_CW_BACK_PIXMAP, values);
xcb_clear_area(config->connection, false, config->screen->root, 0, 0, 0, 0);
xcb_flush(config->connection);
}
}
This code should change the root's pixmap and it should be displayed in my Xephyr window, but it is not. What's wrong?

Direct3D Renders to wrong texture

In the code below I try render a sphere to a texture (renderTargetView), that texture is supposed to be rendered to the back buffer on a quad. I'm experimenting with it to use with glow later. The problem right now is that the sphere is rendered to the back buffer and is visible, it doesn't even matter if I comment out the lower half of the code, same result. I'm using this background color D3DXCOLOR(0.4f, 0.2f, 0.0f) here, but that is not what's on the screen, it's the color set with back buffer devcon->ClearRenderTargetView(backbuffer, D3DXCOLOR(0.0f, 0.2f, 0.4f, 1.0f)); that is showing.
// Set and clear render target
devcon->OMSetRenderTargets(1, &renderTargetView, zbuffer);
devcon->ClearRenderTargetView(renderTargetView, D3DXCOLOR(0.4f, 0.2f, 0.0f, 1.0f));
devcon->PSSetShaderResources(0, 1, &pTextureSun);
devcon->UpdateSubresource(pCBuffer, 0, 0, &cBuffer, 0, 0);
devcon->Draw(sizeOfVertexVector, 0);
// set the shader objects
/*
devcon->VSSetShader(pVS_glow, 0, 0);
devcon->PSSetShader(pPS_glow, 0, 0);
// set the render target as the back buffer
devcon->OMSetRenderTargets(1, &backbuffer, zbuffer);
devcon->IASetVertexBuffers(0, 1, &pVBufferQuad, &stride, &offset);
devcon->UpdateSubresource(pCBuffer, 0, 0, &cBuffer, 0, 0);
devcon->PSSetShaderResources(0, 1, &shaderResourceView);
devcon->Draw(6, 0);*/
Here is where the back and depth buffers set up (I have been trying with different formats such as DXGI_FORMAT_D24_UNORM_S8_UINT for depth buffer and others but no luck):
// create a struct to hold information about the swap chain
DXGI_SWAP_CHAIN_DESC scd;
// clear out the struct for use
ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));
// fill the swap chain description struct
scd.BufferCount = 1; // one back buffer
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // use 32-bit color
scd.BufferDesc.Width = SCREEN_WIDTH; // set the back buffer width
scd.BufferDesc.Height = SCREEN_HEIGHT; // set the back buffer height
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // how swap chain is to be used
scd.OutputWindow = hWnd; // the window to be used
scd.SampleDesc.Count = 4; // how many multisamples
scd.Windowed = TRUE; // windowed/full-screen mode
scd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; // allow full-screen switching
// create a device, device context and swap chain using the information in the scd struct
D3D11CreateDeviceAndSwapChain(NULL,
D3D_DRIVER_TYPE_HARDWARE,
NULL,
NULL,
NULL,
NULL,
D3D11_SDK_VERSION,
&scd,
&swapchain,
&dev,
NULL,
&devcon);
// create the depth buffer texture
D3D11_TEXTURE2D_DESC texd;
ZeroMemory(&texd, sizeof(texd));
texd.Width = SCREEN_WIDTH;
texd.Height = SCREEN_HEIGHT;
texd.ArraySize = 1;
texd.MipLevels = 1;
texd.SampleDesc.Count = 4;
texd.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
texd.BindFlags = D3D11_BIND_DEPTH_STENCIL;
ID3D11Texture2D *pDepthBuffer;
dev->CreateTexture2D(&texd, NULL, &pDepthBuffer);
// create the depth buffer
D3D11_DEPTH_STENCIL_VIEW_DESC dsvd;
ZeroMemory(&dsvd, sizeof(dsvd));
dsvd.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
dsvd.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
dev->CreateDepthStencilView(pDepthBuffer, &dsvd, &zbuffer);
pDepthBuffer->Release();
// get the address of the back buffer
ID3D11Texture2D *pBackBuffer;
swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
// use the back buffer address to create the render target
dev->CreateRenderTargetView(pBackBuffer, NULL, &backbuffer);
pBackBuffer->Release();
// set the render target as the back buffer
devcon->OMSetRenderTargets(1, &backbuffer, zbuffer);
// Set the viewport
D3D11_VIEWPORT viewport;
ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
viewport.TopLeftX = 0; // set the left to 0
viewport.TopLeftY = 0; // set the top to 0
viewport.Width = SCREEN_WIDTH; // set the width to the window's width
viewport.Height = SCREEN_HEIGHT; // set the height to the window's height
viewport.MinDepth = 0; // the closest an object can be on the depth buffer is 0.0
viewport.MaxDepth = 1; // the farthest an object can be on the depth buffer is 1.0
devcon->RSSetViewports(1, &viewport);
And the render-to-texture:
D3D11_TEXTURE2D_DESC textureDesc;
D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;
// Initialize the render target texture description.
ZeroMemory(&textureDesc, sizeof(textureDesc));
// Setup the render target texture description.
textureDesc.Width = SCREEN_WIDTH;
textureDesc.Height = SCREEN_HEIGHT;
textureDesc.MipLevels = 1;
textureDesc.ArraySize = 1;
textureDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
textureDesc.SampleDesc.Count = 1;
textureDesc.Usage = D3D11_USAGE_DEFAULT;
textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
textureDesc.CPUAccessFlags = 0;
textureDesc.MiscFlags = 0;
dev->CreateTexture2D(&textureDesc, NULL, &renderTargetTexture);
// Setup the description of the render target view.
renderTargetViewDesc.Format = textureDesc.Format;
renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
renderTargetViewDesc.Texture2D.MipSlice = 0;
dev->CreateRenderTargetView(renderTargetTexture, &renderTargetViewDesc, &renderTargetView);
// Setup the description of the shader resource view.
shaderResourceViewDesc.Format = textureDesc.Format;
shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
shaderResourceViewDesc.Texture2D.MipLevels = 1;
// Create the shader resource view.
dev->CreateShaderResourceView(renderTargetTexture, &shaderResourceViewDesc, &shaderResourceView);
Any ideas?
UPDATE
This code is executed before rendering to texture, if I comment out it..
// set the render target as the back buffer
devcon->OMSetRenderTargets(1, &backbuffer, zbuffer);
cBuffer.doBlur = 0;
devcon->PSSetShaderResources(0, 1, &pTextureEarth);
devcon->UpdateSubresource(pCBuffer, 0, 0, &cBuffer, 0, 0);
devcon->Draw(sizeOfVertexVector, 0);
...this now renders to texture, currently it just shows the background color of the texture, not the sphere.
// Set and clear render target
devcon->OMSetRenderTargets(1, &renderTargetView, zbuffer);
devcon->ClearRenderTargetView(renderTargetView, D3DXCOLOR(0.4f, 0.2f, 0.0f, 0.3f));
devcon->PSSetShaderResources(0, 1, &pTextureSun);
devcon->UpdateSubresource(pCBuffer, 0, 0, &cBuffer, 0, 0);
devcon->Draw(sizeOfVertexVector, 0);
// set the shader objects
devcon->IASetInputLayout(pLayoutGlow);
devcon->VSSetShader(pVS_glow, 0, 0);
devcon->PSSetShader(pPS_glow, 0, 0);
// set the render target as the back buffer
devcon->OMSetRenderTargets(1, &backbuffer, zbuffer);
devcon->IASetVertexBuffers(0, 1, &pVBufferQuad, &stride, &offset);
devcon->UpdateSubresource(pCBuffer, 0, 0, &cBuffer, 0, 0);
devcon->PSSetShaderResources(0, 1, &shaderResourceView);
devcon->Draw(6, 0);
The problem was that blend wasn't enabled.
I had problems with rendet to texture before because I bound a shader resource view to the same texture as what was the render target, which is forbidden. If you use Visual Studio 2012, you should try checking your code in debug mode. Aren't you making the same mistake as me?

MemDC in OnPaint()-function

My OnPaint() function calls several other drawing functions.
void CGraph::OnPaint ()
{
CPaintDC dc(this);
// CMemDC DC(&dc);
dc.SetViewportOrg (0, 400);
dc.SetMapMode(MM_ISOTROPIC);
dc.SetWindowExt(1000, 800);
dc.SetViewportExt(1000, -800);
ProcessData ();
DrawCoordinateSystem (&dc);
DrawGrid (&dc);
DrawGraph (&dc);
}
Example of DrawCoordianteSystem:
void CGraph::DrawCoordinateSystem (CDC* pDC)
{
CPen PenBlack (PS_SOLID, 1, RGB(0, 0, 0));
pDC->SelectObject (PenBlack);
// Rectangle round the system
pDC->Rectangle (0, -400, 1000, 400);
// Horizontal axis
pDC->MoveTo (0, 0);
pDC->LineTo (1000, 0);
pDC->SetTextColor (RGB(0,0,0));
pDC->SetBkColor (RGB(240, 240, 240));
pDC->TextOut (1001, 0, L"0");
// Vertical axis
pDC->MoveTo (0, -400);
pDC->LineTo (0, 400);
}
I now want to avoid flickering with CMemDC. However, i can't get it to work right. Can somebody show me how to implement CMemDC right?
Thanks
You need to load the memory DC with a bitmap to then BitBlt to the screen DC.
Try something like:
CDC dcMem;
CBitmap bitmap;
dcMem.CreateCompatibleDC( pDC );
bitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height())
CBitmap* pOldBitmap = dcMem.SelectObject(&bitmap);
... DO ALL YOUR DRAWING TO dcMem ...
pDC->BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &dcMem, 0, 0, SRCCOPY);
dcMem.SelectObject(pOldBitmap)
To avoid flickers you should draw everything on CMemDC and BitBlt it to the real DC.
Secondly add windows message handler for WM_ERASEBKGND message and change the code to
BOOL CGraph::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}

Resources