String Property issue

General help with the eC language.
samsam598
Posts: 212
Joined: Thu Apr 14, 2011 9:44 pm

String Property issue

Post by samsam598 »

Below example is an eC question than a networking program although the main code is regarding networking under win32.As I have very poor knowledge to networking program,I did some execises under windows with win32 API.

The problem I encountered is that I defined a string field and string property 'hostInfo' in Form1,when I test,it turned out that the property 'hostInfo' actually did not get its data.Pelase refer to below code.

char* GetHostInfo() read from the OS and get the host_name/host_address ,then combine them into a String.When I build the hostInfo property,I use this GetHostInfo() function to get the host information and build the hostInfo's getter.The issue is that in the client code,using GetHostInfo to show the host information is workable but it isn't if using hostInfo.It would be gratefulf if you can figure me out what I did wrong.

EDIT:just noticed that in (w)sprintf(result,"bla\tbla\t",...) the '\t' does not make sense in GUI.Is this normal?

Code: Select all

 
#ifdef __WIN32__
#define WIN32_LEAN_AND_MEAN
 
#include <windows.h> 
#include <shellapi.h> 
#include <winsock.h> 
#endif
 
#undef MessageBox
 
import "ecere"    
 
class Form1 : Window
{
   text = "Form1";
   background = activeBorder;
   borderStyle = fixed;
   hasMinimize = true;
   hasClose = true;
   tabCycle = true;
   size = { 344, 112 };
   anchor = { horz = -143, vert = -205 };
   showInTaskBar = true;
   nativeDecorations = true;
 
   char hostInfo[1024];
 
   public:
   property char* hostInfo
   {
 
      get
      { 
         strcpy(hostInfo,GetHostInfo());
         //hostInfo=CopyString(GetHostInfo());
 
         return hostInfo;
      }
 
   }                    
   Button btnHostInfo 
   {
      this, text = "(&H)显示主机信息", altH, foreground = darkSlateGray, font = { "黑体", 10, bold = true, underline = true }, size = { 258, 29 }, position = { 32, 24 };
 
      bool NotifyClicked(Button button, int x, int y, Modifiers mods)
      {
         MessageBox {text="主机信息",contents=hostInfo}.Modal();   //hostInfo does not work,GetHostInfo() works!!
         return true;
      }
   };
   char* GetHostInfo()
   {
         int WSA_return;
         WSADATA WSAData;
 
         HOSTENT *host_entry;
         char host_name[256];
         char host_address[256]; 
         char result[1024];    
         WSA_return=WSAStartup(0x0101,&WSAData);
 
       if(WSA_return==0)
       {
        gethostname(host_name,256);
        host_entry=gethostbyname(host_name);
        if(host_entry!=null)
        {
           wsprintf(host_address,"%d.%d.%d.%d",
          (host_entry->h_addr_list[0][0]&0x00ff),
          (host_entry->h_addr_list[0][1]&0x00ff),
          (host_entry->h_addr_list[0][2]&0x00ff),
          (host_entry->h_addr_list[0][3]&0x00ff));
 
          }
 
        }  
        WSACleanup();            
 
        sprintf(result,"Host Name:%s\nHost Address:%s",host_name,host_address);
        return result;  
   }
 
 
}       
 
 
Form1 form1 {};
 
 
 
 
jerome
Site Admin
Posts: 608
Joined: Sat Jan 16, 2010 11:16 pm

Re: String Property issue

Post by jerome »

Hi Sam!

Good to hear back from you :D

You are right, the hostInfo property is not invoked in your code.

That is because you are accessing 'hostInfo' from 'within' your class, and data members have priority over properties within a class (you have a data member with the same name, so it uses that instead). To force the property from being called from within a class, you can access it as property::hostInfo as such:

Code: Select all

MessageBox {text="主机信息",contents=property::hostInfo}.Modal();
Outside of a class, properties have priority (assuming both are public), that is usually the desired behavior. There is a trick to force a data member with the same name as a property to be used (assuming it is accessible), by playing with the indirection operators as such: *&member.

I'm not sure I understand what you are asking about the '\t' character?
Are you asking what the Ecere GUI / graphics engine does when it encounters that?
Different situations will handle it differently.
In the popup menus, it can be used to position hot keys hints at the far right.
In the EditBox, tabs are handled as spacing characters (with options to 'insert tabs' or 'use spaces' instead).
The Surface::WriteText function (and anything else that relies on it) will display the character which is defined for it in the font.

Also I can't help but suggest you use the Ecere functions instead of the WinSock API directly, to fulfill Ecere's aspiration for cross-platform applications:

GetAddressFromName, GetNameFromAddress and GetHostName will help you do what you're doing here with much ease.

Regards,

Jerome
samsam598
Posts: 212
Joined: Thu Apr 14, 2011 9:44 pm

Re: String Property issue

Post by samsam598 »

jerome wrote:Hi Sam!

Good to hear back from you :D
I did not leave.I am living here :D
Besides I was crasy busy on my work recently,I am learning networking and threading program but it seems that the progress is very slow.Really missing the Dao and expect it covers these topics asap.
That is because you are accessing 'hostInfo' from 'within' your class, and data members have priority over properties within a class (you have a data member with the same name, so it uses that instead). To force the property from being called from within a class, you can access it as property::hostInfo as such:

Code: Select all

MessageBox {text="主机信息",contents=property::hostInfo}.Modal();
Got it,so property can have a different name to the field it reflects?For example,if there is a field int m_age,I can define property age rather than m_age?I've been thinking that I can only define m_age as property.
I'm not sure I understand what you are asking about the '\t' character?
Given below code

Code: Select all

char* hostName="samhu";
char* hostAddress="10.88.14.84";
printf("The host name is: %s\nThe host ip is:\t%s\n",hostName,hostAddress);
The escape sequence '\t' here above used is try to align the two lines as :

Code: Select all

output:
The host name is :sam hu
The hot ip is :      10.88.14.84
But the problem I entered is the escape sequence '\t' in the (w)sprintf in GUI circumstance did not place any extra tab (spaces) after "The host ip is:".Hope this is clearer.

Also I can't help but suggest you use the Ecere functions instead of the WinSock API directly, to fulfill Ecere's aspiration for cross-platform applications:

GetAddressFromName, GetNameFromAddress and GetHostName will help you do what you're doing here with much ease.
Yes,and this is what I always expect I can do some day.As I've mentioned I have very poor knowledge (almost zero) on networking and threading program.There are too many thing I need to learn to understand how they are working.If I can program networking and threading in eC using eC's portable library,it would be great.

After been playing with eC these days,I consider it as a serious and very powerful tool built on top of C and provides quite a few of rich features.Many of these I love so much.I have learnt about quite a few other languages,but this is one of the most I love.Also I have a couple of suggestions,or wish list here on eC's development priorities in the future:
1.Bugfix,bugfix,bugfix.I am willing to be the white rat as I am loving to learning everything in eC.And the great thing I can say during the past experience I use eC,it is quite stable now.
2.Document.Based on my experience,reading sample program in the SDK can answer my question,but not eveytime.I do know doc need plenty of time,but I wish one can get detailed information and step to step guide throug examples for somce advanced features in eC,such as generics,containers,networking and threading,2D and 3Ds.
3.Enrich the libraries.I would like to see a complete set of libaries like 2D drawing,encryption,chart and databases,xml,regex,just to name a few.Of course I know Roman was not built in one day,but I can wait.
4.IDE extend.more GUI component controls,say EditBox support masks(password char="*"),Date/DateTime EditBox,EditBox support validating,etc,just to name a few;plug-in support(some thing like dephi/lazarus),one can contribute his own favorite components to eC SDK.

Regards,

Sam
jerome
Site Admin
Posts: 608
Joined: Sat Jan 16, 2010 11:16 pm

Re: String Property issue

Post by jerome »

Hey Sam,

Yes, a property can be named anything. It is a completely separate object, it could even set/return a value that is not at all stored in a data member. I just prefer using the same name for both, for clarity. I do not like variable prefixes like m_age :) But that's just me.

About '\t', as I explained, GUI elements would actually require special handling code to do anything with it, and with variable width fonts it would be rather bothersome. Consider aligning things by using separate labels and using anchors.

I am quite confident the Ecere networking library can do everything you need, in a portable manner.

I agree on those priorities. I'm not sure if you took a look at our current (somewhat outdated) roadmap. A few of those deadlines have already passed by and time is running out on the other ones :P It kind of reflects the bug fixes & documentation goal, which is what we're focusing on (when we have time :P).

About 3 and 4... I think many of those are at least partially implemented already, so I'll try to show you how to use them!
  • 2D drawing: I'm assuming you're referring to things like Ellipses & Polygons? I'm curious what you would use these for? I'm planning to add this support at some point.
  • Encryption: I believe OpenSSL comes with a useful encryption library, it might be nice to have eC wrappers for it (On top of the SSLSocket). Perhaps this link can be useful. On a somewhat related note, you will find SHA256, MD5 and Base64 encoding support in the extras.
  • Chart: You mean like pie charts & histograms? I guess if one was to write an Ecere Spreadsheet program (a fun project if I had the time!) we would have those :)
  • Databases: Have you played much with EDA (Ecere Data Access layer) yet? It is quite a powerful database system! At the moment it supports EDB (our own simplistic database engine) and SQLite (a very powerful yet light full-featuresd SQL RDBMS). There are some samples under samples/db/
  • XML: We have a basic XMLParser under extras, and sample usage under samples/net/XMLSample. I personally much prefer JSON as a generic data storage/retrieval system, and we have built-in JSON support within Ecere (The JSONParser class and WriteJSONObject). JSON is also used by the GlobalSettings class (for the application configuration files, e.g. ecereIDE.ini)
  • regex: We have a Regex class in extras/Regex.ec. It works with the GNU regex library, see this post
  • Password masked EditBox:

    Code: Select all

    class PasswordEdit : EditBox
    {
       font = { "Wingdings", 16 };
     
       void OnRedraw(Surface surface)
       {
          EditLine l;
          int y, x1, x2;
          char * backup = CopyString(contents);
          int len = strlen(backup);
          char * string = new char[len + 1];
          memset(string, 'l', len);
          string[len] = 0;
          GetSelPos(&l, &y, &x1, &l, &y, &x2, false);
          contents = string;
          SetSelPos(l, y, x1, l, y, x2);
          EditBox::OnRedraw(surface);
          memcpy(contents, backup, len);
          delete string;
          delete backup;
       }
    }
  • Date/DateTime EditBox: I thought I gave you some sample code on how to do this with SavingDataBox already?
  • EditBox support validating: This is done automatically when you use a SavingDataBox with a particular data type. You can also implement your own validation either through defining your own data type, or by overriding OnActivate within e.g. your EditBox class, checking for active == false, and validating the contents.
  • Plug-in support: The IDE was designed with this in mind. For example, the FormDesigner for Ecere is built-in within the Ecere library, not the IDE. So it is possible to define a new type of designer for your own class, package it as a DLL, and the IDE will automatically plug it in.
Hope this helps you do more with Ecere! :)

Regards,

Jerome
samsam598
Posts: 212
Joined: Thu Apr 14, 2011 9:44 pm

Re: String Property issue

Post by samsam598 »

jerome wrote:Hey Sam,

Yes, a property can be named anything. It is a completely separate object, it could even set/return a value that is not at all stored in a data member. I just prefer using the same name for both, for clarity. I do not like variable prefixes like m_age :) But that's just me.

About '\t', as I explained, GUI elements would actually require special handling code to do anything with it, and with variable width fonts it would be rather bothersome. Consider aligning things by using separate labels and using anchors.
Noted with thanks.
I am quite confident the Ecere networking library can do everything you need, in a portable manner.
Very glad to hear that.
I agree on those priorities. I'm not sure if you took a look at our current (somewhat outdated) roadmap. A few of those deadlines have already passed by and time is running out on the other ones :P It kind of reflects the bug fixes & documentation goal, which is what we're focusing on (when we have time :P).
Fully understood and really appreciated!
About 3 and 4... I think many of those are at least partially implemented already, so I'll try to show you how to use them!
Yes I know,I know.I did not mean eC is lack of such libraries,actually people like me come here and using eC is coz eC has already provided a very powerful and rich library set which let us can do a lot.
  • 2D drawing: I'm assuming you're referring to things like Ellipses & Polygons? I'm curious what you would use these for? I'm planning to add this support at some point.
Yes,something like that,and more.I think with 2D library we can draw pies and candles charts like stock history,etc,hope you know what I try to say.What's more,we can do some 2D paint stuffs like photoshop.At the last point maybe it is more suitable to do in 3D,but I am just not sure.
[*]Encryption: I believe OpenSSL comes with a useful encryption library, it might be nice to have eC wrappers for it (On top of the SSLSocket). Perhaps this link can be useful. On a somewhat related note, you will find SHA256, MD5 and Base64 encoding support in the extras.
Glad to know.So one more topic I need to learn :P
[*]Chart: You mean like pie charts & histograms? I guess if one was to write an Ecere Spreadsheet program (a fun project if I had the time!) we would have those :)
Exactly.
[*]Databases: Have you played much with EDA (Ecere Data Access layer) yet? It is quite a powerful database system! At the moment it supports EDB (our own simplistic database engine) and SQLite (a very powerful yet light full-featuresd SQL RDBMS). There are some samples under samples/db/
Yes I knew,and it is really cool.I am studing it.My prevois post in this thread "a complet set" just mean "complete".
[*]XML: We have a basic XMLParser under extras, and sample usage under samples/net/XMLSample. I personally much prefer JSON as a generic data storage/retrieval system, and we have built-in JSON support within Ecere (The JSONParser class and WriteJSONObject). JSON is also used by the GlobalSettings class (for the application configuration files, e.g. ecereIDE.ini)
[*]regex: We have a Regex class in extras/Regex.ec. It works with the GNU regex library, see this post
Two more to learn.:P
[*]Password masked EditBox:

Code: Select all

class PasswordEdit : EditBox
{
   font = { "Wingdings", 16 };
 
   void OnRedraw(Surface surface)
   {
      EditLine l;
      int y, x1, x2;
      char * backup = CopyString(contents);
      int len = strlen(backup);
      char * string = new char[len + 1];
      memset(string, 'l', len);
      string[len] = 0;
      GetSelPos(&l, &y, &x1, &l, &y, &x2, false);
      contents = string;
      SetSelPos(l, y, x1, l, y, x2);
      EditBox::OnRedraw(surface);
      memcpy(contents, backup, len);
      delete string;
      delete backup;
   }
}
Cooool!Is it possible to prohibit copying the content from within the PasswordEdit?
[*]Date/DateTime EditBox: I thought I gave you some sample code on how to do this with SavingDataBox already?
No,I mean another thing.If you are familar with Delphi,you should know what I mean.In a DateEdit,it marks as __/__,you can only input valid number to build a date,and no need to type '/' in it.Maybe it is not a must-have component,just an example for " other more components".
[*]EditBox support validating: This is done automatically when you use a SavingDataBox with a particular data type. You can also implement your own validation either through defining your own data type, or by overriding OnActivate within e.g. your EditBox class, checking for active == false, and validating the contents.
[*]Plug-in support: The IDE was designed with this in mind. For example, the FormDesigner for Ecere is built-in within the Ecere library, not the IDE. So it is possible to define a new type of designer for your own class, package it as a DLL, and the IDE will automatically plug it in.[/list]
Hope this helps you do more with Ecere! :)
Great!

BTW,I noticed there is a thread named 'eC for the Web and JIT compiling with TCC
',what's that?web programming in eC?If yes,this is also the one I would like to see in eC.
Regards,

Sam
jerome
Site Admin
Posts: 608
Joined: Sat Jan 16, 2010 11:16 pm

Re: String Property issue

Post by jerome »

Sam,

About drawing Paint stuff, that functionality would usually be implemented as software drawing (directly setting pixel values in a memory buffer, by using a Bitmap object) for that purpose, and would best belong in a separate library (most GUI applications will not require this). e.g. there is a FloodFill sample in samples/guiAndGfx.

For Pie charts, they are indeed all 3D these days :D For real-time drawing, even 2D things are usually drawn using 3D accelerated APIs like OpenGL and Direct3D nowadays. Right now this can be done through the Display and PrimitiveSingle interface, but I'm hoping to make all this functionality more accessible in the future.

Prohibiting copying the content from the PasswordEdit: certainly you could do this. You could hook OnKeyHit, and only chain to EditBox::OnKeyHit if the key is not ctrlC and Control-Insert (Key { insert, ctrl = true }). You could also hook OnRightButtonUp to prevent the right-click menu from popping up.

About your Date edit, the current DateTime editor is quite powerful, letting you enter a date in a lot of different ways. If you want something specific, you can easily implement it yourself. This is usually done by overriding the OnEdit/OnDisplay/OnSaveEdit/OnGetDataFromString/OnGetString methods of your data type (e.g. you can define a class that inherits from Date, e.g. SamDate) and then spawn your own control that edits the data the way you like it. That is the way to do it if you want your own editor to work in all Ecere data controls (e.g. ListBox, DropBox, SavingDataBox). You could also simply create your own control that works the way you like it, using the existing data types.

Yes, web programming in eC, we hope to make that possible some day :)

-Jerome
samsam598
Posts: 212
Joined: Thu Apr 14, 2011 9:44 pm

Re: String Property issue

Post by samsam598 »

jerome wrote:[/b] interface, but I'm hoping to make all this functionality more accessible in the future.

Prohibiting copying the content from the PasswordEdit: certainly you could do this. You could hook OnKeyHit, and only chain to EditBox::OnKeyHit if the key is not ctrlC and Control-Insert (Key { insert, ctrl = true }). You could also hook OnRightButtonUp to prevent the right-click menu from popping up.
-Jerome
Noted with thanks.I also noticed that the focus can not leave the PasswordEdit control after some actions taken in a button control,for example if the user enter a wrong password.In my program below,I would like the enter focus on the EditBox edtName (the first one) but could not make it.How can I fix this?

Code: Select all

 
import "ecere"
import "passwordEdit.ec"
class Form1 : Window
{
   text = "登陆对话框";
   background = activeBorder;
   borderStyle = fixed;
   tabCycle = true;
   size = { 320, 176 };
   anchor = { horz = -139, vert = -133 };
   //icon = { "C:\\person\\CodeLite\\images\\cubes.png" };
   nativeDecorations = true;
 
   Button btnOK 
   {      
      this, text = "(O)验证", altO, isDefault = true, size = { 90, 29 }, position = { 48, 96 };
 
      bool NotifyClicked(Button button, int x, int y, Modifiers mods)
      {
         if(!edtName.contents[0]) 
         {
            MessageBox {master=this,type=ok,text="出错了!",contents="用户名不能为空,请重新输入";}.Modal();
            Activate();
            return true;
         }
         Validate(edtPasswd,"beijing2008");
         return true;
      }
   };
   Button btnCancel 
   {      
      this, text = "(C)放弃", altC, size = { 82, 29 }, position = { 192, 96 };
 
      bool NotifyClicked(Button button, int x, int y, Modifiers mods)
      {
         Destroy(0);
         return true;
      }
   };
   Label label1 { this, text = "用户名:", size = { 92, 21 }, position = { 16, 24 } };
   EditBox edtName { this, text = "edtName", size = { 182, 19 }, position = { 104, 24 } };
   Label label2 { this, text = "密码:", size = { 76, 21 }, position = { 16, 56 } };
   PasswordEdit edtPasswd 
   {
      this, text = "edtPasswd", size = { 182, 19 }, position = { 104, 56 }
   };
 
   bool OnPostCreate(void)
   {
      edtName.Clear();
      edtPasswd.Clear();
      edtName.Activate();
      return true;
   }
   void Validate(EditBox editBox,const char* pass)
   {                        
 
       if(!strcmp(editBox.contents,pass))
       {
          MessageBox {contents="Welcome!"}.Modal();
          Destroy(0);
 
       }
       else
       {
          MessageBox {contents="Access denied."}.Modal();
       }
   }
}
 
Form1 form1 {};
 
 
jerome
Site Admin
Posts: 608
Joined: Sat Jan 16, 2010 11:16 pm

Re: String Property issue

Post by jerome »

Hi Sam, I'm a bit confused by your question, but let's see if I understand it properly.

First of all the caret in the PasswordEdit box is not working. It's somehow related to the box being not high enough, so if you set a height of 26 or higher for the size it fixes it. That makes it easier to see when the box is active and when it's not.

Then, the way 'default' buttons work is that they re-activate the control which was last active when Enter was pressed. So if you are on the PasswordEdit, it will remake the PasswordEdit active, and I personally think that's fine, because people would usually make mistakes on the password (which they cannot see) rather than in the username (which they see).

But if you insist on always reactivating the userName instead, here is some code that will do it:

Code: Select all

   PasswordEdit edtPasswd 
   {
      this, text = "edtPasswd", size = { 182, 26 }, position = { 104, 56 };
 
      bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
      {
         if(active && previous == ((Form1)parent).btnOK)
         {
            ((Form1)parent).activeChild.Deactivate();
            ((Form1)parent).edtName.Activate();
            *goOnWithActivation = false;
            return false;
         }
         return PasswordEdit::OnActivate(active, previous, goOnWithActivation, direct);
      }
   };
Hope this helps!

-Jerome
jerome
Site Admin
Posts: 608
Joined: Sat Jan 16, 2010 11:16 pm

Re: String Property issue

Post by jerome »

Sam,

There were still some issues with the solution I proposed above:
  • Tab-cycling backwards (Shift-Tab) from the 'OK' button would skip the password EditBox
  • Clicking the button with the mouse would not activate the user name
  • Pressing enter while the OK or Cancel button was active would not activate the user name
The truth is you're trying to go against the way the 'default' control works in Ecere, so things can get a bit messy and complicated.

Here is some code that in effect implements its own 'default' control behavior, by using the OnSysKey* methods, to intercept the Enter key before it gets to the default control system:

Code: Select all

import "ecere"
import "passwordEdit.ec"
class Form1 : Window
{
   text = "登陆对话框";
   background = activeBorder;
   borderStyle = fixed;
   tabCycle = true;
   size = { 320, 176 };
   anchor = { horz = -139, vert = -133 };
   //icon = { "C:\\person\\CodeLite\\images\\cubes.png" };
   nativeDecorations = true;
 
   Button btnOK 
   {      
      this, text = "(O)验证", altO, isDefault = true, size = { 90, 29 }, position = { 48, 96 };
 
      bool NotifyClicked(Button button, int x, int y, Modifiers mods)
      {
         if(!edtName.contents[0]) 
         {
            MessageBox {master=this,type=ok,text="出错了!",contents="用户名不能为空,请重新输入";}.Modal();
            edtName.Activate();
            return true;
         }
         Validate(edtPasswd,"beijing2008");
         return false;
      }
   };
   Button btnCancel 
   {      
      this, text = "(C)放弃", altC, size = { 82, 29 }, position = { 192, 96 };
 
      bool NotifyClicked(Button button, int x, int y, Modifiers mods)
      {
         Destroy(0);
         return true;
      }
   };
   Label label1 { this, text = "用户名:", size = { 92, 21 }, position = { 16, 24 } };
   EditBox edtName { this, text = "edtName", size = { 182, 19 }, position = { 104, 24 } };
   Label label2 { this, text = "密码:", size = { 76, 21 }, position = { 16, 56 } };
 
   bool pushed;
   Window prevActive;
   PasswordEdit edtPasswd 
   {
      this, text = "edtPasswd", size = { 182, 26 }, position = { 104, 56 };
   };
 
   bool OnSysKeyDown(Key key, unichar ch)
   {
      if((SmartKey)key == enter)
      {
         // Make the button push down
         btnOK.buttonState = down;
         prevActive = activeChild;
         btnOK.Activate();
         btnOK.Update(null);
         pushed = true;
         return false;
      }
      else if(pushed)
      {
         // Another key was pressed, cancel the push and reactivate previous control
         btnOK.buttonState = up;
         btnOK.Update(null);
         prevActive.Activate();
         pushed = false;
      }
      return true;
   }
 
   bool OnSysKeyUp(Key key, unichar ch)
   {
      if(pushed)
      {
         // The actual Click action occurs when the Enter key is released
         btnOK.buttonState = up;
         btnOK.Update(null);
         btnOK.NotifyClicked(this, btnOK, 0,0, 0);
         pushed = false;
      }
      return true;
   }
 
   bool OnPostCreate(void)
   {
      edtName.Clear();
      edtPasswd.Clear();
      edtName.Activate();
      return true;
   }
   void Validate(EditBox editBox,const char* pass)
   {                        
       if(!strcmp(editBox.contents,pass))
       {
          MessageBox {contents="Welcome!"}.Modal();
          Destroy(0);
       }
       else
       {
          MessageBox {contents="Access denied."}.Modal();
          edtName.Activate();
       }
    }
}
 
Form1 form1 {};
samsam598
Posts: 212
Joined: Thu Apr 14, 2011 9:44 pm

Re: String Property issue

Post by samsam598 »

Hi Jerome,

Thank you so much for your time to taking care of this!

Regards,
Sam
Post Reply