GDI Object leak on System.Drawing.Bitmap.GetHicon() - c++

I've seen similar questions but none satisfies my scenario.
I am fixing a GDI Objects leak on a C++ Windows Form Application.
This is the Exception it throws:
A generic error occurred in GDI+. at System.Drawing.Bitmap.GetHicon()
This is the GetHicon call at the line where the crash happens:
this->notifyIcon1->Icon=Icon->FromHandle(((Bitmap^)imgsApp->Images[0])->GetHicon());
After doing some reading here, and on https://learn.microsoft.com/en-us/dotnet/api/system.drawing.icon.fromhandle?view=net-5.0, I see I need to call DestroyIcon() in order to release the Icon Handle (not sure if the wording is correct here), but I am having trouble doing this not being familiar with Windows Form.

Try this:
IntPtr iconHandle = ((Bitmap^)imgsApp->Images[0])->GetHicon();
Icon ^newIcon = Icon::FromHandle(iconHandle);
this->notifyIcon1->Icon = (Icon^) newIcon->Clone();
newIcon->Dispose();
DestroyIcon((HICON)iconHandle.ToPointer());
Per Icon.FromHandle: should I Dispose it, or call DestroyIcon?:
Conclusion: After Icon.FromHandle, the field ownHandle is false, and thus Dispose / FromHandle won't call DestroyIcon
Therefore: if you create an Icon using Icon.FromHandle you'll have to Dispose() the Icon as well as call DestroyIcon, just as the remarks section says

Related

OnInitialUpdate called twice

One of our MFC legacy applications shows a behavior I do not really understand right now. I am not an MFC expert, however. The symptom that I observe and which is causing problems is that OnInitialUpdate of the views is called twice by the framework during app start-up. As I understand the documentation it should be called only once.
My investigation revealed that the app calls the following code in its InitInstance:
CMainFrame *const pMainFrame = new CMainFrame;
if (!pMainFrame->LoadFrame(IDR_MAINFRAME)) { return FALSE; }
m_pMainWnd = pMainFrame;
This causes CFrameWnd::LoadFrame being called inside the framework. From here both calls to OnInitialUpdate originate. The first when Create is called and the second when SendMessageToDescendants is called to send WM_INITIALUPDATE.
Our app overloads CMainFrame::OnCreateClient to create a splitter window:
Splitter.CreateStatic(this, 2, 2);
Splitter.CreateView(0, 0, RUNTIME_CLASS(MyView),CSize(0,0), pContext);
// ...
The call to Splitter.CreateView is what triggers OnInitialUpdate to be called the first time. But as I could see from the documentation this implementation is as intended. So unfortunately this is where I get stuck. I don't understand if the OnInitialUpdate call from SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE) or from CSplitterWnd::CreateView is wrong.
What else could I take a look at to figure out the root cause of this problem?
Is it possible for OnInitialUpdate to be called twice and we need to make sure that our app can cope with this?
If the answer to question 2 is yes: What is the best way to archive this?
EDIT
Further investigation has shown that CSplitterWnd::CreateView only sends WM_INITIALUPDATE if the passed CCreateContext is a nullptr. So I checked CMainFrame::OnCreateClient and it is indeed called by the framework with pContext being nullptr.
EDIT2
As requested in the comments here is the code adding the DocTemplate:
CSingleDocTemplate *const pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CMenuDoc),
RUNTIME_CLASS(CMainFrame),
RUNTIME_CLASS(CMenuView));
if (!pDocTemplate)
return FALSE;
AddDocTemplate(pDocTemplate);
There is also a call
Splitter.CreateView(1, 1, RUNTIME_CLASS(CMenuView),CSize(0,0), pContext);
in the CMainFrame::OnCreateClient. If I understand the comments correctly this is wrong?
The two calls of OnInitialUpdate are for the same instances of the views. If I followed the stack trace correctly the reason for the CCreateContext being a nullptr is that no context is passed to LoadFrame. The context passed to CFrameWnd::LoadFrame is just forwarded to CMainFrame::OnCreateClient. But what context should I pass?

Direct2D : Unhandled Exception In WM_RESIZE switch case

I am creating a Simple Direct2D Application. Unfortunately it is giving
an unhandled exception. The function where it is taking place:
void DemoApp::OnResize(UINT width, UINT height)
{
if (m_pRenderTarget) <----|****The exception occurs here.....****
{
// Note: This method can fail, but it's okay to ignore the
// error here, because the error will be returned again
// the next time EndDraw is called.
m_pRenderTarget->Resize(D2D1::SizeU(width, height));
}
}
And the code snippet calling OnResize() is:
DemoApp *pDemoApp = reinterpret_cast<DemoApp *>(static_cast<LONG_PTR>(
::GetWindowLongPtrW(
hwnd,
GWLP_USERDATA
)));
bool wasHandled = false;
if (pDemoApp)
{
switch (message)
{
case WM_SIZE:
{
UINT width = LOWORD(lParam);
UINT height = HIWORD(lParam);
pDemoApp->OnResize(width, height);
}
result = 0;
wasHandled = true;
break;
/*rest of switch case*/
}
The exception says:
Unhandled exception at 0x00007FF6BE402CCA in Simple Direct2D application.exe: 0xC000041D: An unhandled exception was encountered during a user callback. occurred
Exception screenshot:
As soon as I start to debug, the program, it gives the exception.I even copied the program word by word from the site.As I am new to the world of DirectX, I am clueless about the exception. What should I do?
I've compiled that sample. It works in 32-bit builds, crashes in 64-bit builds.
The error is in Microsoft's sample code and is unrelated to Direct2D.
They pass this into SetWindowLongPtr, in combination with PtrToUlong macro for type conversion. In 64-bit builds, this is 8-bytes long, SetWindowLongPtr also accepts 8 bytes, however PtrToUlong macro converts to unsigned long which is only 4 bytes. So PtrToUlong macro drops higher 4 bytes from this pointer, and the app fails spectacularly.
You can fix by replacing PtrToUlong( pDemoApp ) with (LONG_PTR)pDemoApp
P.S. I think the root cause is, MS pretends very hard Win32 platform is obsolete, pushes developers to UWP instead. That’s why in their DirectX and Direct2D samples, they don’t use their own ATL, because it’s desktop-only library. Using ATL would dramatically simplify these samples: CComPtr for interface pointers, CWindowImpl for windows creation and message handling, and lots more.
Update: here's a better sample.
Since you are getting an exception in a point where you are doing nothing but reading a member variable, the only possible reason I can think of is that your this pointer is garbage. While it is common for window message handlers to be called before SetWindowLong has been called, in which case the value returned by GetWindowLong is null, you (correctly) check that it isn't, and this is confirmed by your screenshot (as well as the fact that it's garbage). The possible options left are that either what you pass to SetWindowLong is not a pointer to a valid DemoApp object, or that it once was but the object is no longer valid when the message is received. So, as an answer to your question, you should check that
the value you pass to SetWindowLong really is a valid pointer to a DemoApp
the DemoApp whose pointer you pass is in the heap or a global variable, not a local variable that can go out of scope during the lifetime of the window
you don't delete your DemoApp object, if it is heap allocated, during the lifetime of your window
Also, you are explicitly using the Unicode version of GetWindowLongPtr, which is also used in the original example (with no explanation why). Check your project settings that you are compiling an Unicode application.

Why might CreatePointFont() return NULL for me?

In my WTL app Im trying to change the font of a static label. But CreatePointFont returns NULL. Why might this be?
CFont font;
font.CreatePointFont(120, _T("Segoe UI"));
text.Attach(GetDlgItem(IDC_MAINTEXT));
text.SetFont(font);
Are you sure that CreatePointFont is returning NULL?
For a font to be set, it must remain in memory, whereas from your code snippet it appears that the variable font is destroyed directly after setting it.
Declare the variable somewhere that will not be deleted during the lifetime of the text object, such as the class if you are using an MFC object.
The nPointSize argument to CreatePointFont() is in tenths of a point, perhaps your size of 12/10 = 1.2 points is too small. You probably meant to pass in 120.
On a lighter note, you may also want to visit the ban comic sans web site, if you're using this for a business application.
The documentation is not too verbose on the fail conditions, but my guess it you don't have the named font on the machine
Check if it is listed by the EnumFontFamilies function (quote form the documentation):
The Windows EnumFontFamilies function can be used to enumerate all currently available fonts

"Debug Assertion" Runtime Error on VS2008?

I'm writing a C++ MFC program on VS2008 and I'm getting this "Debug Assertion Error" when I first run the program sometimes. When I try to debug it, it takes me to this winhand.cpp file which is not part of the program I wrote so I'm not sure how to debug this.
It takes the error to this place in winhand.cpp
CObject* pTemp = LookupTemporary(h);
if (pTemp != NULL)
{
// temporary objects must have correct handle values
HANDLE* ph = (HANDLE*)((BYTE*)pTemp + m_nOffset); // after CObject
ASSERT(ph[0] == h || ph[0] == NULL);
if (m_nHandles == 2)
ASSERT(ph[1] == h);
}
So why does this error happen? Why does it only happen sometimes (50% of the time)? How would I debug this?
I'll provide some code if is needed.
THANKS!
The code that is asserting is part of MFC's CHandleMap class. MFC deals with windows as CWnd objects, but Windows deals with them as HWND handles. the handle map allows MFC to 'convert' an HWND into a pointer to the MFC object representing that object.
What the assertion seems to be doing is checking that when a lookup of the handle finds an MFC object, that the MFC object also thinks it's wrapping the same handle.
If they're different, then you get the assertion.
So it would appear that something is corrupting the handle map or the MFC object for that handle or you're doing something incorrect that gets these 2 data structures out of sync.
Some things you might do to try to debug the problem is to determine:
what MFC object is being found in the lookup (that's what's being pointed to by pObject)
what the MFC object thinks it's wrapping (that's the handle ph[0] and/or ph[1] - I'm not sure why there can be 2 of them)
what the handle is for (that's h)
Do the handles look like handle values or do they look like garbage? Does pObject point to something that looks like an MFC object, or garbage? Do any of these these things seem related?
The answers to these questions may point to what you need to do next (maybe set a debug write breakpoint on the item that looks like it's trashed).
I got this same assertion few days ago, and after some google search,
I found the solution for my case here:
http://forums.codeguru.com/showthread.php?216770-What-would-cause-this-assertion
In my case, change to misused
CDC* dc = GetDC();
CSize spaceSize = dc->GetTextExtent(" ");
dc->DeleteDC();
to
CDC* dc = GetDC();
CSize spaceSize = dc->GetTextExtent(" ");
ReleaseDC(dc);
would fix it.
Look out for code along those lines (from memory from Stroustrup's book):
c1 = (t2+t3).c_str();
(in spirit, could be other commands and expressions of course).Temporary objects are destroyed after their enclosing full expression has been evaluated, or at least the standard allows them to be. That means that what you would like to allocate to c1 may, or may not, still be in memory where it can be assigned to c1. The compiler may alert you to this issue, and the issue may or may not arise depending on what exactly you assign and other circumstances (I am not compiler writer), which would also explain why you get this error message only sometimes.
So in your shoes, I'd scan my code for similar expressions and clean them up.
When the debugger breaks, head up the call stack to the first bit of your code (if there is any - hopefully there is!). Ideally it's as simple as something in your code calling a library function incorrectly, and the library is catching the error with an assert and alerting you to that. (I don't think anyone will be able to tell what's wrong from the library code, we need to see your code.)
Otherwise, you're in for some tricky debugging: you're doing something wrong with the library that is asserting (looks like MFC) so go back and review all your MFC code and make sure everything is correct and according to the documentation.
This looks suspiciously like an error I had this morning. Is this happening in OnIdle()?
I know this is a very old post, but hoping that someone may get a little help from my answer.
I also faced a similar issue recently because of my simple mistake, then I came across this post and got a hint from "pac"'s post.
What I found is that if I use DeleteDC() to release DC returned from GetWindowDC() or GetDC() I will get the above assertion in MFC frame once CPaintDC object instance goes out of scope.
CDC * pDC = GetWindowDC();
...
ReleaseDC(pDC);
You have to use DeleteDC() only in conjunction with CreateDC() API.
CDC * pDC = new CDC();
pDC->CreateDC();
....
pDC->DeleteDC();
We had this problem when some of our project dlls were linking MFC as static library and some as shared library (check "Use of MFC" in Project settings)

ActiveX plugin causes ASSERT to fail on application exit in VS2008

My MFC application using the "ESRI MapObjects LT2" ActiveX plugin throws an ASSERT at me when closing it.
The error occurs in cmdtarg.cpp:
CCmdTarget::~CCmdTarget()
{
#ifndef _AFX_NO_OLE_SUPPORT
if (m_xDispatch.m_vtbl != 0)
((COleDispatchImpl*)&m_xDispatch)->Disconnect();
ASSERT(m_dwRef <= 1); //<--- Fails because m_dwRef is 3
#endif
m_pModuleState = NULL;
}
I built the (native C++) application with VC9.
When I compile the application with VC6, it behaves nicely.
What could be the reason for this?
That looks like a reference count. Could this "target" be referenced by something else, something that's not releasing it?
You can trace the Addref and Release calls defining _ATL_DEBUG_INTERFACES
from http://msdn.microsoft.com/en-us/library/sycfy8ec(VS.80).aspx
_ATL_DEBUG_INTERFACES
Define this macro before including any ATL header files to trace all AddRef and Release calls on your components' interfaces to the output window.
Using _ATL_DEBUG_INTERFACES did not yield any additional output...
I defined it on the first line of stdafx.h, directly after #pragma once so I guess this is early enough.
Maybe the reason is how I am using the ActiveX control:
I'm not calling AddRef() or Release() by myself.
The MapObjects Installer comes with sample code with lots of wrapper classes which must have been generated by VC6 or something earlier.
I tried to generate wrapper classes myself with VC9 but there occured errors which I wasn't able to fix.
I use the control by letting one of my windows have a member of type CMap1 (derived from CWnd), which is one of those generated wrapper classes. In CMyWnd::OnCreate() I also call CMap1::Create() and that's it, I'm finished: I can add a layer and the control displays a world map.
I have pretty much no idea what the reference-count stuff is about as I have not added or released any references. At least not knowingly...
The control is pretty old: The .OCX file has the year 2000 in its version information.
It's also not officially supported anymore but I don't have any substitue.
The following solved it for me:
In the window that contains the control, add an OnDestroy() handler:
void CMyWnd::OnDestroy()
{
// Apparently we have to disconnect the (ActiveX) Map control manually
// with this undocumented method.
COleControlSite* pSite = GetOleControlSite(MY_DIALOG_CONTROL_ID);
if(NULL != pSite)
{
pSite->ExternalDisconnect();
}
CWnd::OnDestroy();
}