Page 1 of 2

How to get text from a resource into a string (PB4-Win XP)

Posted: Sun Nov 26, 2006 12:18 pm
by BigJack
Hi all, :P
Maybe some PB-expert can help me out here:
I am trying to get the text which is contained in the resource of the exe into a string variable by using the "LoadText_()" API function.
When trying this in order to display icons or bitmaps my code works just fine. But I can't get the text string to work...

Perhaps I am missing something in my code but don't know what I am doing wrong: Here is the source code:

Code: Select all

#ImageGadget_1 = 1
#ImageGadget_2 = 2


If OpenWindow(0,0,0,300,200,"ImageGadget",#PB_Window_SystemMenu|#PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0)) 
  ImageGadget(#ImageGadget_1, 4,4,100,100,0,#PB_Image_Border) 
  ImageGadget(#ImageGadget_2, 104,4,100,100,0,#PB_Image_Border) 
    
  hinstance=GetClassLong_(WindowID(0),#GCL_HMODULE) 
  IconhWnd=LoadIcon_(hinstance, @"#1") 			;get Icon_Resource handle / No_1
  BitmapWnd = LoadBitmap_(hinstance,@"#2")	;get Bitmap_Resource handle / No_1
  TextWnd = LoadString_(hinstance,1,@"#1",10)	;get Text_Resource handle / No_1
  
        
  ; Display Icon_Resource
   SetGadgetState(#ImageGadget_1,IconhWnd) 
	 DestroyIcon_(IconhWnd)
	
	; Display Bitmap Resource
	 SetGadgetState(#ImageGadget_2,BitmapWnd) 
	 DestroyIcon_(BitmapWnd)
	 
	 ; Display Text Resource
	 Text$ = Str(TextWnd)
   MessageRequester("Info",Text$,0)

  Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow 
EndIf

Posted: Sun Nov 26, 2006 1:00 pm
by srod
I would try GetLastError_() to see what is going on.

My guess is the fact that the 3rd parameter need to specifiy the address of a buffer which will receive the string.

Try something like:

Code: Select all

test$=space(10) ;Room for 10 characters
TextWnd = LoadString_(hinstance,1,@text$,10)   ;get Text_Resource handle / No_1 

Posted: Sun Nov 26, 2006 3:31 pm
by Fluid Byte
Srod, is right. You need to specify a valid buffer, not a string. You have set a buffersize of 10 bytes but you didn't asign a pointer one.

Posted: Sun Nov 26, 2006 4:35 pm
by BigJack
Thanks for the quick reply.

I changed the code to this (see below) BUT it still won't return the correct string value:

Code: Select all

*MemoryID = AllocateMemory(12)
	TextWnd = LoadString_(hinstance,1,*MemoryID,12)   ;get Text_Resource handle / No_1 
	Text$ = PeekS(*MemoryID,TextWnd)
	FreeMemory(*MemoryID)

MessageRequester("Info",Text$,0)
PS: I checked the EXE and the resources are all in there.
I thought this one is going to be tough... :evil:

Posted: Sun Nov 26, 2006 5:16 pm
by Fluid Byte
Weird. This should work. I just tested to following example:

Code: Select all

*MemoryID = AllocateMemory(256)

HINSTANCE = OpenLibrary(0,"user32.dll")
TextWnd = LoadString_(HINSTANCE,14,*MemoryID,256)
CloseLibrary(0)

Debug PeekS(*MemoryID,TextWnd)
Works fine. So there just 2 things left to be checked:

1.) Is HINSTANCE a valid handle?
2.) Does the string resource you want to load really exists?

Posted: Sun Nov 26, 2006 7:10 pm
by BigJack
Well, then there is something wrong with my system.
The lines of code you posted, which work for you, don't work either when I compile them - strange, isn't it.
But thanks a lot anyway - atleast now I know a bit more...
Greetings Mike

Posted: Sun Nov 26, 2006 7:17 pm
by srod
I'd have a look inside your resource file at the identifier used for your string resource. Make sure you're at least using the correct identifier etc.

Other than this, like Fluid Byte, the code works for me (except I've never seen an instance handle obtained in that way - neat! :) )

Posted: Sun Nov 26, 2006 11:55 pm
by Sparkie
Save the following as your .rc file

Code: Select all

STRINGTABLE
  
BEGIN

0 "Sparkie was here!"
1 "Sparkie was here too!\012Did you see him?"

END
Run this code after selecting the above .rc file in Complier Options (PB IDE) or under Project Options (jaPBe).

Code: Select all

If OpenWindow(0, 100, 100, 400, 200, "Testing Resources", #PB_Window_ScreenCentered | #PB_Window_SystemMenu) And CreateGadgetList(WindowID(0))
  TextGadget(0, 10, 10, 200, 25, "")
  TextGadget(1, 10, 50, 200, 50, "")
  For g = 0 To 1
    buffer$ = Space(256)
    LoadString_(GetModuleHandle_(0), g, @buffer$, 256)
    SetGadgetText(g, buffer$)
  Next g
  Repeat 
    Event = WaitWindowEvent() 
  Until Event = #PB_Event_CloseWindow 
EndIf 
End 
If you don't see the 2 text strings in the window, then you have very well may have other issues to deal with. :?

Posted: Mon Nov 27, 2006 3:19 am
by netmaestro
For docs on how to create/use resource files in PB a good source is to download PellesC (it's free) and look through the help docs under Resources. Everything's covered and it all works with PureBasic just as described there. It doesn't need precompiled, just create the resource file in notepad and save it with an .rc extension. Then all you have to do is add the .rc file you made in compiler options - resources for your program.

Posted: Mon Nov 27, 2006 1:27 pm
by BigJack
Thanks guys for your help!

Sparkie: Your code worked!

NetMaestro: Thanks - I am going to have a close look at the help file.

My resource file which I wanted to include has just plain text:

Code: Select all

PLEASE READ:
THE PROGRAM IS PROVIDED ONLY ON AN 'As IS' BASIS, WITHOUT
WARRANTIES Or CONDITIONS OF ANY KIND, EITHER EXPRESSED Or 
IMPLIED. UNDER NO CIRCUMSTANCES SHALL THE AUTHOR BE LIABLE
For ANY DAMAGES WHATSOEVER, INCLUDING ANY SPECIAL,
CONSEQUENTIAL, EXEMPLARY, INCIDENTAL Or INDIRECT
DAMAGES (INCLUDING, BUT Not LIMITED To, LOSS OF PROFITS,
REVENUES, Data And/Or USE Or OTHER FINANCIAL LOSS) ARISING
OUT OF Or IN CONNECTION HEREWITH Or THE USE OF; OR INABILITY
To USE THE PROGRAM And ITS DOCUMENTATION.  
How do I include something like the above as a resource and how do I make use of it in the final exe?
Note: Without having to split each line that is (Sparkie: I can get it done your way of course).

Greetings Mike

Posted: Tue Nov 28, 2006 8:17 am
by wayne-c
I use Sparkie's code (with success), but when I try to compile a rc-file that contains unicode characters (unicode or utf-8, does not matter) PB gives me an error. Does anybody know how to compile rc files that contains unicode characters (japanese, russian e.g.)?

Posted: Tue Nov 28, 2006 8:28 am
by netmaestro
Did you specify UTF-8 under "Source text encoding" on the resources page of the compiler options? If you did that it really should work. Also, PORC has a /C option to specify unicode strings.

Posted: Tue Nov 28, 2006 8:57 am
by wayne-c
netmaestro wrote:Did you specify UTF-8 under "Source text encoding" on the resources page of the compiler options? If you did that it really should work.
Yes, UTF-8 is selected.

I did the test with the following files:

ANSI rc file:

Code: Select all

STRINGTABLE
BEGIN
0 "Hello World"
1 "Hello ANSI Text"
2 "Hello Sun, Moon and Stars"
END
Unicode rc file (saved as utf-8 with notepad):

Code: Select all

STRINGTABLE
BEGIN
0 "Hello World"
1 "を多数擁する"
2 "Hello Sun, Moon and Stars"
END
PB File:

Code: Select all

Procedure.s ResString(Id.l)
  Protected Buffer.s= Space(255)
  LoadString_(GetModuleHandle_(0), Id, @Buffer, 255)
  ProcedureReturn PeekS(@Buffer)
EndProcedure

Debug ResString(0)
Debug ResString(1)
Debug ResString(2)
It runs fine with the ANSI rc file, but as soon as I compile with the utf-8 / unicode stuff, it fails. Any ideas?

Posted: Tue Nov 28, 2006 11:41 am
by wayne-c
Googled MSDN and found this (I have not yet tried if it works!):

http://msdn2.microsoft.com/en-us/library/aa381050.aspx

Code: Select all

One or more strings, enclosed in quotation marks. The string must be no longer than 4097 characters and must occupy a single line in the source file. To add a carriage return to the string, use this character sequence: \012. For example, "Line one\012Line two" defines a string that is displayed as follows: 
To embed quotes in the string, use the following sequence: "". For example, """Line three""" defines a string that is displayed as follows:

To encode Unicode characters, use an "L" followed by the Unicode characters enclosed by quotes. See the Examples section for an example.
Resource file with both ASCII and Unicode:

Code: Select all

STRINGTABLE
BEGIN
IDS_1 L"5\x00BC-Inch Floppy Disk"
IDS_1a "5\xBC-Inch Floppy Disk"
IDS_2 L"Don't confuse \x2229 (intersection) with \x222A (union)"
IDS_3 "Copyright \xA92001"
IDS_3a L"Copyright \x00a92001"
END

Posted: Wed Nov 29, 2006 5:14 pm
by BigJack
Hi all,

While browsing the German PB_Forum I received a code example provided by TS-Soft which is is able to handle binary resources in an excellent manner. Here is his code:

Code: Select all

Procedure LoadResource(ResNumber.l, Hmodule.l = 0) 
  Protected ResName.s 
  Protected hFind.l, hLoad.l, hLock.l, hSize.l, Mem.l 
  Protected ResType.s = "RC_DATA" 

  ResName = "#" + Str(ResNumber) 

  If Not Hmodule : Hmodule = GetModuleHandle_(#Null) : EndIf 

  hFind = FindResource_(Hmodule, ResName, @ResType) 
  If hFind 
    hLoad = LoadResource_(Hmodule, hFind) 
    hSize = SizeofResource_(Hmodule, hFind) 
    hLock = LockResource_(hLoad) 

    Mem = AllocateMemory(hSize) 

    If Mem 
      CopyMemory(hLock, Mem, hSize) 
      FreeResource_(hLock) 
      ProcedureReturn Mem 
    EndIf 
  EndIf 
EndProcedure 

*FilePointer = LoadResource(1); File wurde als RC_DATA mit der Nummer 1 im Resource Skript erzeugt 

If *FilePointer 
  If CreateFile(0, "test.exe") 
    WriteData(0, *FilePointer, MemorySize(*FilePointer)) 
    CloseFile(0) 
    FreeMemory(*FilePointer) 
  EndIf 
EndIf 

*TextPointer = LoadResource(2) 

If *TextPointer 
  MyText.s = PeekS(*TextPointer) 
  FreeMemory(*TextPointer) 
EndIf 
Perhaps one must replace the value for "ResType.s" by something like "Text" or "RData". This atleast did it for me.

Thanks TS-Soft