 |
O |
 |
 |
ne of the ways in which applications can make things
easier for a user is by remembering something that |
 |
 |
 |
xxxxxxxxxxxxxxx |
they've done before so that it can easily be repeated.
Wordprocessors remember the most recently accessed
documents. Search utilities will usually remember the last
couple of search requests that have been performed. The
Run dialog on the Start menu remembers the last few appli-
cations that have been started.
What each of these examples have in common is a list
of remembered choices that the user can select, usually
ordered by most recent usage. They are thus called Most
Recently Used lists, or MRU lists. The Windows developers
obviously found them so useful that they created a set of
routines specifically for managing MRU lists. The functions
are all exported from COMCTL32.DLL and, as you've no
doubt come to expect, they're all exported by ordinal. |
 |
The Registry Format |
 |
Windows 95 MRU lists are stored in the registry as a set of
values gathered together under a single key. Each item in
the list is represented by a separate registry value. The
value names are all single characters, using the letters 'a' to
'z', and '{', '|' and '}' (the following three characters in the
ascii table). Obviously that means there can't be more than
29 items in a list.
There is also a value named 'MRUList' which rep-
resents the order of the items in the list. It is just a string
containing the various item names in the correct order
(remember the names are all single characters). |
 |
Creating a List |
 |
 |
HANDLE WINAPI CreateMRUList(
LPCCREATEMRULIST lpCreateInfo);
void WINAPI FreeMRUList(
HANDLE hList); |
Figure 1 Create and Free Functions |
 |
|
 |
You open an MRU list, or
create a new list using the
CreateMRUList function (see
Figure 1 for the function decla-
ration). You pass it a structure
with information about the list,
and it will return a list handle |
|
which you will use in all subsequent functions. The declara- |
|
 |
|
|
tion of the structure passed to the function can
be seen in Figure 2.
cbSize specifies the size of the structure.
nMaxItems specifies the maximum number of
items allowed in the list. dwFlags specifies the
type of list to create (see Figure 3). hKey
identifies the handle of the root registry key
under which the list information will be stored.
lpszSubKey points to a null-terminated string
specifying the name of the registry subkey.
lpfnCompare specifies the function that is used |
 |
 |
typedef struct {
DWORD cbSize;
DWORD nMaxItems;
DWORD dwFlags;
HKEY hKey;
LPCSTR lpszSubKey;
PROC lpfnCompare;
} CREATEMRULIST; |
Figure 2 Create Structure |
 |
|
|
when comparing items in the list. |
|
 |
|
|
If the MRUF_STRING_LIST flag is specified,
list items are stored in the registry as string values.
If the MRUF_BINARY_LIST flag is specified, items
are stored as binary data. For string lists, the com-
parison function should accept two LPCSTR pa-
rameters (the two strings to be compared). For
binary lists, the comparison function should accept |
 |
 |
MRUF_STRING_LIST |
0 |
MRUF_BINARY_LIST |
1 |
MRUF_DELAYED_SAVE |
2 |
Figure 3 Create Flags |
 |
|
|
three parameters - two LPCVOID parameters (the data for
the two items) and a DWORD specifying the number of |
|
 |
|
|
bytes to compare (see Figure 4 for
the function declarations).
The MRUF_DELAYED_SAVE
flag determines how often the list
order data is saved to the registry.
Normally it would be saved
whenever you add an item to the
list, but if the MRUF_DELAYED_
SAVE flag is specified when the list
is constructed, the order data is
only saved when the list handle is |
 |
 |
int CALLBACK MRUCompareString(
LPCSTR lpszString1,
LPCSTR lpszString2);
int CALLBACK MRUCompareData(
LPCVOID lpData1,
LPCVOID lpData2,
DWORD cbData); |
Figure 4 Comparison Callback Functions |
 |
|
|
finally freed. You free the list using the FreeMRUList
function (see Figure 1 for the declaration). This will free
any internal data structures used by the list, as well as
flushing the unsaved order data if necessary.
The ordinal values for CreateMRUList and Free-
MRUList are 151 and 152 respectively. |
|
 |
|
|
 |
Adding Items |
 |
You can add an item to the list using the AddMRUString
function or the AddMRUData function (the function decla-
rations are shown in Figure 5). AddMRUString passes the
new item in as a string. AddMRUData passes the item in |
as a chunk of binary data - you specify a
pointer to a buffer and the number of bytes
in the buffer.
If the item being added already exists, it
isn't added again - its position is just moved
to the front of the list order. If the list is full,
the least recently used item in the list is rep-
laced with the new item. The return value is
a number corresponding to the registry
name where the item is stored. 0 corres-
ponds with the 'a' value, 1 corresponds with |
 |
 |
int WINAPI AddMRUString(
HANDLE hList,
LPCSTR lpszString);
int WINAPI AddMRUData(
HANDLE hList,
LPCVOID lpData,
DWORD cbData); |
Figure 5 Add Functions |
 |
|
|
'b', etc. If there was an error adding the item, the function
returns -1.
The ordinal values for AddMRUString and Add-
MRUData are 153 and 167 respectively. |
|
 |
|
|
 |
Removing Items |
 |
To remove an item from an MRU list, you can use the Del-
MRUString function (see Figure 6), passing it the position in
the list of the item you wish to remove (0 specifies the most
recently used item - this is not the same as the return value
from the AddMRUxxx functions). DelMRUString can also
be used for removing items from binary lists - there isn't a |
corresponding DelMRUData function, al-
though you could easily #define an alias
for the sake of consistency.
Unfortunately, that isn't the end of the
story. Due to a bug in the DelMRUString
implementation, if you attempt to add a |
 |
 |
BOOL WINAPI DelMRUString(
HANDLE hList,
int nItemPos); |
Figure 6 Delete Function |
 |
|
|
new item to the list after removing an item, you may end up
corrupting memory or causing your application to crash. To
work around this, you should always close the list and
reopen it again before you attempt any other operations on
the list.
DelMRUString returns TRUE if the item was removed
successfully. If the specified position is out of range, the
return value is FALSE. The ordinal value is 156. |
|
 |
|
|
 |
Enumerating Items |
 |
You can enumerate through the items in a list with the
EnumMRUList function (see Figure 7 for the function
declaration). nItemPos is the position in the list of the item
you wish to retrieve (0 being the most recently used item).
lpBuffer points to a buffer where the item will be stored. |
nBufferSize specifies the buffer size (for
string lists the size is in characters; for binary
lists it's in bytes).
The return value specifies how many
bytes were copied to the buffer in the case
of a binary list (this may be less than the full
size of the item if the buffer is too small). For
string lists, the return value is the full length |
 |
 |
int WINAPI EnumMRUList(
HANDLE hList,
int nItemPos,
LPVOID lpBuffer,
DWORD nBufferSize); |
Figure 7 Enumerate Function |
 |
|
|
of the string being retrieved (which may be longer than the
actual string returned if the buffer is too small). If you
enumerate past the end of the list, the function returns -1.
You can also determine the exact number of items in a
list by specifying a NULL buffer pointer, or by specifiying a
negative value for nItemPos. The return value is then the
number of items in the list. The ordinal value for Enum-
MRUList is 154. |
|
 |
|
|
 |
Searching the List |
 |
 |
int WINAPI FindMRUString(
HANDLE hList,
LPCSTR lpszString,
LPINT lpRegNum);
int WINAPI FindMRUData(
HANDLE hList,
LPCVOID lpData,
DWORD cbData,
LPINT lpRegNum); |
Figure 8 Find Functions |
 |
|
 |
If you need to search for a particular item
in the list, you should use the functions
FindMRUString and FindMRUData (the
function declarations can be seen in Figure
8). Much like the AddMRUxxx functions,
FindMRUString specifies the item as a
string and FindMRUData passes it in as
binary data in a buffer.
The return value is the position in the
list order, 0 being the most recently used
item. You can also determine the registry |
|
value where the item is stored by specifying a non-null
value for the lpdwRegNum pointer. It will be filled in with a
number corresponding to the item's registry name (this is
the same as the value returned by the AddMRUxxx
functions).
If the item could not be found, or there was some other
error, the functions will return -1. The ordinal values for
FindMRUString and FindMRUData are 155 and 169 res-
pectively. |
|
 |
|
|
 |
Windows NT and Unicode Strings |
 |
Unlike most undocumented functions, you don't have to
worry about using unicode strings on Windows NT and ansi
strings on Windows 95. The string-related MRU functions
all accept ansi strings, regardless of the operating system
(although, internally, the string data is stored in unicode on
Windows NT).
What's even nicer, though, is that there are also uni-
code equivalents of all the string-related functions if you
need them (although they're only available on NT). If you
do use them, though, don't forget that your string compari-
son function will also have to accept unicode strings. The
effected functions are CreateMRUList, AddMRUString,
FindMRUString and EnumMRUList (ordinals 400 to 403).
Unfortunately, if you're using a binary list on NT, you
have to use the wide-string version of EnumMRUList (the
ansi version has a bug in it which prevents it from returning
the item data). Of course, if you need your application to
run on Windows 95 as well, you'll have to link to the
function at run-time with GetProcAddress (it gets rather
messy). I guess that's one of the reasons why they don't
documented this stuff. |
 |
BACK TO HOME |