Channels ▼
RSS

Tech Tips


Tips

Download the code for this issue

Locking Window Updates

by Matthew Wilson
matthew@synesis.com.au

A classic problem when updating windows in lengthy and granular operations is that of window flashing, where changing the contents of a control results in the repeated redrawing of part or all of its visible area. When a large number of such updates occur in a short time, this becomes problematic, and the repeated redrawing appears as a very unappealing visual disturbance.

Two common solutions to this problem are to use the API function LockWindowUpdate and the WM_SETREDRAW message.

LockWindowUpdate is implemented by swapping out the window's normal device context and replacing it with one whose visible region is empty. When LockWindowUpdate is called with NULL (which unlocks the window), the original device context is replaced, and the system invalidates an area within it equivalent (in size and location) to that of the temporary one such that the window will receive a request to redraw the modified area. Hence all drawing is effectively performed in a single operation, and the visual effect is much more seamless. The disadvantage of using LockWindowUpdate is that it can only be used for one window at a time, so it cannot be used to simultaneously lock a collection of related controls. The first window to call the function is locked, and all other calls preceding the unlock call fail. (This can be easily shown by uncommenting the artificial lock of the run — button on line 93 of the test application implementation file, wndscope.cpp, which is included in this month's code archive.) Interestingly, if two versions of the application using LockWindowUpdate are run simultaneously it appears that whichever process calls the function "owns" the lock, removing the ownership of the previously successful call, which reverts to the unlocked behavior of flashing on the string inserts.

WM_SETREDRAW is a message implemented by various standard common and custom controls, including the listbox, combobox, list view, button, and tab control. It works by clearing and setting the window redraw flag. The only slight disadvantage is that the application must invalidate the window rectangle after sending the reactivating message, and therefore the whole visible window rectangle will be redrawn. Use of WM_SETREDRAW generally supersedes use of LockWindowUpdate. Of course, for windows that do not support this message, LockWindowUpdate remains the tool of choice.

Presented here are two classes from the WinSTL libraries (http://winstl.org/) — window_update_scope and window_redraw_scope — that provide automated scoping of these two forms of locking. (Abridged implementations of the two classes are shown in Listings 1 and 2. The full implementations are provided in the archive, and are also available online at the WinSTL site.) In the constructors of the classes the lock is set, then reset in the destructors: window_update_scope calls LockWindowUpdate in its constructor and, if successful, calls LockWindowUpdate(NULL) in its destructor; window_redraw_scope sends WM_SETREDRAW (passing False) in its constructor and sends WM_SETREDRAW (passing True). They both take the handle of the window to lock in their constructors; window_redraw_scope takes a second parameter (defaulted to True) that specifies whether the window is invalidated (via a call to InvalidateRect) when unlocked.

The uses of these two techniques are demonstrated in the accompanying application (Figure 1), which sends many items to a listbox, with or without the two locking techniques just described. To demonstrate the techniques, simply execute the program and select "Run," demonstrating the flashing. Then select, in turn, the "Use LockWindowUpdate" and "Use WM_SETREDRAW" boxes and run, demonstrating the locking.

A Better Macro Wrapper for Visual C++

By John Szakmeister
jszakmeister@actelesys.com

The February 2003 "Tech Tips" column included a tip on using the do/while construct to avoid some pitfalls in defining some macros ("do/while Macros for C++" by Raja Venkataraman). This tip is useful, but I thought I'd offer my two cents to improve upon it. There is actually an easier way to get the same result. In C and C++, you can insert curly braces anywhere inside a function to section off a piece of code. I've found this ability to be extremely helpful since I do both Windows and embedded programming. Most cross-compilers do exactly what you tell them (even though some optimizations may be performed), so wrapping something with a do/while loop can actually result in code being generated for the loop. A simple way to avoid this is not to wrap it with a do-while loop, but just wrap it in braces. I also use this feature to help inline several slightly more complicated functions in C, but get to keep the speed that I desperately need to process other things.

Listing 3 shows how the original Tech Tip code would change. The wonderful (and harmful if not used correctly) feature of this technique is that you can also define local variables that will not interfere with other variables in your function. For instance, you normally can't declare a local variable after the first code statement in a .c file (Listing 4(a)). Listing 4(b), however, shows a code segment that works fine because of the new macro. Here you could even change the variable j to i and it would leave the outer variable untouched. So the code in Listing 5 would produce the following output:

i: 10
i: 100
i: 10

Displaying Full Path Names in the Recent File List Menu Item

By Pablo Presedo
ppresedo@hotmail.com

Recently, someone sent me an e-mail asking me how to get an MFC application to display the file's full path and name in the recent file list. The default behavior is to display the full path only if the current directory is different than the directory where the file is located. It will also abbreviate the path name if it is too long.

The filenames that are displayed in the recent file list are created by the CRecentFileList::GetDisplayName function. This function is called by CRecentFileList::UpdateMenu, which is called by the CWinApp::On- UpdateRecentFileMenu function. The CWinApp::OnUpdateRecentFileMenu function is called in response to the ON_UPDATE_COMMAND_UI(ID_FILE_MRU_FILE1, OnUpdateRecentFileMenu) message map entry found in appcore.cpp.

void CWinApp::OnUpdateRecentFileMenu(CCmdUI*pCmdUI)

{
    ASSERT_VALID(this);
    if (m_pRecentFileList == NULL)      
    // no MRU files
       pCmdUI->Enable(FALSE);
    else

       // *** This function will call GetDisplayName. ***
       m_pRecentFileList->UpdateMenu(pCmdUI);  
}

One solution to this problem is to delete the CRecentFileList* m_pRecentFileList after the LoadStdProfileSettings call made in your CWinApp derived InitInstance. We replace this with a class of our own that was derived from CRecentFileList (Listing 6). Our CRecentFileList will override the GetDisplayName function.

Make sure the nSize argument of the CRecentFileList derived class constructor is set to the value of the nMaxMRU argument of the LoadStdProfileSettings. That's all that there is to it. In this month's code archive, I have included an example that demonstrates this, as well as how to get an MFC dialog application to display a recent file list. By default, MFC dialog applications do not support a recent file list.


George Frazier is a software engineer in the System Design and Verification group at Cadence Design Systems Inc. and has been programming for Windows since 1991. He can be reached at georgefrazier@yahoo.com.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video