<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Marius Bancila's Blog &#187; MFC</title>
	<atom:link href="http://mariusbancila.ro/blog/tag/mfc/feed/" rel="self" type="application/rss+xml" />
	<link>http://mariusbancila.ro/blog</link>
	<description>Sharing my opinions and ideas!</description>
	<lastBuildDate>Fri, 06 Apr 2012 13:45:55 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Sorting a CTreeCtrl</title>
		<link>http://mariusbancila.ro/blog/2012/04/06/sorting-a-ctreectrl/</link>
		<comments>http://mariusbancila.ro/blog/2012/04/06/sorting-a-ctreectrl/#comments</comments>
		<pubDate>Fri, 06 Apr 2012 13:45:55 +0000</pubDate>
		<dc:creator>Marius Bancila</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[MFC]]></category>
		<category><![CDATA[CTreeCtrl]]></category>
		<category><![CDATA[sort]]></category>
		<category><![CDATA[tree]]></category>

		<guid isPermaLink="false">http://mariusbancila.ro/blog/?p=1270</guid>
		<description><![CDATA[The CTreeCtrl supports several ways to sort its content: InsertItem allows to insert the child item alphabetically, when specifying TVI_SORT for hInsertAfter SortChildren performs an alphabetical sorting of the child items of the given parent item in a tree SortChildrenCB performs a sort with a user-defined callback (hence the CB suffix) of the children of [...]]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://msdn.microsoft.com/en-us/library/8bkz91b4.aspx">CTreeCtrl</a> supports several ways to sort its content:</p>
<ul>
<li><a href="msdn.microsoft.com/en-us/library/ettyybhw.aspx">InsertItem</a> allows to insert the child item alphabetically, when specifying TVI_SORT for <tt>hInsertAfter</tt></li>
<li><a href="http://msdn.microsoft.com/en-us/library/dt51k7hx.aspx">SortChildren</a> performs an alphabetical sorting of the child items of the given parent item in a tree</li>
<li><a href="http://msdn.microsoft.com/en-us/library/8b8aytc5.aspx">SortChildrenCB</a> performs a sort with a user-defined callback (hence the CB suffix) of the children of the specified item</li>
</ul>
<p>Let&#8217;s consider this tree and investigate these two sorting methods.<br />
<img alt="" src="/blog/wp-content/uploads/2012/04/sorttree1.png" title="Unsorted tree" class="alignnone" width="444" height="353" /></p>
<p><strong>Alphabetical sorting</strong><br />
SortChildren() does an alphabetical sorting. It is important to note that SortChildren() does not work recursively. It only sorts the children of the specified item. Therefore the following call would only sort the immediate children of the root item.</p>
<pre name="code" class="cpp">
  m_tree.SortChildren(TVI_ROOT);
</pre>
<p>To sort the entire tree one needs to traverse the tree and call SortChildren for every item that has children (actually only items with more than one child need sorting). The following method performs a depth-first traversal and sorts all nodes that have children.</p>
<pre name="code" class="cpp">
void CTreeSortDemoDlg::SortItem(HTREEITEM item)
{
   if(item != NULL)
   {
      if(item == TVI_ROOT || m_tree.ItemHasChildren(item))
      {
         HTREEITEM child = m_tree.GetChildItem(item);

         while(child != NULL)
         {
            SortItem(child);
            child = m_tree.GetNextItem(child, TVGN_NEXT);
         }

         m_tree.SortChildren(item);
      }
   }
}

// ...
SortItem(TVI_ROOT);
</pre>
<p>The result for the given tree is<br />
<img alt="" src="/blog/wp-content/uploads/2012/04/sorttree2.png" title="Alphabetically sorted tree" class="alignnone" width="444" height="353" /></p>
<p><strong>User defined sorting</strong><br />
SortChildrenCB() allows the user to set a callback functions that the framework calls each time it needs to compare two items to perform the sorting. This allows to customize the sorting. Just like SortChildren() this method only sorts the children of the specified item, and does not perform a recursive sorting of the entire sub-tree.</p>
<p>This method has a single argument, a pointer to a <a href="msdn.microsoft.com/en-us/library/bb773462.aspx">TVSORTCB</a> structure, that is defined like this:</p>
<pre name="code" class="cpp">
typedef struct tagTVSORTCB {
  HTREEITEM    hParent;
  PFNTVCOMPARE lpfnCompare;
  LPARAM       lParam;
} TVSORTCB, *LPTVSORTCB;
</pre>
<p>The fields have the following meaning:</p>
<ul>
<li>hParent: is the item whose children are to be sorted</li>
<li>lpfnCompare: a pointer to the user-defined callback function that does the sorting</li>
<li>lParam: is the value that is passed as to the 3rd parameter of the callback function, which looks like this:
<pre name="code" class="cpp">
int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
</pre>
<p>Usually, this parameter is a pointer to the tree itself, so that you can retrieve information about the items in the callback if necessary. However, it can be anything, including NULL.</p>
<p>The lParam1 and lParam2 parameters correspond to the lParam member of the TVITEM structure for the two items being compared.</p>
<p>The callback function must return a negative value if the first item should precede the second, a positive value if the first item should follow the second, or zero if the two items are equivalent.
</li>
</ul>
<p>Suppose we set for each item a pointer to a structure that looks like this:</p>
<pre name="code" class="cpp">
struct ItemData
{
   CString  Name;
   int      Value;

   CString ToString() const
   {
      CString str;
      str.Format(_T("%s = %d"), Name, Value);
      return str;
   }
};

ItemData* data = MakeData(base, prefix);
HTREEITEM item = m_tree.InsertItem(data->ToString(), parent);
m_tree.SetItemData(item, (DWORD_PTR)data);
</pre>
<p>A user defined callback (a class method declared static) defines the precedence between two items based on the Value field.</p>
<pre name="code" class="cpp">
int CALLBACK CTreeSortDemoDlg::CustomCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
   ItemData* data1 = reinterpret_cast&lt;ItemData*&gt;(lParam1);
   ItemData* data2 = reinterpret_cast&lt;ItemData*&gt;(lParam2);

   return (data1 != NULL &amp;&amp; data2 != NULL) ? (data1->Value > data2->Value) : 0;
}
</pre>
<p>Sorting the entire tree with this callback is similar with the previous recursive method. The call to SortChildren() is replaced with a call to SortChildrenCB().</p>
<pre name="code" class="cpp">
void CTreeSortDemoDlg::CustomSortItem(HTREEITEM item)
{
   if(item != NULL)
   {
      if(item == TVI_ROOT || m_tree.ItemHasChildren(item))
      {
         HTREEITEM child = m_tree.GetChildItem(item);

         while(child != NULL)
         {
            CustomSortItem(child);
            child = m_tree.GetNextItem(child, TVGN_NEXT);
         }

         TVSORTCB tvs;
         tvs.hParent = item;
         tvs.lpfnCompare = &amp;CTreeSortDemoDlg::CustomCompare;
         tvs.lParam = reinterpret_cast&lt;LPARAM&gt;(&amp;m_tree);

         m_tree.SortChildrenCB(&amp;tvs);
      }
   }
}

// ...
CustomSortItem(TVI_ROOT);
</pre>
<p>The result on the given example is:<br />
<img alt="" src="/blog/wp-content/uploads/2012/04/sorttree3.png" title="Custom-defined sorted tree" class="alignnone" width="444" height="353" /></p>
<p>For a full sample see <a class="downloadlink" href="http://mariusbancila.ro/blog/wp-content/plugins/download-monitor/download.php?id=9" title="Version1.0 downloaded 55 times" >TreeSortDemo (55)</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://mariusbancila.ro/blog/2012/04/06/sorting-a-ctreectrl/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New MFC Toolbar Controls in Visual Studio 2010</title>
		<link>http://mariusbancila.ro/blog/2009/11/01/new-mfc-toolbar-controls-in-vs-2010/</link>
		<comments>http://mariusbancila.ro/blog/2009/11/01/new-mfc-toolbar-controls-in-vs-2010/#comments</comments>
		<pubDate>Sun, 01 Nov 2009 21:57:01 +0000</pubDate>
		<dc:creator>Marius Bancila</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[CTPs & Betas]]></category>
		<category><![CDATA[MFC]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[Visual Studio]]></category>
		<category><![CDATA[controls]]></category>
		<category><![CDATA[designer]]></category>
		<category><![CDATA[toolbar]]></category>
		<category><![CDATA[VS2010]]></category>

		<guid isPermaLink="false">http://mariusbancila.ro/blog/?p=386</guid>
		<description><![CDATA[With VC++ Feature Pack Microsoft has added new classes to MFC to provide support for new controls. However, these controls were not available from the designer. One had to manually wrote all the code for enabling an application to use these controls. Visual Studio 2010 Beta 2, released a couple of weeks ago, provides support [...]]]></description>
			<content:encoded><![CDATA[<p>With VC++ Feature Pack Microsoft has added new classes to MFC to provide support for new controls. However, these controls were not available from the designer. One had to manually wrote all the code for enabling an application to use these controls. Visual Studio 2010 Beta 2, released a couple of weeks ago, provides support in the designer for these controls. </p>
<div class="wp-caption alignnone" style="width: 249px"><img alt="MFC controls in the Toolbar" src="/blog/wp-content/uploads/2009/11/mfcnewcontrols_toolbar.png" title="MFC controls in the Toolbar" width="239" height="251" /><p class="wp-caption-text">MFC controls in the Toolbar</p></div>
<p>Here is a screen shot of a dialog application with these controls:</p>
<div class="wp-caption alignnone" style="width: 772px"><img alt="New MFC Controls" src="/blog/wp-content/uploads/2009/11/mfcnewcontrols_demo.png" title="New MFC Controls" width="762" height="571" /><p class="wp-caption-text">New MFC Controls</p></div>
<p>The controls are:</p>
<ul>
<li><strong>Color button</strong> (CMFCColorButton): represent a color picker control allowing users to select a color</li>
<li><strong>Font combo box</strong> (CMFCFontComboBox) : represent a combo control that displays a list of fonts available in the system</li>
<li><strong>Edit browse</strong> (CMFCEditBrowseCtrl): an editable control with a button that displays a dialog for selecting a file or a folder</li>
<li><strong>Visual Studio list box</strong> (CVSListBox): an editable list control with buttons for adding, removing or rearranging items in the list</li>
<li><strong>Masked edit</strong> (CMFCMaskedEdit): a masked edit control that has a string template representing the structure of the allowed input, which is validated against the value provided by the user</li>
<li><strong>Menu button</strong> (CMFCMenuButton): displays a pop-up menu (from a menu resource) and reports the command selected by the user</li>
<li><strong>Property grid</strong> (CMFCPropertyGridCtrl): an editable property grid control</li>
<li><strong>Shell list</strong> (CMFCShellListCtrl): a list control that displays the files and folders from you system just list Windows Explorer list view does</li>
<li><strong>Shell tree</strong> (CMFCShellTreeCtrl): a tree control that displays the folder from your system just like the Windows Explorer folder view does</li>
<li><strong>Link control</strong> (CMFCLinkCtrl): is a special button that has the appearance of a hyperlink and invokes the target link when pressed</li>
</ul>
<p>Not all the properties for these controls are available from the designer. For instance the properties list still needs hand coding, it is not possible to select a menu resource for the menu button nor the starting point for the shell tree and list. However, having them available in the toolbar is a good step forward.</p>
]]></content:encoded>
			<wfw:commentRss>http://mariusbancila.ro/blog/2009/11/01/new-mfc-toolbar-controls-in-vs-2010/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>File Dialog with Custom Controls</title>
		<link>http://mariusbancila.ro/blog/2009/08/11/file-dialog-with-custom-constrol/</link>
		<comments>http://mariusbancila.ro/blog/2009/08/11/file-dialog-with-custom-constrol/#comments</comments>
		<pubDate>Tue, 11 Aug 2009 19:12:05 +0000</pubDate>
		<dc:creator>Marius Bancila</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[MFC]]></category>
		<category><![CDATA[file dialog]]></category>
		<category><![CDATA[preview]]></category>
		<category><![CDATA[stc32]]></category>

		<guid isPermaLink="false">http://mariusbancila.ro/blog/?p=349</guid>
		<description><![CDATA[Sometimes you want to customize a file dialog, maybe to provide a preview for images or files in general. Fortunately, the common file dialog can be easily extended to achieve this. I will explain in this post how to do that. There are several things one needs to do to extend the file dialog. First [...]]]></description>
			<content:encoded><![CDATA[<p>Sometimes you want to customize a file dialog, maybe to provide a preview for images or files in general. Fortunately, the common file dialog can be easily extended to achieve this. I will explain in this post how to do that.</p>
<p>There are several things one needs to do to extend the file dialog. First step is to create a dialog template. There are several properties (styles that have to be set on this template).</p>
<ul>
<li>WS_CHILD, necessary because this dialog is a child of the original file dialog</li>
<li>WS_CLIPSIBLINGS, required so that the child dialog box does not paint over the original file dialog</li>
<li>DS_3DLOOK, so that consistency of the look of the controls in the child dialog and the original dialog is preserved</li>
<li>DS_CONTROL, allows the user to navigate through the controls of the customized dialog with TAB or navigation keys</li>
</ul>
<p>When using the template, the following should be done for the OPENFILENAME structure:</p>
<ul>
<li>if the template is a resource in an application or DLL library, then:
<ul>
<li><strong>Flags</strong> should contain OFN_ENABLETEMPLATE</li>
<li><strong>hInstance</strong> must point to the module containing the resource</li>
<li><strong>lpTemplateName</strong> should contain the template name</li>
</ul>
</li>
<li>if the template is already in memory then
<ul>
<li><strong>Flags</strong> should contain OFN_ENABLETEMPLATEHANDLE</li>
<li><strong>hInstance</strong> member must identify the memory object that contains the template</li>
</ul>
</li>
</ul>
<p>The following code shows how to display a customized file dialog with a template with the ID set to &#8220;DIALOG_PREVIEW&#8221;:</p>
<pre name="code" class="cpp">
	CFileDialog fileDialog(TRUE, NULL, NULL, OFN_HIDEREADONLY, _T("All files (*.*)|*.*||"));

	fileDialog.m_ofn.Flags |= OFN_ENABLETEMPLATE;
	fileDialog.m_ofn.hInstance = AfxGetInstanceHandle();
	fileDialog.m_ofn.lpTemplateName = _T("DIALOG_PREVIEW");

	fileDialog.DoModal();
</pre>
<p>The common file dialog is expanded on the sides so that the new controls have enough space. There are several rules that apply to this repositioning. I will explain them and exemplify with some images.</p>
<ul>
<li>By default all the controls from the custom dialog are placed below the controls from the original file dialog. The following images show a simple dialog template with a check box and a static control (for a preview). By default, these controls are placed at the bottom of the dialog.<br />
<div class="wp-caption alignnone" style="width: 200px"><img alt="Simple dialog template" src="/blog/wp-content/uploads/2009/08/custompreviewtemplate1.png" title="Simple dialog template" width="190" height="182" /><p class="wp-caption-text">Simple dialog template</p></div><br />
<div class="wp-caption alignnone" style="width: 571px"><img alt="Custom dialog with preview controls placed at the bottom" src="/blog/wp-content/uploads/2009/08/customfiledialog1.png" title="Custom Dialog with Preview" width="561" height="589" /><p class="wp-caption-text">Custom dialog with preview controls placed at the bottom</p></div>
</li>
<li>If the dialog template contains a static control with the id stc32 (defined in DLG.h), the controls will be positioned relative to this control (with the original dialog being displayed in its placed, in the original size).
<ul>
<li>all controls above and to the left of stc32 are positioned above and to the left of the original controls, with the same amount.<br />
<div class="wp-caption alignnone" style="width: 200px"><img alt="Template with stc32 control position on the right and middle" src="/blog/wp-content/uploads/2009/08/custompreviewtemplate2.png" title="Template with stc32 control" width="190" height="186" /><p class="wp-caption-text">Template with stc32 control position on the right and middle</p></div><br />
<div class="wp-caption alignnone" style="width: 738px"><img alt="Custom File Fialog with Preview controls on the top left" src="/blog/wp-content/uploads/2009/08/customfiledialog2.png" title="Custom File Dialog with Preview controls" width="728" height="580" /><p class="wp-caption-text">Custom File Fialog with Preview controls on the top left</p></div>
</li>
<li>all controls below and to the right of stc32 are positioned below and to the right of the original controls.<br />
<div class="wp-caption alignnone" style="width: 203px"><img alt="Template with stc32 control position on the left and middle" src="/blog/wp-content/uploads/2009/08/custompreviewtemplate3.png" title="Template with stc32 control" width="193" height="186" /><p class="wp-caption-text">Template with stc32 control position on the left and middle</p></div><br />
<div class="wp-caption alignnone" style="width: 741px"><img alt="Custom File Fialog with Preview controls on the top and on the right" src="/blog/wp-content/uploads/2009/08/customfiledialog3.png" title="Custom File Dialog with Preview controls" width="731" height="580" /><p class="wp-caption-text">Custom File Fialog with Preview controls on the top and on the right</p></div>
</li>
</ul>
</li>
</ul>
<p>Base on that, if you want to place the preview controls on the right (as I would do), you&#8217;d have to place the stc32 control on the left of all the controls from your template. In other words, the template needs to look like this:<br />
<div class="wp-caption alignnone" style="width: 203px"><img alt="Template with stc32 on the left of all controls" src="/blog/wp-content/uploads/2009/08/custompreviewtemplate4.png" title="Template with stc32 on the left" width="193" height="186" /><p class="wp-caption-text">Template with stc32 on the left of all controls</p></div></p>
<p>The resulting file dialog would look like this:<br />
<div class="wp-caption alignnone" style="width: 741px"><img alt="Custom File Dialog with Preview Controls on the right side" src="/blog/wp-content/uploads/2009/08/customfiledialog4.png" title="Custom File Dialog with Preview Controls" width="731" height="440" /><p class="wp-caption-text">Custom File Dialog with Preview Controls on the right side</p></div></p>
<p>Note: In the above images the stc32 control had the border style set one one hand to make the control visible on the dialog template and on the other hand to have the the original file dialog controls more visible within the resulting file dialog. You wouldn&#8217;t do that with an actual file dialog.</p>
<p>As you could see from the sample code above, it&#8217;s very simple to extend the common file dialog. Of course, the part I haven&#8217;t shown so far is how to make use of these additional controls. But that is very simple. You just derive CFileDialog, add handlers for the new controls, implement all the logic you want, and instead of instantiating a CFileDialog object you instantiate an object of your derived class. In a following post I will explain how you can add preview functionality to such a custom file dialog.</p>
<p>You can read more about this topic in the following articles:</p>
<ul>
<li><a href="http://msdn.microsoft.com/en-us/library/ms646960%28VS.85%29.aspx">Open and Save As Dialog Boxes</a></li>
<li><a href="http://support.microsoft.com/kb/102332">How to Show a Custom Common Dialog using CFileDialog</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://mariusbancila.ro/blog/2009/08/11/file-dialog-with-custom-constrol/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>.NET out string[] to Automation SAFEARRAY**</title>
		<link>http://mariusbancila.ro/blog/2009/07/23/net-out-string-to-automation-safearray/</link>
		<comments>http://mariusbancila.ro/blog/2009/07/23/net-out-string-to-automation-safearray/#comments</comments>
		<pubDate>Thu, 23 Jul 2009 11:44:13 +0000</pubDate>
		<dc:creator>Marius Bancila</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[MFC]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Windows Programming]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[SAFEARRAY]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://mariusbancila.ro/blog/?p=328</guid>
		<description><![CDATA[.NET allows you to expose components as COM and consume them from unmanaged code. There are many references on how to this (and you can only start with MSDN), and I will not talk about that part. What I want to explain here is something different. Suppose you have this interface: [Guid("2F8433FE-4771-4037-B6B2-ED5F6585ED04")] [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] public interface [...]]]></description>
			<content:encoded><![CDATA[<p>.NET allows you to expose components as COM and consume them from unmanaged code. There are many references on how to this (and you can only start with <a href="http://msdn.microsoft.com/en-us/library/zsfww439(VS.71).aspx" target="_blank">MSDN</a>), and I will not talk about that part. What I want to explain here is something different. Suppose you have this interface:</p>
<pre name="code" class="csharp">
[Guid("2F8433FE-4771-4037-B6B2-ED5F6585ED04")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IAccounts
{
      [DispId(1)]
      string[] GetUsers();
}
</pre>
<p>Method GetUsers() returns an array on string representing the user names. But what if you also wanted the user passwords or addresses? Since this is exposed as COM, you cannot return an array of User. But you can return multiple arrays of string. So, how would you deal with out string[]? This is what I want to show you in this tutorial.</p>
<p>This is a .NET interface exposed to COM. It has two methods, GetUsers() that returns an array of string representing user names, and GetUsers2() that returns an array of strings as an output parameters and a bool as return type, indicating whether any user was found.</p>
<pre name="code" class="csharp">
namespace SampleLibrary
{
   [Guid("2F8433FE-4771-4037-B6B2-ED5F6585ED04")]
   [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
   public interface IAccounts
   {
      [DispId(1)]
      string[] GetUsers();

      [DispId(2)]
      bool GetUsers2(out string [] users);
   }
}
</pre>
<p>And this is the implementation:</p>
<pre name="code" class="csharp">
namespace SampleLibrary
{
   [Guid("C4713144-5D29-4c65-BF9C-188B1B7CD2B6")]
   [ClassInterface(ClassInterfaceType.None)]
   [ProgId("SampleLibrary.DataQuery")]
   public class Accounts : IAccounts
   {
      List&lt; string &gt; m_users;

      public Accounts()
      {
         m_users = new List&lt; string &gt; {
            "marius.bancila",
            "john.doe",
            "anna.kepler"
         };
      }

      #region IDataQuery Members

      public string[] GetUsers()
      {
         return m_users.ToArray();
      }

      public bool GetUsers2(out string[] users)
      {
         users = m_users.ToArray();

         return users.Length &gt; 0;
      }

      #endregion
   }
}
</pre>
<p>Note: If you are trying this example make sure you set the ComVisible attribute to true, either for each type or per assembly (in AssemblyInfo.cs)</p>
<pre name="code" class="csharp">
[assembly: ComVisible(true)]
</pre>
<p>Second, you have to check the &#8220;Register for COM interop&#8221; setting in the Build page of the project properties.</p>
<p>The first thing to do in C++ is importing the .TLB file that was generated by regasm.exe.</p>
<pre name="code" class="cpp">
#import "SampleLibrary.tlb"
using namespace SampleLibrary;
</pre>
<p>If we look in the .TLB file, we can see how the IAccounts interface looks like:</p>
<pre name="code" class="cpp">
struct __declspec(uuid("2f8433fe-4771-4037-b6b2-ed5f6585ed04"))
IAccounts : IDispatch
{
    //
    // Wrapper methods for error-handling
    //

    // Methods:
    SAFEARRAY * GetUsers ( );
    VARIANT_BOOL GetUsers2 (
        SAFEARRAY * * users );
};
</pre>
<p>The following C++ functions, GetUsers1() retrieves the users users list using method GetUsers() from IAccounts. It puts the users in a CStringArray (notice that this container does not have an assignment operator, so the only way to return such an array is with a reference in the parameters list).</p>
<pre name="code" class="cpp">
void GetUsers1(CStringArray&amp; arrUsers)
{
   IAccountsPtr pAccounts(__uuidof(Accounts));

   SAFEARRAY* sarrUsers = pAccounts-&gt;GetUsers();

   _variant_t varUsers;
   varUsers.parray = sarrUsers;
   varUsers.vt = VT_ARRAY | VT_BSTR;

   UnpackBstrArray(varUsers, arrUsers);
   SafeArrayDestroy(sarrUsers);

   pAccounts-&gt;Release();
}
</pre>
<p>UnpackBstrArray() is a function (see below) that extracts the elements of a SAFEARRAY and adds them to a CStringArray.</p>
<p>Function GetUsers2() uses the second method, GetUsers2() from IAccounts. This needs the address of a pointer to a SAFEARRAY (i.e. SAFEARRAY**) that will hold the values returned by the COM method. This time we have to create an empty SAFEARRAY and then pass its address to the COM method. The rest is similar to the previous case.</p>
<pre name="code" class="cpp">
void GetUsers2(CStringArray&amp; arrUsers)
{
   IAccountsPtr pAccounts(__uuidof(Accounts));

   SAFEARRAYBOUND aDim[1];
   aDim[0].lLbound = 0;
   aDim[0].cElements = 0;

   SAFEARRAY* sarrUsers = SafeArrayCreate(VT_BSTR, 1, aDim);

   VARIANT_BOOL ret = pAccounts-&gt;GetUsers2(&amp;sarrUsers);
   if(ret != VARIANT_FALSE)
   {
      _variant_t varUsers;
      varUsers.parray = sarrUsers;
      varUsers.vt = VT_ARRAY | VT_BSTR;
      UnpackBstrArray(varUsers, arrUsers);
   }

   SafeArrayDestroy(sarrUsers);

   pAccounts-&gt;Release();
}
</pre>
<p>The helper method UnpackBstrArray() used previous looks like this:</p>
<pre name="code" class="cpp">
void UnpackBstrArrayHelper(VARIANT* pvarArrayIn, CStringArray* pstrarrValues)
{
   if (!pstrarrValues || !pvarArrayIn || pvarArrayIn->vt == VT_EMPTY)
      return;

   pstrarrValues-&gt;RemoveAll();

   VARIANT* pvarArray = pvarArrayIn;
   SAFEARRAY* parrValues = NULL;

   SAFEARRAYBOUND arrayBounds[1];
   arrayBounds[0].lLbound = 0;
   arrayBounds[0].cElements = 0;

   if((pvarArray-&gt;vt &#038; (VT_VARIANT|VT_BYREF|VT_ARRAY)) == (VT_VARIANT|VT_BYREF) &#038;&#038;
      NULL != pvarArray-&gt;pvarVal &#038;&#038;
      (pvarArray-&gt;pvarVal-&gt;vt &#038; VT_ARRAY))
   {
      pvarArray = pvarArray-&gt;pvarVal;
   }

   if (pvarArray-&gt;vt &#038; VT_ARRAY)
   {
      if (VT_BYREF &amp; pvarArray-&gt;vt)
         parrValues = *pvarArray-&gt;pparray;
      else
         parrValues = pvarArray-&gt;parray;
   }
   else
      return;

   if (parrValues != NULL)
   {
      HRESULT hr = SafeArrayGetLBound(parrValues, 1, &amp;arrayBounds[0].lLbound);
      hr = SafeArrayGetUBound(parrValues, 1, (long*)&amp;arrayBounds[0].cElements);
      arrayBounds[0].cElements -= arrayBounds[0].lLbound;
      arrayBounds[0].cElements += 1;
   }

   if (arrayBounds[0].cElements &gt; 0)
   {
      for (ULONG i = 0; i &lt; arrayBounds[0].cElements; i++)
      {
         LONG lIndex = (LONG)i;
         CString strValue = _T("");

         VARTYPE vType;
         BSTR bstrItem;

         ::SafeArrayGetVartype(parrValues, &amp;vType);
         HRESULT hr = ::SafeArrayGetElement(parrValues, &amp;lIndex, &amp;bstrItem);

         if(SUCCEEDED(hr))
         {
            switch(vType)
            {
            case VT_BSTR:
               strValue = (LPCTSTR)bstrItem;
               break;
            }

            ::SysFreeString(bstrItem);
         }

         pstrarrValues-&gt;Add(strValue);
      }
   }
}

void UnpackBstrArray( const _variant_t &amp;var, CStringArray &amp;strarrValues  )
{
   UnpackBstrArrayHelper( &amp;(VARIANT)const_cast&lt; _variant_t &#038; &gt;(var), &amp;strarrValues );
}
</pre>
<p>Attached you can find a demo project (C# and C++) with the complete example show in this tutorial.</p>
<a class="downloadlink" href="http://mariusbancila.ro/blog/wp-content/plugins/download-monitor/download.php?id=4" title="Version1.0 downloaded 365 times" >output SAFEARRAY** example (365)</a>
<p></p>
]]></content:encoded>
			<wfw:commentRss>http://mariusbancila.ro/blog/2009/07/23/net-out-string-to-automation-safearray/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Task Dialog in MFC</title>
		<link>http://mariusbancila.ro/blog/2009/03/10/task-dialog-in-mfc/</link>
		<comments>http://mariusbancila.ro/blog/2009/03/10/task-dialog-in-mfc/#comments</comments>
		<pubDate>Tue, 10 Mar 2009 19:55:03 +0000</pubDate>
		<dc:creator>Marius Bancila</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[CTPs & Betas]]></category>
		<category><![CDATA[MFC]]></category>
		<category><![CDATA[VS2010]]></category>

		<guid isPermaLink="false">http://mariusbancila.ro/blog/?p=222</guid>
		<description><![CDATA[The new MFC library from Visual Studo 2010 supports another Vista specific feature, the task dialog. This is meant as a replacement for the classic dialog box, and can display command links, customized buttons, customized icons, and a footer. Here is an example of such a dialog (from Windows Server 2008). MFC contains a new [...]]]></description>
			<content:encoded><![CDATA[<p>The new MFC library from Visual Studo 2010 supports another Vista specific feature, the task dialog. This is meant as a replacement for the classic dialog box, and can display command links, customized buttons, customized icons, and a footer.</p>
<p>Here is an example of such a dialog (from Windows Server 2008).</p>
<p><img src="/blog/wp-content/uploads/2009/03/taskdialog1.png" atl="Demo task dialog" /></p>
<p>MFC contains a new class called CTaskDialog that implements the task dialog. You must include afxtaskdialog.h in your files to be able to use it. Since the task dialog is available only on Vista or newer versions (Server 2003, Server 2008, Windows 7) you must check whether you can use it or not. For that the class CTaskDialog provides a static method called IsSupported() that returns true if the task dialog is available on the running operating system. In addition, the task dialog is only available when you build for UNICODE.</p>
<p>The code below shows how to create and display the task dialog from the previous image.</p>
<pre class="prettyprint">
void CTasksDemoDlg::OnBnClickedButtonTasks1()
{
   CString strMessage("Do you want to save your changes to the document?");
   CString strDialogTitle("Save document");
   CString strMainInstruction("Save document options");

   CString expandedLabel("Hide extra information");
   CString collapsedLabel("Show extra information");
   CString expansionInfo("You can select to save your document either as XML or binary. You should prefer to save as XML as this is the new standard format.");

   if (CTaskDialog::IsSupported())
   {
      CTaskDialog taskDialog(strMessage, strMainInstruction, strDialogTitle, TDCBF_OK_BUTTON);
      taskDialog.SetMainIcon(TD_INFORMATION_ICON);

      taskDialog.SetCommonButtons(TDCBF_NO_BUTTON | TDCBF_CANCEL_BUTTON);
      taskDialog.LoadCommandControls(IDS_SAVE_OPTION1, IDS_SAVE_OPTION2);
      taskDialog.SetExpansionArea(expansionInfo, collapsedLabel, expandedLabel);
      taskDialog.SetFooterText(L"Note: If you don't chose to save your changes will be lost.");
      taskDialog.SetVerificationCheckboxText(L"Remember your selection");

      INT_PTR result = taskDialog.DoModal();

      if (taskDialog.GetVerificationCheckboxState() )
      {
         // PROCESS IF the user selects the verification checkbox
      }

      switch (result)
      {
         case IDS_SAVE_OPTION1:
            AfxMessageBox(L"You chose to save as XML");
            break;
         case IDS_SAVE_OPTION2:
            AfxMessageBox(L"You chose to save as binary");
            break;
         case IDNO:
            AfxMessageBox(L"You chose not to save");
            break;
         case IDCANCEL:
            AfxMessageBox(L"You chose to cancel");
            break;
         default:
            // this case should not be hit
            ASSERT(FALSE);
            break;
      }

   }
   else
   {
      AfxMessageBox(strMessage);
   }
}
</pre>
<p>In this sample IDS_SAVE_OPTION1 (&#8220;Save in XML based format&#8221;) and IDS_SAVE_OPTION2 (&#8220;Save in binary format (old version)&#8221;) are two strings defined in the string table from the Resource editor.</p>
<p>There are several predefined icons in commctrl.h that can be used as the main icon.</p>
<pre class="prettyprint">
#define TD_WARNING_ICON         MAKEINTRESOURCEW(-1)
#define TD_ERROR_ICON           MAKEINTRESOURCEW(-2)
#define TD_INFORMATION_ICON     MAKEINTRESOURCEW(-3)
#define TD_SHIELD_ICON          MAKEINTRESOURCEW(-4)
</pre>
<p>The following flags for default buttons are defined in the same header:</p>
<pre class="prettyprint">
enum _TASKDIALOG_COMMON_BUTTON_FLAGS
{
    TDCBF_OK_BUTTON            = 0x0001, // selected control return value IDOK
    TDCBF_YES_BUTTON           = 0x0002, // selected control return value IDYES
    TDCBF_NO_BUTTON            = 0x0004, // selected control return value IDNO
    TDCBF_CANCEL_BUTTON        = 0x0008, // selected control return value IDCANCEL
    TDCBF_RETRY_BUTTON         = 0x0010, // selected control return value IDRETRY
    TDCBF_CLOSE_BUTTON         = 0x0020  // selected control return value IDCLOSE
};
typedef int TASKDIALOG_COMMON_BUTTON_FLAGS;
</pre>
<p>An easier way to create a task dialog, but with fewer customization options is using the static method ShowDialog() from CTaskDialog. The following example displays a dialog similar to the first one.</p>
<pre class="prettyprint">
void CTasksDemoDlg::OnBnClickedButtonTasks2()
{
   HRESULT result2 = CTaskDialog::ShowDialog(
      L"Do you want to save your changes to the document?",
      L"Save document options",
      L"Save document",
      IDS_SAVE_OPTION1,
      IDS_SAVE_OPTION2,
      TDCBF_NO_BUTTON | TDCBF_CANCEL_BUTTON,
      TDF_ENABLE_HYPERLINKS | TDF_USE_COMMAND_LINKS,
      L"Note: If you don't chose to save your changes will be lost.");
}
</pre>
<p><img src="/blog/wp-content/uploads/2009/03/taskdialog2.png" atl="Simpler task dialog" /></p>
<p></p>
]]></content:encoded>
			<wfw:commentRss>http://mariusbancila.ro/blog/2009/03/10/task-dialog-in-mfc/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Restart Manager in MFC</title>
		<link>http://mariusbancila.ro/blog/2009/03/08/restart-manager-in-mfc/</link>
		<comments>http://mariusbancila.ro/blog/2009/03/08/restart-manager-in-mfc/#comments</comments>
		<pubDate>Sun, 08 Mar 2009 19:13:08 +0000</pubDate>
		<dc:creator>Marius Bancila</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[CTPs & Betas]]></category>
		<category><![CDATA[MFC]]></category>
		<category><![CDATA[VS2010]]></category>

		<guid isPermaLink="false">http://mariusbancila.ro/blog/?p=218</guid>
		<description><![CDATA[One of the new features available in MFC in the Visual Studio 2010 CTP is the Restart Manager. This was introduced with Windows Vista to offer support for restarting application when a crash occurs or when an automatic update needs to close and then restart an application. When you create a new MFC project in [...]]]></description>
			<content:encoded><![CDATA[<p>One of the new features available in MFC in the Visual Studio 2010 CTP is the Restart Manager. This was introduced with Windows Vista to offer support for restarting application when a crash occurs or when an automatic update needs to close and then restart an application.</p>
<p>When you create a new MFC project in Visual Studio 2010, in the <b>Advanced Features</b> property page you can specify the level of support you want for the restart manager.</p>
<p><img src="/blog/wp-content/uploads/2009/03/recovdemo1.png" atl="Select level of support" /></p>
<p>You can select one of the following:</p>
<ul>
<li><b>Support Restart Manager</b>: restarts after crash or upgrade</li>
<li><b>Reopen previously open documents</b>: reopens previously open documents</li>
<li><b>Support application recovery</b>: recovers auto saved documents</li>
</ul>
<p>There are three flags defined for these three options:</p>
<ul>
<li><b>AFX_RESTART_MANAGER_SUPPORT_RESTART</b> for Support Restart Manager</li>
<li><b>AFX_RESTART_MANAGER_SUPPORT_RESTART_ASPECTS</b> for Reopen previously open documents</li>
<li><b>AFX_RESTART_MANAGER_SUPPORT_ALL_ASPECTS</b> for Support application recovery</li>
</ul>
<p>These are defined in the afxwin.h header.</p>
<pre class="prettyprint">
// Restart Manager support flags
#define AFX_RESTART_MANAGER_SUPPORT_RESTART           0x01  // restart support, means application is registered via RegisterApplicationRestart
#define AFX_RESTART_MANAGER_SUPPORT_RECOVERY          0x02  // recovery support, means application is registered via RegisterApplicationRecoveryCallback
#define AFX_RESTART_MANAGER_AUTOSAVE_AT_RESTART       0x04  // auto-save support is enabled, documents will be autosaved at restart by restart manager
#define AFX_RESTART_MANAGER_AUTOSAVE_AT_INTERVAL      0x08  // auto-save support is enabled, documents will be autosaved periodically for crash recovery
#define AFX_RESTART_MANAGER_REOPEN_PREVIOUS_FILES     0x10  // reopen of previously opened documents is enabled, on restart all previous documents will be opened
#define AFX_RESTART_MANAGER_RESTORE_AUTOSAVED_FILES   0x20  // restoration of auto-saved documents is enabled, on restart user will be prompted to open auto-saved documents intead of last saved
#define AFX_RESTART_MANAGER_SUPPORT_NO_AUTOSAVE       AFX_RESTART_MANAGER_SUPPORT_RESTART |
                                                      AFX_RESTART_MANAGER_SUPPORT_RECOVERY |
                                                      AFX_RESTART_MANAGER_REOPEN_PREVIOUS_FILES
#define AFX_RESTART_MANAGER_SUPPORT_ALL_ASPECTS       AFX_RESTART_MANAGER_SUPPORT_NO_AUTOSAVE |
                                                      AFX_RESTART_MANAGER_AUTOSAVE_AT_RESTART |
                                                      AFX_RESTART_MANAGER_AUTOSAVE_AT_INTERVAL |
                                                      AFX_RESTART_MANAGER_RESTORE_AUTOSAVED_FILES
#define AFX_RESTART_MANAGER_SUPPORT_RESTART_ASPECTS   AFX_RESTART_MANAGER_SUPPORT_RESTART |
                                                      AFX_RESTART_MANAGER_AUTOSAVE_AT_RESTART |
                                                      AFX_RESTART_MANAGER_REOPEN_PREVIOUS_FILES |
                                                      AFX_RESTART_MANAGER_RESTORE_AUTOSAVED_FILES
#define AFX_RESTART_MANAGER_SUPPORT_RECOVERY_ASPECTS  AFX_RESTART_MANAGER_SUPPORT_RECOVERY |
                                                      AFX_RESTART_MANAGER_AUTOSAVE_AT_INTERVAL |
                                                      AFX_RESTART_MANAGER_REOPEN_PREVIOUS_FILES |
                                                      AFX_RESTART_MANAGER_RESTORE_AUTOSAVED_FILES
</pre>
<p>Enabling this support is done with a single line in the constructor of the CWinAppEx derived class.</p>
<pre class="prettyprint">
CRecoveryDemoApp::CRecoveryDemoApp()
{
	m_bHiColorIcons = TRUE;

	// support Restart Manager
	m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_ALL_ASPECTS;

	// TODO: add construction code here,
	// Place all significant initialization in InitInstance
}
</pre>
<p>Here is an application with the full support for restart enabled. There are two opened documents, one that is saved (on the left) and one that is not saved (on the right).</p>
<p><img src="/blog/wp-content/uploads/2009/03/recovdemo2.png" atl="Application with two documents" /></p>
<p>When I hit the crash button, the application uses a null pointer and crashes.</p>
<p><img src="/blog/wp-content/uploads/2009/03/recovdemo3.png" atl="Application has stopped working" /></p>
<p>Now, when I press the <b>Ignore</b> button of the crash report window, I get the restart manager window tha allows me to <b>Restart the program</b>.</p>
<p><img src="/blog/wp-content/uploads/2009/03/recovdemo4.png" atl="Restarting the program" /></p>
<p>The restart manager will attempt to restart the program and reopen my documents, which it successfully does.</p>
<p><img src="/blog/wp-content/uploads/2009/03/recovdemo5.png" atl="Application restarted" /></p>
<p>However, you can see that though the support for recovering auto saved documents was enabled, the second, unsaved document was not recovered. The reason was that this document was not auto saved, because the default interval for the auto save is 5 minutes and I crashed the program immediatelly after writing into the document. This default interval can be changed by calling the SetAutosaveInterval() method of the data recovery handler. In the following example I change this interval to one minute.</p>
<pre class="prettyprint">
BOOL CRecoveryDemoApp::InitInstance()
{
   // ...

   CDataRecoveryHandler* autohandler = AfxGetApp()->GetDataRecoveryHandler();
   autohandler->SetAutosaveInterval(60000);

   return TRUE;
}
</pre>
<p>Here is another instance of the application with the first document saved, and the second not directly saved, but auto saved after one minute of inactivity.</p>
<p><img src="/blog/wp-content/uploads/2009/03/recovdemo6.png" atl="Application with two documents" /></p>
<p>When the application restarts, because there was an auto saved document that can be recovered, a new window is displayed.</p>
<p><img src="/blog/wp-content/uploads/2009/03/recovdemo7.png" atl="Recovery options" /></p>
<p>If I choose <b>Recover the auto-saved documents</b> my unsaved (but auto saved) document is recovered.</p>
<p><img src="/blog/wp-content/uploads/2009/03/recovdemo8.png" atl="Recovered auto-saved document" /></p>
<p>These options for restarting the application and saving and loading the application data (documents) are exposed through virtual methods in the CWinAppEx class.</p>
<pre class="prettyprint">
virtual void PreLoadState() {}    // called before anything is loaded
virtual void LoadCustomState() {} // called after everything is loaded
virtual void PreSaveState() {}    // called before anything is saved
virtual void SaveCustomState() {} // called after everything is saved
</pre>
<p>You can override these methods in your application for custom handling of the save and load operations.</p>
<p>To learn more about this new feature I suggest you read the <a href="http://blogs.msdn.com/vcblog/archive/2009/02/18/mfc-restart-manager.aspx" target="_blank">Visual C++ team&#8217;s blog</a>.</p>
<p></p>
]]></content:encoded>
			<wfw:commentRss>http://mariusbancila.ro/blog/2009/03/08/restart-manager-in-mfc/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>MFC Feature Pack</title>
		<link>http://mariusbancila.ro/blog/2008/03/12/mfc-feature-pack/</link>
		<comments>http://mariusbancila.ro/blog/2008/03/12/mfc-feature-pack/#comments</comments>
		<pubDate>Wed, 12 Mar 2008 06:56:44 +0000</pubDate>
		<dc:creator>Marius Bancila</dc:creator>
				<category><![CDATA[CTPs & Betas]]></category>
		<category><![CDATA[MFC]]></category>
		<category><![CDATA[Windows Programming]]></category>
		<category><![CDATA[article]]></category>
		<category><![CDATA[beta]]></category>
		<category><![CDATA[MDI]]></category>
		<category><![CDATA[Office2007]]></category>
		<category><![CDATA[ribbon]]></category>

		<guid isPermaLink="false">http://mariusbancila.ro/blog/?p=104</guid>
		<description><![CDATA[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 [...]]]></description>
			<content:encoded><![CDATA[<p>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:</p>
<ul>
<li>Office Ribbon</li>
<li>Office 2003, XP and 2007 look and feel</li>
<li>docking toolbars and panes in the Visual Studio style</li>
<li>customizable toolbars and menus</li>
<li>advanced GUI controls</li>
<li>advaced MDI tabs and groups</li>
</ul>
<p>I have published an article on <a href="http://www.codeguru.com/">www.codeguru.com</a> about enabling Office 2007 style on a MDI application. The article is called <a target="_blank" href="http://www.codeguru.com/cpp/cpp/cpp_mfc/tutorials/article.php/c14929/">MFC Feature Pack: An Introduction</a>. I encourage you to read it. A Romanian version will be available soon at <a href="http://www.codexpert.ro/">www.codexpert.ro</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://mariusbancila.ro/blog/2008/03/12/mfc-feature-pack/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Create a font with the desired size</title>
		<link>http://mariusbancila.ro/blog/2007/11/14/create-a-font-with-the-desire-size/</link>
		<comments>http://mariusbancila.ro/blog/2007/11/14/create-a-font-with-the-desire-size/#comments</comments>
		<pubDate>Wed, 14 Nov 2007 08:04:43 +0000</pubDate>
		<dc:creator>Marius Bancila</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[MFC]]></category>
		<category><![CDATA[CreateFont]]></category>
		<category><![CDATA[font]]></category>
		<category><![CDATA[GetDeviceCaps]]></category>
		<category><![CDATA[MulDiv]]></category>
		<category><![CDATA[SetFont]]></category>

		<guid isPermaLink="false">http://mariusbancila.ro/blog/?p=90</guid>
		<description><![CDATA[Let&#8217;s asume you want to change the font of a window\control and for the sake of simplicity let&#8217;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 [...]]]></description>
			<content:encoded><![CDATA[<p>Let&#8217;s asume you want to change the font of a window\control and for the sake of simplicity let&#8217;s consider an MFC dialog application. In that case, there are several steps you should follow:</p>
<ul>
<li>declare a CFont variable in the dialog class</li>
<li>create the font in OnInitDialog (using CreateFont)</li>
<li>set the font to the control (using SetFont)</li>
</ul>
<p>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:</p>
<pre class="prettyprint">
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(&amp;editFont);   

	return TRUE;  // return TRUE  unless you set the focus to a control
}</pre>
<p>The result should be the following:</p>
<p><img border="0" align="middle" width="461" src="/blog/wp-content/uploads/2007/11/font1.png" alt="control with Arial of wrong size" height="166" /></p>
<p>Look carefully and you&#8217;ll see that&#8217;s not the right size 12? Why? Because the height and width (which doesn&#8217;t matter in this case) parameters for <a target="_blank" href="http://msdn2.microsoft.com/en-us/library/2ek64h34(VS.80).aspx">CreateFont()</a> 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 <a target="_blank" href="http://msdn2.microsoft.com/en-us/library/ms533266.aspx">GetDeviceCaps()</a> with the appropriate device context. To compute the actual value, <a target="_blank" href="http://msdn2.microsoft.com/en-us/library/aa383718.aspx">MulDiv()</a> is used. This function multiplies two 32-bit integers and devides the 64-bit result by a third 32-bit integer.</p>
<p>In this case, OnInitDialog() becomes:</p>
<pre class="prettyprint">
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(&amp;editFont);   

	return TRUE;  // return TRUE  unless you set the focus to a control
}</pre>
<p>and the result is:</p>
<p><img border="0" align="middle" width="461" src="/blog/wp-content/uploads/2007/11/font2.png" alt="Arial with correct size 12 pixels" height="166" /></p>
<p>and that is what we wanted in the first place.</p>
]]></content:encoded>
			<wfw:commentRss>http://mariusbancila.ro/blog/2007/11/14/create-a-font-with-the-desire-size/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

