Recently a customer of mine faced this issue. So he had an ActiveX control and when displaying the ActiveX control in browser a string is displayed right in the middle of the control: “ATL 9.0″.
So this issue happens because you didn’t override CComControlBase::OnDraw function. The default code for CComControlBase::OnDraw looks like the following…
HRESULT CComControlBase::YourClassName::OnDraw(_In_ ATL_DRAWINFO& di)
{
::SetTextAlign(di.hdcDraw, TA_CENTER|TA_BASELINE);
LPCTSTR pszText = _T("ATL ") _T(_ATL_VER_RBLD); // "ATL 9.0"
::TextOut(di.hdcDraw,
di.prcBounds->left + (di.prcBounds->right - di.prcBounds->left) / 2,
di.prcBounds->top + (di.prcBounds->bottom - di.prcBounds->top) / 2,
pszText,
lstrlen(pszText));
return S_OK;
}
MSDN documentation for CComControlBase::OnDraw function confirms this behavior. Quote…
The wizard’s default OnDraw draws a rectangle with the label “ATL 8.0″.The solution for this is to override CComControlBase::OnDraw function in your derived class and provide your own drawing or just return S_OK.
When working in MFC/ATL and then using a resource dll can at times cause bugs because resource handle is not properly set. For e.g. if you have a dialog resource in a dll and you instantiate a CDialog which results in an error because resource cannot be located in this application or dll since it’s in the resource dll. So solution for above problem will be to set correct resource handle.
MFC provides two functions…
- AfxGetResourceHandle
- AfxSetResourceHandle
pretty obvious names.
So we should first save our current resource handle and then set new resource handle before loading such a resource. Also don’t forget to set our old handle since its good practice.
Sample code snippet.
extern HINSTANCE hResDll = NULL; HINSTANCE hDefInstance = AfxGetResourceHandle(); AfxSetResourceHandle(hResDll); CBitmap Bmp; Bmp.LoadBitmap( IDB_NIBUS_FACE ); AfxSetResourceHandle(hDefInstance);
Internally MFC calls FindResource and LoadResource using this handle, so if it’s not properly set this will cause failure in loading resources.
In ATL it’s quite similar except that we’ve got a new function called AddResourceInstance which adds our new resource handle to existing list of handles. So when a look up is done given resource handle is also used. Following functions are provided in ATL to work with resource handles…
- AddResourceInstance
- GetResourceInstance – Similar to AfxGetResourceHandle
- SetResourceInstance – Similar to AfxGetSetResourceHandle
For newbies this is always a painful bug to resolve as they don’t know what went wrong since they expect this to be automagically done.
Well quite simple, but still quite frequently asked in forums…
There are two macros that does this for us. They are as follows.
Note: You must include atlconv.h
A2W – ANSI to UNICODE
W2A – UNICODE to ANSI
Before using these two macros you have to use this macro too…
USES_CONVERSION
Here is a code snippet for you…
#include <atlconv .h> //An example for converting from ANSI to UNICODE //use this first USES_CONVERSION; //An ANSI string LPSTR lpsz_ANSI_String = "An ANSI String"; //ANSI string being converted to a UNICODE string LPWSTR lpUnicodeStr = A2W( lpsz_ANSI_String ) //Another example for converting from UNICODE to ANSI //Use this first USES_CONVERSION //A UNICODE string LPWSTR lp_UNICODE_STR = L"A Unicode String"; //UNICODE string being converted to a ANSI string LPSTR lpsz_ANSI_STR = W2A( lp_UNICODE_STR );
Another option is to call WideCharToMultiByte and MultiByteToWideChar directly, it’s quite easy to use, at least easier than above macros. If you have doubts on usage of above functions then take a look at AfxW2AHelper and AfxA2WHelper functions. Since these are the functions that A2W and W2A internally calls.
Also as a homework take a look at CW2AEX and CA2WEX classes. Will be similar to above macros, looks to me like a secure version overload.
