How to obtain call stack programmatically in ATL and WTL (actually, ATL only)

While debugging, obtaining call stack at a certain [problematic] point of execution, such as especially deadlock condition or on assert, is an invaluable help. Debugger shows it, however it is possible to get the call stack programmatically and even more: having program database along with the executable it is even possible to resolve symbols and source code position. All this programmatically, without debugger running!

14-image001.png

Continue reading →

WTL style notification message cracking macros for common control notifications

Windows Template Library contains atlcrack.h header file with macros to reinterpret window message parameters: split if required and cast to proper type. For instance, instead of:

MESSAGE_HANDLER_EX(WM_SIZE, OnSize)

LRESULT OnSize(UINT, WPARAM wParam, LPARAM lParam)
{
UINT nType = (UINT) wParam;
CSize Extent(LOWORD(lParam), HIWORD(lParam));

it allows to make things simpler and in a more reliable fashion:

MSG_WM_SIZE(OnSize)

LRESULT OnSize(UINT nType, CSize Extent)
{

However, WTL’s macros only crack messages. WM_NOTIFY notifications are to be handled using MSG_WM_NOTIFY macro and the parameters are to be casted in each hander.

An aiwtlcrack.h header file included into project below defines macros to crack notifications for common controls (commctrl.h defined in header file in Platform SDK). The header defines, for example, macros: MSG_NM_DBLCLK, MSG_LVN_ITEMCHANGED, MSG_TVN_CUSTOMDRAW etc. Some of the notifications are duplicated to be able to use specific of the control class. For example, NM_CUSTOMDRAW notification message for a list view can be handled with both MSG_NM_CUSTOMDRAW and MSG_LVN_CUSTOMDRAW. In the latter case the argument will be casted to NMLVCUSTOMDRAW.

Continue reading →

Regular Expression bug in Visual Studio 2005

I already encountered similar issue once before but did not write down the details.

Text:

#define TBN_GETBUTTONINFO (TBN_FIRST-0)
#define TBN_BEGINDRAG (TBN_FIRST-1)
#define TBN_ENDDRAG (TBN_FIRST-2)
#define TBN_BEGINADJUST (TBN_FIRST-3)
#define TBN_ENDADJUST (TBN_FIRST-4)
#define TBN_RESET (TBN_FIRST-5)
#define TBN_QUERYINSERT (TBN_FIRST-6)
#define TBN_QUERYDELETE (TBN_FIRST-7)
#define TBN_TOOLBARCHANGE (TBN_FIRST-8)
#define TBN_CUSTHELP (TBN_FIRST-9)

Find What (using regular expressions):

^\#define:b+({([A-z\_])+}):b+.+$

Replace With:

#define MSG_\1(nIdentifier, Function) CC_MSG_WM_NOTIFY(\1, NMHDR, nIdentifier, Function)

Visual Studio C++.NET 2003 (correct):

#define MSG_TBN_GETBUTTONINFO(nIdentifier, Function) CC_MSG_WM_NOTIFY(TBN_GETBUTTONINFO, NMHDR, nIdentifier, Function)
#define MSG_TBN_BEGINDRAG(nIdentifier, Function) CC_MSG_WM_NOTIFY(TBN_BEGINDRAG, NMHDR, nIdentifier, Function)
#define MSG_TBN_ENDDRAG(nIdentifier, Function) CC_MSG_WM_NOTIFY(TBN_ENDDRAG, NMHDR, nIdentifier, Function)
#define MSG_TBN_BEGINADJUST(nIdentifier, Function) CC_MSG_WM_NOTIFY(TBN_BEGINADJUST, NMHDR, nIdentifier, Function)
#define MSG_TBN_ENDADJUST(nIdentifier, Function) CC_MSG_WM_NOTIFY(TBN_ENDADJUST, NMHDR, nIdentifier, Function)
#define MSG_TBN_RESET(nIdentifier, Function) CC_MSG_WM_NOTIFY(TBN_RESET, NMHDR, nIdentifier, Function)
#define MSG_TBN_QUERYINSERT(nIdentifier, Function) CC_MSG_WM_NOTIFY(TBN_QUERYINSERT, NMHDR, nIdentifier, Function)
#define MSG_TBN_QUERYDELETE(nIdentifier, Function) CC_MSG_WM_NOTIFY(TBN_QUERYDELETE, NMHDR, nIdentifier, Function)
#define MSG_TBN_TOOLBARCHANGE(nIdentifier, Function) CC_MSG_WM_NOTIFY(TBN_TOOLBARCHANGE, NMHDR, nIdentifier, Function)

Visual Studio C++.NET 2005 (wrong):

#define TBN_GETBUTTONINFO (TBN_FIRST-0)
#define MSG_(nIdentifier, Function) CC_MSG_WM_NOTIFY(, NMHDR, nIdentifier, Function)
#define MSG_(nIdentifier, Function) CC_MSG_WM_NOTIFY(, NMHDR, nIdentifier, Function)
#define MSG_(nIdentifier, Function) CC_MSG_WM_NOTIFY(, NMHDR, nIdentifier, Function)
#define MSG_(nIdentifier, Function) CC_MSG_WM_NOTIFY(, NMHDR, nIdentifier, Function)
#define MSG_(nIdentifier, Function) CC_MSG_WM_NOTIFY(, NMHDR, nIdentifier, Function)
#define MSG_(nIdentifier, Function) CC_MSG_WM_NOTIFY(, NMHDR, nIdentifier, Function)
#define MSG_(nIdentifier, Function) CC_MSG_WM_NOTIFY(, NMHDR, nIdentifier, Function)
#define MSG_(nIdentifier, Function) CC_MSG_WM_NOTIFY(, NMHDR, nIdentifier, Function)
#define MSG_(nIdentifier, Function) CC_MSG_WM_NOTIFY(, NMHDR, nIdentifier, Function)

How to create cursors on runtime in ATL and WTL

This sample projects shows how to create a cursor on runtime using CreateIconIndirect API as well as compose a new cursor out of the two cursor images, base and overlay image. A new cursor is composed out of system IDC_ARROW cursor and an application cursor resource.

Keywords: HCURSOR, GetIconInfo, CreateIconIndirect.

Visual C++.NET 2005 source code can be downloaded here, compiled binary – here.

How to intercept paste from clipboard into standard EDIT control with ATL and WTL

This sample project features subclassing EDIT control to intercept paste from clipboard and handle it programmatically. The sample fetches text from clipboard, converts it to upper case and replaces control’s selection with this text. There may be more specific handling, such as, for example, recognizing URL being pasted, splitting it into parts and filling multiple controls with URL parts (protocol, host, port, query etc.)

Keywords: CContainedWindow, ALT_MSG_MAP, WM_PASTE, CF_TEXT, GetClipboardData

Visual C++.NET 2003 source code can be downloaded here, compiled binary – here.

How to customize OLE property frame window with ATL and WTL

Window API provides useful functions OleCreatePropertyFrame and OleCreatePropertyFrameIndirect, which allow easily to pop up object’s property pages, OLE property pages. The frame, however, is not customizable, does not even allows centering relative to parent’s window. COlePropertyFrameDialogT template class is to be a solution for this problem.

Additionally the template offers useful methods to discover available property pages from object’s ISpecifyPropertyPages interface, if available. With multiple objects you have a choice to show union of individual object’s pages, or intersection of the pages (that is show only pages supported by all provided objects).

31-Image001.png

Code excerpt:

CMyOlePropertyFrameDialog Dialog;
Dialog.SetObject(pSampleObjectUnknown);
// NOTE: This instructs dialog to query for proeprty pages from assigned object(s)
Dialog.SetObjectPages();
const INT_PTR nDialogResult = Dialog.DoModal(m_hWnd);

Continue reading →