Further we can set a timer to periodically change m_dWeight value from 0.0f to 1.0f. So far, so good but a better solution is to use Windows Animation interfaces that allow to implement animations that are smooth, natural, and interactive. Moreover, MFC offers wrapper classes that can make programmer’s life much more easier than in case of direct using COM interfaces.

Using MFC support for animation

To use MFC support for animation do the following:

first of all we need an object of type CAnimationController which is the key class that manages animations;

call CAnimationController::SetRelatedWnd in order to establish a window that will receive WM_PAINT message when animation manager status has changed or animation timer has been updated;

call CAnimationController::EnableAnimationTimerEventHandler;

add an animation object, in our case of type CAnimationValue as long as we only need an “animated” FLOAT to set cross-fade weight property; here is a list of MFC animation object classes defined in afxanimationcontroller.h

CAnimationValue

CAnimationPoint

CAnimationSize

CAnimationColor

CAnimationRect

add transition(s) to animation object; here is a list of transition MFC classes:

CAccelerateDecelerateTransition

CConstantTransition

CCubicTransition

CDiscreteTransition

CInstantaneousTransition

CLinearTransition

CLinearTransitionFromSpeed

CSmoothStopTransition

CParabolicTransitionFromAcceleration

CReversalTransition

CSinusoidalTransitionFromRange

CSinusoidalTransitionFromVelocity

CSinusoidalTransitionFromVelocity

uncomment the line containing m_spAnimCrossFadeWeightValue->GetValue(m_dWeight) in the previous example;

finally, call CAnimationController::AnimateGroup.

Here is some sample code:

C++

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

voidCAnimationWnd::PreSubclassWindow()

{

// ...

// this window receive WM_PAINT when animation manager state has changed

Like this:

Once have enabled Direct2D support in an MFC application, there is no sweat to load an image from a file, by using one of CD2DBitmap constructors.
Unfortunately, we cannot find a CD2DBitmap method to save it into a image file (something similar to CImage::Save or Gdiplus::Image::Save).
No problem, we can try to do it ourselves. Here is an example:

Looks good although it can be refactorized and/or can be improved for saving multiple frames, metadata and so on. However, it’s a problem: if the Direct2D bitmap (pBitmap) has been created in the window’s render target, EndDraw returns D2DERR_WRONG_RESOURCE_DOMAIN error (the resource was realized on the wrong render target). That is because CWnd::EnableD2DSupport creates a render target of type D2D1_RENDER_TARGET_TYPE_DEFAULT and as stated in the documentation, it cannot share its resources with another render targets. So, let’s replace EnableD2DSupport call with a call to another one (let’s say it EnableD2DSoftwareSupport).

// instantiate new CHwndRenderTarget and attach the GDI-compatible render target

m_pRenderTarget=newCHwndRenderTarget;

GetRenderTarget()->Attach(pHwndRenderTarget);

}

More details can be found in the demo application attached below. Just to note that forcing software rendering for window’s render target leads in performance penalty but generally, we can live with that until finding a better solution.

Like this:

In an older article, I presented a function that enumerates Windows Imaging Component codecs. Recently I had the idea to make a set of WIC Interfaces wrapper classes for easily enumerate and get info about all types of WIC components: bitmap decoders and encoders, metadata readers and writers, format converters, and supported pixel formats. Here are just few samples of code.

Demo solution

The demo solution contains an MFC and a console project that use the classes described above in order to enumerate WIC components and get info about each one. The MFC one allows choosing the component type(s) as well as enum options (include the disabled components or enum only Windows built-in components). The console application is simpler and I wrote it just to demonstrate that my little library of wrapper classes can be used both in MFC and non-MFC applications.

Notes

I hope, this article can be useful.

If you have any observation or remarks, please do not hesitate to post a reply!

Like this:

Let’ say we have to implement a function that search a folder to recursively find files having an extension from a given list of extensions. This article shows three possible implementations: one using FindFirstFile and FindNextFile WinAPI functions, one using CFileFind MFC class and one using Filesystem Library.

Find files using FindFirstFile and FindNextFile WinAPI functions

Althugh this implementation uses some ATL stuff to make things easier, it appears still quite complicated.

C++

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

voidFindFiles(

constCString&strRootPath,// initial path to search

conststd::list<CString>listExt,// a list of file extensions

std::list<CString>&listFiles)// output list of files found

{

CString strFileToFind=strRootPath;

ATLPath::Append(CStrBuf(strFileToFind,MAX_PATH),_T("*.*"));

WIN32_FIND_DATA findData={0};

HANDLE hFileFind=::FindFirstFile(strFileToFind,&findData);

if(INVALID_HANDLE_VALUE!=hFileFind)

{

do

{

CString strFileName=findData.cFileName;

if((strFileName==_T("."))||(strFileName==_T("..")))

continue;

CString strFilePath=strRootPath;

ATLPath::Append(CStrBuf(strFilePath,MAX_PATH),strFileName);

if(ATLPath::IsDirectory(strFilePath))

{

// call recursive

FindFiles(strFilePath,listExt,listFiles);

}

else

{

CString strExt=ATLPath::FindExtension(strFilePath);

strExt.TrimLeft(_T('.'));

if(IsStringInListNoCase(strExt,listExt))

{

listFiles.push_back(strFilePath);

}

}

}while(::FindNextFile(hFileFind,&findData));

::FindClose(hFileFind);

}

}

Find files using CFileFind MFC class

Using CFileFind MFC class can make code a little bit shorter and the programmer’s life easier.

C++

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

voidFindFiles(

constCString&strRootPath,// initial path to search

conststd::list<CString>listExt,// a list of file extensions

std::list<CString>&listFiles)// output list of files found

{

CString strFileToFind=strRootPath+_T("\\*.*");

CFileFind fileFind;

BOOLbMoreFiles=fileFind.FindFile(strFileToFind);

while(bMoreFiles)

{

bMoreFiles=fileFind.FindNextFile();

if(fileFind.IsDots())

continue;

CString strFilePath=fileFind.GetFilePath();

if(fileFind.IsDirectory())

{

// call recursive

FindFiles(strFilePath,listExt,listFiles);

}

else

{

intnPos=strFilePath.ReverseFind(_T('.'));

if(-1!=nPos)

{

CString strExt=strFilePath.Right(strFilePath.GetLength()-nPos-1);

if(IsStringInListNoCase(strExt,listExt))

{

listFiles.push_back(strFilePath);

}

}

}

}

}

Note: IsStringInListNoCase searches a list for a string, not case sensitive. You can find its implementation in the attached demo solution.

Find files using Filesystem Library

Here it is:

C++

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

voidFindFiles(

constCString&strRootPath,// initial path to search

conststd::list<CString>listExt,// a list of file extensions

std::list<CString>&listFiles)// output list of files found

{

_FSPFX path root_path(strRootPath.GetString());

_FSPFX recursive_directory_iterator end;

_FSPFX recursive_directory_iterator iter(root_path);

while(iter!=end)

{

constauto&path=iter->path();

CString strExt=path.extension().c_str();

strExt.TrimLeft(_T('.'));

if(IsStringInListNoCase(strExt,listExt))

{

listFiles.push_back(path.c_str());

}

++iter;

}

}

Hurray, we did it in just few lines of code!
Of course, it can be used in MFC, ATL, Win32 and Console applications, as well.

Like this:

In a previous article, I showed how to trim a text which overflows the layout box. In the example presented there, the ellipsis is added at the end of truncated text. But if, let’s say, we have to show a long path and file name, it is not meaningful if the file name is not displayed. No problem, this can be easily resolved if have a look at DWRITE_TRIMMING structure which passed to IDWriteTextFormat::SetTrimming. The second parameter is a character code used as delimiter and the third one is the delimiter count. The text is preserved from the end until is found the delimiter which coresponds to delimiter count. For example, if the delimiter is backslash and the delimiter count is 2, a text like “e:\Articles\MFC Support for DirectWrite\DirectWrite Trimming Demo\D2DStaticCtrl.cpp” may be displayed as follows “e:\Articles…\DirectWrite Trimming Demo\D2DStaticCtrl.cpp”.

Demo project

Download: DirectWrite Trimming Demo.zip (337)
The demo project is a simple MFC application which demonstrate how to trim text rendered with DirectWrite. You can choose the granularity, the delimiter and the delimiter count and see what is displayed.