• Welcome to PlanetSquires Forums.
 

WinFBX Version 1.0

Started by José Roca, November 21, 2017, 05:19:32 PM

Previous topic - Next topic

Paul Squires

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.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

James Fuller

Quote from: 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.
I may be wrong but I get the impression Dominic is more commercially motivated than is Jose.

James

José Roca

#32
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.


' ########################################################################################
'                                *** 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.

ganlinlao

hi,jose

    Happy Christmas, thank you for your hard work, bringing Freebasic an easy-to-use framework.

José Roca

Thank you for using it. I wish you a Happy New Year.

José Roca

#35
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.

José Roca

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

Vinod Chandran

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.
' // 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 ?

José Roca

#38
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.


Vinod Chandran

Yeah, Thanks for the reply. Is there any dynamic list or array feature in WinFBX  framework ? Does CSafeArray is a dynamic array ?

José Roca

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.


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


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


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:


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


José Roca

#41
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.


#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.

José Roca

New help file uploaded. Corrected some inaccuracies in the documentation.

Johan Klassen


Eros Olmi

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