WM_PRINTCLIENT to BMP coming out all black - visual-c++

I am new to working with MFC and bitmaps. I have a HWND, which I want to print onto a bitmap using WM_PRINTCLIENT. This is what I have thus far:
EDIT:
CRect rcWindow;
GetClientRect(hWnd, &rcWindow);
HDC hDC = GetDC(hWnd);
HDC hBitmapDC = CreateCompatibleDC(hDC);
HBITMAP hBitmap = CreateCompatibleBitmap(hDC, rcWindow.Width(), rcWindow.Height());
SelectObject(hBitmapDC, hBitmap);
SendMessage(hWnd, WM_PRINTCLIENT, (WPARAM)hBitmapDC, PRF_CHILDREN | PRF_CLIENT | PRF_NONCLIENT);
CImage image;
image.Attach(hBitmap);
image.Save(_T("C:\\Test.bmp"), Gdiplus::ImageFormatBMP);
This however results in a bitmap that is all black. Can anyone see what I am doing wrong?

Try the following :
HDC hBitmapDC = ::CreateCompatibleDC(hDC);
HBITMAP hBitmap = ::CreateCompatibleBitmap(hDC, rcWindow.Width(), rcWindow.Height());
::SelectObject(hBitmapDC, hBitmap);
// Blt the existing background into the bitmap DC
::BitBlt(hBitmapDC,
0, 0, rcWindow.Width(), rcWindow.Height(),
hDC, rcWindow.left, rcWindow.top, SRCCOPY);
Don't forget to delete the bitmap object using ::DeleteObject, and the bitmap DC using DeleteDC, when you've finished with them...
Hope this helps

Related

StretchBlt giving monochrome bitmap as output

I m writing code for scaling down the image in VC++. When i save destination bitmap it gives monochrome image.
Code:
int iNewWidth = 400;
int iNewHeight = 500;
CImage image;
HRESULT rs=image.Load(_T("E:\\input.jpg"));
int a=10;
CDC destDC;
int res=destDC.CreateCompatibleDC(NULL);
HDC hdcDest=HDC(destDC);
HBITMAP hDestBitmap=CreateCompatibleBitmap(hdcDest, iNewWidth, iNewHeight);
HBITMAP hOldBitmap=(HBITMAP)SelectObject(hdcDest,hDestBitmap);
SetStretchBltMode(hdcDest,BLACKONWHITE);
BOOL bl=image.StretchBlt(hdcDest,0, 0, iNewWidth, iNewHeight, 0, 0, image.GetWidth(), image.GetHeight(), SRCERASE);
HRESULT res2;
CImage new_image;
new_image.Attach(hDestBitmap);
res2=new_image.Save(_T("E:\\NewImage.jpg"));
HBITMAP hb=new_image.Detach();
ReleaseDC(NULL,hdcDest);
I will be very thankful if someone help me here.
Thanks in advance
When you create a DC it initially has a monochrome bitmap selected into it. When you use CreateCompatibleBitmap with that DC, it uses the characteristics of that selected bitmap - i.e. it creates another monochrome bitmap.
Use the DC returned by GetDC(NULL) in your CreateCompatibleBitmap call.

How to get pixels from window using Direct2D

My problem is getting the pixels in a window. I can't find a way to do this. I using standard windows functions and Direct2D (not DirectDraw).
I am using standard initialization of new window:
WNDCLASS wc;
wc.style = CS_OWNDC;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(6);
wc.lpszMenuName = 0;
wc.lpszClassName = L"WINDOW"; RegisterClass(&wc);
hWnd = CreateWindow(L"WINDOW", L"Game", WS_OVERLAPPEDWINDOW,100,100,1024,768,NULL,NULL,hInstance,NULL);
Then I create a D2D1factory object and draw the bitmap in the window:
HWND hWnd = NULL;
srand((unsigned int)time((time_t)NULL));
ID2D1Factory* factory = NULL;
ID2D1HwndRenderTarget* rt = NULL;
CoInitializeEx(NULL,COINIT_MULTITHREADED);
My_CreateWindow(&hWnd, hInstance);
My_CreateFactory(&hWnd, factory, rt);
D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,&factory);
factory->CreateHwndRenderTarget(RenderTargetProperties(), HwndRenderTargetProperties(hWnd,SizeU(800,600)), &rt);
// tons of code
rt->BeginDraw(); rt->DrawBitmap(background[0], RectF(0,0,800,600));
rt->DrawBitmap(GIFHorse[(int)iterator],
RectF(0+MyX-100,0+MyY-100,100+MyX,100+MyY));
rt->DrawBitmap(Star[(int)iterator], RectF(0 + starX, 0 + starY, 50 + starX, 50+starY)); rt->EndDraw();
I need to calculate the hits (I am trying to make simple game). So that's why I need access to all pixels in window.
I'm thinking about using other algorithms, but they're harder to make and I want to start with something easier.
I know about the GetPixel() function, but I cant understand what I should use for HDC.
There is no simple and easy way to get to D2D pixels.
A simple collision detection can be implemented using geometries. If you have outlines of your objects in ID2D1Geometry objects you can compare them using ID2D1Geometry::CompareWithGeometry.
If you insist on the pixels, a way to access them is from the DC obtainable via IDXGISurface1::GetDC
In this case you need to use the DXGI surface render target and the swap chain instead of the hwnd render target.
Step by step:
D3D11CreateDeviceAndSwapChain gives you the swap chain.
IDXGISwapChain::GetBuffer gives you the DXGI surface.
ID2D1Factory::CreateDxgiSurfaceRenderTarget gives you the render target.
IDXGISurface1::GetDC gives you the DC. Read the remarks on this page!

GetDIBits: bitmap modifications, but crashes out?

GetDIBits: trying to modify the bitmap, but not sure how to go about it? I tried lpvBits but it crashes out in the comparison in the "pig" area. How should I do this? thx
LPVOID lpvBits=NULL; // pointer to bitmap bits array
BITMAPINFO bi;
ZeroMemory(&bi.bmiHeader, sizeof(BITMAPINFOHEADER));
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
if (!GetDIBits(dc, m_bmp, 0, 400, lpvBits, &bi, DIB_RGB_COLORS))
AfxMessageBox("1");
char *pig = (char*)lpvBits;
for (int m=0;m<100;m++)
{
if (pig[m] > 100)
{
pig[m] = 250;
}
}
SetDIBits( dc, m_bmp, 0, 400, (void *)pig, &bi, DIB_RGB_COLORS );
http://msdn.microsoft.com/en-us/library/dd144879(v=vs.85).aspx
lpvBits [out]
A pointer to a buffer to receive the bitmap data. If this parameter is NULL, the function passes the dimensions and format of the bitmap to the BITMAPINFO structure pointed to by the lpbi parameter.
example found here:
http://msdn.microsoft.com/en-us/library/dd183402(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/ms969901.aspx
http://www.codeproject.com/KB/graphics/drawing2bitmap.aspx
http://www.cplusplus.com/forum/general/28469/
Read the documentation for GetDIBits carefully - the lpvBits pointer is not returned to you - you need to allocate enough memory for the bitmap data you want to fetch, and pass it to GetDIBits to fill it in with image data.

Using DirectX 9; Sprite Anti-Aliasing Halo

So I am coding in DirectX 9 and whenever I place a sprite inside of a 2D world. There is a white colored "halo" that appears around the sprite image p. I am using PNGs and the background behind the sprite is transparent. I have also tried using a pink background as well. It seems that the halo only appears on straight lines of pixels but only on some edges. Any help is greatly appreciated!
m_d3d = Direct3DCreate9(D3D_SDK_VERSION); // create the Direct3D interface
D3DPRESENT_PARAMETERS d3dpp; // create a struct to hold various device information
ZeroMemory(&d3dpp, sizeof(d3dpp)); // clear out the struct for use
d3dpp.Windowed = windowed; // is program fullscreen, not windowed?
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; // discard old frames
d3dpp.hDeviceWindow = hWnd; // set the window to be used by Direct3D
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; // set the back buffer format to 32-bit
d3dpp.BackBufferWidth = screenWidth; // set the width of the buffer
d3dpp.BackBufferHeight = screenHeight; // set the height of the buffer
d3dpp.EnableAutoDepthStencil = TRUE; // automatically run the z-buffer for us
d3dpp.AutoDepthStencilFormat = D3DFMT_D16; // 16-bit pixel format for the z-buffer
// create a device class using this information and the info from the d3dpp stuct
m_d3d->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&m_d3ddev);
D3DXCreateSprite(m_d3ddev, &m_d3dspt); // create the Direct3D Sprite object
LPDIRECT3DTEXTURE9 texture;
D3DXCreateTextureFromFileEx(m_d3ddev, "DC.png", D3DX_DEFAULT, D3DX_DEFAULT,
D3DX_DEFAULT, NULL, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_DEFAULT,
D3DX_DEFAULT, D3DCOLOR_XRGB(255, 0, 255), NULL, NULL, &texture);
m_d3ddev->BeginScene();
m_d3dspt->Begin(D3DXSPRITE_ALPHABLEND); // begin sprite drawing with transparency
D3DXVECTOR3 center(0.0f, 0.0f, 0.0f), position((appropriate x), (appropriate y), 1);
m_d3dspt->Draw(texture, NULL, &center, &position, D3DCOLOR_ARGB(255, 255, 255, 255));
m_d3dspt->End(); // end sprite drawing
m_d3ddev->EndScene();
m_d3ddev->Present(NULL, NULL, NULL, NULL);
Thanks
Peter
This occurs when you screw up your texture co-ordinates from sprite atlasing and you accidentally run off the texture or on to another texture.
Most commonly, anyway, AFAIK.

how to capture desktop using vc++

I am trying to capture desktop. i found some code which capture the desktop , but takes some time.
void CSDITESTView::OnFileTest()
{
int nScreenWidth = GetSystemMetrics(SM_CXSCREEN);
int nScreenHeight = GetSystemMetrics(SM_CYSCREEN);
HWND hDesktopWnd = GetDesktopWindow()->m_hWnd;
HDC hDesktopDC = ::GetDC(hDesktopWnd);
HDC hCaptureDC = CreateCompatibleDC(hDesktopDC);
HBITMAP hCaptureBitmap =CreateCompatibleBitmap(hDesktopDC,nScreenWidth, nScreenHeight);
SelectObject(hCaptureDC,hCaptureBitmap);
BitBlt(hCaptureDC,0,0,nScreenWidth,nScreenHeight, hDesktopDC,0,0,SRCCOPY|CAPTUREBLT);
::ReleaseDC(hDesktopWnd,hDesktopDC);
DeleteDC(hCaptureDC);
}
But i need code which capture quick and save it as image.
Thanks in Advance..
I've tested your code using performance counter functions, as follows:
void CMainFrame::OnTestTest()
{
LARGE_INTEGER lFreq, lStart, lEnd;
::QueryPerformanceFrequency(&lFreq);
::QueryPerformanceCounter(&lStart);
/// BEGIN BENCHMARK ///
int nScreenWidth = ::GetSystemMetrics(SM_CXSCREEN);
int nScreenHeight = ::GetSystemMetrics(SM_CYSCREEN);
HWND hDesktopWnd = ::GetDesktopWindow();
HDC hDesktopDC = ::GetDC(hDesktopWnd);
HDC hCaptureDC = ::CreateCompatibleDC(hDesktopDC);
HBITMAP hCaptureBitmap = ::CreateCompatibleBitmap(hDesktopDC,nScreenWidth, nScreenHeight);
::SelectObject(hCaptureDC,hCaptureBitmap);
::BitBlt(hCaptureDC,0,0,nScreenWidth,nScreenHeight, hDesktopDC,0,0,SRCCOPY|CAPTUREBLT);
::ReleaseDC(hDesktopWnd,hDesktopDC);
::DeleteDC(hCaptureDC);
/// END BENCHMARK ///
::QueryPerformanceCounter(&lEnd);
double dTime = ((double)lEnd.QuadPart - lStart.QuadPart) / lFreq.QuadPart;
// ..
}
The resulted time was about 80 microseconds.
I don't think your computer is incredible slow. Probably the problem is in another side (e.g. a matter of thread synchronization).

Resources