The beta version of the MFC Feature Pack (the extension to MFC 9 from Visual Studio 2008) contains an extended dialog class implementation, CDialogEx. What this brings new, publicly, is the ability to set the background of the dialog box to a color or an image.

A first new method allows to set a background color.

void SetBackgroundColor(COLORREF color, BOOL bRepaint = TRUE);

Dialog box with yellow background.

A second overloaded method allows to set an image on the background.

void SetBackgroundImage(
    HBITMAP hBitmap,
    BackgroundLocation location = BACKGR_TILE,
    BOOL bAutoDestroy = TRUE,
    BOOL bRepaint = TRUE);

BOOL SetBackgroundImage(
    UINT uiBmpResId,
    BackgroundLocation location = BACKGR_TILE,
    BOOL bRepaint = TRUE);

You can use it like this:

BOOL CDialogDemoDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// ...

	HBITMAP bmp = ::LoadBitmap(AfxGetResourceHandle(), MAKEINTRESOURCE(IDB_BITMAP_LOGO));
	SetBackgroundImage(bmp, BACKGR_TILE);

	return TRUE;
}

Dialog box with image on the background

What is very weird is that the only styles for the image are these:

enum BackgroundLocation
{
	BACKGR_TILE,
	BACKGR_TOPLEFT,
	BACKGR_TOPRIGHT,
	BACKGR_BOTTOMLEFT,
	BACKGR_BOTTOMRIGHT,
};

This implementation lacks two basic styles: Center and Stretch. I really don’t understand why they were not implemented. It’s much more likely to need an image centered or stretched that aligned at the bottom-left, for instance. Thus, I don’t see how good this class is if I have to override the entire painting myself if I need that functionality.

Here is an implementation of a dialog class that supports those styles.

Hits for this post: 19980 .

At the beginning of January, Microsoft released a beta version of MFC Feature Pack, an exstension to the MFC shipped with Visual Studio 2008. This feature pack allows developers to create applications with the look and feel of Office, Visual Studio and Internet Explorer. MFC application can now support:

  • Office Ribbon
  • Office 2003, XP and 2007 look and feel
  • docking toolbars and panes in the Visual Studio style
  • customizable toolbars and menus
  • advanced GUI controls
  • advaced MDI tabs and groups

I have published an article on www.codeguru.com about enabling Office 2007 style on a MDI application. The article is called MFC Feature Pack: An Introduction. I encourage you to read it. A Romanian version will be available soon at www.codexpert.ro.

, , , , , Hits for this post: 33360 .

Let’s asume you want to change the font of a window\control and for the sake of simplicity let’s consider an MFC dialog application. In that case, there are several steps you should follow:

  • declare a CFont variable in the dialog class
  • create the font in OnInitDialog (using CreateFont)
  • set the font to the control (using SetFont)

For example, say that you want to use Arial size 12 for a multiline edit control. In that case you could put the following code in OnInitDialog:

BOOL CFontSampleDlg::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   

	VERIFY(editFont.CreateFont(
		12,                        // nHeight
		0,                         // nWidth
		0,                         // nEscapement
		0,                         // nOrientation
		FW_NORMAL,                 // nWeight
		FALSE,                     // bItalic
		FALSE,                     // bUnderline
		0,                         // cStrikeOut
		ANSI_CHARSET,              // nCharSet
		OUT_DEFAULT_PRECIS,        // nOutPrecision
		CLIP_DEFAULT_PRECIS,       // nClipPrecision
		DEFAULT_QUALITY,           // nQuality
		DEFAULT_PITCH | FF_SWISS,  // nPitchAndFamily
		_T("Arial")));             // lpszFacename   

	GetDlgItem(IDC_EDIT_SAMPLE)->SetFont(&editFont);   

	return TRUE;  // return TRUE  unless you set the focus to a control
}

The result should be the following:

control with Arial of wrong size

Look carefully and you’ll see that’s not the right size 12? Why? Because the height and width (which doesn’t matter in this case) parameters for CreateFont() are given in logical units and not pixels. When you passed 12 we meant pixels, so to correctly create a font of size 12 pixels, you must convert from pixels to logical units. To do that, you need to determine the number of pixels per logical inch along the screen height. For that you have to use GetDeviceCaps() with the appropriate device context. To compute the actual value, MulDiv() is used. This function multiplies two 32-bit integers and devides the 64-bit result by a third 32-bit integer.

In this case, OnInitDialog() becomes:

BOOL CFontSampleDlg::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   

	CDC* pDC = GetDC();
	int desiredHeight = 12;
	int height = -MulDiv(desiredHeight, pDC->GetDeviceCaps(LOGPIXELSY), 72);
	ReleaseDC(pDC);   

	VERIFY(editFont.CreateFont(
		height,                    // nHeight
		0,                         // nWidth
		0,                         // nEscapement
		0,                         // nOrientation
		FW_NORMAL,                 // nWeight
		FALSE,                     // bItalic
		FALSE,                     // bUnderline
		0,                         // cStrikeOut
		ANSI_CHARSET,              // nCharSet
		OUT_DEFAULT_PRECIS,        // nOutPrecision
		CLIP_DEFAULT_PRECIS,       // nClipPrecision
		DEFAULT_QUALITY,           // nQuality
		DEFAULT_PITCH | FF_SWISS,  // nPitchAndFamily
		_T("Arial")));             // lpszFacename   

	GetDlgItem(IDC_EDIT_SAMPLE)->SetFont(&editFont);   

	return TRUE;  // return TRUE  unless you set the focus to a control
}

and the result is:

Arial with correct size 12 pixels

and that is what we wanted in the first place.

, , , , , Hits for this post: 25498 .

You probably noticed that IE7 or Windows Media Player 11 don’t have the menu shown by default; it only shows up when you press the ALT key. This is one particularity of the look and feel of Windows Vista Aero. You can find guidelines about designing menus here:

As revealed by the VC++ team some time ago, MFC 9.0 offers support for hiding the menus automatically and manually, in accordance with the Aero look and feel. A recent article in the MSDN Magazine by Tarek Madkour, explains how: by calling the SetMenuBarVisibility method from CFrameWnd with the AFX_MBV_DISPLAYONFOCUS. What is not told is that works only for SDI applications.

Menus in SDI applications 

In a SDI application you have a class derived from CFrameWnd, usually called CMainFrame. In the OnCreate() method, after calling the CFrameWnd’s OnCreate, you can call SetMenuBarVisibility:

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
   if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
      return -1; 

   SetMenuBarVisibility(AFX_MBV_DISPLAYONFOCUS); 

   // other stuff here 

   return 0;
}



AFX_MBV_DISPLAYONFOCUS is defined in afxwin.h:

// Frame window menu bar visibility styles
#define AFX_MBV_KEEPVISIBLE    0x01L // always visible
#define AFX_MBV_DISPLAYONFOCUS 0x02L // toggle state on ALT
#define AFX_MBV_DISPLAYONF10   0x04L // display on F10



The result is that the menu is automatically hidden (as can be seen in the image)

SDI menu is hidden 

and shown only when pressing the ALT key.

SDI menu is shown

Menus in MDI applications

The same technique does not work for MDI menus. In such an application you have

  • a main frame, represented by a (usually called) CMainFrame class derived from CMDIFrameWnd, which in turn is derived from CFrameWnd, and
  • one or more child frames, derived from CMDIChildFrame, which in turn is derived from CFrameWnd

Both the main window and the child windows can have menus, but the menu of a child window is shown on the same bar with the menu of the main window. As long as a child window exists the menu of that document is shown. When no child window exists the menu of the main window is shown. Both on the same bar.

Trying to make the menu of the child window(s) hidden by default does not work. Calling SetMenuBarVisibility has no effect:

int CChildFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
   if (CMDIChildWnd::OnCreate(lpCreateStruct) == -1)
      return -1;

   SetMenuBarVisibility(AFX_MBV_DISPLAYONFOCUS);

   return 0;
}



Calling SetMenuBarVisibility for the main frame results in an assertion failure because the implementation in the CMDIFrameWnd expects the parameter to be always AFX_MBV_KEEPALIVE; it doesn’t do anything else, such as calling the function from the base class.

void CMDIFrameWnd::SetMenuBarVisibility(DWORD dwStyle)
{
   ENSURE_ARG(dwStyle == AFX_MBV_KEEPVISIBLE);
   ASSERT(m_dwMenuBarVisibility == AFX_MBV_KEEPVISIBLE);
}



Overriding the method in CMainFrame accept any parameter and call the method in CFrameWnd to bypass CMDIFrameWnd does not have any effect either.

void CMainFrame::SetMenuBarVisibility(DWORD dwStyle)
{
   CFrameWnd::SetMenuBarVisibility(dwStyle);
}



In conclusion MFC 9.0 supports the Aero look-and-feel for the automatically hiding of menus, but only in SDI applications.

Hits for this post: 13605 .

Windows Vista redesigned the way the file dialogs look. MFC 9.0 (that will ship with Visual Studio 2008) was updated to support the new look and feel. If you compile your MFC application with VS 2008 you get the new file dialogs with no additional change. On the other hand if you run the application under Win XP the old file dialogs are shown. This is possible because of an additional parameter to the constructor of CFileDialog. The old constructor signature was:

explicit CFileDialog(
   BOOL bOpenFileDialog,
   LPCTSTR lpszDefExt = NULL,
   LPCTSTR lpszFileName = NULL,
   DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
   LPCTSTR lpszFilter = NULL,
   CWnd* pParentWnd = NULL,
   DWORD dwSize = 0);



The new constructor in MFC 9.0 has an additional parameter, a BOOL flag indicating whether the Vista dialogs should be displayed of not.

explicit CFileDialog(
   BOOL bOpenFileDialog,
   LPCTSTR lpszDefExt = NULL,
   LPCTSTR lpszFileName = NULL,
   DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
   LPCTSTR lpszFilter = NULL,
   CWnd* pParentWnd = NULL,
   DWORD dwSize = 0,
   BOOL bVistaStyle = TRUE);



To display the Vista file dialogs, all you have to do is instantiate a CFileDialog object and create the dialog itself:

CFileDialog dlg(TRUE, NULL, NUL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
                L"Text files (*.txt)|*.txt||", this);
dlg.DoModal();



Vista look and feel file dialog

You can still use the old file dialog look and feel if you set the last parameter to FALSE:

CFileDialog dlg(TRUE, NULL, NUL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
                L"Text files (*.txt)|*.txt||", this, 0, FALSE);
dlg.DoModal();



Win XP look and feel file dialog

This old dialog is what you automatically get when running on a previous operating system.

Hits for this post: 13861 .

Visual Studio 2008 (formely code-named ‘Orcas’) has several important updates for VC++ and MFC. Among them the possibility to create syslink controls, command or split buttons and network address controls. In this post I will show how you can work with the syslink control. The control provides a way to embed hypertext links in a window. It is actually a window that renders marked-up text just as hyperlinks in a web browser. Multiple links can be put in a single control, and are accessed by a zero-based index.

Currently it supports the anchor tag (<A>) with the HREF and ID attributes. HREF is used to specify a URL of any protocol (http, ftp, mailto, etc.). On the other hand ID specifies an unique name within the control, associated with an individual link.

The content is available in the toolbar, so you can simply drag and drop syslink controls onto you dialog template.

Syslink controls on dialog

You can specify the text, including the anchor tag from the properties page, or you can use the SetWindowText function to set it at run-time.

GetDlgItem(IDC_SYSLINK1)->SetWindowText(
   L"Visit my web site"
   L" and check my blog.");



You have to handle the NM_CLICK notification, check which link was clicked and take the appropriate action:

BEGIN_MESSAGE_MAP(CMFCDemoDlg, CDialog)
	ON_NOTIFY(NM_CLICK, IDC_SYSLINK1, &CMFCDemoDlg::OnNMClickSyslink1)
END_MESSAGE_MAP()   

void CMFCDemoDlg::OnNMClickSyslink1(NMHDR *pNMHDR, LRESULT *pResult)
{
	PNMLINK pNMLink = (PNMLINK) pNMHDR;   

	if (wcscmp(pNMLink->item.szUrl, WEB_SITE) == 0)
	{
		ShellExecuteW(NULL, L"open", pNMLink->item.szUrl, NULL, NULL, SW_SHOWNORMAL);
	}
	else if(wcscmp(pNMLink->item.szUrl, BLOG_LINK) == 0)
	{
		ShellExecuteW(NULL, L"open", pNMLink->item.szUrl, NULL, NULL, SW_SHOWNORMAL);
	}   

	*pResult = 0;
}

In MFC 9.0 (version that will ship with Visual Studio 2008) class CLinkCtrl is a wrapper over the Windows API for working with the syslink control.

You can associate an instance of CLinkCtrl with a syslink control through the DDX mechanism:

void CMFCDemoDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_SYSLINK2, Link2);
}

In my demo application that you can download from here I used a second syslink with an ID attribute. Each time the link is clicked it increments a counter, which is shown. For that I created two helper functions first, one to generate part of the text and the second to set the text to the link control:

CString CMFCDemoDlg::GetClickText() const
{
	CString str;
	str.Format(L"clicked %d times", Clicks);
	return str;
}   

void CMFCDemoDlg::SetLink2Text()
{
	Link2.SetWindowText(L"Link was " + GetClickText() + L"");
}

When handling the NM_CLICK notification, I checked the szID member of structure LITEM and took the appropriate action:

void CMFCDemoDlg::OnNMClickSyslink2(NMHDR *pNMHDR, LRESULT *pResult)
{
	PNMLINK pNMLink = (PNMLINK) pNMHDR;   

	if (wcscmp(pNMLink->item.szID, L"clicked") == 0)
	{
		Clicks++;
		SetLink2Text();
	}   

	*pResult = 0;
}

The result is shown here:

Syslink controls on dialog

Hopefully the sample code that I put together will help you work with CLinkCtrl and the syslink control in VS 2008.

Hits for this post: 19012 .

If you want to find an item in a tree control (CTreeCtrl from MFC) by its name you need a recursive function. Below is a function that does that. How does it work: you pass the text of the item to search, the tree reference and an item in the tree. The function will search through the sub-tree of that item for a match. If it finds it, it returns the tree item, otherwise NULL. To search the entire tree, pass the root of the tree. If your tree has more than just one root and you want to search the entire tree, you’d have to call it once for each root item.

// name - the name of the item that is searched for
// tree - a reference to the tree control
// hRoot - the handle to the item where the search begins
HTREEITEM FindItem(const CString& name, CTreeCtrl& tree, HTREEITEM hRoot)
{
	// check whether the current item is the searched one
	CString text = tree.GetItemText(hRoot);
	if (text.Compare(name) == 0)
		return hRoot; 

	// get a handle to the first child item
	HTREEITEM hSub = tree.GetChildItem(hRoot);
	// iterate as long a new item is found
	while (hSub)
	{
		// check the children of the current item
		HTREEITEM hFound = FindItem(name, tree, hSub);
		if (hFound)
			return hFound; 

		// get the next sibling of the current item
		hSub = tree.GetNextSiblingItem(hSub);
	} 

	// return NULL if nothing was found
	return NULL;
}

[Update]
To search the entire tree you can use this helper function, which will work regardless how many roots the tree has.

HTREEITEM CTreeDemoDlg::FindItem(const CString& name, CTreeCtrl& tree)
{
   HTREEITEM root = m_tree.GetRootItem();
   while(root != NULL)
   {
      HTREEITEM hFound = FindItem(name, tree, root);
      if (hFound)
         return hFound; 

      root = tree.GetNextSiblingItem(root);
   }

   return NULL;
}
Hits for this post: 13072 .

I have decided to make a comparison for file IO operations on Win32, CRT, STL and MFC.

For all four libraries/APIs I have done the profiling in the following way:

  • open the file
  • allocate the buffer used for reading
  • start the timer
  • read/write from/to the file
  • stop the timer
  • close the file
  • release the memory

This way, the profiling only applies on the read or write operations, not on other task such as opening and closing files, allocating or releasing memory.

What I’ve used:

  • Win32: functions CreateFile, ReadFile, WriteFile and CloseHandle
  • CRT: functions FILE, fopen, fread, fwrite and fclose
  • STL: for reading class std::ifstream, and methods, open(), read() and close() and for writing class std::ofstream and methods open(), write() and close()
  • MFC: class CFile, and methods Open(), Read(), Write and Close()

I have performed the reading with different buffer sizes: 32, 64, 128, 256, 512 bytes and 1KB, 2KB, 4KB, 8KB, 16KB, 32KB, as well as with a buffer accomodating the entire file. Same buffer sizes were used for writing. For testing the write operation I also wrote the file at once. In all cases, I generated a 16MB file.

To decide which one is better overall, I have associated a score with each result. The faster (for each buffer size) got 4 points, the next 3, 2, and 1. The bigger the sum, the more performant overall.

I have run the program on two files for reading on a Intel(R) Pentium(R) 4 CPU at 3.20GHz, 1 GB RAM, running Windows XP, SP2. The results, representing an average of 15 runs, are shown bellow:

File 1: size 2,131,287 bytes

Buffer Size CRT Win32 STL MFC CRT Win32 STL MFC
32 0.01917630 0.063093700 0.02123180 0.064283700 4 2 3 1
64 0.01474360 0.031909200 0.01460960 0.032482700 3 2 4 1
128 0.01118370 0.016183700 0.01164060 0.016426700 4 2 3 1
256 0.00929148 0.008573490 0.01063090 0.008840810 2 4 1 3
512 0.01071420 0.004684040 0.00985086 0.004745970 1 4 2 3
1024 0.00883909 0.002584480 0.00907385 0.002486950 2 3 1 4
2048 0.00847502 0.001531440 0.00894887 0.001477660 2 3 1 4
4096 0.00776395 0.000981391 0.00891128 0.001009350 2 4 1 3
8192 0.00740465 0.000744340 0.00913489 0.000749145 2 4 1 3
16384 0.00740928 0.000604900 0.00936410 0.000673978 2 4 1 3
32768 0.00736531 0.000657141 0.00837419 0.000610040 2 3 1 4
file size 0.00955846 0.002496180 0.00981464 0.002428280 2 3 1 4
          28 38 20 34

File 2: size 110,999,662 bytes

Buffer Size CRT Win32 STL MFC CRT Win32 STL MFC
32 1.011360 3.3216500 2.47695 3.2822700 4 1 3 2
64 0.742683 1.6815600 0.804563 1.6836300 4 2 3 1
128 0.600344 0.8697840 0.639113 0.8750610 4 2 3 1
256 0.521233 0.4661430 0.586376 0.4751340 2 4 1 3
512 0.501420 0.2734540 0.532212 0.2653010 2 3 1 4
1024 0.474670 0.1532950 0.510266 0.1587330 2 4 1 3
2048 0.458538 0.1012430 0.479981 0.1067980 2 4 1 3
4096 0.432552 0.0715536 0.488251 0.0774886 2 4 1 3
8192 0.417481 0.0607284 0.467426 0.0674372 2 4 1 3
16384 0.400320 0.0510897 0.458111 0.0602826 2 4 1 3
32768 0.406497 0.0503835 0.461796 0.0572124 2 4 1 3
file size 0.523950 0.1867240 0.583327 0.1828440 2 3 1 4
          30 39 18 33

The first conclusion is that overall Win32 is the fastest, followed by MFC, then by CRT, the slowest being the STL.

The second conclusion is that CRT is the fastest with buffer sizes smaller than 256 bytes, and then Win32 and MFC are the faster.

The results for writing were a quite similar. Of course, running several times, can produce slight variation in the results (both for read and write).

File 3 : size 16,809,984

Buffer Size CRT Win32 STL MFC CRT Win32 STL MFC
32 0.273796 0.890973 0.335245 0.877301 4 1 3 2
64 0.219715 0.465254 0.259597 0.450076 4 1 3 2
128 0.181927 0.24715 0.201949 0.245169 4 1 3 2
256 0.178976 0.141146 0.189154 0.143666 2 4 1 3
512 0.153816 0.0872411 0.172239 0.0851424 2 3 1 4
1024 0.148846 0.0608282 0.159186 0.0601419 2 3 1 4
2048 0.139997 0.0493811 0.150503 0.0496117 2 4 1 3
4096 0.125797 0.0705146 0.15275 0.0508061 2 3 1 4
8192 0.126708 0.15708 0.1459 0.0655567 3 1 2 4
16384 0.121919 0.0282886 0.14662 0.158024 3 4 2 1
32768 0.124429 0.0247259 0.145496 0.0267301 2 4 1 3
16809984 0.148424 0.47066 0.146321 0.513205 3 2 4 1
          33 31 23 33

You can download the project I used for the benchmark from here.

Hits for this post: 18801 .

In a previous post I explained than when you create a MFC application with the March CTP of ‘Orcas’ and add a command or split button to a dialog, the .rc file is not compiled, because styles such as BS_COMMANDLINK are not found. My workaround for the moment was to redeclare them in the resource.h header. But that is not a good idea, because the IDE overwrites the file, removing what you put there. So, eventually, I brought that up to the VC++ team, and it seems that the March CTP has a problem with the resource headers, used by the resource compilers. In other words, at least commctrl.rc was not updated to contain the required definitions.

You can work around this in two better ways:

  • install the Windows RTM SDK, or
  • redefine the necessary styles in commctrl.rc
    #if _WIN32_WINNT >= 0x0600
    
    // BUTTON STATE FLAGS
    #define BST_DROPDOWNPUSHED      0x0400
    
    // BUTTON STYLES
    #define BS_SPLITBUTTON          0x0000000CL
    #define BS_DEFSPLITBUTTON       0x0000000DL
    #define BS_COMMANDLINK          0x0000000EL
    #define BS_DEFCOMMANDLINK       0x0000000FL
    
    #endif
    

I decided to go for the second, and now the applications are successfully built. I have been told that the problem has been already fixed for the upcoming CTP/beta. The VC++ team will soon post about this on their blog too. I want to thank to Marian Luparu for the help with this matter.

Hits for this post: 13488 .

MFC in Orcas comes with several important changes, such as support for Vista specific command button and split button. I have put together a small demo application displaying a command button with the tex Say “Hello Vista” and the note “Click on this button to show a “Hello Vista” message!”.

The command button is still a CButton, but with the style BS_COMMANDLINK (or BS_DEFCOMMANDLINK for a default command button) set. To set the note you should use the SetNote() method. Additional GetNote() and GetNoteLength() methods are available for it. Here is a screenshot:

Demo of command button for Vista

However, there are several problems with the Orcas March CTP that I want to mention (and I hope these will fixed for the next beta version).

When you create a project, add a command button and try to compile, the resource compiler will say that BS_COMMANDLINK is not recognized. The style is defined in commctrl.h like this:

#if _WIN32_WINNT >= 0x0600

// BUTTON STATE FLAGS
#define BST_DROPDOWNPUSHED      0x0400

// BUTTON STYLES
#define BS_SPLITBUTTON          0x0000000CL
#define BS_DEFSPLITBUTTON       0x0000000DL
#define BS_COMMANDLINK          0x0000000EL
#define BS_DEFCOMMANDLINK       0x0000000FL


Trying to define _WIN32_WINNT as 0×0600 either in the project properties or in stdafx.h (if you use precompiled headers) does not help. You have to redeclare the styles whether in resource.h or in the .rc file, but as soon as the IDE modifies them, the code you put there is gone. This is a real bummer, and I’m still looking for the best solution. If I find it, I’ll post it here.

The methods that are available for the command button are defined only for UNICODE builds for Vista, as can be seen in afxwin.h:

#if ( _WIN32_WINNT >= 0x0600 ) && defined(UNICODE)
	CString GetNote() const;
	_Check_return_ BOOL GetNote(_Out_z_cap_(*pcchNote) LPTSTR lpszNote, _Inout_ UINT* pcchNote) const;
	BOOL SetNote(_In_z_ LPCTSTR lpszNote);
	UINT GetNoteLength() const;
	BOOL GetSplitInfo(_Out_ PBUTTON_SPLITINFO pInfo) const;
	BOOL SetSplitInfo(_In_ PBUTTON_SPLITINFO pInfo);
	UINT GetSplitStyle() const;
	BOOL SetSplitStyle(_In_ UINT nStyle);
	BOOL GetSplitSize(_Out_ LPSIZE pSize) const;
	BOOL SetSplitSize(_In_ LPSIZE pSize);
	CImageList* GetSplitImageList() const;
	BOOL SetSplitImageList(_In_ CImageList* pSplitImageList);
	TCHAR GetSplitGlyph() const;
	BOOL SetSplitGlyph(_In_ TCHAR chGlyph);
	BOOL SetDropDownState(_In_ BOOL fDropDown);

	// Sets whether the action associated with the button requires elevated permissions.
	// If elevated permissions are required then the button should display an elevated icon.
	HICON SetShield(_In_ BOOL fElevationRequired);
#endif // ( _WIN32_WINNT >= 0x600 ) && defined(UNICODE)


However, if you look in MSDN, method SetShield is not found (though you can find the BCM_SETSHIELD window message). Instead SetElevationRequired() is listed as a member of CButton. This method does not actually exists. Moreover, the people that wrote the documentation don’t seem to know the difference between BOOL and bool (explained here). This method takes a BOOL and returns a BOOL, but MSDN says it returns

true if the method is successful; otherwise false

Using SetShield() with TRUE, displays a shield icon on the button, as shown here:

Demo command button for Vista with shield icon

I hope the issues I mentioned above will be address very soon.

Hits for this post: 8113 .