I have a problem with LoadImage.(Invalid Handle Error*)
HDC screen = CreateCompatibleDC(0);
HDC imageDC = CreateDC(0, 0, 0, 0);
HBITMAP filebmp = (HBITMAP)LoadImage(NULL,_T("C:\\file.bmp"),IMAGE_BITMAP,200,200, LR_CREATEDIBSECTION | LR_LOADFROMFILE);
SelectObject(imageDC, filebmp);
BOOL d = BitBlt(screen, 0, 0, 1920, 1080, imageDC, 0, 0, SRCCOPY);
This is my main Code. Where am I doing wrong?
I searched about it but couldn't find any solution for this.
Problem you may have is that your bitmap file is invalid, you can't just change .jpg to .bmp, your image needs to be saved as bmp.
I'm a little confused on how to double buffer this. I'm
not sure if I need to create another CreateCompatibleBitmap or CreateCompatibleDC and how to link it all.
This works as is but I don't think its double buffered right.
void __OnPaint(HWND hWnd, HDC _hdc = nullptr)
{
HDC hdc = _hdc;
PAINTSTRUCT paint;
RECT& rcClient = paint.rcPaint;
if (!_hdc)
hdc = BeginPaint(hWnd, &paint);
else
GetClientRect(hWnd, &rcClient);
if (hdc)
{
int width = rcClient.right - rcClient.left;
int height = rcClient.bottom - rcClient.top;
HDC hDCMem = CreateCompatibleDC(_hdc);
HBITMAP hBitmapMem = CreateCompatibleBitmap(hDCMem, width, height);
SelectObject(hDCMem, hBitmapMem);
Rectangle(hDCMem, 0, 0, width, height);
BLENDFUNCTION bfn;
bfn.BlendOp = AC_SRC_OVER;
bfn.BlendFlags = 0;
bfn.AlphaFormat = 0;
bfn.SourceConstantAlpha = 0x50;
AlphaBlend(hdc, 0, 0, width, height, hDCMem, 0, 0, width, height, bfn);
SetTextColor(hdc, RGB(255, 0, 0));
SetBkMode(hdc, TRANSPARENT);
DrawText(hdc, "Your text here", -1, &rcClient, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
//BitBlt(hdc, 0, 0, width, height, hDCMem, 0, 0, SRCCOPY);
DeleteDC(hDCMem);
DeleteObject(hBitmapMem);
}
if (!_hdc)
EndPaint(hWnd, &paint);
}
Also i found i have another problem with this.
i move my window in WM_TIMER, i call my __onpaint, problem im having is that it does not redraw it has something todo with the alphaBlend, it keeps what ever was under the window at the time of 1st draw, since it worked before i was using that
double buffering is to do all your printing and drawing on a temporary bitmap, that should be stored somewhere. the drawings on that bitmap can happen outside of WM_PAINT event (eg: on Adding items or selection change).
then on WM_PAINT event, the only thing you have to do is to project that bitmap to the window via BitBlt function or similar functions.
the way you are using AlphaBlend is wrong. AlphaBlend is used to draw images that have an AlphaChanel over an existing image as an overlay.
How do I make it so that this code strictly does the conversion from a Windows ICON to a CBitmap?
The code is incorrectly displaying the new bitmap on screen. :(
This code was acquired from 'someone' on the web. And though it achieves it's goal of converting the ICON, it also displays the icon on screen (upper left hand corner) which it should not be doing.
D'oh!
void CUIHelper::ConvertIconToBitmap2(CBitmap& bmpObj, HICON hIcon)
{
CClientDC clientDC(NULL);
CDC memDC;
memDC.CreateCompatibleDC(&clientDC);
ASSERT(hIcon);
ICONINFO info;
VERIFY(GetIconInfo(hIcon, &info));
BITMAP bmp;
GetObject(info.hbmColor, sizeof(bmp), &bmp);
HBITMAP hBitmap = (HBITMAP)CopyImage(info.hbmColor, IMAGE_BITMAP, 0, 0, 0);
ASSERT(hBitmap);
ASSERT(memDC.GetSafeHdc());
HBITMAP hOldBmp = (HBITMAP)memDC.SelectObject(hBitmap);
clientDC.BitBlt(0, 0, bmp.bmWidth, bmp.bmHeight, &memDC, 0, 0, SRCCOPY);
memDC.SelectObject(hOldBmp);
VERIFY( bmpObj.Attach(hBitmap) );
DeleteObject(info.hbmColor);
DeleteObject(info.hbmMask);
}
I am dumb when it comes to GDI.
clientDC.BitBlt(0, 0, bmp.bmWidth, bmp.bmHeight, &memDC, 0, 0, SRCCOPY);
should be
memDC.BitBlt(0, 0, bmp.bmWidth, bmp.bmHeight, &memDC, 0, 0, SRCCOPY);
I've looked at multiple responses to similar questions from both this site and others, and while I feel like I've gotten closer, I just can't quite get it right. Still, this is probably a super-noobish question.
So I used to only call the WndProc case "WM_Paint" (via InvalidateRect) one every few minutes, so I didn't really notice the leak. Now I've added something that calls it about 5 times a second. In that second my memory usage jumps about 3800k. Yeah, that got noticed...
Here's the code:
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
// Other cases omitted since we skip them due to "case WM_Paint:".
case WM_PAINT:
wndProc_Paint(hwnd);
break;
// Other cases omitted since we skip them due to "break;".
}
return 0;
}
void wndProc_Paint(HWND hwnd)
{
g_hbmBoard = ConvertIplImageToHBITMAP(targetBoardImg); //OpenCV command
BITMAP bm;
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps); // <- Breakpoint here while monitoring mem usage shows this is what is adding ~772k per call which never gets released.
HDC hdcMem = CreateCompatibleDC(hdc);
HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, g_hbmBoard);
GetObject(g_hbmBoard, sizeof(bm), &bm);
BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
hbmOld = (HBITMAP)SelectObject(hdcMem, g_hbmGreenLight);
GetObject(g_hbmGreenLight, sizeof(bm), &bm);
BitBlt(hdc, screenResW - 59, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
hbmOld = (HBITMAP)SelectObject(hdcMem, g_hbmWorkingLight);
GetObject(g_hbmWorkingLight, sizeof(bm), &bm);
BitBlt(hdc, screenResW - 94, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
hbmOld = (HBITMAP)SelectObject(hdcMem, g_hbmWorkingIndicator);
GetObject(g_hbmWorkingIndicator, sizeof(bm), &bm);
BitBlt(hdc, screenResW - 129, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
//DeleteObject(hbmOld);
SelectObject(hdcMem, hbmOld);
DeleteDC(hdcMem);
//SelectObject(hdc, hbmOld);
//ReleaseDC(hwnd, hdc);
//DeleteDC(hdc);
//DeleteObject(hdc);
EndPaint(hwnd, &ps);
}
With the exception of the g_hbmWorkingIndicator segment and the commented out parts, this is what my WM_Paint looked like before it got called 5times/sec (even before I put it into it's own function - which was a separate issue).
The line "HDC hdc = BeginPaint(hwnd, &ps);" is where the memory gets added, and it never gets released. This happens every time we go through the function. So now for the stuff I tried in fixing the issue.
Reading up on similar issues, I assumed that I needed to Release or Delete the DC of hdc. I wasn't (still aren't - yes I've read the MSDN page) sure how SelectObject works with these, so I've tried it with and without ReleaseDC & DeleteDC (&both) for both hdc and hdcMem. I also tried DeleteObject for hdc & hdcMem. None of those had any affect.
DeleteObject(hbmOld) had an effect. It solved the issue. Except it's the wrong solution, because although I don't have the memory climbing out of control, I do have some of the visuals getting replaced with the wrong visuals. g_hbmGreenLight usually gets g_hbmBoard's graphic while g_hbmWorkingLight turns green (g_hbmGreenLight's graphic). Moving "DeleteObject(hbmOld);" to after EndPaint(~) or trying to use a "SelectObject" just changes which objects get replaced by which wrong graphic - also; returns the memory leak.
EDIT: For completeness's sake, I have included the code for ConvertIplImageToHBITMAP(IplImage* image) here. It is entirely possible that this is the culprit.
HBITMAP ConvertIplImageToHBITMAP(IplImage* pImage)
{
IplImage* image = (IplImage*)pImage;
bool imgConverted = false;
if(pImage->nChannels != 3)
{
IplImage* imageCh3 = cvCreateImage(cvGetSize(pImage), 8, 3);
if(pImage->nChannels==1){cvCvtColor(pImage, imageCh3, CV_GRAY2RGB);}
image = imageCh3;
imgConverted = true;
}
int bpp = image->nChannels * 8;
assert(image->width >= 0 && image->height >= 0 && (bpp == 8 || bpp == 24 || bpp == 32));
CvMat dst;
void* dst_ptr = 0;
HBITMAP hbmp = NULL;
unsigned char buffer[sizeof(BITMAPINFO) + 255*sizeof(RGBQUAD)];
BITMAPINFO* bmi = (BITMAPINFO*)buffer;
BITMAPINFOHEADER* bmih = &(bmi->bmiHeader);
ZeroMemory(bmih, sizeof(BITMAPINFOHEADER));
bmih->biSize = sizeof(BITMAPINFOHEADER);
bmih->biWidth = image->width;
bmih->biHeight = image->origin ? abs(image->height) : -abs(image->height);
bmih->biPlanes = 1;
bmih->biBitCount = bpp;
bmih->biCompression = BI_RGB;
if (bpp == 8)
{
RGBQUAD* palette = bmi->bmiColors;
int i;
for (i = 0; i < 256; i++)
{
palette[i].rgbRed = palette[i].rgbGreen = palette[i].rgbBlue = (BYTE)i;
palette[i].rgbReserved = 0;
}
}
hbmp = CreateDIBSection(NULL, bmi, DIB_RGB_COLORS, &dst_ptr, 0, 0);
cvInitMatHeader(&dst, image->height, image->width, CV_8UC3, dst_ptr, (image->width * image->nChannels + 3) & -4);
cvConvertImage(image, &dst, image->origin ? CV_CVTIMG_FLIP : 0);
if(imgConverted)
{cvReleaseImage(&image);}
return hbmp;
}
So, all that said: Help me StackExchange, you're my only hope! ;_;
You are losing the original HBITMAP that is returned by SelectObject(hdcMem, g_hbmBoard), so you are not restoring it correctly before calling DeleteDC(), and thus it gets leaked. You are overwriting the hbmOld variable every time you call SelectObject(), but you are not restoring the current hbmOld value back into dcMem before overwriting hbmOld again. When using SelectObject(), you MUST restore the original object when you are done making changes to the HDC.
Try this instead:
void wndProc_Paint(HWND hwnd)
{
g_hbmBoard = ConvertIplImageToHBITMAP(targetBoardImg); //OpenCV command
BITMAP bm;
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
HDC hdcMem = CreateCompatibleDC(hdc);
HBITMAP hbmOld = (HBITMAP) SelectObject(hdcMem, g_hbmBoard); // save the original HBITMAP
GetObject(g_hbmBoard, sizeof(bm), &bm);
BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, g_hbmGreenLight); // returns g_hbmBoard, no need to save it to hbmpOld
GetObject(g_hbmGreenLight, sizeof(bm), &bm);
BitBlt(hdc, screenResW - 59, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, g_hbmWorkingLight); // returns g_hbmGreenLight, no need to save it to hbmpOld
GetObject(g_hbmWorkingLight, sizeof(bm), &bm);
BitBlt(hdc, screenResW - 94, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, g_hbmWorkingIndicator); // returns g_hbmWorkingLight, no need to save it to hbmpOld
GetObject(g_hbmWorkingIndicator, sizeof(bm), &bm);
BitBlt(hdc, screenResW - 129, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, hbmOld); // restore the original HBITMAP
DeleteDC(hdcMem);
EndPaint(hwnd, &ps);
// who owns g_hbmBoard? ConvertIplImageToHBITMAP() creates
// a new HBITMAP, so you need to free it with DeleteObject()
// before calling ConvertIplImageToHBITMAP() again. It would
// be better to create g_hbmBoard one time outside of WM_PAINT,
// recreate g_hbmBoard only when the source image actually changes,
// and then re-use g_hbmBoard as-is inside of WM_PAINT.
// ConvertIplImageToHBITMAP() really does not belong in WM_PAINT...
//
//DeleteObject(g_hbmBoard);
}
Alternatively, use SaveDC()/RestoreDC() instead:
void wndProc_Paint(HWND hwnd)
{
g_hbmBoard = ConvertIplImageToHBITMAP(targetBoardImg); //OpenCV command
BITMAP bm;
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
HDC hdcMem = CreateCompatibleDC(hdc);
int iOldState = SaveDC(hdcMem); // save everything the HDC currently has selected
SelectObject(hdcMem, g_hbmBoard);
GetObject(g_hbmBoard, sizeof(bm), &bm);
BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, g_hbmGreenLight);
GetObject(g_hbmGreenLight, sizeof(bm), &bm);
BitBlt(hdc, screenResW - 59, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, g_hbmWorkingLight);
GetObject(g_hbmWorkingLight, sizeof(bm), &bm);
BitBlt(hdc, screenResW - 94, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, g_hbmWorkingIndicator);
GetObject(g_hbmWorkingIndicator, sizeof(bm), &bm);
BitBlt(hdc, screenResW - 129, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
RestoreDC(hdcMem, iOldState); // restore everything the HDC originally had selected
DeleteDC(hdcMem);
EndPaint(hwnd, &ps);
// who owns g_hbmBoard? ConvertIplImageToHBITMAP() creates
// a new HBITMAP, so you need to free it with DeleteObject()
// before calling ConvertIplImageToHBITMAP() again. It would
// be better to create g_hbmBoard one time outside of WM_PAINT,
// recreate g_hbmBoard only when the source image actually changes,
// and then re-use g_hbmBoard as-is inside of WM_PAINT...
// ConvertIplImageToHBITMAP() really does not belong in WM_PAINT...
//
//DeleteObject(g_hbmBoard);
}
I would like to owner-draw a red border to a EDIT or Push button in C++ win32 api. NO MFC Please.
I have gotten this far. Drawing a black border but most if not all the hButtonDC,hButtonBitmap are undeclared.
PAINTSTRUCT ps;
HDC hdc;
HBRUSH hBrush;
BeginPaint(hwndButton2, &ps);
// Create memory DC to contain hButtonBitmap
hButtonDC = CreateCompatibleDC(ps.hdc);
hButtonBitmap = SelectObject(hButtonDC, hButtonBitmap);
// Create second memory DC where the button borders will be drawn and select into this DC an empty bitmap with the
// size of the button bitmap
hMemDC = CreateCompatibleDC(ps.hdc);
hBitmap = CreateCompatibleBitmap(ps.hdc, ps.rcPaint.right, ps.rcPaint.bottom);
hBitmap = SelectObject(hMemDC, hBitmap);
// Copy hButtonDC into hMemDC
BitBlt(hMemDC, 0, 0, ps.rcPaint.right, ps.rcPaint.bottom, hButtonDC, 0, 0, SRCCOPY);
// Paint the button borders with black pixels (1 pixel width)
PatBlt(hMemDC, 0, 0, ps.rcPaint.right - 1, 1, BLACKNESS);
PatBlt(hMemDC, ps.rcPaint.right - 1, 0, 1, ps.rcPaint.bottom, BLACKNESS);
PatBlt(hMemDC, 0, ps.rcPaint.bottom - 1, ps.rcPaint.right , 1, BLACKNESS);
PatBlt(hMemDC, 0, 0, 1, ps.rcPaint.bottom - 1, BLACKNESS);
// Paint the button with drawn borders to its window DC, ps.hdc .
BitBlt(ps.hdc, 0, 0, ps.rcPaint.right, ps.rcPaint.bottom, hMemDC, 0, 0, SRCCOPY);
// Delete hBitmap e hMemDC
DeleteObject(SelectObject(hMemDC, hBitmap));
DeleteDC(hMemDC);
// Delete hButtonDC
SelectObject(hButtonDC, hButtonBitmap);
DeleteDC(hButtonDC);
EndPaint(hWnd, &ps);