Do I need to call DeleteObject on CFont - mfc

I was wondering, do I need to call DeleteObject in the following case?
CFont* oldFont = label.GetFont();
LOGFONT oldLogFont;
oldFont->GetLogFont(&oldLogFont);
oldLogFont.lfWeight = FW_BOLD;
CFont newFont;
newFont.CreateFontIndirectW(&oldLogFont);
label.SetFont(&newFont, true);
// Do I need to call oldFont->DeleteObject() or newFont->DeleteObject()?
Thanks.

No you don't. MFC classes are RAII classes. When the object drops out of scope (ie gets deconstructed) the object will be deleted appropriately.

Related

HDC memory leak

Not sure why but im using Deleaker plugin to detect memory leaks.
in my code in debug build its saying i have amemory leak at GetDC
Then in release build it is saying i have a leak at CreateCompatibleDC
are these real leaks or false?
my delete objects are called when my class closes.
HDC hdc = GetDC(_hWnd);
_hdcMem = CreateCompatibleDC(hdc);
HBITMAP hbmOld = (HBITMAP)SelectObject(_hdcMem, _hBitmap);
while (_execute.load(std::memory_order_acquire))
{
func();
BitBlt(hdc, 0, 0, _Width, _Height, _hdcMem, 0, 0, SRCCOPY);
}
SelectObject(_hdcMem, hbmOld);
DeleteDC(_hdcMem);
DeleteObject(hbmOld);
DeleteObject(_hBitmap);
DeleteDC(hdc);
After GetDC, you must call ReleaseDC—not DeleteDC. DeleteDC is only used with CreateCompatibleDC. This is all spelled out in the documentation in case you forget.
Also, you are incorrectly cleaning up your device context. The reason you save the handles to the old objects is so that you can reselect them into the DC. You cannot delete them! Objects that are selected into a device context cannot be deleted—they are in use. (If you were checking the return values of these API functions, you would know that, because they would have returned an error.)
The code should look like this:
HDC hdc = GetDC(_hWnd);
_hdcMem = CreateCompatibleDC(hdc);
HBITMAP hbmOld = (HBITMAP)SelectObject(_hdcMem, _hBitmap);
while (_execute.load(std::memory_order_acquire))
{
func();
BitBlt(hdc, 0, 0, _Width, _Height, _hdcMem, 0, 0, SRCCOPY);
}
SelectObject(_hdcMem, hbmOld);
DeleteObject(_hBitmap);
DeleteDC(_hdcMem);
ReleaseDC(_hWnd, hdc);
It is unclear to me why you are using global variables for _hdcMem and _hBitmap when their scope is limited to this single bit of code. You create them at the top, and destroy them at the bottom, so they are useless outside of this code. You should limit their scope to just this section of the code, too. Being able to reason about the lifetime of objects/variables is key to stomping out memory leaks.
Note that using a library that wraps these native resources up in an RAII fashion (constructor acquires; destructor releases) would be a wonderful idea. It not only frees you from having to remember the details of how to clean up each time, but it also ensures that your code is exception-safe. If func() were to throw here, you would certainly have a memory leak. That is something a really good static analyzer would tell you as well.
You must use ReleaseDC() to free the HDC returned by GetDC().
Do not delete the hbmOld that SelectObject() returned. Just select it back into the HDC and let ReleaseDC() handle its deletion.

How do I call the Win32 API version of a function from an MFC application?

Specifically, I created a console with AllocConsole(). Now I want to take that window and move it.
First I want to call GetWindowRect to get its width and height. But if I just type that in it calls the implementation in CWnd. I need to call the one that accepts a HWND as the first parameter.
How do I do this?
Prefix the function name by the namespace operator scope resolution operator when you call it. This will prevent the CWnd member function from being a match.
void MyWindow::foo()
{
HWND wnd; // = ...
CRect rect;
::GetWindowRect(wnd, &rect);
}

Deleting GDI objects does not decrease their number

When I look in the Task Manager on the number of GDI objects for my process, then I see that not every call of function DeleteObject() for a GDI object causes decrementing this number, and the function call does not return FALSE (as it should if the object deletion was unsuccessful). I'm using plain Windows API GDI functions without additional libraries and wrappers such as MFC. Why such situation can happen and does it mean GDI resource leakage?
Here is the code how to recreate the problem:
void gditest()
{
HBRUSH h = CreateSolidBrush(RGB(255, 237, 5));
HRGN rgn = CreateRectRgn(0, 100, 100, 0);
FillRgn(g_DC, rgn, h);
int before = GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS);
int rs = DeleteObject( h );
if ( !rs )
throw;
int after = GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS);
}
Variables 'before' and 'after' are equal. g_DC is the HDC of the main window.
Stock GDI objects are never created nor destroyed. They are maintained by Windows and you can use them as you wish. If you have code like the following
HPEN hPen = (HPEN)GetStockObject(BLACK_PEN);
DeleteObject(hPen);
you will not see the GDI count go up or down. The call to DeleteObject will return TRUE even though the object is not really deleted.
If you want to check for resource leaks you can place calls to GetGuiResources in your code to compare the before/after values. You would typically place those calls where the resource counts should match, i.e. creation and destruction of resources match.
You should select a NULL object to Device Context before deleting the object.
Example:
SelectObject(g_DC, GetStockObject(NULL_BRUSH));
DeleteObject(h);

the function CWnd::CreateControl succeeds, but m_hWnd is NULL

I run the code with VC++ 6.0, everything is OK. But when run the same code under Visual C++ 2010, the handle of wnd(namely m_hWnd) is always NULL. Besides, the return value bRet is TRUE (i.e. success).
Here is my code:
BOOL CDemoDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
CRect rect;
GetClientRect(rect);
CWnd wnd;
BOOL bRet = wnd.CreateControl(_T("WMPlayer.OCX"), NULL, WS_VISIBLE, rect, this, 19089);
return TRUE; // return TRUE unless you set the focus to a control
}
The wnd object is going out of scope - try making it a member and checking what happens then. Also, if you are trying to assign a different handle to your dialog m_hWnd object, then you are making a mistake, since the m_hWnd should be valid for your dialog by the time that OnInitDialog is called (in response to the Create call), so you should not be reassigning the dialogs member window handle, but rather creating a separate member for it. Hope this helps.

RegisterClassEx Fails as Invalid Parameter - C++

A call to RegisterClassEx in my application is failing with error code 87, "The parameter is incorrect."
memset( &m_wcx, 0, sizeof(WNDCLASSEX) );
m_wcx.cbSize = sizeof(WNDCLASSEX); // size of structure
m_wcx.style = WS_ICONIC; // initially minimized
m_wcx.lpfnWndProc = &WndProc; // points to window procedure
m_wcx.cbClsExtra = 0; // no extra class memory
m_wcx.cbWndExtra = 0; // no extra window memory
m_wcx.hInstance = m_hInstance; // handle to instance
m_wcx.hIcon = ::LoadIcon( NULL, IDI_APPLICATION ); // default app icon
m_wcx.hCursor = ::LoadCursor( NULL, IDC_ARROW ); // standard arrow cursor
m_wcx.hbrBackground = NULL; // no background to paint
m_wcx.lpszMenuName = NULL; // no menu resource
m_wcx.lpszClassName = _pwcWindowClass; // name of window class
m_wcx.hIconSm = NULL; // search system resources for sm icon
m_atom = ::RegisterClassEx( &m_wcx );
if ( m_atom == 0 )
{
TRACE(_T("CNotifyWindow::CNotifyWindow : Failed to register window class.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), ::GetLastError(), __WFILE__, __LINE__);
THROW(::GetLastError());
}
Does anyone know what I'm doing wrong? Thanks.
The style member of the WNDCLASSEX structure accepts class styles, not window styles. In other words, you can't make all windows of that class initially minimized that way.
You should pass WS_ICONIC in the dwStyle argument to CreateWindow() or CreateWindowEx() instead.
The first thing is the WS_ICONIC. The window class style is something entirely diferent from window style. The class styles are the CS_* ones.
Usually "The parameter is incorrect" is the WINAPI's way of saying, "dude, you're sending me crap."
So one of the WNDCLASSEX member variables is probably crap. Start by taking a closer look at the variables that are most likely to have something inappropriate in them: m_wcx.hInstance, m_wcx.lpfnWndProc, and m_wcx.lpszClassName.
EDIT:
As pointed out by #Johann Gerell, m_wcx.style = WS_ICONIC is an example of this. The documentation says that this is a class style, but you've sent a window style. No good.
What's the difference? Well, you know the difference between a C++ class and an object, right? A class is like a blueprint. An object is an instantiation of that blueprint. Same is true of Window Classes & Windows. A Window Class is a blueprint for creating a window, and a window is an instantiation of that Window Class. Window Classes have styles that specify things like what kind of DC to use, when to vertical refresh -- low level stuff like that which applies to every instance of that window class. Windows also have styles, but these are different. Window styles specify per-window things like if the window should be visible, minimized, etc. So RegisterClassEx asked you for an orange, and you tried to give it an apple.