You can store many types of resources in a ROOS:
|Accelerator table||Group cursor|
|Bitmap resource||Group icon|
|Cursor resource||Icon resource|
|Dialog box||Menu resource|
|Font directory resource||String resource|
|Font Resource||User-defined resource|
A ROOS has two components. The first is the resource module, a special file created with an application such as Microsoft Visual C++. The resource module contains all the resources you want to store and retrieve. The second element of the ROOS is a method to retrieve a resource from the resource module. At TMS, we prefer to expand the functionality of the ROOS methods so that string values can be parsed with input parameters. The following example illustrates this.
String ID: 400 String value: "The operation completed with % errors"
StringID = 400 MyText = GetStringFromROOS(StringID, "no")
Public Function GetStringFromROOS(StringID As String, _ Param) As String Dim sText As String sText = GetString(StringID) sText = MergeString(sText, Param) GetStringFromROOS = sText End Function
MyText: "The operation completed with no errors"
Many projects store custom error messages or other display text in a database file. In an error handler, the custom error text is better in a ROOS because the execution speed is much faster, and many organizations restrict access to make database changes to the database administrator-no good if you're a programmer and have to wait two days to change the caption on a button! Another excellent use of a ROOS is to store icons and bitmaps. Imagine you're lucky enough to have an artist to create all your graphics. You can create a ROOS with dummy resources, and then the artist can add the real graphics to the ROOS as they become available without having to access any source code. (No more multiple access problems!)
Creating a resource module is easy if you have the right tools. You simply enter the resources you want. Each resource has an ID value, which is a long integer. To retrieve the resource from the resource module, you simply use the LoadResData, LoadResPicture, or LoadResString command specifying the resource's ID. Figure 14-12 shows a typical resource file in Microsoft Visual C++ 6. Once the resource module is created (it's actually an RC file), you simply compile it with the RC.EXE program (supplied on the Visual Basic CD-ROM) to create a RES file that you can add to your ROOS project. You can have only one RES file in a single Visual Basic project, but one is plenty! (If you don't have access to Visual C++ or any other tool for creating resource files, you can use an editor such as Notepad. Before attempting this, however, you should study an RC file and a RESOURCE.H file to become familiar with the format.)
Obviously, any client requesting data from the ROOS will need to know the ID value for each resource. In Visual Basic 4, you would need to include your ID constants in each client application, either as hard-coded constants or in a shared type library. With Visual Basic 5 and 6, you can declare all your IDs within the ROOS as enumerated constants, which makes them automatically available to client applications.
Listing 14-1 shows a slightly more advanced ROOS that retrieves string and bitmap resources. The ROOS allows you to merge an unlimited number of tokens into a string resource. To create a string resource with tokens, simply insert a % symbol in the string where the supplied parameter(s) will be substituted.
Figure 14-12 A resource file created in Microsoft Visual C++ 6
Listing 14-1 ROOS for retrieving string and bitmap resources
' The following Enums declare the resource ID of the bitmaps ' in our RES file. The include file "resource.h" generated ' by the resource editor defines the constants to match each ' bitmap. Checking this file shows the first bitmap resource ' ID to be 101; therefore, these Enums are declared to match ' this. Public Enum BITMAPS ' *** ' *** NOTE: Any new bitmaps added must be inserted between ' *** IDB_TOPVALUE and IDB_LASTVALUE because these constants are ' *** used to validate input parameters. ' *** idb_topvalue = 100 IDB_SELECTSOURCE IDB_SELECTDESTIN IDB_NUMBERSOURCE IDB_COMPLETED idb_lastvalue End Enum Public Enum STRINGS ' VBP project file key ID words IDS_VBP_KEY_FORM = 500 IDS_VBP_KEY_CLASS IDS_VBP_KEY_MODULE IDS_VBP_SEP_FORM IDS_VBP_SEP_CLASS IDS_VBP_SEP_MODULE IDS_VBP_SEP_RESFILE IDS_VBP_KEY_RESOURCE16 IDS_VBP_KEY_RESOURCE32 ' Procedure keywords IDS_PROCKEY_SUB1 = 600 IDS_PROCKEY_SUB2 IDS_PROCKEY_SUB3 IDS_PROCKEY_FUNC1 IDS_PROCKEY_FUNC2 IDS_PROCKEY_FUNC3 IDS_PROCKEY_PROP1 IDS_PROCKEY_PROP2 IDS_PROCKEY_PROP3 IDS_PROCKEY_END1 IDS_PROCKEY_END2 IDS_PROCKEY_END3 IDS_PROCKEY_SELECT IDS_PROCKEY_CASE IDS_PROCKEY_COMMENT ' File filter strings IDS_FILTER_FRX = 700 IDS_FILTER_PROJECT IDS_FILTER_CLASS IDS_FILTER_FORM IDS_FILTER_MODULE IDS_FILTER_CONFIG IDS_FILE_TEMP ' Displayed caption strings IDS_CAP_STEP1 = 800 IDS_CAP_STEP2 IDS_CAP_STEP3 IDS_CAP_STEP4 IDS_CAP_NUMBER IDS_CAP_UNNUMBER IDS_CAP_CANCEL IDS_CAP_FINISH IDS_CAP_CANCEL_ALLOWED ' Message strings IDS_MSG_NOT_TEMPLATE = 900 IDS_MSG_COMPLETE_STATUS IDS_MSG_TEMPL_CORRUPT IDS_MSG_INVALID_CONFIG IDS_MSG_CREATE_TMPL_ERR IDS_MSG_NO_SOURCE IDS_MSG_INVALID_DESTIN IDS_MSG_SAME_SRC_DESTIN IDS_MSG_QUERY_EXIT IDS_MSG_ABORTED ' Err.Description strings IDS_ERR_GDI = 1000 IDS_ERR_PROCESS_ERROR End Enum ' Resource ROOS error constants Public Enum RR_Errors RR_INVALID_BITMAP_ID = 2000 ' Invalid bitmap resource ID RR_INVALID_STRING_ID ' Invalid string resource ID End Enum Public Sub PuGetBmp(ByVal ilBitmapID As Long, _ ByVal ictl As Control) ' Check that the ID value passed is valid. This is an ' Assert type of message, but the class cannot be part ' of the design environment, so raise an error instead. If ilBitmapID <= idb_topvalue Or _ ilBitmapID >= idb_lastvalue Then Err.Description = "An invalid bitmap ID value '" & _ ilBitmapID & "' was passed." Err.Number = RR_INVALID_BITMAP_ID Err.Raise Err.Number Exit Sub End If ' Load the bitmap into the picture of the control passed. ictl.Picture = LoadResPicture(ilBitmapID, vbResBitmap) End Sub Public Function sPuGetStr(ByVal ilStringID As Long, _ Optional ByVal ivArgs As Variant) As String Dim nIndex As Integer Dim nPointer As Integer Dim nTokenCount As Integer Dim sResString As String Dim vTempArg As Variant Const ARG_TOKEN As String = "%" sResString = LoadResString(ilStringID) If IsMissing(ivArgs) Then GoTo END_GETRESOURCESTRING If (VarType(ivArgs) And vbArray) <> vbArray Then ' Single argument passed. Store the value so that we can ' convert ivArgs to an array with this single ' value. vTempArg = ivArgs ivArgs = Empty ReDim ivArgs(0) ivArgs(0) = vTempArg End If nTokenCount = 0 Do While nTokenCount < UBound(ivArgs) _ = LBound(ivArgs) + 1 nPointer = InStr(sResString, ARG_TOKEN) If nPointer = 0 Then ' There are more arguments than tokens in the RES ' string, so exit the loop. Exit Do End If Call sPiReplaceToken(sResString, ARG_TOKEN, _ ivArgs(LBound(ivArgs) + nTokenCount)) nTokenCount = nTokenCount + 1 Loop END_GETRESOURCESTRING: sPuGetStr = sResString End Function Private Function sPiReplaceToken(ByRef iosTokenStr As String, _ ByVal isToken As String, ByVal ivArgs As Variant) Dim nPointer As Integer nPointer = InStr(iosTokenStr, isToken) If nPointer <> 0 Then iosTokenStr = Left$(iosTokenStr, nPointer - 1) & _ ivArgs & Mid$(iosTokenStr, nPointer + 1) End If End Function