in direct2d drawing dimensions change after window resizing - c++

I am a beginner, and I have made a program in direct2d using c++ in visual studio 2015, just a very basic program that draws a white square on a black background , and it does show the square in a small window. But the problem is that if the user maximizes that window the vertical dimension of the drawing becomes elongated and the square becomes rectangle.
This is the screenshot of the window before maximizing it:
enter image description here
And this is the screenshot of the window after maximizing it:
enter image description here
What am I doing wrong ?
here is my code and thanks in advance:
ID2D1HwndRenderTarget* pRT = NULL;
ID2D1Factory* pD2DFactory = NULL;
ID2D1SolidColorBrush* pBlackBrush = NULL;
ID2D1SolidColorBrush* pRedBrush = NULL;
HRESULT hr;
RECT rc;
POINT pt;
void draw(){
pRT->BeginDraw();
pRT->FillRectangle( D2D1::RectF((FLOAT)rc.left,
(FLOAT)rc.top,(FLOAT)rc.right, (FLOAT)rc.bottom),pBlackBrush);
pRT->FillRectangle( D2D1::RectF((FLOAT)pt.x,
(FLOAT)pt.y,pt.x + 50.0f ,pt.y + 50.0f),pRedBrush);
hr = pRT->EndDraw();
}
int APIENTRY wWinMain(/* wWinMain parameters */){
/*
...
window making
...
*/
hr = D2D1CreateFactory(
D2D1_FACTORY_TYPE_SINGLE_THREADED,&pD2DFactory );
// Obtain the size of the drawing area.
GetClientRect(hWnd, &rc);
// Create a Direct2D render target
hr =pD2DFactory->CreateHwndRenderTarget(
D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties(
hWnd,D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top)
),
&pRT
);
if (SUCCEEDED(hr)){
pRT->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::White),
&pRedBrush
);
pRT->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::Black),
&pBlackBrush
);
}
pt.x = 0;
pt.y = 0;
while (1) {
PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE);
if (msg.message == WM_QUIT) break;
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
draw();
}
}

It seems like you don't resize the render target when your window resizes. I expect you run into similar problems not just from maximizing, but when you resize your window too? See https://learn.microsoft.com/en-us/windows/desktop/LearnWin32/dpi-and-device-independent-pixels#resizing-the-render-target.
Code snippet from the linked document:
void Resize()
{
if (pRenderTarget != NULL)
{
RECT rc;
GetClientRect(m_hwnd, &rc);
D2D1_SIZE_U size = D2D1::SizeU(rc.right, rc.bottom);
pRenderTarget->Resize(size);
InvalidateRect(m_hwnd, NULL, FALSE);
}
}
You'll want to call this by catching WM_SIZE.

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);
}

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 draw a opaque image on the Aero glass window?

I have used DWM API to create a Aero glass window by calling DwmExtendFrameIntoClientArea.
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))
TRACE0("Failed to DwmExtendFrameIntoClientArea\n");
}
}
}
And then, I draw a bitmap image on the window (I also have tried to call DrawThemeIcon and CImageList::Draw to draw the image).
void CMainFrame::DisplayBitmap( CBitmap *p, CDC *pDC)
{
CDC dcMemory;
BITMAP bm;
dcMemory.CreateCompatibleDC(pDC);
dcMemory.SelectObject(p);
p->GetBitmap(&bm);
pDC->BitBlt(100,100,bm.bmWidth,bm.bmHeight,&dcMemory,0,0,SRCCOPY);
}
void CMainFrame::OnNcPaint(){
CFrameWnd::OnNcPaint();
CDC* dc = GetWindowDC();
CRect rct;
GetWindowRect(&rct);
dc->FillSolidRect(0, 0, rct.right - rct.left, rct.bottom - rct.top, RGB(0, 0, 0));
DisplayBitmap(&bmpBtn,dc);
ReleaseDC(dc);
}
I found out the image is ugly and translucency. How to draw a opaque image on the Aero glass window?
Update:
I still need somebody who can provide another solution without using GDI+ library for me. Thanks!
Solution 1:
CMainFrame::CMainFrame()
{
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
//Initialize GDI+.
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
m_pImage = m_pImage->FromFile (_T("lena.bmp"));
}
void CMainFrame::OnNcPaint(){
CFrameWnd::OnNcPaint();
CDC* dc = GetWindowDC();
CRect rct;
GetWindowRect(&rct);
dc->FillSolidRect(0, 0, rct.right - rct.left, rct.bottom - rct.top, RGB(0, 0, 0));
CPaintDC gdc(this);
Graphics g(gdc);
//I don't why the image will disappear sometimes when I move the window.
g.DrawImage ( m_pImage, 0, 0 );
ReleaseDC(dc);
}
The Result:

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);
}
}

how to stretch a background image in win32 using visual studio c

I'm trying to create an application in Win32 api with c++ and I want to make it FullScreen without any bar , i succeeded but i still have a problem in the background image. The image is repeated but i want it to be stretched. Have you any idea?
below part from the code :
int WINAPI WinMain (HINSTANCE cetteInstance, HINSTANCE precedenteInstance,
LPSTR lignesDeCommande, int modeDAffichage)
{
HWND fenetrePrincipale;
MSG message;
WNDCLASS classeFenetre;
instance = cetteInstance;
classeFenetre.style = 0;
classeFenetre.lpfnWndProc = procedureFenetrePrincipale;
classeFenetre.cbClsExtra = 0;
classeFenetre.cbWndExtra = 0;
classeFenetre.hInstance = NULL;
classeFenetre.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION));
classeFenetre.hCursor = LoadCursor(NULL, IDC_ARROW);
// classeFenetre.hbrBackground = (HBRUSH)(1 + COLOR_BTNFACE);
//classeFenetre.hbrBackground = CreatePatternBrush(LoadBitmap( instance, MAKEINTRESOURCE("images\Image1.bmp" ) ) );
HBITMAP hbmp = LoadBitmap(instance,MAKEINTRESOURCE(IDB_BITMAP1));
if(NULL == hbmp)
{
MessageBox(NULL,L"BitMap Loading Failed.",L"Error",MB_ICONEXCLAMATION | MB_OK);
}
else
{
HBRUSH hbr = CreatePatternBrush(hbmp);
if(NULL == hbr)
{
MessageBox(NULL,L"Brush Creation Failed.",L"Error",MB_ICONEXCLAMATION | MB_OK);
}
else
{
//StretchBlt();
HDC hdcMem = GetDC (NULL) ;
HDC wndHDC = GetDC (fenetrePrincipale) ;
StretchBlt(hdcMem, 0, 0, 800, 600, wndHDC, 0, 0, 1280, 1024, SRCCOPY);
classeFenetre.hbrBackground = hbr ;
}
}
classeFenetre.lpszMenuName = NULL;
classeFenetre.lpszClassName = L"classeF";
//fullscreen mode and delete minimize and max buttons
// On prévoit quand même le cas où ça échoue
if(!RegisterClass(&classeFenetre)) return FALSE;
//WS_OVERLAPPEDWINDOW
fenetrePrincipale = CreateWindow(L"classeF", L"Ma premiere fenetre winAPI !",WS_MAXIMIZE|WS_POPUP ,
CW_USEDEFAULT, CW_USEDEFAULT, 800, 630,
NULL,
NULL,//LoadMenu(instance, L"ID_MENU"),
cetteInstance,
NULL);
if (!fenetrePrincipale) return FALSE;
//ShowWindow(fenetrePrincipale, modeDAffichage);
ShowWindow(fenetrePrincipale,SW_MAXIMIZE);
UpdateWindow(fenetrePrincipale);
while (GetMessage(&message, NULL, 0, 0))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
return message.wParam;
}
thanks
You haven't shown the exact code, but it appears that you load a bitmap, create a brush from it, and then set that brush as the brush for your window. Brushes would indeed lead to the repeating-image behavior you report. To get a stretched bitmap, you may skip any brush-related code. Instead, handle the WM_ERASEBKGND message sent to your window. In it, call StretchBlt to paint your bitmap onto the client area of your window. The HDC to paint to is given in the message's wParam argument.
Steps
1, CreateWindowEx to create the window
2, SetWindowPos to place your window on top of all windows and Fullscreen
3, On your windows's WindowProce handle WM_PAINT message
4, Load your bitmap
5, Create a memory dc using CreateCompatibleDC
6, Selet your bitmap into memory dc by calling SelectObject
7, Do the StretchBlt to your actual dc, using the prepared memory dc as the source, you should know the actual width and height of the bitmap for proper stretching