PlanetSquires Forums

Support Forums => WinFBX - Windows Framework for FreeBASIC => Topic started by: José Roca on November 21, 2017, 05:19:32 PM

Title: WinFBX Version 1.0
Post by: José Roca on November 21, 2017, 05:19:32 PM
After many release candidate versions, I think that it is time to release the first official version.

All the source code, including examples and templates, is hosted in GitHub:
https://github.com/JoseRoca/WinFBX

On-line documentation:
http://www.jose.it-berater.org/WinFBX/WinFBX.html

23 Nov 2017
- Bug fix: Changed DIM vArgs(1 TO 15) AS VARIANT to DIM vArgs(1 TO 16) AS VARIANT in the
last overloaded Invoke function of the CDispInvoke class. Thanks to ganlinlao for reporting it.

15 Dec 2017  - Version 1.0.02
- Added the Resize method to the CWSTR class.
- Modified the AfxStrLSet, AfxStrRSet and AfxStCSet functions to work with Unicode.

19 Dec 2017  - Version 1.0.02
- Added the following functions:
      AfxGetBrowserHandle
      AfxGetInternetExplorerHandle
      AfxGetFireFoxHandle
      AfxGetGoogleChromeHandle

20 Dec 2017 - Version 1.0.02
- Added the following functions:
      AfxCWstrArrayAppend
      AfxCWstrArrayInsert
      AfxCWstrArrayRemove
      AfxCWstrArrayRemoveFirst
      AfxCWstrArrayRemoveLast
      AfxCWstrArraySort

30 Dec 2017 - Version 1.0.03
- Added two overloaded AfxStrExtract functions.

6 Jan 2018 - Version 1.0.03
- Added two overloaded AfxStrRemove functions.

11 May 2018 - Version 1.0.03
- Modified the AfxStrLSet, AfxStrRset and AfxStrCSet functions because they GPFed with
the 64 bit compiler.

26 May 2018 - Version 1.0.03
- Modified the internal code of several functions that used INSTR with CWSTR variables.

28 May 2018 - Version 1.0.03
- Modified the AfxOpenFileDialog and AfxSaveFileDialog functions because they GPFed with
the 64 bit compiler. Also changed an instruction in AfxOpenFileDialog that prevented to work
with non Latin alphabets.

31 May 2018 - Version 1.0.03
- Modified AfxOpenFileDialog again to check for double double null only if the flag
OFN_ALLOWMULTISELECT is used.
- Modified the FilepPath method of the CFindFile class to use the Root method instead of
the GetFullPathName API function.

16 Jun 2018 - Version 1.0.03
- Typo: LietView_GetTooltipsFont changed to ListView_GetTooltipsFont.

17 Jun 2018 - Version 1.0.03
- Modified CXpButton.inc to allow coloured buttons.

20 Jun 2018 - Version 1.0.03
- AfxGetWindowLocation: Changed parameters from AS LONG PTR to BYREF AS LONG.

22 Jun 2018 - Version 1.0.03
- AfxWin.inc: Added the function AfxCommand.

24 Jun 2018 - Version 1.0.03
- CWSTR.inc and CVAR.inc: Changed the casting from BYREF AS WSTRING to BYREF AS CONST WSTRING.

27 Jun 2018 - Version 1.0.03
- CXpButton: Added DPI awareness to the text and image margins.

29 Jun 2018 - Version 1.0.03
- Removed the 80 characters limitation to the AfxAddTooltip and AfxSetTooltipText functions.
- Added CONST to the string parameters of several procedures.

1 Jul 2018 - Version 1.0.03
- Modified CXpButton.inc to add properties.

2 Jul 2018 - Version 1.0.03
- CTextStream.inc: Added OpenForInputA / W, OpenForOutputA / W and OpenForAppendA / W methods.

4 Jul 2018 - Version 1.0.03
- CWSTR: Changed the [] operator from one-based index to zero-based index.

6 Jul 2018 - Version 1.0.03
- CWSTR: Changed CONSTRUCTOR (BYVAL nChars AS UINT, BYVAL nCodePage AS UINT)
to CONSTRUCTOR (BYVAL nChars AS UINT, BYVAL bClear AS BOOLEAN)
The nCodePage parameter was no longer useful and the new bClear parameter allows to specify
if the memory will be intialized (cleared) or not.
- The default constructor now initializes the memory.

10 Jul 2018 - Version 1.0.03
- CXputton: Added support for the BM_CLICK message.

29 Jul 2018 - Version 1.0.03
- CXputton: Added ButtonBkColorDown and BkBrushDown properties.



Title: Re: WinFBX Version 1.0
Post by: Paul Squires on November 21, 2017, 08:01:14 PM
Congratulations Jose! all your incredibly hard work has paid off.

I am in the last week of the sale of my house and move into my new condo. I have done a little bit of programming but not much over the past number of weeks. However, this weekend I will at least release a new version of WinFBE to include your Version 1 library code.

Awesome, way to go Jose, your library is the #1 FreeBasic Windows resource by far.
Title: Re: WinFBX Version 1.0
Post by: James Fuller on November 22, 2017, 07:09:36 AM
Jose,
  Congratulations on the version 1.0 release!!
For new users (and those of us with bad memories) how did you, or better yet, how should we set up our computers (Which Fb downloads,updates,folder structure,etc) to work seamlessly with your massive framework?

James

Title: Re: WinFBX Version 1.0
Post by: David Warner on November 22, 2017, 08:17:12 AM
Well done Jose and thanks for all your efforts.

FYI, I just downloaded the GitHub files and noticed what appears to be a filename conflict between CVAR.inc and CVar.inc in the Afx folder when unzipping the master archive from https://github.com/JoseRoca/WinFBX/archive/master.zip onto my machine.

These files are listed in the following location...
https://github.com/JoseRoca/WinFBX/tree/master/Afx
Title: Re: WinFBX Version 1.0
Post by: José Roca on November 22, 2017, 10:18:11 AM
I have removed CVAR.inc, which is older. Apparently, GitHub is case sensitive and considers that CVAR.inc AND CVar.inc are different files. Thanks very much for reporting it.
Title: Re: WinFBX Version 1.0
Post by: ganlinlao on November 22, 2017, 09:21:46 PM
hi,jose
Congratulations on the version 1.0 release!!

There is a mistake in the indispinvoke.inc file
Title: Re: WinFBX Version 1.0
Post by: José Roca on November 22, 2017, 09:55:22 PM
Thanks for reporting it.I have modified the file.
Title: FBPiano
Post by: José Roca on November 24, 2017, 09:22:58 PM
FBPiano, based on PBPiano, public domain control originally written by Börje Hagsten in June 2016 for PowerBASIC.

Options:

ComboBox 1 shows available midi devices (usually 1).
ComboBox 2 shows a collection of 16 midi channels, but we usually only use channel 1 for normal play.
Note: Channel 10 is reserved for percussion sets, turning each key from D2# to D7# into an instrument.
Always on top - program stays topmost on screen.
Show Key text - show/hide computer keyboard key text.
Show Note text - show/hide piano key notes.

Effects:

Arrow left - decrease octave
Arrow right - increase octave
Arrow up - pitch bend up 
Arrow down - pitch bend down
Sustain on/off, for sustain (reverb) on played keys.
Sustain can cause eternal notes to for example string and brass instruments and should be used with care.
If eternal notes occur, just uncheck this checkbox.
On octave change, pressed notes are repeated for a nice replay effect.
Mouse controls Volume, Balance, Vibrato and Pitch bend.

Remarks: I have had problems to get it working properly. For no apparent reason, the octave setting was being sometimes reset to 0 after changing the instrument or playing notes, but could not be reproduced at will. It was alleatory. I have kept this version as CPiano_v01.inc to demonstrate the problem. In the current CPiano.inc file, I have declared the m_pk and m_hRgn arrays as global instead of as intance variables of the class. This solves the problem. Apparently, the use of arrays as instance variables must be used with caution.

Title: Re: WinFBX Version 1.0
Post by: ganlinlao on November 25, 2017, 10:16:07 PM
hi,jose
1、 I found cdicobj.inc support newEnum method, maybe we can add a "foreach ... in" statement, only used in the collection class.
I would like to ask, iEnumVariant must manually support next, skip, reset method? Is this the difference between cdicobj and vb's collection?

2、 CDispInvoke.inc, why not increase the property set members, like put? We can use the wstring parameter or any ptr, so that we can use the afxstrsplit function to divide the parameter values into a one-dimensional safeArrary when receiving the parameter values using object.set ("method") = "cArg1, cArg2, cArg3, ..., cArgN" . Because I over-love object.put ("method") = value of this style.

thank you !
Title: Re: WinFBX Version 1.0
Post by: José Roca on November 25, 2017, 11:00:07 PM
Quote
2、 CDispInvoke.inc, why not increase the property set members, like put? We can use the wstring parameter or any ptr, so that we can use the afxstrsplit function to divide the parameter values into a one-dimensional safeArrary when receiving the parameter values using object.set ("method") = "cArg1, cArg2, cArg3, ..., cArgN" . Because I over-love object.put ("method") = value of this style.

Sorry, I don't understand what you mean. How are you going to pass several VARIANT parameters as a string?
Title: Re: WinFBX Version 1.0
Post by: José Roca on November 26, 2017, 12:56:14 AM
Quote
1、 I found cdicobj.inc support newEnum method, maybe we can add a "foreach ... in" statement, only used in the collection class.
I would like to ask, iEnumVariant must manually support next, skip, reset method? Is this the difference between cdicobj and vb's collection?

I have looked at the FreeBasic documentation for implementing iterators, but there is no way to pass a pointer to the enumerator.

However, you can enumerate the collection this way:

Code: [Select]
DIM pDic AS CDicObj

pDic.Add "a", "Athens"
pDic.Add "b", "Madrid"
pDic.Add "c", "Roma"

DIM cvKeys AS CVAR = pDic.Keys
FOR i AS LONG = cvKeys.GetLBound TO cvKeys.GetUBound
   DIM cvKey AS CVAR = cvKeys.GetVariantElem(i)
   print cvKey, pDic.Item(cvKey)
NEXT
Title: Re: WinFBX Version 1.0
Post by: ganlinlao on November 27, 2017, 12:21:49 AM
hi,jose

      Please forgive me constantly asking, I would like to ask, winFBX 1.0 help documentation will provide offline chm file? Because I and my friends want to translate help documentation into Chinese. Currently we just translate the help file for cWindowsRC29 into Chinese.

Thanks again for your great sacrifice, for everyone to bring more convenience
Title: Re: WinFBX Version 1.0
Post by: José Roca on November 27, 2017, 02:39:52 AM
I have uploaded a .chm help file in the first post.
Title: Re: WinFBX Version 1.0
Post by: ganlinlao on December 07, 2017, 05:24:32 AM
hi,jose

In the process of translating winFBX documents, I found that there is a mistake here

Title: Re: WinFBX Version 1.0
Post by: José Roca on December 07, 2017, 07:18:33 AM
Thanks very much for reporting it. I have modified it as follows:

point1

[in] Reference to a GpPoint structure that specifies the starting point of the gradient. The starting boundary line passes through the starting point.

point2

[in] Reference to a GpPoint structure that specifies the ending point of the gradient. The ending boundary line passes through the ending point.

color1

[in] An ARGB value that specifies the color at the starting boundary line of this linear gradient brush.

color2

[in] An ARGB value that specifies the color at the ending boundary line of this linear gradient brush.

rc

[in] Reference to a rectangle that specifies the starting and ending points of the gradient. The upper-left corner of the rectangle is the starting point. The lower-right corner is the ending point.
Title: Re: WinFBX Version 1.0
Post by: ganlinlao on December 08, 2017, 09:50:33 PM
hi ,jose
I found the UIribbon.inc class in your winapi for powerbasic package and wondered if you plan to provide a freebasic version of the cUIribbon class.
Because from windows vista, win7-win10, the system has brought uiRibbon.dll, for some do not want to use the old menu and want to use ribbon style, the use of cUIribbon class, will bring a lot of convenience.

  Thanks!
Title: Re: WinFBX Version 1.0
Post by: ganlinlao on December 08, 2017, 10:06:34 PM
hi,jose
I found that there is a mistake here
Title: Re: WinFBX Version 1.0
Post by: José Roca on December 09, 2017, 06:44:47 AM
The FreeBasic GDI+ headers are a total mess. The ColorPalette structure is defined twice

In gdiplus-c.bi as:

Code: [Select]
type ColorPalette
Flags as UINT
Count as UINT
Entries(0 to 0) as ARGB
end type

and in GdiplusPixelFormats.bi as

Code: [Select]
type ColorPalette
Flags as UINT
Count as UINT
Entries(0 to 1-1) as ARGB
end type

Entries(0 to 0) as ARGB and Entries(0 to 1-1) as ARGB are the same. Anyway, I will change it to Entries(0 to 0).
Title: Re: WinFBX Version 1.0
Post by: José Roca on December 09, 2017, 07:01:50 AM
hi ,jose
I found the UIribbon.inc class in your winapi for powerbasic package and wondered if you plan to provide a freebasic version of the cUIribbon class.
Because from windows vista, win7-win10, the system has brought uiRibbon.dll, for some do not want to use the old menu and want to use ribbon style, the use of cUIribbon class, will bring a lot of convenience.

  Thanks!

I will see. Because FB doesn't have support for COM classes, with more than one implemented interface, it will be a bit more difficult. However, if I haven't done it yet it is because, although many people would like to use ribbons, the interest disappears suddenly when they realize that have to learn XAML, install a XAML compiler, etc. Absolutely nobody used it with PowerBasic.

Title: Re: WinFBX Version 1.0
Post by: José Roca on December 09, 2017, 07:27:55 AM
Another problem is that the ribbon api uses propvariants, and although I have done some work with the CPropVar class, it have not yet thoroughly tested it. Also FB does not provide headers and libraries for the UI interfaces and propvariants.
Title: Re: WinFBX Version 1.0
Post by: ganlinlao on December 10, 2017, 07:37:06 AM
hi,jose
I found that there is a mistake here.
rect and rectF
Title: Re: WinFBX Version 1.0
Post by: José Roca on December 10, 2017, 09:30:47 AM
Changed to

width

Specifies the width of a rectangle.

height

Specifies the height of a rectangle.

Also changed SIZEF to SIZE in the entry for the SIZE structure.

BTW please note that because it is declared as Rect_ in gdiplus-c.bi (to avoid conflicting with GDI's Rect) and as class in GdiPlusTypes.bi, in my headers I'm using the functions GDIP_RECT, GDIP_RECTF, GDIP_POINT, GDIP_POINTF. Otherwise, there is no way to compile the same code to 32 and 64 bit. The FB headers for GDI+ need a complete rewrite.

Thinking about it, I'm going to use the aliases in the documentation, i.e. GpPoint, GpPointF, GpRect, GpRectF, GpSize and GpSizeF.

Title: Re: WinFBX Version 1.0
Post by: José Roca on December 11, 2017, 10:00:58 AM
I'm going to add this method to the CWSTR class.

Code: [Select]
' ========================================================================================
' Resizes the string to a length of n characters.
' Parameters:
' nSize : New string length, expressed in number of characters.
' ch: Character used to fill the new character space added to the string (in case the
' string is expanded).
' If nSize is smaller than the current string length, the current value is shortened to
' its first nSize characters.
' If nSize is greater than the current string length, the current content is extended by
' inserting at the end as many characters as needed to reach a size of nSize. If ch is
' specified, the new elements are initialized as copies of ch, otherwise, spaces are added.
' ========================================================================================
PRIVATE SUB CWstr.Resize (BYVAL nSize AS UINT, BYREF ch AS WSTRING = "")
   CWSTR_DP("CWSTR Resize")
   IF m_BufferLen \ 2 = nSize THEN EXIT SUB
   IF m_BufferLen \ 2 > nSize THEN
      m_BufferLen = nSize * 2
      m_Capacity = nSize * 2
      m_pBuffer[m_BufferLen] = 0
      m_pBuffer[m_BufferLen + 1] = 0
   ELSE
      DIM cws AS CWSTR
      DIM nChars AS UINT = ((nSize * 2) - m_BufferLen) \ 2
      IF ch <> "" THEN cws = STRING(nChars, ASC(ch, 1)) ELSE cws = SPACE(nChars)
      this.Add(cws)
   END IF
END SUB
' ========================================================================================
Title: Re: WinFBX Version 1.0
Post by: ganlinlao on December 14, 2017, 09:02:04 PM
hi,jose
Thank you, this method is very good, my friend and I a few days ago, just talked about the string and custom structure types of memory self-growth and cleaning problems.

Title: Re: WinFBX Version 1.0
Post by: José Roca on December 15, 2017, 05:02:31 AM
Thank you. I have modified the text to

Returns a GpPoint color value initialized with the specified values for the x and y coordinates.

Returns a GpPointF color value initialized with the specified values for the x and y coordinates.

and also the return types from GpRect/F to GpPoint/F.
Title: Re: WinFBX Version 1.0
Post by: José Roca on December 15, 2017, 05:05:28 AM
Regarding the Resize method, I have changed it to

Code: [Select]
' ========================================================================================
' Resizes the string to a length of n characters.
' Parameters:
' nSize : New string length, expressed in number of characters.
' ch: Character used to fill the new character space added to the string (in case the
' string is expanded).
' If nSize is smaller than the current string length, the current value is shortened to
' its first nSize characters.
' If nSize is greater than the current string length, the current content is extended by
' inserting at the end as many characters as needed to reach a size of nSize. If ch is
' specified, the new elements are initialized as copies of ch, otherwise, spaces are added.
' ========================================================================================
PRIVATE SUB CWstr.Resize (BYVAL nSize AS UINT, BYREF ch AS WSTRING = "")
   CWSTR_DP("CWSTR Resize")
   IF m_BufferLen \ 2 = nSize THEN EXIT SUB
   IF m_BufferLen \ 2 > nSize THEN
      m_BufferLen = nSize * 2
      m_Capacity = nSize * 2
      m_pBuffer[m_BufferLen] = 0
      m_pBuffer[m_BufferLen + 1] = 0
   ELSE
      IF LEN(ch) > 1 THEN ch = LEFT(ch, 1)
      DIM nChars AS UINT = ((nSize * 2) - m_BufferLen) \ 2
      DIM cws AS CWSTR = SPACE(nChars)
      IF ch <> "" THEN
         FOR i AS LONG = 1 TO nChars
            MID(**cws, i, 1) = ch
         NEXT
      END IF
      this.Add(cws)
   END IF
END SUB
' ========================================================================================

Because the FreeBasic STRING function does not work with Unicode.

Will have to also modify other functions that use STRING. Fortunately they're only three: AfxStrLset, AfxStrRSet and AfxStrCSet.

Title: Re: WinFBX Version 1.0
Post by: José Roca on December 15, 2017, 05:31:54 AM
Done. Changed these functions to:

Code: [Select]
' ========================================================================================
' Returns a string containing a left-justified (padded) string.
' If the optional parameter wszPadCharacter not specified, the function pads the string with
' space characters to the left. Otherwise, the function pads the string with the first
' character of wszPadCharacter
' Example: DIM cws AS CWSTR = AfxStrLSet("FreeBasic", 20, "*")
' ========================================================================================
PRIVATE FUNCTION AfxStrLSet (BYREF wszMainStr AS WSTRING, BYVAL nStringLength AS LONG, BYREF wszPadCharacter AS WSTRING = " ") AS CWSTR
   IF LEN(wszPadCharacter) > 1 THEN wszPadCharacter = LEFT(wszPadCharacter, 1)
   DIM cws AS CWSTR = SPACE(nStringLength)
   IF wszPadCharacter <> "" THEN
      FOR i AS LONG = 1 TO LEN(cws)
         MID(**cws, i, 1) = wszPadCharacter
      NEXT
   END IF
   MID(**cws, 1, LEN(wszMainStr)) = wszMainStr
   RETURN cws
END FUNCTION
' ========================================================================================

' ========================================================================================
' Returns a string containing a right-justified (padded) string.
' If the optional parameter wszPadCharacter not specified, the function pads the string with
' space characters to the left. Otherwise, the function pads the string with the first
' character of wszPadCharacter.
' Example: DIM cws AS CWSTR = AfxStrRSet("FreeBasic", 20, "*")
' ========================================================================================
PRIVATE FUNCTION AfxStrRSet (BYREF wszMainStr AS WSTRING, BYVAL nStringLength AS LONG, BYREF wszPadCharacter AS WSTRING = " ") AS CWSTR
   IF LEN(wszPadCharacter) > 1 THEN wszPadCharacter = LEFT(wszPadCharacter, 1)
   DIM cws AS CWSTR = SPACE(nStringLength)
   IF wszPadCharacter <> "" THEN
      FOR i AS LONG = 1 TO LEN(cws)
         MID(**cws, i, 1) = wszPadCharacter
      NEXT
   END IF
   MID(**cws, nStringLength - LEN(wszMainStr) + 1, LEN(wszMainStr)) = wszMainStr
   RETURN cws
END FUNCTION
' ========================================================================================

' ========================================================================================
' Returns a string containing a centered (padded) string.
' If the optional parameter wszPadCharacter not specified, the function pads the string with
' space characters to the left. Otherwise, the function pads the string with the first
' character of wszPadCharacter.
' Example: DIM cws AS CWSTR = AfxStrCSet("FreeBasic", 20, "*")
' ========================================================================================
PRIVATE FUNCTION AfxStrCSet (BYREF wszMainStr AS WSTRING, BYVAL nStringLength AS LONG, BYREF wszPadCharacter AS WSTRING = " ") AS CWSTR
   IF LEN(wszPadCharacter) > 1 THEN wszPadCharacter = LEFT(wszPadCharacter, 1)
   DIM cws AS CWSTR = SPACE(nStringLength)
   IF wszPadCharacter <> "" THEN
      FOR i AS LONG = 1 TO LEN(cws)
         MID(**cws, i, 1) = wszPadCharacter
      NEXT
   END IF
   MID(**cws, (nStringLength - LEN(wszMainStr)) \ 2 + 1, LEN(wszMainStr)) = wszMainStr
   RETURN cws
END FUNCTION
' ========================================================================================
Title: Re: WinFBX Version 1.0
Post by: Paul Squires on December 15, 2017, 09:11:04 AM
Hi Jose,

Just looking at the new LSet function. Seems like it can be simplified a bit because the PadCharacter will always be at least 1 character (the default if no parameter is passed is a blank character).

Code: [Select]
PRIVATE FUNCTION AfxStrLSet (BYREF wszMainStr AS WSTRING, BYVAL nStringLength AS LONG, BYREF wszPadCharacter AS WSTRING = " ") AS CWSTR
   wszPadCharacter = LEFT(wszPadCharacter, 1)
   DIM cws AS CWSTR = SPACE(nStringLength)
   FOR i AS LONG = 1 TO LEN(cws)
      MID(**cws, i, 1) = wszPadCharacter
   NEXT
   MID(**cws, 1, LEN(wszMainStr)) = wszMainStr
   RETURN cws
END FUNCTION

Agree?
Title: Re: WinFBX Version 1.0
Post by: José Roca on December 15, 2017, 09:16:13 AM
Yes. I forgot that the default was " " instead of "".

Code: [Select]
' ========================================================================================
' Returns a string containing a left-justified (padded) string.
' If the optional parameter wszPadCharacter not specified, the function pads the string with
' space characters to the left. Otherwise, the function pads the string with the first
' character of wszPadCharacter
' Example: DIM cws AS CWSTR = AfxStrLSet("FreeBasic", 20, "*")
' ========================================================================================
PRIVATE FUNCTION AfxStrLSet (BYREF wszMainStr AS WSTRING, BYVAL nStringLength AS LONG, BYREF wszPadCharacter AS WSTRING = " ") AS CWSTR
   wszPadCharacter = LEFT(wszPadCharacter, 1)
   DIM cws AS CWSTR = SPACE(nStringLength)
   FOR i AS LONG = 1 TO LEN(cws)
      MID(**cws, i, 1) = wszPadCharacter
   NEXT
   MID(**cws, 1, LEN(wszMainStr)) = wszMainStr
   RETURN cws
END FUNCTION
' ========================================================================================

' ========================================================================================
' Returns a string containing a right-justified (padded) string.
' If the optional parameter wszPadCharacter not specified, the function pads the string with
' space characters to the left. Otherwise, the function pads the string with the first
' character of wszPadCharacter.
' Example: DIM cws AS CWSTR = AfxStrRSet("FreeBasic", 20, "*")
' ========================================================================================
PRIVATE FUNCTION AfxStrRSet (BYREF wszMainStr AS WSTRING, BYVAL nStringLength AS LONG, BYREF wszPadCharacter AS WSTRING = " ") AS CWSTR
   wszPadCharacter = LEFT(wszPadCharacter, 1)
   DIM cws AS CWSTR = SPACE(nStringLength)
   FOR i AS LONG = 1 TO LEN(cws)
      MID(**cws, i, 1) = wszPadCharacter
   NEXT
   MID(**cws, nStringLength - LEN(wszMainStr) + 1, LEN(wszMainStr)) = wszMainStr
   RETURN cws
END FUNCTION
' ========================================================================================

' ========================================================================================
' Returns a string containing a centered (padded) string.
' If the optional parameter wszPadCharacter not specified, the function pads the string with
' space characters to the left. Otherwise, the function pads the string with the first
' character of wszPadCharacter.
' Example: DIM cws AS CWSTR = AfxStrCSet("FreeBasic", 20, "*")
' ========================================================================================
PRIVATE FUNCTION AfxStrCSet (BYREF wszMainStr AS WSTRING, BYVAL nStringLength AS LONG, BYREF wszPadCharacter AS WSTRING = " ") AS CWSTR
   wszPadCharacter = LEFT(wszPadCharacter, 1)
   DIM cws AS CWSTR = SPACE(nStringLength)
   FOR i AS LONG = 1 TO LEN(cws)
      MID(**cws, i, 1) = wszPadCharacter
   NEXT
   MID(**cws, (nStringLength - LEN(wszMainStr)) \ 2 + 1, LEN(wszMainStr)) = wszMainStr
   RETURN cws
END FUNCTION
' ========================================================================================
Title: Re: WinFBX Version 1.0
Post by: José Roca on December 19, 2017, 10:25:03 AM
After a discussion in the PowerBasic forum, I have written the following functions to get the handle of the top level window of a web browser. I will incorporate them in AfxWin.inc

Code: [Select]
' ========================================================================================
' Retrieves the handle of the top level window of the web browser.
' Parameter:
'    pwszClassName: The browser class name.
' Return value:
'    The handle of the top level window of the browser.
' Thanks to Dominic Mitchell for the information provided in this thread:
' https://forum.powerbasic.com/forum/user-to-user-discussions/powerbasic-for-windows/767812-handle-to-browser-window?p=767896#post767896
' Examples:
' DIM hwndBrowser AS HWND = AfxGetBrowserHandle("IEFrame")              ' // Internet Explorer
' DIM hwndBrowser AS HWND = AfxGetBrowserHandle("MozillaWindowClass")   ' // Firefox
' DIM hwndBrowser AS HWND = AfxGetBrowserHandle("Chrome_WidgetWin_1")   ' // Chrome
' ========================================================================================
FUNCTION AfxEnumThreadWndProc (BYVAL hwnd AS HWND, BYVAL lParam AS LPARAM) AS WINBOOL
   DIM dwStyle AS DWORD = GetWindowLongPtr(hwnd, GWL_STYLE)
   IF ((dwStyle AND (WS_POPUP OR WS_CHILD)) = 0) AND ((dwStyle AND WS_VISIBLE) <> 0) THEN
      DIM phwndTop AS HWND PTR
      CAST(LPARAM, phwndTop) = lParam
      *phwndTop = hwnd
      RETURN FALSE
   END IF
   RETURN CTRUE
END FUNCTION
' ========================================================================================
' ========================================================================================
FUNCTION AfxGetBrowserHandle (BYVAL pwszClassName AS WSTRING PTR) AS HWND
  DIM hwndBrowser AS HWND = FindWindowW(pwszClassName, NULL)
  IF hwndBrowser = NULL THEN RETURN NULL
  DIM dwThread AS DWORD = GetWindowThreadProcessId(hwndBrowser, NULL)
  IF dwThread = 0 THEN RETURN NULL
  DIM hwndTop AS HWND
  EnumThreadWindows(dwThread, @AfxEnumThreadWndProc, CAST(LPARAM, @hwndTop))
  RETURN hwndTop
END FUNCTION
' ========================================================================================
' ========================================================================================
' Retrieves the top level window handle of Intenet Explorer.
' ========================================================================================
FUNCTION AfxGetInternetExplorerHandle () AS HWND
   RETURN AfxGetBrowserHandle("IEFrame")
END FUNCTION
' ========================================================================================
' ========================================================================================
' Retrieves the top level window handle of Firefox.
' ========================================================================================
FUNCTION AfxGetFireFoxHandle () AS HWND
   RETURN AfxGetBrowserHandle("MozillaWindowClass")
END FUNCTION
' ========================================================================================
' ========================================================================================
' Retrieves the top level window handle of Google Chrome.
' ========================================================================================
FUNCTION AfxGetGoogleChromeHandle () AS HWND
   RETURN AfxGetBrowserHandle("Chrome_WidgetWin_1")
END FUNCTION
' ========================================================================================
Title: Re: WinFBX Version 1.0
Post by: Paul Squires on December 19, 2017, 12:26:24 PM
It would be so incredibly awesome if Dominic Mitchell would convert over to FreeBasic as well. Dominic and Jose are the two smartest PB programmers on the planet.
Title: Re: WinFBX Version 1.0
Post by: James Fuller on December 19, 2017, 12:56:33 PM
It would be so incredibly awesome if Dominic Mitchell would convert over to FreeBasic as well. Dominic and Jose are the two smartest PB programmers on the planet.
I may be wrong but I get the impression Dominic is more commercially motivated than is Jose.

James
 
Title: Re: WinFBX Version 1.0
Post by: José Roca on December 20, 2017, 10:55:00 AM
Since we can use the Free Basic intrinsic array procedures to work with arrays of CWSTR strings, I have added some helper functions to CWSTR.inc.

Code: [Select]
' ########################################################################################
'                                *** HELPER FUNCTIONS ***
' ########################################################################################

' ========================================================================================
' qsort CWstr comparison function
' ========================================================================================
PRIVATE FUNCTION AfxCWstrArrayCompare CDECL (BYVAL a AS CWSTR PTR, BYVAL b AS CWSTR PTR) AS LONG
   FUNCTION = wcscmp(cast(WSTRING PTR, a->m_pBuffer), cast(WSTRING PTR, b->m_pBuffer))
END FUNCTION
' ========================================================================================
' ========================================================================================
' Reverse qsort CWstr comparison function
' ========================================================================================
PRIVATE FUNCTION AfxCWStrArrayReverseCompare CDECL (BYVAL a AS CWSTR PTR, BYVAL b AS CWSTR PTR) AS LONG
   DIM r AS LONG = wcscmp(cast(WSTRING PTR, a->m_pBuffer), cast(WSTRING PTR, b->m_pBuffer))
   IF r = 1 THEN r = -1 ELSE IF r = -1 THEN r = 1
   RETURN r
END FUNCTION
' ========================================================================================

' ========================================================================================
' Sorts a one-dimensional CWSTR array calling the C qsort function.
' Parameters:
' - rgwstr : Start of target array.
' - numElm : Number of elements in the array.
' - bAscend: TRUE for sorting in ascending order; FALSE for sorting in descending order.
' Example:
' DIM rg(1 TO 10) AS CWSTR
' FOR i AS LONG = 1 TO 10
'    rg(i) = "string " & i
' NEXT
' FOR i AS LONG = 1 TO 10
'   print rg(i)
' NEXT
' print "---- after sorting ----"
' AfxCWstrSort @rg(1), 10, TRUE
' FOR i AS LONG = 1 TO 10
'    print rg(i)
' NEXT
' ========================================================================================
PRIVATE SUB AfxCWstrSort (BYREF rgwstr AS ANY PTR, BYVAL numElm AS LONG, BYVAL bAscend AS BOOLEAN = TRUE)
   IF rgwstr = NULL OR numElm < 2 THEN EXIT SUB
   IF bAscend THEN
      qsort rgwstr, numElm, SIZEOF(CWSTR), CPTR(ANY PTR, @AfxCWstrArrayCompare)
   ELSE
      qsort rgwstr, numElm, SIZEOF(CWSTR) , CPTR(ANY PTR, @AfxCWStrArrayReverseCompare)
   END IF
END SUB
' ========================================================================================
' ========================================================================================
PRIVATE SUB AfxCWstrArraySort (rgwstr() AS CWSTR, BYVAL bAscend AS BOOLEAN = TRUE)
   DIM numElm AS LONG = UBOUND(rgwstr) - LBOUND(rgwstr) + 1
   AfxCWstrSort @rgwstr(LBOUND(rgwstr)), numElm, bAscend
END SUB
' ========================================================================================

' ========================================================================================
' Appends a CWSTR at the end of a one-dimensional CWSTR array.
' Parameters:
' - rgwstr(): The CWSTR array
' - cws: The CWSTR to append
' Return value:
'   TRUE or FALSE
' Example:
' #INCLUDE ONCE "Afx/CWSTR.inc"
' USING Afx
' REDIM rg(1 TO 10) AS CWSTR
' FOR i AS LONG = 1 TO 10
'    rg(i) = "string " & i
' NEXT
' AfxCwstrArrayAppend(rg(), "string 11")
' FOR i AS LONG = LBOUND(rg) TO UBOUND(rg)
'    print rg(i)
' NEXT
' Note: REDIM PRESERVE cannot be used on fixed-size arrays - i.e. arrays with constant bounds
' made with DIM. If after calling REDIM PRESERVE the upper bound has not changed, it means
' that it is a fixed string.
' ========================================================================================
PRIVATE FUNCTION AfxCWstrArrayAppend (rgwstr() AS CWSTR, BYREF cws AS CWSTR) AS BOOLEAN
   DIM upperBound AS LONG = UBOUND(rgwstr)
   REDIM PRESERVE rgwstr(LBOUND(rgwstr) TO upperBound + 1) AS CWSTR
   IF UBOUND(rgwstr) > upperBound THEN rgwstr(UBOUND(rgwstr)) = cws : RETURN TRUE
   RETURN FALSE
END FUNCTION
' ========================================================================================

' ========================================================================================
' Inserts a new CWSTR element before the specified position in a one-dimensional CWSTR array.
' Parameters:
' - rgwstr(): The CWSTR array
' - nPos: The position in the array where the new element will be added.
'         This position is relative to the lower bound of the array.
' - cws: The CWSTR to append
' Return value:
'   TRUE or FALSE
' Example:
' #INCLUDE ONCE "Afx/CWSTR.inc"
' USING Afx
' REDIM rg(1 TO 10) AS CWSTR
' FOR i AS LONG = 1 TO 10
'    rg(i) = "string " & i
' NEXT
' AfxCwstrArrayInsert(rg(), 3, "Inserted element")
' FOR i AS LONG = LBOUND(rg) TO UBOUND(rg)
'    print rg(i)
' NEXT
' Note: REDIM PRESERVE cannot be used on fixed-size arrays - i.e. arrays with constant bounds
' made with DIM. If after calling REDIM PRESERVE the upper bound has not changed, it means
' that it is a fixed string.
' ========================================================================================
PRIVATE FUNCTION AfxCWstrArrayInsert (rgwstr() AS CWSTR, BYVAL nPos AS LONG, BYREF cws AS CWSTR) AS BOOLEAN
   DIM lowerBound AS LONG = LBOUND(rgwstr)
   DIM upperBound AS LONG = UBOUND(rgwstr)
   nPos = nPos - 1 + lowerBound
   IF nPos < lowerBound OR nPos > upperBound THEN RETURN FALSE
   REDIM PRESERVE rgwstr(lowerBound TO upperBound + 1) AS CWSTR
   IF UBOUND(rgwstr) = upperBound THEN RETURN FALSE
   ' // Move all the elements down
   FOR i AS LONG = UBOUND(rgwstr) TO nPos + 1 STEP - 1
      rgwstr(i) = rgwstr(i - 1)
   NEXT
   rgwstr(nPos) = cws
   RETURN TRUE
END FUNCTION
' ========================================================================================

' ========================================================================================
' Removes the specified element of a one-dimensional CWSTR array.
' Parameters:
' - rgwstr(): The CWSTR array
' - nPos: The position in the array of the element to remove.
'         This position is relative to the lower bound of the array.
' - cws: The CWSTR to append
' Return value:
'   TRUE or FALSE
' Example:
' #INCLUDE ONCE "Afx/CWSTR.inc"
' USING Afx
' REDIM rg(1 TO 10) AS CWSTR
' FOR i AS LONG = 1 TO 10
'    rg(i) = "string " & i
' NEXT
' AfxCwstrArrayRemove(rg(), 3)
' FOR i AS LONG = LBOUND(rg) TO UBOUND(rg)
'    print rg(i)
' NEXT
' Note: REDIM PRESERVE cannot be used on fixed-size arrays - i.e. arrays with constant bounds
' made with DIM. If after calling REDIM PRESERVE the upper bound has not changed, it means
' that it is a fixed string.
' ========================================================================================
PRIVATE FUNCTION AfxCWstrArrayRemove (rgwstr() AS CWSTR, BYVAL nPos AS LONG) AS BOOLEAN
   DIM lowerBound AS LONG = LBOUND(rgwstr)
   DIM upperBound AS LONG = UBOUND(rgwstr)
   nPos = nPos - 1 + lowerBound
   IF nPos < lowerBound OR nPos > upperBound THEN RETURN FALSE
   FOR i AS LONG = nPos TO upperBound - 1
      rgwstr(i) = rgwstr(i + 1)
   NEXT
   REDIM PRESERVE rgwstr(lowerBound TO upperBound - 1) AS CWSTR
   IF UBOUND(rgwstr) = upperBound THEN RETURN FALSE
   RETURN TRUE
END FUNCTION
' ========================================================================================

' ========================================================================================
' Removes the first element of a one-dimensional CWSTR array.
' ========================================================================================
PRIVATE FUNCTION AfxCWstrArrayRemoveFirst (rgwstr() AS CWSTR) AS BOOLEAN
   DIM lowerBound AS LONG = LBOUND(rgwstr)
   DIM upperBound AS LONG = UBOUND(rgwstr)
   DIM nPos AS LONG = lowerBound
   FOR i AS LONG = nPos TO upperBound - 1
      rgwstr(i) = rgwstr(i + 1)
   NEXT
   REDIM PRESERVE rgwstr(lowerBound TO upperBound - 1) AS CWSTR
   IF UBOUND(rgwstr) = upperBound THEN RETURN FALSE
   RETURN TRUE
END FUNCTION
' ========================================================================================

' ========================================================================================
' Removes the last element of a one-dimensional CWSTR array.
' ========================================================================================
PRIVATE FUNCTION AfxCWstrArrayRemoveLast (rgwstr() AS CWSTR) AS BOOLEAN
   DIM lowerBound AS LONG = LBOUND(rgwstr)
   DIM upperBound AS LONG = UBOUND(rgwstr)
   REDIM PRESERVE rgwstr(lowerBound TO upperBound - 1) AS CWSTR
   IF UBOUND(rgwstr) = upperBound THEN RETURN FALSE
   RETURN TRUE
END FUNCTION
' ========================================================================================

I wonder if there is a way to detect if an array is fixed other that checking if REDIM PRESERVE has failed.
Title: Re: WinFBX Version 1.0
Post by: ganlinlao on December 24, 2017, 11:08:10 AM
hi,jose

    Happy Christmas, thank you for your hard work, bringing Freebasic an easy-to-use framework.
Title: Re: WinFBX Version 1.0
Post by: José Roca on December 24, 2017, 11:32:54 AM
Thank you for using it. I wish you a Happy New Year.
Title: Re: WinFBX Version 1.0
Post by: José Roca on December 25, 2017, 08:20:59 PM
Removed "Pass -1 to use the default styles." in the documentation of the dwStyle and dwExStyle parameters of the Create method of the CWindow class. This was a leftover of an earlier version.

AfxResizeTabPages function
Changed FUNCTION AfxDestroyAllTabPages (BYVAL hTab AS HWND) AS BOOLEAN to FUNCTION AfxResizeTabPages (BYVAL hTab AS HWND) AS BOOLEAN.

ComboBox_ResetContent
Changed "Limits the length of the text the user may type into the edit control of a combo box." to "Removes all items from the list box and edit control of a combo box."

TOOLINFOW
Changed "Contains information specific to an NM_CUSTOMDRAW notification message sent by a ToolTip control." to "Contains information about a tool in a tooltip control."

AfxSetPrinterCollateStatus
Changed "Switches between color and monochrome on color printers." to "Specifies whether collation should be used when printing multiple copies."

CFileSys
Several methods were documented as returning a CWSTR instead of a CBSTR.

AfxGdiPlus.inc

FUNCTION GDIP_RECT ( _
   BYVAL x AS LONG, _
   BYVAL y AS LONG, _
   BYVAL nWidth AS LONG, _
   BYVAL nHeight AS LONG _
) AS GpRect

Returns a GpRect structure initialized with the specified values for the x, y, width, and height components.

FUNCTION GDIP_RECTF ( _
   BYVAL x AS SINGLE, _
   BYVAL y AS SINGLE, _
   BYVAL nWidth AS SINGLE, _
   BYVAL nHeight AS SINGLE _
) AS GpRectF

Returns a GpRectF structrure initialized with the specified values for the x, y, width, and height components.
Title: Re: WinFBX Version 1.0
Post by: José Roca on December 26, 2017, 07:32:02 PM
Updated to version 1.0.02.

WinFBX
Windows Framework for FreeBASIC.

20 Dec 2017 - Version 1.0.02
- Added the following functions:
      AfxCWstrArrayAppend
      AfxCWstrArrayInsert
      AfxCWstrArrayRemove
      AfxCWstrArrayRemoveFirst
      AfxCWstrArrayRemoveLast
      AfxCWstrArraySort

19 Dec 2017  - Version 1.0.02
- Added the following functions:
      AfxGetBrowserHandle
      AfxGetInternetExplorerHandle
      AfxGetFireFoxHandle
      AfxGetGoogleChromeHandle

15 Dec 2017  - Version 1.0.02
- Added the Resize method to the CWSTR class.
- Modified the AfxStrLSet, AfxStrRSet and AfxStCSet functions to work with Unicode.

23 Nov 2017  - Version 1.0.01
- Bug fix: Changed DIM vArgs(1 TO 15) AS VARIANT to DIM vArgs(1 TO 16) AS VARIANT in the
last overloaded Invoke function of the CDispInvoke.class. Thanks to ganlinlao for reporting it.

21 Nov 2017
- Version 1.0 released
Title: Re: WinFBX Version 1.0
Post by: Vinod Chandran on March 05, 2018, 03:36:19 PM
Hi,
I am learning some new stuff from WinFBX framework. Such a giant library and it gives more simplicity to FreeBasic. Especially i love Cwstr library. It is must have for any language. Dynamic unicode string handling is a must have feature. By the way, i got stumbled upon the usage of period in some functions. For example, in DoEvents function.
Code: [Select]
' // Show the window and update its client area
   IF nCmdShow = 0 THEN .ShowWindow m_hwnd, SW_SHOW ELSE .ShowWindow m_hwnd, nCmdShow
   .UpdateWindow m_hwnd
See this line ? What is the meaning of that period in the left side of ShowWindow function.  I know that ShowWindow is an api function. Then why it is used with a period ?
Title: Re: WinFBX Version 1.0
Post by: José Roca on March 05, 2018, 04:20:21 PM
To avoid possible name conflicts, present or future. It makes sure that it calls that symbol in the global namespace and not a duplicate symbol in another namespace.

If someone else writes a class with a method called ShowWindow, and you use it together with mine, without an "." my code won't know if you intend to call the API function ShowWindow or the ShowWindow method of the other class.

All the code that I have written with FreeBasic is unicode aware. It is unavoidable if one wants to attract international users. And with the WinFBE editor you can use unicode string literals if you save the file with the option UTF-8 BOM. The string literals will be saved in the file as UTF-8, but the CWSTR class will perform the conversion. This way you can work as if dynamic unicode strings were natively supported by FreeBasic.

DIM cws AS CWSTR = "Дмитрий Дмитриевич Шостакович"

WYSIWYG (What you see is what you get), without having to use CHR.

Title: Re: WinFBX Version 1.0
Post by: Vinod Chandran on March 06, 2018, 06:36:44 AM
Yeah, Thanks for the reply. Is there any dynamic list or array feature in WinFBX  framework ? Does CSafeArray is a dynamic array ?
Title: Re: WinFBX Version 1.0
Post by: José Roca on March 06, 2018, 07:05:51 AM
CSafeArray implements support for safe arrays that are used in COM programming. It works with VARIANTs.

We can use CWSTR as if it was a native data type. Therefore, you can have arrays of CWSTRrings as easily as arrays of FreeBasic ansi strings.

We can use arrays of CWSTR strings transparently, e.g.

Code: [Select]
DIM rg(1 TO 10) AS CWSTR

FOR i AS LONG = 1 TO 10
  rg(i) = "string " & i
NEXT

FOR i AS LONG = 1 TO 10
  print rg(i)
NEXT

A two-dimensional array

Code: [Select]
DIM rg2 (1 TO 2, 1 TO 2) AS CWSTR
rg2(1, 1) = "string 1 1"
rg2(1, 2) = "string 1 2"
rg2(2, 1) = "string 2 1"
rg2(2, 2) = "string 2 2"
print rg2(2, 1)

REDIM PRESERVE / ERASE

Code: [Select]
REDIM rg(0) AS CWSTR
rg(0) = "string 0"
REDIM PRESERVE rg(0 TO 2) AS CWSTR
rg(1) = "string 1"
rg(2) = "string 2"
print rg(0)
print rg(1)
print rg(2)
ERASE rg

And we can also sort one-dimensional arrays calling the AfxCWstrSort procedure:

Code: [Select]
DIM rg(1 TO 10) AS CWSTR

FOR i AS LONG = 1 TO 10
  rg(i) = "string " & i
NEXT

FOR i AS LONG = 1 TO 10
 print rg(i)
NEXT

print "---- after sorting ----"

AfxCWstrSort @rg(1), 10

FOR i AS LONG = 1 TO 10
  print rg(i)
NEXT
Title: Re: WinFBX Version 1.0
Post by: José Roca on March 06, 2018, 07:12:42 AM
As noted in the documentation, CWSTR behaves as if it was a native data type, working directly with the intrinsic Free Basic string functions and operators. The only exception is MID when used as a statement: Something like MID(cws, 2, 1) = "x" compiles but does not change the contents of the dynamic unicode string. MID(cws.wstr, 2, 1) = "x" or MID(**cws, 2, 1) = "x" works.

It even works with files, e.g.

Code: [Select]
#include once "Afx/CWStr.inc"

DIM cws AS CWSTR = "Дмитрий Дмитриевич Шостакович"

DIM f AS LONG = FREEFILE
OPEN "test.txt" FOR OUTPUT ENCODING "utf16" AS #f
PRINT #f, cws
CLOSE #f

There are also wrapper procedures to Append, Insert and Remove elements of the array: AfxCWstrArrayAppend, AfxCWstrArrayInsert, AfxCWstrArrayRemove, AfxCWstrArrayRemoveFirst and AfxCWstrArrayRemoveLast.
Title: Re: WinFBX Version 1.0
Post by: José Roca on March 26, 2018, 06:45:43 PM
New help file uploaded. Corrected some inaccuracies in the documentation.
Title: Re: WinFBX Version 1.0
Post by: Johan Klassen on March 26, 2018, 10:19:59 PM
thank Jose Roca  :)
Title: Re: WinFBX Version 1.0
Post by: Eros Olmi on April 02, 2018, 07:12:47 AM
Dear Jose,

I tried to download you .rar files but they seems corrupted.
I use 7-Zip to open them, tied to clear the browser cache, tried to download from different browser but always the same problem.
7-Zip report that "There are some data after the end of the payload data"

I'm the only one having problems?

Thanks a lot
Eros
Title: Re: WinFBX Version 1.0
Post by: José Roca on April 02, 2018, 08:19:57 AM
Paul has moved the forum to another server and some things have become corrupted.

Meanwhile, you can download it from GitHub.
https://github.com/JoseRoca/WinFBX
Title: Re: WinFBX Version 1.0
Post by: Eros Olmi on April 02, 2018, 08:42:12 AM
Thanks Jose.
Yes I got from github.
Title: Re: WinFBX Version 1.0
Post by: Paul Squires on April 02, 2018, 10:07:53 AM
Hmmm... that's too bad with the corrupted files. Just when I thought everything was moving over okay from the old server.  :(

I knew I was having trouble with the avatars but I didn't realize zip files might be affected. It seems you will need to re-upload your personal avatars.

Looks like FileZilla (by default) treats filenames with no extensions as ASCII files rather than binary. Therefore when uploaded to the new forum the line encodings of attachments were affected. I am attempting to redownload from old site and reupload. Hopefully it can be fixed.
Title: Re: WinFBX Version 1.0
Post by: José Roca on April 02, 2018, 01:19:06 PM
You have fallen in the same trap that I did several years ago.

See: http://www.jose.it-berater.org/smfforum/index.php?topic=4183.msg14552#msg14552
Title: Re: WinFBX Version 1.0
Post by: Paul Squires on April 02, 2018, 01:27:09 PM
I most certainly did! Luckily I have been able to get it all corrected. The only issue is now in posts where your name was (with an accent) it looks like the message got truncated at the accent character.
Title: Re: WinFBX Version 1.0
Post by: José Roca on May 11, 2018, 04:40:32 PM
Modified the AfxStrLSet, AfxStrRset and AfxStrCSet functions because they GPFed with the 64 bit compiler.

Code: [Select]
' ========================================================================================
' Returns a string containing a left-justified (padded) string.
' If the optional parameter wszPadCharacter not specified, the function pads the string with
' space characters to the left. Otherwise, the function pads the string with the first
' character of wszPadCharacter
' Example: DIM cws AS CWSTR = AfxStrLSet("FreeBasic", 20, "*")
' ========================================================================================
PRIVATE FUNCTION AfxStrLSet (BYREF wszMainStr AS CONST WSTRING, BYVAL nStringLength AS LONG, BYREF wszPadCharacter AS WSTRING = " ") AS CWSTR
   DIM cws AS CWSTR = WSTRING(nStringLength, wszPadCharacter)
   MID(**cws, 1, LEN(wszMainStr)) = wszMainStr
   RETURN cws
END FUNCTION
' ========================================================================================

' ========================================================================================
' Returns a string containing a right-justified (padded) string.
' If the optional parameter wszPadCharacter not specified, the function pads the string with
' space characters to the left. Otherwise, the function pads the string with the first
' character of wszPadCharacter.
' Example: DIM cws AS CWSTR = AfxStrRSet("FreeBasic", 20, "*")
' ========================================================================================
PRIVATE FUNCTION AfxStrRSet (BYREF wszMainStr AS CONST WSTRING, BYVAL nStringLength AS LONG, BYREF wszPadCharacter AS WSTRING = " ") AS CWSTR
   IF LEN(wszMainStr) > nStringLength THEN RETURN LEFT(wszMainStr, nStringLength)
   DIM cws AS CWSTR = WSTRING(nStringLength, wszPadCharacter)
   MID(**cws, nStringLength - LEN(wszMainStr) + 1, LEN(wszMainStr)) = wszMainStr
   RETURN cws
END FUNCTION
' ========================================================================================

' ========================================================================================
' Returns a string containing a centered (padded) string.
' If the optional parameter wszPadCharacter not specified, the function pads the string with
' space characters to the left. Otherwise, the function pads the string with the first
' character of wszPadCharacter.
' Example: DIM cws AS CWSTR = AfxStrCSet("FreeBasic", 20, "*")
' ========================================================================================
PRIVATE FUNCTION AfxStrCSet (BYREF wszMainStr AS CONST WSTRING, BYVAL nStringLength AS LONG, BYREF wszPadCharacter AS WSTRING = " ") AS CWSTR
   IF LEN(wszMainStr) > nStringLength THEN RETURN LEFT(wszMainStr, nStringLength)
   DIM cws AS CWSTR = WSTRING(nStringLength, wszPadCharacter)
   MID(**cws, (nStringLength - LEN(wszMainStr)) \ 2 + 1, LEN(wszMainStr)) = wszMainStr
   RETURN cws
END FUNCTION
' ========================================================================================
Title: Re: WinFBX Version 1.0
Post by: José Roca on May 26, 2018, 10:35:07 AM
Modified the internal code of some string functions that worked with INSTR and CWSTR variables without using **.
Title: Re: WinFBX Version 1.0
Post by: José Roca on May 28, 2018, 09:03:57 AM
Modified the AfxOpenFileDialog and AfxSaveFileDialog that GPFed with FB 64 bit.

As always, you can get the most recent code in GitHub: https://github.com/JoseRoca/WinFBX
Title: Re: WinFBX Version 1.0
Post by: José Roca on June 21, 2018, 11:41:37 PM
AfxWin.inc: Added the function AfxCommand. Like FB's COMMAND but Unicode aware.

Code: [Select]
' ========================================================================================
' Returns command line parameters used to call the program
' Unicode replacement for FreeBasic Command keyword.
' Usage: result = AfxCommand ( [ index ] )
' Parameter:
' - index : Zero-based index for a particular command-line argument.
' Return Value
'   Returns the command-line arguments(s).
' Description
'   - AfxCommand returns command-line arguments passed to the program upon execution.
'   - If index is less than zero (< 0), a space-separated list of all command-line arguments
'   is returned, otherwise, a single argument is returned. A value of zero (0) returns the
'   name of the executable; and values of one (1) and greater return each command-line argument.
'   - If index is greater than the number of arguments passed to the program, a null
'     string ("") is returned.
' ========================================================================================
PRIVATE FUNCTION AfxCommand (BYVAL nIndex AS LONG = -1) AS CWSTR
   DIM pArgsList AS WSTRING PTR PTR, nArgs AS LONG, cwsArgs AS CWSTR
   pArgsList = CAST(WSTRING PTR PTR, CommandLineToArgvW(GetCommandLineW, @nArgs))
   IF pArgsList = NULL OR nIndex > nArgs THEN RETURN cwsArgs
   IF nIndex < 0 THEN
      FOR i AS LONG = 1 TO nArgs - 1
         cwsArgs += *pArgsList[i] & " "
      NEXT
      cwsArgs = RTRIM(**cwsArgs)
   ELSE
      cwsArgs = *pArgsList[nIndex]
   END IF
   LocalFree CAST(HLOCAL, pArgsList)
   RETURN cwsArgs
END FUNCTION
' ========================================================================================
Title: Re: WinFBX Version 1.0
Post by: José Roca on July 02, 2018, 03:42:37 PM
Added some convenience wrappers to CTextStream.inc: OpenForInputA / W, OpenForOutputA / W and OpenForAppendA / W. This class allows to work easily with sequential files in ansi or unicode, with some advanced methods.

For binary files, the Windows API provides API functions that work perfectly with CWSTR strings, e.g.:

Code: [Select]
DIM cwsFilename AS CWSTR = "тест.txt"
DIM cwsText AS CWSTR = "Дмитрий Дмитриевич Шостакович"
DIM hFile AS HANDLE = CreateFileW(cwsFilename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)
WriteFile(hFile, cwsText, LEN(cwsText) * 2, NULL, NULL)
CloseHandle(hFile)

However, in the FB forum prefer to walk in circles:
https://www.freebasic.net/forum/viewtopic.php?f=2&t=26839
Title: Re: WinFBX Version 1.0
Post by: Johan Klassen on July 02, 2018, 04:12:32 PM
thank you José Roca :)
just out curiosity I looked up "Дмитрий Дмитриевич Шостакович" and I got info on Dmitri Dmitriyevich Shostakovich
Title: Re: WinFBX Version 1.0
Post by: José Roca on July 08, 2018, 07:16:01 PM
6 Jul 2018 - Version 1.0.03

- CWSTR: Changed CONSTRUCTOR (BYVAL nChars AS UINT, BYVAL nCodePage AS UINT)
to CONSTRUCTOR (BYVAL nChars AS UINT, BYVAL bClear AS BOOLEAN)
The nCodePage parameter was no longer useful and the new bClear parameter allows to specify
if the memory will be intialized (cleared) or not.

- CWSTR: The default constructor now initializes the memory.

4 Jul 2018 - Version 1.0.03

- CWSTR: Changed the [] operator from one-based index to zero-based index.
Title: Re: WinFBX Version 1.0
Post by: ChrisC on July 25, 2018, 08:20:35 PM
Hello all

what is the purpose of WinFBX ?   is it something like Jose's includes files for PB?
Title: Re: WinFBX Version 1.0
Post by: ChrisC on July 26, 2018, 11:36:40 AM
WinFBX -- where can i get sample codes and applications on how to use it?

Any suggestions?  thanks all help appreciated
Title: Re: WinFBX Version 1.0
Post by: José Roca on July 26, 2018, 11:39:41 AM
The WinFBE editor comes with the include fiiles, examples and templates.

On-line help: http://www.jose.it-berater.org/WinFBX/WinFBX.html
Title: Re: WinFBX Version 1.0
Post by: ChrisC on July 26, 2018, 07:33:08 PM
Cool, thanks a lot Jose

These examples are so cool !
Title: Re: WinFBX Version 1.0
Post by: José Roca on July 30, 2018, 10:46:31 PM
I have uploaded an updated help file. It is attached to the first post of this thread.
Title: Re: WinFBX Version 1.0
Post by: Eros Olmi on July 31, 2018, 05:08:43 AM
Sorry for the dummy question but which is the correct way to proceed for using WinFBX?
Where do I have to place all files?

I've FreeBasic installed in C:\FreeBasic\
Do I have to copy all WinFBX file inside C:\FreeBasic\inc\ directory?

Thanks a lot
Eros
Title: Re: WinFBX Version 1.0
Post by: José Roca on July 31, 2018, 09:40:35 AM
As long as they're in a folder or subfolder called Afx, you can put them anywhere. When compiling you will need to use the switch -i followed by the path of the include files.
Title: Re: WinFBX Version 1.0
Post by: Paul Squires on July 31, 2018, 02:29:15 PM
Do I have to copy all WinFBX file inside C:\FreeBasic\inc\ directory?

That's the way that I have my system setup. I copy all of Jose's WinFBX files into a subfolder called "Afx" and place that subfolder off of the "\inc" folder of the compiler. I do that for both 32 bit and 64 bit compilers.