// ======================================================================== // THIS CLASS AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. // // Copyright 1997-1998 Giuseppe "Jo" Parrello. All Rights Reserved. // // Sites : http://www.geocities.com/SiliconValley/Hills/8145 // http://space.tin.it/computer/giparrel // E-Mail : joparrello@geocities.com, joparrel@tin.it // ======================================================================== // // Class: JPMRURegistry (Release 2.0 - August 18, 1998). // // Files: jpmrureg.cpp jpmrureg.h // // Purpose: Provides a Most-Recent-Used List using Windows registry. // // Platforms: This class has been tested on Windows 95 and on Windows 3.1 // and it should run on Windows NT too. // I've used Borland C++ 5.02 to build this class, but I think // that it should run with 5.01 release too. // // Comments: JPMRURegistry class is derived from TEventHandler class. // Its purpose is to provide you a replacement for // TRecentFiles class. Now you can use the registry to store // the MRU List. Read the following notes to use this class. // // Overview: My only aim is to provide you a class that can store // the most recent used files into registry instead of // using a .ini file. At the same time I've tried to solve // some problems that afflict TRecentFiles class. // These problems are : // 1) When I declare TRecentFiles and use as second param // the number "10" and when I open the "File" menu, // the MRU appears so: // ------------------------------ // 1 C:\BC5\HELP\OWL5.HLP // ........ // 10 C:\WINDOWS\README.TXT // ------------------------------ // As you can see up here the last row is not // aligned with the first row. The string "C:\WINDOWS..." // is shifted by one character to right. // Using my class "File" menu will appear: // ------------------------------ // 1 C:\BC5\HELP\OWL5.HLP // ........ // 10 C:\WINDOWS\README.TXT // ------------------------------ // 2) Moreover, as described up here, you can note that // the shortcut keys are "1" for the first row and // "1" for the last row. // When I want to select the number "10" row, I // must press "1" twice; I've solved this problem // putting an ampersand before "0" as this number // was never treated as a shortcut. So if I want // to select the last row, now I can press "0" and // the file associated with the last item on list // will be opened without problems. // // NOTE: Before using this class consider the following // changes and considerations: // 1) The MRU is read once when the application is started // and is written only when the application is // terminated. If application crashes or hungs up or // doesn't terminate correctly, you will lose // the files opened most recently and inserted into the // MRU List. TRecentFiles, instead, immediately writes // the last opened file into the .ini file when you // open a file or select a file from the MRU List. // If you want to avoid these situations, use the // "ForceUpdate" param, to force the registry update. // 2) When you reduce the MRU List's size at runtime, // the remaining items ("tail") are deleted from the list // and when the application terminates, this items // are lost forever. I think that this problem afflicts // TRecentFiles class too. // 3) When you execute your application more than once // the MRU List is only one for each session of it; // you cannot create more than one MRU List at a time // and these MRU lists will share the same data. // To solve this problem, limit your application // to be opened only once, giving a message if user // opens another session of your application. // This problem afflicts TRecentFiles class too. // 4) This class is compatible with Win 3.1's registry. // But in this registry the data are stored // in HKEY_CLASSES_ROOT key while if your application // was declared as a Win16 target and runs under // Windows 95, the data are always stored in // HKEY_CURRENT_USER key. The functions that have // to do with registry in Win 3.1 API can only // store data in HKEY_CLASSES_ROOT key but, // when are under Windows 95, can store data // in other keys too. However note that the string // created or opened on registry cannot include spaces // (when the target application is Win16) and that // in Windows 3.1 there is no conception of "current user", // so the data are declared as "global", for all users. // // Declaration: JPMRURegistry(const _TCHAR far* regKey, // uint MRUsize = MaxMenuItems, // bool IsCurDir = false, // bool IsUnderExitMenu = false, // bool ForceUpdate = false, // bool CheckFileExistence = false, // bool NoExtDisplay = false, // int MaxItemLen = 0); // "regKey" param is a string containing the registry key. // This is string must be written as // "CompanyName\\ProductName\\Version" (beware of the double // backslash "\\"), as described in "The Windows Interface // Guidelines for Software Design" Help File (UIGUIDE.HLP file). // Refer to this file if you want more info (open this file // and search the string "Software integration" on index tab). // "MaxMenuItems" is the size of the MRU List (you can change // this size at runtime using the "SetMaxMruItems" function). // The default value is 10, the maximum value allowed. // The third param is new. This allows you to "track" the // current directory. Try to understand this example: // I've opened four files: "C:\WINDOWS\README.TXT", // "C:\BC5\HELP\UIGUIDE.HLP", "C:\BC5\INSTALL.LOG" and // "D:\FREE\DOCS.TXT". If this param is true (false is default), // and the current directory is "C:\" the MRU List will appear: // 1 D:\FREE\DOCS.TXT // 2 C:\BC5\INSTALL.LOG // 3 C:\BC5\HELP\UIGUIDE.HLP // 4 C:\WINDOWS\README.TXT // I open the "Open" menu item on "File" menu and change the // current directory, moving to "C:\BC5". I don't select any // file and close the Open File dialog. // Now the MRU List is: // 1 D:\FREE\DOCS.TXT // 2 INSTALL.LOG // 3 C:\BC5\HELP\UIGUIDE.HLP // 4 C:\WINDOWS\README.TXT // Note that the second row is now only the file name, not // the full-path file name, as the current directory is // just that directory stored in "C:\BC5\INSTALL.LOG". // Following the procedure described up here, I change // the current directory to "C:\BC5\HELP". Now the MRU List is: // 1 D:\FREE\DOCS.TXT // 2 C:\BC5\INSTALL.LOG // 3 UIGUIDE.HLP // 4 C:\WINDOWS\README.TXT // Now the third row is only a file name. And so on..... // You can declare this param in source file or change // the current boolean value using "EnableDirectoryFeature" // function to enable or disable this feature. // The Fourth param is new. It allows you to put the MRU List // under the "Exit" menu item on "File" menu. Default is false. // Declare this param "true" (or change at runtime using // "PutMRUUnderExitMenu" function) and you emulate the MRU List // that you can see on your Borland C++ compiler!!. // The Fifth param "ForceUpdate" is new on release 2.0, and // if it is true, it forces to update the registry whenever // you choose a menu item from the MRU List or when you // add a file to MRU list. The default value is false. // The sixth param "CheckFileExistence" is new on release 2.0, // and if is true, it checks the file existence when it // reads the MRU from the registry. Only if the file exists, it // will be added to the MRU List. The default value is false. // The seventh param "NoExtDisplay" is new on release 2.0, // and if is true, it avoids to insert the file extension in the // string that will be displayed in the menu. // The default value is false. // The last param "MaxItemLen" is new on release 2.0, // and if its value is greater than 0, it shrinks the size // of the filename string to n characters. Default is 0. // The parameters "IsCurDir", "NoExtDisplay" and "MaxItemLen" // can be used together and they can reduce the size of the // string very-very well. See the method "RetrieveMenuItemString" // if you want to know how these three params can work together. // // Methods: Constructor // We initialize our internal variables, we create our // main key on the registry, and we read the MRU List. // // Destructor // We write the MRU on the registry and we close the key. // // SetMaxMruItems(int max, bool update) // Set the max number of items on MRU and delete the // remaining items from it. If the param "update" is true // and the optional feature "ForceUpdate" is true, // we update the registry. // // GetMenuText // We retrieve the text of the item based on menu ID. // Note that this retrieve only the fullpath filename, // without any kind of shrinking. // If you want to retrieve the string without extension, or // without the current directory (see the Declaration section), // you must use the "RetrieveMenuItemString" function. // // SaveMenuChoice // Save the menu item on the MRU List. // If the "ForceUpdate" feature is true, we update the registry. // // CmSelect // The user has selected an item in the MRU menu. // // CeExit // We obtain the menu handle to update the MRU menu. // // GetMRUSize // We retrieve the current MRU List's size. // // ReadMRU // If our main registry key exists, then we read the MRU // from the registry. If the "CheckFileExistence" feature // is true, we add it to the MRU only if the file really exists. // If the "UpdateRegistry" feature is true, we update the // registry. // // WriteMRU // We write the MRU List on the registry. // // FindTextInArray // We find a string in the MRU List. From the release 2.0 // this search is case-insensitive. // // AddStringToList // Add a string to MRU List. If "ForceUpdate" feature is true, // we update the registry. // // RemoveStringFromList // We remove a string from the MRU list. // // DeleteScraps // We delete the unnecessary strings from the MRU List. // // RetrieveMenuItemString(LPTSTR lpszFileName) // Given a fullpath filename string, it retrieves a // filename according to the optional parameters of MRU List. // This function works in this order: // 1) If "NoExtDisplay" feature is true, it cuts the file // extension from the string. // 2) If "TrackCurrentDir" feature is true, it checks if // the file is in the current directory. If it is so, // we retrieve only the file name without the directory. // 3) If "MaxMenuItemLength" feature is true, and the length // of the input string is greater than the max value, // we try to shrink the length of the string. // If we have a fullpath filename // "C:\Programs\ButtonApp\buttonap.txt" and the max value // is 30, we must shrink this string. The result is // "C:\...\ButtonApp\buttonap.txt". But if you have // "C:\Programs\Internet Browser\Readme.txt", the result is // "C:\...\Readme.txt", as "c:\...\Internet Browser\Readme.txt" // is greater than 30 chars. // // UpdateMenu // This method inserts the MRU List in "File" menu. // The code was rewritten to solve a bug on Win16 targets, // that, often, don't insert a separator above the "Exit" // menu item. This code forces the insertion if the // separator doesn't exist. // // EnableDirectoryFeature/GetDirectoryFeature // These two methods have to do with the "IsCurDir" feature. // // PutMRUUnderExitMenu/IsMRUUnderExitMenu // These two methods have to do with the "MRUUnderExitMenu" // feature. // // SetMRUUpdate/GetMRUUpdate // These two methods have to do with the "ForceUpdate" // feature. // // SetMRUFileExistence/GetMRUFileExistence // These two methods have to do with the "CheckFileExistence" // feature. // // SetNoExtDisplay/GetNoExtDisplay // These two methods have to do with the "NoExtDisplay" // feature. // // SetMaxItemLength/GetMaxItemLength // These two methods have to do with the "MaxMenuItemLength" // feature. // // GetRegistryRootKey // Retrieve our main registry's key. // // CreateRegistrySubkey // Create or open if exists the subkey of a given key. // // CreateRegistryKey // Create or open if exists our main registry's key. // // GetRegistryStringValue // Read a string value from the registry. You can specify // a default string, so if it cannot read this string, // it will return your default value. // // SetRegistryStringValue // Write a string value on the registry. // // GetRegistryIntegerValue // Read an integer value from the registry. You can specify // a default value, so if it cannot read this value, // it will return your default value. // Note that in Win32 we use the REG_DWORD type for reading // a numeric value, while in Win16 we read the string // and convert it to a number. // // SetRegistryIntegerValue // Write a numeric value on the registry. // Note that in Win32 we use the REG_DWORD type for writing // a numeric value, while in Win16 we convert the numeric // value to a string and write it. // // DeleteRegKey // Delete a value from the registry. // // Comment: I've not used TRegKey class because I am not sure that // this class runs well if you don't specify a key in // first parameter and it's not sure that this key can be // created. Note that my class even runs if the key cannot // be created, the only difference is when you close your // application the MRU List won't be stored anywhere. // I used TArrayAsVector template that saved my life.... // I hope that this class can help you (and me!!). // Contact me (using my e-mail) if you discover bugs or // problems, and to let me know this class runs on Windows NT. // // HISTORY: Release 2.0 (August 18, 1998) // More options that make your life easy and I solved // the bug of first release rewriting parts of code. // // Release 1.0 (March 16, 1998) // The first release. This release has a bug when // inserts the separator under Windows 3.1. //--------------------------------------------------------------------------- //===========================================================================