4
votes

I have a native MFC C++ application for which I've got a ribbon UI based version and a toolbar based version. Both EXEs are similar size (~30mb), but running the ribbon based version takes about 25s whereas the toolbar version takes about 5s. This is just to get the frame window displayed with tools. I've profiled the start up of the ribbon UI based version, and sure enough the time is being spent in CMFCRibbonBar::LoadFromResource and deeper down in

BOOL CMFCRibbonInfoLoader::LoadImage(CMFCRibbonInfo::XImage& image, BOOL bSingle)
{
'
'
'
    image.m_Image.SetTransparentColor(GetGlobalData()->clrBtnFace);  // 15%
    image.m_Image.SmoothResize(dblScale);                            // 64%
'
}

Digging deeper, a lot of time seems to be spent manually shading the toolbar ~44% of the total time.

Is there any way to speed up this load time, possibly by setting a non-transparent drawing scheme? 25 seconds to run a program seems a bit excessive, this is on an 8 core 4ghz AMD 8350 with the EXE image coming from an SSD.

Edit: Tried the following which helped understand the problem but doesn't really make for a useful answer.

After some poking around, it seems a call to afxGlobalData.EnableRibbonImageScale(FALSE); disables the scaling but can leave poor results visually on some monitors. If the image sizes are correct for the monitor to start with, 40x40 pixels on my 1920x1080 display, the scaling will also get skipped. I haven't tried it yet, but I'd imagine if you specify HDPI images for all the ribbon controls and you are lucky enough to get 1:1 scaling for your HDPI images, it would also get skipped. Searching the MFC source code (\Program Files (x86)\Microsoft Visual Studio 14.0\VC\atlmfc\include\afxglobals.h) for m_bIsRibbonImageScale and m_dblRibbonImageScale yield most of the relevant code.

If the large button images aren't 32x32 the ribbon editor seems to treat them as they were, and chops the base BMP up incorrectly. So resizing a the base large button BMP to 40x40 resulted in garbage on screen.

Edit: I had thought Vlad's answer would work, but apparently the XML used in an MFC ribbon resource is not Ribbon XML. See related question on MSDN here.

Edit Further discussion on MSDN here

2

2 Answers

5
votes

The page Specifying Ribbon Image Resources states:

For any image, the exact pixel size is dependent on the display resolution, or dots per inch (dpi), of the monitor being used. At 96 dpi, large images are 32x32 pixels in size and small images are 16x16 pixels in size. The image sizes increase in a linear fashion relative to dpi as illustrated in the following table.

DPI       Small Image     Large Image 
96  dpi   16x16 pixels    32x32 pixels 
120 dpi   20x20 pixels    40x40 pixels 
144 dpi   24x24 pixels    48x48 pixels 
192 dpi   32x32 pixels    64x64 pixels

The Ribbon framework scales image resources as required. However, because resizing may yield undesirable artifacts and image degradation, it is highly recommended that the application provide a small set of image resources that span various commonly used dpi settings. If an exact match is not found, the nearest image will be scaled up or down.

To facilitate this, image resources can be declared in Ribbon markup by using a set of Image elements for each Command element. At run time, the framework selects the image to display based on the MinDPI attribute of each Image element.

There is an example at the bottom.

0
votes

Problem solved: Configuration -> Manifest Tool -> Input And Output -> Enable DPI Awareness NO

NO, is the solution. The default value is unfortunately YES.