• Welcome to PlanetSquires Forums.
 

CWindow Release Candidate 31

Started by José Roca, August 06, 2017, 02:51:36 PM

Previous topic - Next topic

José Roca

#45
Hi Marc,

Your posts are always welcome and the information that you have posted is useful. What happens is that the PowerBasic users are not used to this nasty business of compiler switches and import libraries, and we try to avoid its use like a pest.

Its annoyig to download old code that does not compile, not only because of changes in the compiler, but also because you need some updated library. And when you search for a C library, these Linux guys often don't provide binaries and you're supposed to know C programming, install some C compiler and toolchain, etc. If it was a C programmer I won't be using Free Basic.

Why all these complications? They are only good for scaring beginners. Basic is supposed to be a language easy to use.

And don't worry about being disruptive because currently there are only two users of my framework, Paul and me. I'm using these threads as bloc-notes.

Richard Kelly

I've been off in the wilds of Alaska chasing grayling this month and just returned. A guy takes off and look at what you've done...geez...I'm already tired thinking about all the possible ways to use cWindow and the new designer.

Rick

José Roca

File reuploaded in the original post.

Added an explicit return value to several functions that used IF xxx THEN RETURN xxx. According to a post in the FB forum, failing to do it could give unexpected results or crashes.


Richard Kelly

With all you have accomplished, it looks like it is now possible to create Excel files without Excel installed. Take a look at:

https://gallery.technet.microsoft.com/scriptcenter/Export-XLSX-PowerShell-f2f0c035

Rick

Richard Kelly

Jose:

Windows has, I think since 7/Vista days, had the Network List Manager (NLM) built on top of the Network Connectivity Status Indicator (NCSI), which is part of a broader feature called Network Awareness. What happens is:

1.When connected to the network, the system sends an HTTP-request to http://www.msftncsi.com/ncsi.txt. This is a plain text file which contains just a single line 'Microsoft NCSI'. In case of a successful query, the server should send back a response with the header “200 OK” containing this line.

2.The DNS service health is checked in the second step with the NCSI trying to resolve the name dns.msftncsi.com to an IP address. The expected value is 131.107.255.255

If these two steps are OK, Internet/WAN connectivity is assumed to be functional.

Using your COM functions, do you think the objects documented at:

https://msdn.microsoft.com/en-us/library/windows/desktop/aa370799(v=vs.85).aspx

could be hosted?

All the approaches I've seen, and even used myself, was to do some HTTP to a known site such as WhatsMyIP and see if it works.

Rick

José Roca

You will need interface declarations (see attached file).

What I can't do is to test it because I don't have a network.

Richard Kelly

Quote from: Jose Roca on August 30, 2017, 03:17:11 PM
You will need interface declarations (see attached file).

What I can't do is to test it because I don't have a network.

I'll test it over the next few days. I have both wired and wireless with a NAT router connected to a cable modem. I can try various points of failure and see what results come in.

Rick

José Roca

One of the reasons to write the class is that it can be used as an alternative to multi-dimensional arrays. We can use a memory SQLite database to store the data and use SQL to access it.

José Roca

#53
Next update will include several new functions, among them AfxFileScanA/W, a replacement for PowerBasic FILESCAN, but in both ansi and unicode versions. These two functions are truly speed demons, even a bit faster than FILESCAN.

Included in AfxWin.inc:


' ========================================================================================
' Scans a text file ans returns the number of occurrences of the specified delimiter.
' Default value is CHR(13, 10), which returns the number of lines.
' ========================================================================================
PRIVATE FUNCTION AfxFileScanA (BYREF wszFileName AS WSTRING, BYREF szDelimiter AS ZSTRING = CHR(13, 10)) AS DWORD
   DIM dwCount AS DWORD, dwFileSize AS DWORD, dwHighSize AS DWORD, dwBytesRead AS DWORD
   IF LEN(szDelimiter) = 0 THEN EXIT FUNCTION
   ' // Open the file
   DIM hFile AS HANDLE = CreateFileW(@wszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, _
                         OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL)
   IF hFile = INVALID_HANDLE_VALUE THEN EXIT FUNCTION
   ' // Get the size of the file
   dwFileSize = GetFileSize(hFile, @dwHighSize)
   DIM pBuffer AS UBYTE PTR
   pBuffer = CAllocate(1, dwFileSize)
   IF pBuffer = NULL THEN EXIT FUNCTION
   DIM bSuccess AS LONG = ReadFile(hFile, pBuffer, dwFileSize, @dwBytesRead, NULL)
   CloseHandle(hFile)
   IF bSuccess = FALSE THEN EXIT FUNCTION
   DIM nLen AS LONG = LEN(szDelimiter)
   DIM pstr AS ANY PTR = pBuffer
   DO
      pstr = strstr(pstr, szDelimiter)
      IF pstr = NULL THEN EXIT DO
      pstr += nLen
      dwCount += 1
   LOOP
   DeAllocate(pBuffer)
   FUNCTION = dwCount
END FUNCTION
' ========================================================================================
' ========================================================================================
' Version for unicode text files.
' ========================================================================================
PRIVATE FUNCTION AfxFileScanW (BYREF wszFileName AS WSTRING, BYREF wszDelimiter AS WSTRING = CHR(13, 10)) AS DWORD
   DIM dwCount AS DWORD, dwFileSize AS DWORD, dwHighSize AS DWORD, dwBytesRead AS DWORD
   IF LEN(wszDelimiter) = 0 THEN EXIT FUNCTION
   ' // Open the file
   DIM hFile AS HANDLE = CreateFileW(@wszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, _
                         OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL)
   IF hFile = INVALID_HANDLE_VALUE THEN EXIT FUNCTION
   ' // Get the size of the file
   dwFileSize = GetFileSize(hFile, @dwHighSize)
   DIM pBuffer AS UBYTE PTR
   pBuffer = CAllocate(1, dwFileSize)
   IF pBuffer = NULL THEN EXIT FUNCTION
   DIM bSuccess AS LONG = ReadFile(hFile, pBuffer, dwFileSize, @dwBytesRead, NULL)
   CloseHandle(hFile)
   IF bSuccess = FALSE THEN EXIT FUNCTION
   DIM nLen AS LONG = LEN(wszDelimiter) * 2
   DIM pstr AS ANY PTR = pBuffer
   DO
      pstr = wcsstr(pstr, @wszDelimiter)
      IF pstr = NULL THEN EXIT DO
      pstr += nLen
      dwCount += 1
   LOOP
   DeAllocate(pBuffer)
   FUNCTION = dwCount
END FUNCTION
' ========================================================================================


José Roca

#54
The following functions read all lines of the specified file into a safe array.

Included in CSafeArray.inc:


' ========================================================================================
' Reads all the lines of the specified file into a safe array.
' - wszFileName: Path of the file
' - szDelimiter: Delimiter of the line (CHR(13, 10) in Windows, CHR(10) in Linmux).
' ========================================================================================
PRIVATE FUNCTION AfxFileReadAllLinesA (BYREF wszFileName AS WSTRING, BYREF szDelimiter AS ZSTRING = CHR(13, 10)) AS CSafeArray
   DIM _csa AS CSafeArray = CSafeArray(VT_BSTR, 0, 1)
   DIM dwCount AS DWORD, dwFileSize AS DWORD, dwHighSize AS DWORD, dwBytesRead AS DWORD
   IF LEN(szDelimiter) = 0 THEN RETURN _csa
   ' // Open the file
   DIM hFile AS HANDLE = CreateFileW(@wszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, _
                         OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL)
   IF hFile = INVALID_HANDLE_VALUE THEN RETURN _csa
   ' // Get the size of the file
   dwFileSize = GetFileSize(hFile, @dwHighSize)
   DIM pBuffer AS UBYTE PTR
   pBuffer = CAllocate(1, dwFileSize)
   IF pBuffer = NULL THEN RETURN _csa
   DIM bSuccess AS LONG = ReadFile(hFile, pBuffer, dwFileSize, @dwBytesRead, NULL)
   CloseHandle(hFile)
   IF bSuccess = FALSE THEN RETURN _csa
   ' // Get the number of lines
   DIM nLen AS LONG = LEN(szDelimiter)
   DIM pstr AS ANY PTR = pBuffer
   ' // Check for UTF-8 BOM
   s = "   "
   strncpy STRPTR(s), _pstr, 3
   IF s = CHR(&hEF, &hBB, &hBF) THEN _pstr += 3
   ' // Parse the buffer
   DO
      pstr = strstr(pstr, szDelimiter)
      IF pstr = NULL THEN EXIT DO
      pstr += nLen
      dwCount += 1
   LOOP
' -------------------------------------------------------------------
  ' // Dimension a safe array with dwCount elements
'   DIM csa AS CSafeArray = CSafeArray(VT_BSTR, dwCount, 1)
'   Note: strtok can't be used because it skips empty lines.
'   ' // Fill the array with the lines
'   DIM pwsz AS ZSTRING PTR = strtok(pBuffer, @szDelimiter)
'   DIM idx AS LONG = 1
'   WHILE pwsz <> NULL
'      IF idx < dwCount THEN csa.PutElement(idx, CBSTR(*pwsz))
'      idx += 1
'      pwsz = strtok(NULL, @szDelimiter)
'   WEND
' -------------------------------------------------------------------
  ' // Dimension a safe array with dwCount elements
   DIM csa AS CSafeArray = CSafeArray(VT_BSTR, dwCount, 1)
   DIM s AS STRING, sLen AS LONG
   DIM idx AS LONG = 1
   DIM _pstr AS ANY PTR = pBuffer
   pstr = pBuffer
   DO
      pstr = strstr(pstr, szDelimiter)
      IF pstr = NULL THEN EXIT DO
      sLen = pstr - _pstr
      s = ""
      IF sLen > nLen THEN
         s = STRING(sLen, CHR(0))
         strncpy STRPTR(s), _pstr, sLen
      END IF
      IF idx <= dwCount THEN csa.PutElement(idx, CBSTR(s))
      idx += 1
      pstr += nLen
      _pstr = pstr
   LOOP
   DeAllocate(pBuffer)
   RETURN csa
END FUNCTION
' ========================================================================================

' ========================================================================================
' Reads all the lines of the specified file into a safe array.
' - wszFileName: Path of the file
' - szDelimiter: Delimiter of the line (CHR(13, 10) in Windows, CHR(10) in Linmux).
' ========================================================================================
PRIVATE FUNCTION AfxFileReadAllLinesW (BYREF wszFileName AS WSTRING, BYREF wszDelimiter AS WSTRING = CHR(13, 10)) AS CSafeArray
   DIM _csa AS CSafeArray = CSafeArray(VT_BSTR, 0, 1)
   DIM dwCount AS DWORD, dwFileSize AS DWORD, dwHighSize AS DWORD, dwBytesRead AS DWORD
   IF LEN(wszDelimiter) = 0 THEN RETURN _csa
   ' // Open the file
   DIM hFile AS HANDLE = CreateFileW(@wszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, _
                         OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL)
   IF hFile = INVALID_HANDLE_VALUE THEN RETURN _csa
   ' // Get the size of the file
   dwFileSize = GetFileSize(hFile, @dwHighSize)
   DIM pBuffer AS UBYTE PTR
   pBuffer = CAllocate(1, dwFileSize)
   IF pBuffer = NULL THEN RETURN _csa
   DIM bSuccess AS LONG = ReadFile(hFile, pBuffer, dwFileSize, @dwBytesRead, NULL)
   CloseHandle(hFile)
   IF bSuccess = FALSE THEN RETURN _csa
   ' // Get the number of lines
   DIM nLen AS LONG = LEN(wszDelimiter) * 2
   DIM pstr AS ANY PTR = pBuffer
   DO
      pstr = wcsstr(pstr, @wszDelimiter)
      IF pstr = NULL THEN EXIT DO
      pstr += nLen
      dwCount += 1
   LOOP
  ' // Dimension a safe array with dwCount elements
   DIM csa AS CSafeArray = CSafeArray(VT_BSTR, dwCount, 1)
   DIM cws AS CWSTR, sLen AS LONG
   DIM idx AS LONG = 1
   DIM _pstr AS ANY PTR = pBuffer
   pstr = pBuffer
   ' / Skip the BOM
   DIM s AS STRING = "  "
   strncpy STRPTR(s), _pstr, 2
   ' // Check for UTF-16 BOM (little endian)
   IF s = CHR(&hFF, &hFE) THEN
      _pstr += 2
   ELSE
      ' // Check for UTF-8 BOM
      s = "   "
      strncpy STRPTR(s), _pstr, 3
      IF s = CHR(&hEF, &hBB, &hBF) THEN _pstr += 3
   END IF
   ' // Parse the buffer
   DO
      pstr = wcsstr(pstr, @wszDelimiter)
      IF pstr = NULL THEN EXIT DO
      sLen = (pstr - _pstr) \ 2
      cws = ""
      IF sLen > nLen THEN
         cws = STRING(sLen, CHR(0))
         wcsncpy cws, _pstr, sLen
      END IF
      IF idx <= dwCount THEN csa.PutElement(idx, CBSTR(cws))
      idx += 1
      pstr += nLen
      _pstr = pstr
   LOOP
   DeAllocate(pBuffer)
   RETURN csa
END FUNCTION
' ========================================================================================


These functions are equivalent to the following PowerBasic code:


OPEN "datafile.dat" FOR INPUT AS #1
FILESCAN #1, RECORDS TO count&
DIM TheData(1 TO count&) AS STRING
LINE INPUT #1, TheData() TO count&
CLOSE #1


But also work with unicode files.

Paul Squires

These FileScan routines are an awesome addition to the framework.

BTW, you need to change the name of the library now.... it is so much more than CWindow that it seems to be a shame to call it that. :)

Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

José Roca

What about WinFBX (Windows FreeBasic eXtensions)? Makes a good couple with WinFBE.

Paul Squires

I think it's perfectly alright :)
You can also have WinLIB if you prefer that. I'll just rename the library that I'm making that works on top of yours.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

José Roca

I think that WinFBX is a bit more suited that WinLib because it is more descriptive, since it includes Win for Windows, FB for FreeBasic and X for extensions.

Paul Squires

Sounds good :)
Have you tried using GitHub to keep your code? I started using it for WinFBE and it is incredibly easy. Just download the GitHub Desktop client and it handles everything.  https://desktop.github.com
I never have to worry that I will lose my source code. It is always online and releasing packages is a breeze. Just a thought in case it interests you.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer