Category Archive for MFC

Fixing Unreadable Window Titles in Maximized MFC Ribbon Bar Applications

If you use MFC to create an MFC ribbon bar application, you might notice that when you maximize your application, that the text in the window title bar has a different color compared to a non-maximized window. For example, here is a screenshot of a non-maximized default MFC ribbon bar application created by the Visual Studio project wizard:

When you maximize the window, the result could be as follows:

The text in the title bar becomes white, while it was black in the non-maximized window.
This is a long-standing bug in MFC. Luckily, there is an easy workaround for it. I’ll be using the Windows 7 MFC theme, but similar workarounds can be implemented for the other themes.

First, you need to derive your own class from CMFCVisualManagerWindows7 and override two methods: DrawNcText() and DrawTextOnGlass(). Here is the code:

#pragma once

class CMyVisualManager7 : public CMFCVisualManagerWindows7
{
	DECLARE_DYNCREATE(CMyVisualManager7)

	virtual void DrawNcText(CDC* pDC, CRect& rect, const CString&
		strTitle, BOOL bActive, BOOL bIsRTL, BOOL bTextCenter, BOOL bGlass = FALSE,
		int nGlassGlowSize = 0, COLORREF clrGlassText = (COLORREF)-1) override;

	virtual BOOL DrawTextOnGlass(CDC* pDC, CString strText, CRect rect,
		DWORD dwFlags, int nGlowSize = 0, COLORREF clrText = (COLORREF)-1) override;
};

And here is the implementation:

#include "stdafx.h"
#include "MyVisualManager7.h"

IMPLEMENT_DYNCREATE(CMyVisualManager7, CMFCVisualManagerWindows7)

void CMyVisualManager7::DrawNcText(CDC* pDC, CRect& rect, const CString&
	strTitle, BOOL bActive, BOOL bIsRTL, BOOL bTextCenter, BOOL bGlass /*= FALSE*/,
	int nGlassGlowSize /*= 0*/, COLORREF clrGlassText /*= (COLORREF)-1*/)
{
	if (bGlass && afxGlobalData.bIsWindows7)
	{
		// If we're drawing text on the DWM caption and Windows is Win7 or later, always use default text color
		// (in WinVista, the maximized "aero" caption was black):
		clrGlassText = (COLORREF)-1;
		nGlassGlowSize = 10;
	}

	__super::DrawNcText(pDC, rect, strTitle, bActive, bIsRTL,
		bTextCenter, bGlass, nGlassGlowSize, clrGlassText);
}

BOOL CMyVisualManager7::DrawTextOnGlass(CDC* pDC, CString strText, CRect rect,
	DWORD dwFlags, int nGlowSize /*= 0*/, COLORREF clrText /*= (COLORREF)-1*/)

{
	if (afxGlobalData.bIsWindows7)
	{
		// If we're on Windows 7 or later, always use default color.
		clrText = (COLORREF)-1;
		nGlowSize = 10;
	}

	return __super::DrawTextOnGlass(pDC, strText, rect, dwFlags,
		nGlowSize, clrText);
}

The overridden DrawNcText() method makes sure that the text for the window title is correct, while the overriden DrawTextOnGlass() method makes sure that Quick Access Toolbar controls with
text labels have the correct color.

Once you have your derived class, you have to use it. Your application probably contains something as follows:

CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows7));

Just replace CMFCVisualManagerWindows7 with your CMyVisualManager7:

CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMyVisualManager7));

That’s it.
Just compile and run your application. When you now maximize your window, the color in the title bar will be correct.
For example, here is the previous window maximized:

Looks much better 🙂

Share

VC++ 2015 RC Includes a Dynamic Dialog Layout Feature

The VC++2015 Release Candidate includes an extremely long overdue new feature for MFC: Dynamic Dialogs.

It’s now finally possible to define how controls should move and resize when an MFC dialog is resized. The behavior can be configured with the dialog resource editor.

Artur Laksberg has written an article about the new feature.


Share

Visual Studio 2010 Service Pack 1

Microsoft has released Visual Studio 2010 Service Pack 1.
MSDN subscribers can download it right now.
It will be publicly available on 10th of March.
See Soma Segar’s blog for details on what is included/changed with SP1.

Share

The New MFC Animation API

Introduction

Microsoft Visual Studio 2010 Service Pack 1 includes a number of enhancements and new features for MFC developers. One of those changes is an animation API to make it easy for you to create animations in MFC applications. This article will briefly introduce this animation API.
This articles was also posted on Codeguru.com.
Read the rest of this entry »

Share

Technical Editor for “Ivor Horton’s Beginning Visual C++ 2010”

I was technical editor for the book “Ivor Horton’s Beginning Visual C++ 2010“, published by Wiley. According to the author:

I would particularly like to thank my technical editor, Marc Gregoire, for doing such an outstanding job of reviewing the text and checking out all the code fragments and examples in the book. His many constructive comments and suggestions for better ways of presenting the material has undoubtedly made the book a much better tutorial.

Below is a description of what you can expect from the book.

By following author Ivor Horton’s accessible tutorial approach and detailed examples you can quickly become an effective C++ programmer. Thoroughly updated for the 2010 release, this book introduces you to the latest development environment and teached you how to build real-world applications using Visual C++. With this book by your side, you are well on your way to writing applications in both versions of C++ and becoming a successful C++ programmer.

Ivor Horton’s Beginning Visual C++ 2010:

  • Teaches the essentials of C++ programming using both of the C++ language technologies supported by Visual C++ 2010.
  • Shares techniques for finding errors in C++ programs and explains general debugging principles.
  • Discusses the structure and essential elements that are present in every Windows application.
  • Demonstrates how to develop native Windows applications using the Microsoft Foundation Classes.
  • Guides you through designing and creating substantial Windows applications in both C++ and C++/CLI.
  • Features numerous working examples and exercises that help build programming skills.
Share

Microsoft Visual Studio 2010 and .NET Framework 4 Released

Today, Microsoft released Visual Studio 2010 and the .NET Framework 4. A lot of new features are included. One of them is a completely new editor.

“Visual Studio 2010 and .NET Framework 4 have something for every developer. The new editor, now using Windows Presentation Foundation, delivers a more flexible, feature-rich environment that supports concepts such as the use of multiple monitors. This enables a developer to have one monitor with code, another with the user interface designer, and yet another with database structure.”

Visual C++ 2010 also includes a lot of new features, some of them are:

  • MSBuild and multi-targeting
  • IntelliSense and Browsing (#include auto completion, call hierarchy, red squiggles, find all references, class wizard)
  • C++ compiler changes (static_assert, auto keyword, lambda, decltype, rvalue references)
  • Ribbon designer
  • Deployment changes
  • Task dialog support
  • Restart manager support

Read the full press release here or watch the keynote.

Later this week, Silverlight 4 will also be released to the web (RTW). At that time, an update for Visual Studio 2010 will also become available that will allow you to develop applications using Silverlight 4.

Share

Overview of New Features in Visual C++ 2010

A friend of mine, Marius Bancila, wrote several blog posts with details about new features in Visual C++ 2010.

He touches the following features:

  • MSBuild and multi-targeting
  • IntelliSense and Browsing (#include auto completion, call hierarchy, red squiggles, find all references, class wizard)
  • C++ compiler changes (static_assert, auto keyword, lambda, decltype, rvalue references)
  • Ribbon designer
  • Deployment changes
  • Task dialog support
  • Restart manager support

You can read his posts here. They give you a good idea of new features in VC++ 2010 🙂

Share

How To Handle Custom URL Protocols with the Microsoft WebBrowser Control

Now that you know “How To Use the Microsoft WebBrowser Control to Render HTML from Memory” and “How To Navigate to an Anchor in the Microsoft WebBrowser Control when Rendering HTML from Memory“, it’s time to learn how to handle custom URL protocols to tailor the navigation inside the WebBrowser Control to fit your application. The following demonstrates a custom URL protocol called “app”:

<a href="app://some.target">Test</a>

When you would put this link in a normal Internet Explorer window, clicking the link will generate an error because IE does not know how to handle the APP protocol. The name APP is chosen arbitrarily. You can use whatever you want. Handling these custom protocols in your C++ application is actually pretty simple and it doesn’t even involve any real COM coding like in the previous articles. The first thing you need to do is to add a handler for the BeforeNavigate2 handler. Open the resource editor and open your dialog with the WebBrowser control. Right click the WebBrowser control and select “Add Event Handler…”. Select “BeforeNavigate2” as message type, select the appropriate class and click “Add and Edit”. This handler will be called right before the WebBrowser control will navigate to a new page. To handle the custom protocol, implement the handler as follows:

void CMyDlg::BeforeNavigate2Explorer(LPDISPATCH pDisp, VARIANT* URL, VARIANT* Flags,
    VARIANT* TargetFrameName, VARIANT* PostData, VARIANT* Headers, BOOL* Cancel)
{
    const wchar_t* cpszProtocolName = L"app";
    const wchar_t* cpszProtocolSeparator = L"://";

    // We only handle VT_BSTR.
    if (URL->vt != VT_BSTR)
        return;

    // Check the protocol of the URL
    CString str = URL->bstrVal;
    int iPos = str.Find(cpszProtocolSeparator);
    if (iPos == -1)    // Unable to figure out protocol
        return;

    // Extract protocol and check if it's our APP protocol
    CString strProtocol = str.Mid(0, iPos);
    if (strProtocol.CompareNoCase(cpszProtocolName))
        return;    // not our APP protocol

    // It's our APP protocol, so start processing it.
    // Start by preventing Internet Explorer from handling the protocol.
    *Cancel = TRUE;

    // Extract target URL
    CString strTarget = str.Mid(iPos+wcslen(cpszProtocolSeparator));
    strTarget.TrimRight(L"/");

    // Now we are ready to process our protocol.
    // For this demo, I just render a new HTML page with the name
    // of the URL target without the protocol part of the string.
    CString strHTML;
    strHTML.Format(L"My APP protocol processing: \"%s\"", strTarget);
    WriteHTML(strHTML);
}

The flow is pretty straightforward. The URL protocol is extracted; if it’s not our protocol, we let Internet Explorer handle the URL for us. If it is our custom “APP” protocol, we first set Cancel to TRUE which will prevent Internet Explorer from handling this URL protocol. Once that is done, we are completely free to implement the handling of the “APP” protocol however we want. As demonstration I just write a new HTML document from memory which will just mention that we are processing an “APP” protocol URL and that will also display the target part of the URL.

You can quickly test the code with the following piece of HTML rendered from memory:

WriteHTML(L"<html><body>"
    L"<p><a href=\"app://FirstAppProtocolTestLink\">test 1</a></p>"
    L"<p><a href=\"APP://SecondAppProtocolTestLink.Withdots\">test 2</a></p>"
    L"</body></html>");

Run the application, click on the “test 1” or “test 2” link and see what happens.

That’s it for handling custom URL protocols in C++ 🙂

Share

How To Navigate to an Anchor in the Microsoft WebBrowser Control when Rendering HTML from Memory

In my previous blog entry titled “How To Use the Microsoft WebBrowser Control to Render HTML from Memory” I described a method how you could use the Microsoft WebBrowser Control to display HTML from memory. One commenter said that it was not possible to navigate to an anchor in the body onload handler. I did some research and it seems all navigation within the rendered page is not working. For example, the following piece of HTML code will not work correctly:

<a href="#n25">Jump to anchor n25</a>
<a name="n25">25</a>

It took me a while to find a workaround, so that’s why I’m posting it now for other people to use. Basically, we cannot use the standard navigation techniques. I tried several possible workaround and the only one that I got working properly is by manually scrolling the window until the requested anchor is visible. It sounds complicated, but it really works pretty nicely. I wrote this little wrapper function to do all the hard work.

void CMyDlg::ScrollToAnchor(const wchar_t* anchor)
{
    IDispatch* pHtmlDoc = m_explorer.get_Document();
    if (!pHtmlDoc)
        return;
    CComPtr<IHTMLDocument2> doc2;
    doc2.Attach((IHTMLDocument2*)pHtmlDoc);
    if (doc2)
    {
        CComPtr<IHTMLElementCollection> anchors;
        HRESULT hr = doc2->get_anchors(&anchors);
        if (SUCCEEDED(hr) && anchors)
        {
            _variant_t index = 0;
            _variant_t str = anchor;
            IDispatch *pdisp;
            hr = anchors->item(str, index, &pdisp);
            if (SUCCEEDED(hr) && pdisp)
            {
                CComPtr<IHTMLElement> el;
                hr = pdisp->QueryInterface(IID_IHTMLElement, (void**)&el);
                if (SUCCEEDED(hr) && el)
                {
                    long yTotal = 0;
                    while (1)
                    {
                        long y;
                        el->get_offsetTop(&y);
                        yTotal += y;
                        CComPtr<IHTMLElement> el2;
                        hr = el->get_offsetParent(&el2);
                        if (SUCCEEDED(hr) && el2)
                            el = el2;
                        else
                            break;
                    }
                    CComPtr<IHTMLWindow2> wnd;
                    hr = doc2->get_parentWindow(&wnd);
                    if (SUCCEEDED(hr) && wnd)
                        wnd->scrollTo(0, yTotal);
                }
            }
        }
    }
}

What it does is it gets a pointer to the document. Then gets a list of all the anchors in the document and get the anchor with the given name out of that list. Once we have the target element, we calculate the offset from the top of the document. This is done in a while loop, because the target anchor could be inside another element like a div or a table. After calculating the offset, we get a pointer to the HTML window and call the scrollTo function to make it scroll to the anchor position.

Now the only thing you need to do is to render your HTML using the method in my previous blog entry and then call this new ScrollToAnchor function with the name of the anchor to which you want to scroll.

Share

How To Use the Microsoft WebBrowser Control to Render HTML from Memory

Microsoft has a WebBrowser control that is actually an Internet Explorer control that you can use to display HTML in your own applications. More information about this WebBrowser control can be found on MSDN. By using this control it’s very easy to display online or offline webpages. However, it’s not immediately obvious how to make it display HTML that you might have in a memory buffer. Of course, one solution is to write the HTML to a temporary file and then load that file using the WebBrowser control, but obviously there is a better way for doing this which I will explain below.

The first thing you have to do is to add the WebBrowser control to your dialog. So, in Visual Studio, open the resource editor and then open the dialog onto which you want to put the WebBrowser control. Once the dialog is opened in the resource editor, right click on an empty space on the dialog and select “Insert ActiveX Control…”. This will open a new window in which you can select “Microsoft Web Browser” and then click OK. Visual Studio will automatically create a wrapper class for this ActiveX control which will probably be called explorer.h and explorer.cpp while the wrapper class will most likely be called CExplorer.

Now, right click the WebBrowser control on your dialog and select “Add Variable”. Make a variable with category set to “Control” and with the variable type set to the wrapper class “CExplorer” and hit OK.

Now we can start writing code. The first thing required is to load up some basic document; I use about:blank. Do this in your OnInitDialog handler as follows.

COleVariant loc(L"about:blank");
m_explorer.Navigate2(loc, NULL, NULL, NULL, NULL); 

The above is very important. If you don’t load an initial document, the WebBrowser control will not render any HTML that you try to push to it. This also means that before you can start writing HTML from memory in the WebBrowser control, you have to wait until the initial document has been fully loaded. This can be done with the “DocumentComplete” event. In the dialog editor, right the WebBrowser control and click on “Add Event Handler…”. Select “DocumentComplete” as message type, select the appropriate class and click “Add and Edit”. You can use that handler to change a boolean variable in your code to mark whether the document has been fully loaded. When it is fully loaded you can start writing HTML from memory to it.

Once that is finished, you can add the following helper function:

#include <MsHTML.h>
void CMyDlg::WriteHTML(const wchar_t* html)
{
	IDispatch* pHtmlDoc = m_explorer.get_Document();
	if (!pHtmlDoc)
		return;
	CComPtr<IHTMLDocument2> doc2;
	doc2.Attach((IHTMLDocument2*)pHtmlDoc);
	if (!doc2)
		return;
	 // Creates a new one-dimensional array
	SAFEARRAY* psaStrings = SafeArrayCreateVector(VT_VARIANT, 0, 1);
	if (!psaStrings)
		return;
	BSTR bstr = SysAllocString(html);
	if (bstr)
	{
		VARIANT* param;
		HRESULT hr = SafeArrayAccessData(psaStrings, (LPVOID*)&param);
		if (SUCCEEDED(hr))
		{
			param->vt = VT_BSTR;
			param->bstrVal = bstr;
			hr = SafeArrayUnaccessData(psaStrings);
			if (SUCCEEDED(hr))
			{
				doc2->write(psaStrings);
				doc2->close();
			}
		}
	}
	// SafeArrayDestroy calls SysFreeString for each BSTR!
	if (psaStrings)
		SafeArrayDestroy(psaStrings);
}

With the above function, it’s very easy to dynamically create and display HTML from memory. For example:

WriteHTML(L"<html><body><h1>My Header</h1><p>Some text below the header</p></body></html>");

Note that the above code is expecting a Unicode build. If you don’t use Unicode, you need to change the wchar_t types and you need to change the way how you allocate the BSTR variable.

That’s it. Pretty easy if you know how to do it, but it took me some time to figure it out.

[ Update: Fixed some typos and added mshtml.h reference. ]

[ Update 2: Added a call to “doc2->close();” after “doc2->write()” and added code to check the result of the doc2.Attach() call. ]

Share

Visual Studio 2010 and .NET Framework 4 Release Candidate

Microsoft has released the Release Candidate version of Visual Studio 2010 and the .NET Framework 4.

See Scott Guthrie blog post about it.

Right now it’s available for MSDN subscribers.
On Wednesday 10th of February everyone will be able to get their hands on it 🙂

Two important things to know (from Scott Guthrie blog post):

  • If you have previously installed VS 2010 Beta 2 on your computer you should use Add/Remove Programs (within Windows Control Panel) to remove VS 2010 Beta2 and .NET 4 Beta2 before installing the VS 2010 RC.  Note that VS 2010 RC can be installed on the same machine side-by-side with VS 2008 and VS 2005.
  • Silverlight 3 projects are supported with today’s VS 2010 RC build – however Silverlight 4 projects are not yet supported.  We will be adding VS 2010 RC support for SL4 with the next public Silverlight 4 drop. If you are doing active Silverlight 4 development today we recommend staying with the VS10 Beta 2 build for now.
Share

Visual Studio 2010 and .NET Framework 4 Beta 2

Visual Studio 2010 and .NET Framework 4 Beta 2 are now available. The final version is scheduled for 22nd of March 2010. I’m looking forward to it 🙂

For Visual C++ developers there are lots of new things to look forward to, like parallel programming, MFC ribbon resource editor, easy application local deployment model etc etc…

When you use the .NET Framework you will apparently be able to have deployments with up to 81% reduction in the framework size by using the Client Profile.

According to the press release:

“The company also outlined a simplified product lineup and pricing options for Visual Studio 2010 as well as new benefits for MSDN subscribers, including the Ultimate Offer, available to all active MSDN Premium subscribers at the official product launch on March 22, 2010.”

The product lineup is simplified with the following versions:

  • Microsoft Visual Studio 2010 Ultimate with MSDN. The comprehensive suite of application life-cycle management tools for software teams to help ensure quality results from design to deployment
  • Microsoft Visual Studio 2010 Premium with MSDN. A complete toolset to help developers deliver scalable, high-quality applications
  • Microsoft Visual Studio 2010 Professional with MSDN. The essential tool for basic development tasks to assist developers in implementing their ideas easily

Download Beta 2 now.

Read the full Microsoft press release.

Share

MFC Restart Manager Support in Visual C++ 2010

Windows Vista introduced the restart manager. It is used to automatically restart an application after it crashes. It can also be used to restart application after a reboot by a Windows Installer or update. If you create a new MFC application using the project wizard in Visual C++ 2010, you will automatically get support for the restart manager. If you want to add support to an existing MFC application, you only need to add 1 line of code to the constructor of your CWinApp or CWinAppEx derived class. Read the rest of this entry »

Share

CTaskDialog in MFC in Visual C++ 2010

Windows Vista introduced the concept of Task Dialogs. Those are a powerful replacement for the standard message boxes. Read the rest of this entry »

Share

Script Errors in Visual Studio 2005/2008 With Internet Explorer 8

After installation of Internet Explorer 8, some wizard in Visual Studio 2005 and 2008 might give a script error. The following wizards might be affected:

  • Add Function
  • Add Variable
  • Smart Device – New Project Creation
  • Smart Device – Add Class

Get the workaround from the Visual C++ Team Blog.

Share

Binding to the most recent Visual Studio Libraries

Every version of Visual Studio comes with certain versions of Microsoft libraries, like the C runtime library, the MFC library and so on. For example, Visual Studio 2008 comes with version 9.0.21022.8 of the Microsoft C runtime library and version 9.0.21022.8 of the MFC library. Read the rest of this entry »

Share

Microsoft MVP Global Summit 2008 Pictures

I finally found some time to post a few pictures of the Microsoft MVP Global Summit 2008 in Seattle. The summit was great. There were 1753 MVPs from all over the world attending the summit. The sessions given by Microsoft product groups were very interesting. I went to all the Visual C++ sessions and it was great to hear the direction in which they are going with the product. One thing they made perfectly clear is that MFC is not dead 🙂 They are putting interesting new things in upcoming versions of MFC which allow you to create modern user interfaces for your MFC applications. One such thing is the ribon bar which is part of the MFC Feature Pack for Visual Studio 2008. Below you can see some pictures taken during the summit. Read the rest of this entry »

Share

Visual C++ 2008 Feature Pack Beta

Maybe a bit late, but for those who missed the announcement, Microsoft has released a beta of the Visual C++ 2008 Feature Pack.

The Visual C++ 2008 Feature Pack extends the VC++ Libraries shipped with Visual Studio 2008.New MFC features include:

  • Office Ribbon style interface
  • Office 2007, Office 2003 and Office XP look and feel
  • Modern Visual Studio-style docking toolbars and panes
  • Fully customizable toolbars and menus
  • A rich set of advanced GUI controls
  • Advanced MDI tabs and groups
  • And much more!

This feature pack also includes an implementation of TR1. Portions of TR1 are scheduled for adoption in the upcoming C++0x standard as the first major addition to the ISO 2003 standard C++ library. The following feature are currently supported:

  • Smart pointers
  • Regular expression parsing
  • New containers (tuple, array, unordered set, etc)
  • Sophisticated random number generators
  • Polymorphic function wrappers
  • Type traits
  • And more!

Note: This feature pack does not include C99 compatibility or support for special math functions.

Download the beta.

Share

How to Save and Load a Windows Region with MFC

I wrote an article for CodeGuru that explains in details how to save a Windows region to a file using CRgn::GetRegionData and how to load and re-create this saved region with CRgn::CreateFromData using MFC.

There are 2 functions in the article: SaveRegion and LoadRegion. Read the rest of this entry »

Share