Strings in Resources   ..



Strings in Resources are rarely used because they are at least double the size (Unicode storage + Resources tree headers + dummy Strings, when required) and because they are slower to access. So, you should never consider Resources as a good place where to store your Applications Strings. Usual Memory is the preferred place for this.


In RosAsm, the whole size of Resources Strings is limited to 0FFFF.


To load a String:


call  'USER32.LoadStringA'  D§hInstance  ID  StringBufferAddress  D§StringBufferLength



Resources Strings are well designed for storing small Strings that you wish to access randomly, using the Strings IDs as an access index, as, for example, with ToolTips Strings. Here is a clever example from a Test Department's Tutorial. 


;============================================

; WM_NOTIFY (value=4Eh) message, here used to show the toolbar tip !

; With a WM_NOTIFY message Windows gives you pointer to a NMHDR structure.

;------------------------------------------------------------------------------

WP1_uMsg_04E:

    cmp eax 04E                          ;check if WM_NOTIFY message recieved

    jne WP1_uMsg_0A0          ;if not goto label

;------------------------------------------------------------------------------

; The NMHDR structure contains information about a notification message.

; The TOOLTIPTEXT structure identifies a tool for which text is to be displayed

; and receives the text for the tool.

; We must fill it with the CORRECT values ...

; The POINTER to this structure is specified as lParam member of WM_NOTIFY.

; This POINTER is given to us with the WM_NOTIFY message by Windows.

;------------------------------------------------------------------------------

; - NMHDR structure -

; hwndFrom =  D$WP1_lParam+0  ;handle to control sending message 

; idFrom =    D$WP1_lParam+4  ;identifier of control sending message

; code =      D$WP1_lParam+8  ;notification code

; - TOOLTIPTEXT structure -

; hdr = placeholder for NMHDR ;required for all WM_NOTIFY messages

; lpszText =  D$WP1_lParam+12 ;Pointer string or resource ID

; szText[80]= D$WP1_lParam+16 ;buffer for text, alternate to lpszText

; hinst =      D$WP1_lParam+20 ;handle instance, 0 if lpszText=pointer

; uFlags =    D$WP1_lParam+24 ;Flag indicates how to interpret idFrom

;------------------------------------------------------------------------------

    mov ebx D$WP1_lParam  ;pointer to struc, given by windows !

    mov eax D$ebx+8                  ;move code ( NMHDR structure ) into eax

    cmp eax 0FFFFFDF8          ;check if code TTN_NEEDTEXT received

    jne TB_customize_0        ;if not goto label

    mov eax D$ebx+4          ;move idFrom ( NMHDR structure ) to eax

        

    cmp eax 0C0                          ;is it toolbar button ID=0C1h

    jb WP1_return

    cmp eax 0CD ;last identifier in TBBUTTON structure

    ja WP1_return

    mov D$ebx+12 eax ;store resource ID of tooltiptext

    mov eax D$hInstance

    mov D$ebx+20 eax ;store module instance


As you can see, the 3 last instructions are enough to return the information expected in response to the WM_NOTIFY message. TD has ranged his ToolBar Buttons IDs from 0C0 to 0CD. Then, he saved in Resources the respective ToolTips Strings with the same ID numbers so that there is no computation at all to perform the attributions.



Strings Editor usage


Enter your Strings in the Strings Edit Box. Begin each String with the decimal #Number of each String ID:



    #1 First string.

    #2 Second string with

    one CR/FL inside

    #3 Third string with...


    ... 2 CR/LF inside.



The First entered Chararacter of a new String *MUST* be '#', immediately followed by the decimal number, with one single space before the String data. If you hit 2 Spaces between the number and your first 'non-Space' data, your String begins by one Space. 


CR/LF and Tabs are allowed.


ID numbers are from 0 to 0FFFF and are to be given in Decimal notation only.



IDs Internals


It might seem surprising that a zeroed  ID would be impossible, but, for strings, it is. In Resources, the true user_IDs are split this way: (User_ID shr 4) + 1. These 'main IDs' are the ones stored in the Resources tree. The relative Resources pointers point to groups of 16 unicodes Strings written in Pascal convention one after another (Len, String, len, String,...). The 4 Bit lower part of the user_IDs are not stored at all. The loading functions simply read as many records as wished to access the target String inside a group.


When entering Strings IDs that are *not* aligned on 16 bit boundaries, or that are not conforming to the numeric order, the Editor fills the missing records with dummy Strings. When reloading a Strings table, the Editor shows you these added Strings paddings.



Inserting Strings


Because of this complicated organization, the Editor is featured for helping you at inserting Strings inside long tables. You can add any String with any ID, anywhere you like. If the IDs you enter are not in numeric order, the Editor will rearrange the Strings for you. If two Strings have the same ID, the Editor will increase the following IDs, only as far as required, saving you the pain of rewriting all the downward IDs and checking these damned boundaries. This simplifies a lot the problems you would encounter when inserting new Strings. Example:


You have entered a table like this:


#1 One

#2 Three

#3 Four

#16 Sixteen

#17 Eighteen


Now, you add, at the bottom, two Strings to be inserted:


#1 One

#2 Three

#3 Four

#16 Sixteen

#17 Eighteen

#1 Two <<<<

#16 Seventeen <<<<


If you hit [OK] and, again, [Resources] / [Strings], you will see:


#0  

#1 One

#2 Two <<<<

#3 Three

#4 Four

#16 Sixteen

#17 Seventeen <<<<

#18 Eighteen


~~~~~~~