8

I'm working on a UI library powered by D2D, DWrite and Wic for (SDK API) Native C++ Desktop Applications (as in no XAML, no WinRT, just old school C++). I'm all set to write a windowless UI to give a more modern (as in this century look) to my C++ tools.

I'm a backender at heart so I've spent minimal time in the UI and mostly interacted with the Windows Standard & Common Controls and some custom drawn GDI stuff. Anyways, nothing fancy.

I'm currently experimenting with D2D and I'm interested to learn what's the standard way for UI animations. Like when you hover over a button making the border glow a bit, or an UI element moving smoothly as a result of interaction, or something fading from the screen. (think jQuery fade, slide and such short but meaningful animations in the economy of UX)

Thinking of this, two ways of handling animations in UI come to my mind:

  • A standalone Thread handles the calculations for an animation queue while the UI thread draws the results. Each interaction would put animation jobs in the queue and the thread calculates stuff and repositions the elements before they get drawn.
  • Use same-thread Timers to schedule and iterate through the animations.

The alternate Thread Worker method seems like a good method... but requires a bit of interlocking when visual properties are updated so it does not happen while actually drawing, to keep things consistent.

Now, for a single-thread UI... timers seem to be the solution. This makes sure drawing cannot overlap with animation calculations. But to me it feels so awkward. I'm very not used to the single thread way of life. :)

Is there another way? Or which method is recommended? I'd appreciate any information on existing implementations details or reading material.

PS: I'd appreciate if downvoters or those who request close would actually give a reason. (1) If you don't know what I'm asking, just carry on... this is definitely not a question for you. (2) If this seems too obvious/simple for you, answer it. --- I don't see a third reason, unless you're trolls. --- Or this is a really silly question, but as I said, I'm a decade+ backender so I can get away with it.

CodeAngry
  • 12,760
  • 3
  • 50
  • 57
  • The problem with splitting this sort of thing between threads is that it get's really easy to end up with nasty juddering. There's no point in multi-threading if you don't have lots of work to do. – Spudd86 Nov 29 '13 at 01:09
  • 1
    @Spudd86 So... `timers`?! – CodeAngry Nov 29 '13 at 08:24
  • You might want to take a look at [Ncurses](http://en.wikipedia.org/wiki/Ncurses) for good measure. It's a UI lib for terminal applications. Also see: [Ncurses on Windows](http://stackoverflow.com/questions/138153/is-ncurses-available-for-windows). – Domi Nov 29 '13 at 09:13
  • @Domi :) Thanks but if that UI sufficed, I'd just use a XML/JSON config file. I'm actually working on a UI similar to Metro UI (Modern UI). So, no DOS/Terminal stuff. It is tagged Direct2D... - *PS: If you were kidding, it was a VERY GOOD joke!* – CodeAngry Nov 29 '13 at 09:18
  • The current standard in UI styling and animation is whatever was not the standard two years ago. This moves fast, UI styling fashions have the survival skill of the milk in your refrigerator. Not in the least empowered by excellent tooling available these days that allows changing it quickly with relatively little effort. By designers instead of programmers, such tooling does not include C++. It uses what is in your *not* list. Committing to heavy code changes that turns sour a year or two from now is a mistake. – Hans Passant Nov 29 '13 at 10:34
  • @HansPassant I'm building a Direct2D UI framework. The actual drawing will be handled by each control itself. **But I need the environment, like the Windows window manager.** It will forward user interaction messages, timers, draw events, parent-child relationships, resizing, moving and so on. **And trust me, anything looks better than the standard 90's C++ windows controls.** --- So technically, I want to build a new Windows system on top of Direct 2D and Write and Wic for native C++. Drawing the controls, that's easy to change once the framework is in place. The technology behind will stick. – CodeAngry Nov 29 '13 at 10:47

4 Answers4

6

Well, Windows seems to have an API for everything. :)

I just found the Windows Animation Manager. It does not only do what I need but at the end of the page, it has some very good videos explaining UI animation concepts and how they work with the Animation Manager. And it's a set of COM objects designed for C++ use.

PS: As a bonus, it's graphics platform independent. So it works with GDI, GDI+, Direct2D...

PPS: One day later, I already sank my teeth in it and it's very good. I got graphical elements predictably moving around the screen with minimum code. And it's logic. One single issue is that it can only animate a DOUBLE value. So it has no notion or support for a POINT, RECT, SIZE, POLYGON, multiple FLOATs, PATH... etc. Once I understand how it works properly, I will wrap it and add support for the above data types and I'm done.

CodeAngry
  • 12,760
  • 3
  • 50
  • 57
  • Microsoft Channel 9 has a few videos on this topic such as [Inside Windows 7: Animation Manager Deep Dive and Tutorial](https://channel9.msdn.com/Blogs/yochay/Inside-Windows-7-Animation-Manager-Deep-Dive) and there are several samples such as the image browser [Hilo: Developing C++ Applications for Windows 7](https://msdn.microsoft.com/en-us/library/windows/desktop/ff708696.aspx) which uses the Animation Manager. – Richard Chambers Aug 01 '16 at 00:06
  • @RichardChambers can you know where can I found source code for Hilo: Developing C++ Applications for Windows 7? – Sonny D Jul 18 '20 at 12:22
  • 1
    @SonnyD Here is a link to the Visual Studio C++ Samples, https://learn.microsoft.com/en-us/cpp/overview/visual-cpp-samples?view=vs-2019 which contains links to a wide variety of sample applications. There is a link to this GitHub repository that claims to be Hilo, https://github.com/Microsoft/VCSamples/tree/master/VC2013Samples/Hilo and it looks like source and documentation is there. Looks to be VS 2010 and Windows 7 so conversion will probably be needed. VS 2019 with UWP may be more appropriate for Windows 10. – Richard Chambers Jul 18 '20 at 14:51
  • @SonnyD You may also find this GitHub repository of Microsoft Visual Studio samples of interest, https://github.com/Microsoft/vcsamples as it covers several versions of Visual Studio from VS 2008 to VS 2017 and appears to be a kind of archive of old source code samples. – Richard Chambers Jul 18 '20 at 14:53
3

I can't tell you the standard way but the WPF way (and the Java Swing way too I think) is to have a special thread named the UI thread whose only job is to execute the dispatcher loop. The dispatcher loop is just a fancy word for a queue (with sugar). The framework would schedule a draw function for every frame on that queue. If you would want an animation you would have to schedule these tiny stepwise updates on that queue too. That is because WPF and the like don't want locking/blocking on the UI thread and they also don't want race conditions.

So to answer your question: It is neither a different thread nor a timer. It's a scheduler that executes animation steps.

Jonas Bötel
  • 4,452
  • 1
  • 19
  • 28
  • This answer gave me a good idea. Thanks! I'll select it later on unless something more detailed comes along. – CodeAngry Nov 29 '13 at 09:10
  • @LumpN, I knew about UI thread in WPF, have you any more in depth articles about how UI is designed in WPF? Other than: https://learn.microsoft.com/en-us/dotnet/framework/wpf/advanced/threading-model – Sonny D Jul 17 '20 at 22:23
3

I know it's necromancy (I do that often), plus you already accepted your answer... But you or other readers might be interested to have a look at DirectComposition. Note it's Windows 8+ only though.

Microsoft DirectComposition is a Windows component that enables high-performance bitmap composition with transforms, effects, and animations.

polyvertex
  • 749
  • 6
  • 15
  • 1
    It's W8+ only but W8+ is a lot more widespread now compared to 2013. So it's a good addition to the answers here. – CodeAngry Apr 14 '15 at 11:04
2

There's no standard in the GUI. C++ does not have gui either. Has threads now, though :)

  • Apps like word or outlook should use C# for gui and C++ for core.
  • Apps for tech and dev users in labs, and universities, and military bunkers can usually get away with simple, cross-platform gui. QT is widespread. For really simple stuff, like demos - fltk might suffice.
  • Narrow purpose small tools (file compressor, torrent client, task manager) can use native winapi windowing functions. C style. Unmaintainable. Unscalable. Native to windows platform. Optimized for performance after many years.
  • Video games usually reinvent the wheel and perform all gui activity inside the game using d3d.
  • Apps like skype, that require the most advanced gui features like floating/dockable/tray/custom shaped/transparency/absolutely tailor made GUI whatever the cost - will probably go with something shiny from MS, like silverlight or Wic, for that matter.
  • Monstrous projects are likely to choose MFC or ATL.

Likely choices would be C# or Qt for serious gui. For smaller things winapi + gdi or a small cross-platform, c++ gui toolkit.

For any non-console programming on Windows, get yourself familiar with "window procedures" and winapi message loops. Begin with creating a new default win32 project in visual studio and looking at the code it produces. Do not write like that. Just notice the following pattern:

// Handles window messages. Gets called by the DispatchMessage indirectly.
LRESULT __stdcall WindowProc(HWND hWnd, UINT msg, WPARAM, LPARAM)
{
    switch(msg) {
        case WM_PAINT: BeginPaint(...);
                       // Some GDI drawing might go here
                       EndPaint(...); break;
        case WM_TIMER: InvalidateWindow(hWnd); break;
        case WM_DESTROY: PostQuitMessage(0); break;
    default: return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    return 0;
}

int __stdcall WinMain(HINSTANCE, HINSTANCE, char *cmdLine, int cmdShow)
{
    // create your gui here
    HWND hWnd = CreateWindow(...);
    ShowWindow(hWnd, cmdShow);
    UpdateWindow(hWnd);

    // Main message loop : make the gui "run"
    MSG msg = {0};
    while(GetMessage(&msg, 0, 0, 0) > 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return 0;
}

This is the native winapi application skeleton. It's what MFC/ATL/Qt do underneath. Winapi offers some really basic controls out of the box: window, text box, button, radio button, select button, listbox. All do basic shadows, highlighting on focus - stuff that's available since win95, but not really much more. If the gui is very modest, then you may get away with using just plain winapi for it.

As a gui library developer, the best combo is probably win32 api and com components from ms or other vendors.

Yury Korobkin
  • 105
  • 1
  • 8
  • 1
    +1 for the first part but the final part is slightly offensive considering I've been doing Win32 programming *(+Standard UI & Custom Drawn Controls)* since 1998. It's about 15 years of it... I use my own custom UI library *(on top of the Standard Controls myself)* plus my own C++ library wrapping most of the Win32 C API. Time to graduate my UI skills to something **shiny... like the Serenity**. - **PS**: It's more like `while(GetMessage(&msg, 0, 0, 0) > 0)` as `WM_QUIT` returns `0` and error returns `-1` which evaluates to `TRUE` in your `while`. MSDN explicitly advises against your while. :) – CodeAngry Nov 30 '13 at 05:03
  • Hi, thanks for the vote - now i can add comments instead of writing an answer. please forgive me for the last part. And that loop condition: vs2013 generated that line for me, and yet, the msdn advises against it. Thank you, for pointing out. – Yury Korobkin Nov 30 '13 at 16:09
  • NP:) Now change your user name into something meaningful, add an email if you didn't, and you've got a proper SO account. – CodeAngry Nov 30 '13 at 18:42