Oxygen Basic

Programming => Example Code => General => Topic started by: on October 09, 2018, 11:16:44 AM

Title: AfxWin - a start
Post by: on October 09, 2018, 11:16:44 AM
Testing the C-headers compatibility and, at the same time, writing some useful functions (at least for me) to retrieve Windows version information. Place the zipped files in the Afx subfolder of the Oxygen inc subfolder.

10 Oct 2018 - Added new functions.
Title: Re: AfxWin - a start
Post by: JRS on October 09, 2018, 11:20:47 AM
José Roca Rocks!

A new BASIC beginning.
Title: Re: AfxWin - a start
Post by: on October 09, 2018, 09:01:05 PM
Added new functions, some using a workaround because of a bug in MID.

New file uploaded in the first post.

Notice that I always use unicode because it is superfluous to write both ansi and unicode versions.
Title: Re: AfxWin - a start
Post by: JRS on October 09, 2018, 11:12:10 PM
You may be the first to give O2 a good unicode workover. Most of us are still ansi centric.
Title: Re: AfxWin - a start
Post by: José Roca on October 09, 2018, 11:52:49 PM
Too many ansi cooks spoil the broth. The only ansi only function that remain in Windows is GetProcAddress. All the other "A" functions are mere wrappers that convert the ansi strings to unicode and call the "W" functions. Therefore, when using the Windows API, using Unicode is more efficient. These "A" wrappers were written for compatibility reasons with existing code. Current applications must be unicode and DPI aware.




Title: Re: AfxWin - a start
Post by: JRS on October 09, 2018, 11:58:37 PM
That post deserves a Sticky.

I wonder how long the automatic conversion to Unicode has been in place. News to me.

I think Unicode and managed code (.Net) scared many Windows programmers away. It was my motivation to get into web programming.
Title: Re: AfxWin - a start
Post by: Aurel on October 10, 2018, 02:23:17 AM
Quote
Therefore, when using the Windows API, using Unicode is more efficient

 :o
how is that possible?
do you can explain this?
Title: Re: AfxWin - a start
Post by: JRS on October 10, 2018, 02:31:32 AM
Quote
Therefore, when using the Windows API, using Unicode is more efficient

 :o
how is that possible?
do you can explain this?

Please reread the post. Unicode is the default calling method. ANSI needs to be converted first before the call is made. Why it's faster.
Title: Re: AfxWin - a start
Post by: on October 10, 2018, 08:53:06 AM
There must have some functions with dual procedures, like some string manipulation functions in the shell, but the rule is to convert ansi parameters to unicode, call the unicode function, and convert strings back to ansi. For example:

Code: [Select]
/***********************************************************************
 *           GetShortPathNameA   (KERNEL32.@)
 */
DWORD WINAPI GetShortPathNameA( LPCSTR longpath, LPSTR shortpath, DWORD shortlen )
{
    WCHAR *longpathW;
    WCHAR shortpathW[MAX_PATH];
    DWORD ret;

    TRACE("%s\n", debugstr_a(longpath));

    if (!(longpathW = FILE_name_AtoW( longpath, FALSE ))) return 0;

    ret = GetShortPathNameW(longpathW, shortpathW, MAX_PATH);

    if (!ret) return 0;
    if (ret > MAX_PATH)
    {
        SetLastError(ERROR_FILENAME_EXCED_RANGE);
        return 0;
    }
    return copy_filename_WtoA( shortpathW, shortpath, shortlen );
}

And there are some recent procedures available only in unicode (they haven't bothered in writing an ansi wrapper).

> I wonder how long the automatic conversion to Unicode has been in place. News to me.

Since Windows NT.

See: https://msdn.microsoft.com/en-us/library/cc194797.aspx

Quote
Because the system is based on Unicode, Win32-based applications that use Unicode will run more efficiently on Windows NT and can process as many characters as the system can. This is especially true for programs localized for Far Eastern languages. Because the Windows NT system converts non-Unicode API parameters to Unicode at run time, not using Unicode adds a layer of overhead to some function calls and message processing. In addition, the system converts text returned from function calls to a local character set for non–Unicode-based applications, and information can be lost during the conversion because, like Windows 3.x, Windows NT supports only one local code page at a time. If the installed local code page is Latin 1 and the application calls GetLocaleInfoA to retrieve the Russian word for January, the system returns a string of question marks because there are no Cyrillic characters in the Latin 1 code page. A similar conversion process takes place for Windows messages and clipboard text.
Title: Re: AfxWin - a start
Post by: on October 10, 2018, 09:10:23 AM
This remembers me that many people use the integer functions of GDI+, instead of the float functions, thinking that they will be faster. But what it happens is that they are mere wrappers that call the float functions. Therefore, they are slightly slower because of the overhead.
Title: Re: AfxWin - a start
Post by: JRS on October 10, 2018, 11:40:18 AM
This reminds me of how blind Microsoft can make you with their legacy wrappers.
Title: Re: AfxWin - a start
Post by: José Roca on October 10, 2018, 11:58:26 AM
Even after knowing it, many people continues using ansi. It's like a superstititon.
Title: Re: AfxWin - a start
Post by: JRS on October 10, 2018, 12:23:21 PM
Even after knowing it, many people continues using ansi. It's like a superstititon.

There are people still promoting the Z80 8 bit BASIC languages even today.  :o
Title: Re: AfxWin - a start
Post by: JRS on October 10, 2018, 05:05:05 PM
José,

What are your thoughts about trying to use C header files as a default WinAPI?

I'm still assuming we would need your wrappers but creating them might not be so much work.
Title: Re: AfxWin - a start
Post by: on October 10, 2018, 06:18:05 PM
Well, Charles should enlighten us about what is supported and what is not, and the changes required.

I have made an small test and it works:

Code: [Select]
typedef sys HWND
typedef char* LPCSTR
typedef wchar* LPCWSTR
typedef dword uint

extern lib "user32.dll"
int MessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
int MessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType);
end extern

MessageBoxW 0, "Hello World", "declare", 0

We will have to write a base include file, that all the other header files will have to include directly or indirectly, with typedefs for all the Windows Data Types, e.g.

Code: [Select]
typedef sys HWND
typedef char* LPCSTR
typedef wchar* LPCWSTR
typedef dword uint

Windows Data Types: https://docs.microsoft.com/en-us/windows/desktop/winprog/windows-data-types

If a C data type is not defined, O2 does not report an error. What it does? It tries to guess it?
Title: Re: AfxWin - a start
Post by: on October 10, 2018, 08:05:35 PM
WTypes.inc

Defines and typedefs to help in the C headers adaptation to O2.

Code: [Select]
' The calling convention for system functions.
#ifndef mode64bit
   #define WINAPI stdcall
#else
   #define WINAPI ms64
#endif
#define APIENTRY WINAPI

' An atom.
typedef word ATOM;

' A Boolean variable (should be TRUE or FALSE).
typedef int BOOL;
typedef byte BOOLEAN;

' A byte (8 bits).
typedef unsigned char BYTE;

' The calling convention for callback functions.
#ifndef mode64bit
   #define CALLBACK stdcall
#else
   #define CALLBACK ms64
#endif

' An 8-bit Windows (ANSI) character.
typedef char CHAR;

' An 8-bit Windows (ANSI) character.
typedef char CCHAR;

' The red, green, blue (RGB) color value (32 bits). See COLORREF for information on this type.
' This type is declared in WinDef.h as follows:
typedef dword COLORREF;

' A variable whose value is to remain constant during execution.
#define CONST const

' A 32-bit unsigned integer. The range is 0 through 4294967295 decimal.
typedef unsigned long DWORD;

' A 64-bit unsigned integer. The range is 0 through 18446744073709551615 decimal.
'typedef unsigned __int64 DWORDLONG;
typedef quad DWORDLONG;

' A 32-bit unsigned integer.
typedef dword DWORD32;

' A 64-bit unsigned integer.
'typedef unsigned __int64 DWORD64;
typedef quad DWORD64;

' A floating-point variable.
typedef float FLOAT;

' A handle to an accelerator table.
typedef sys HACCEL;

' Half the size of a pointer. Use within a structure that contains a pointer and two small fields.
'#ifdef _WIN64
' typedef int HALF_PTR;
'#else
' typedef short HALF_PTR;
'#endif
#ifndef mode64bit
   typedef word HALF_PTR;
#else
   typedef int HALF_PTR;
#endif

' A handle to an object.
'typedef PVOID HANDLE;
typedef sys HANDLE;

' A handle to a bitmap.
'typedef HANDLE HBITMAP;
typedef HANDLE HBITMAP;

' A handle to a brush.
'typedef HANDLE HBRUSH;
typedef HANDLE HBRUSH;

' A handle to a color space.
typedef HANDLE HCOLORSPACE;

' A handle to a dynamic data exchange (DDE) conversation.
typedef HANDLE HCONV;

' A handle to a DDE conversation list.
typedef HANDLE HCONVLIST;

' A handle to a cursor.
'typedef HICON HCURSOR;
typedef HANDLE HCURSOR;

' A handle to a device context (DC).
typedef HANDLE HDC;

' A handle to DDE data.
typedef HANDLE HDDEDATA;

' A handle to a desktop.
typedef HANDLE HDESK;

' A handle to an internal drop structure.
typedef HANDLE HDROP;

' A handle to a deferred window position structure.
typedef HANDLE HDWP;

' A handle to an enhanced metafile.
typedef HANDLE HENHMETAFILE;

' A handle to a file opened by OpenFile, not CreateFile.
typedef int HFILE;

' A handle to a font.
typedef HANDLE HFONT;

' A handle to a GDI object.
typedef HANDLE HGDIOBJ;

' A handle to a global memory block.
typedef HANDLE HGLOBAL;

' A handle to a hook.
typedef HANDLE HHOOK;

' A handle to an icon.
typedef HANDLE HICON;

' A handle to an instance. This is the base address of the module in memory.
' HMODULE and HINSTANCE are the same today, but represented different things in 16-bit Windows.
typedef HANDLE HINSTANCE;

' A handle to a registry key.
typedef HANDLE HKEY;

' An input locale identifier.
typedef HANDLE HKL;

' A handle to a local memory block.
typedef HANDLE HLOCAL;

' A handle to a menu.
typedef HANDLE HMENU;

' A handle to a metafile.
typedef HANDLE HMETAFILE;

' A handle to a module. The is the base address of the module in memory.
' HMODULE and HINSTANCE are the same in current versions of Windows, but represented different things in 16-bit Windows.
'typedef HINSTANCE HMODULE;
typedef HANDLE HMODULE;

' A handle to a display monitor.
' if(WINVER >= 0x0500) typedef HANDLE HMONITOR;
typedef HANDLE HMONITOR;

' A handle to a palette.
typedef HANDLE HPALETTE;

' A handle to a pen.
typedef HANDLE HPEN;

' The return codes used by COM interfaces. To test an HRESULT value, use the FAILED and SUCCEEDED macros.
typedef long HRESULT;

' A handle to a region.
typedef HANDLE HRGN;

' A handle to a resource.
typedef HANDLE HRSRC;

' A handle to a DDE string.
typedef HANDLE HSZ;

' A handle to a window station.
typedef HANDLE WINSTA;

' A handle to a window.
typedef HANDLE HWND;

' A 32-bit signed integer. The range is -2147483648 through 2147483647 decimal.
typedef int INT;

' A signed integer type for pointer precision.
' Use when casting a pointer to an integer to perform pointer arithmetic.
'#if defined(_WIN64)
' typedef __int64 INT_PTR;
'#else
' typedef int INT_PTR;
'#endif
#ifndef mode64bit
   typedef int INT_PTR;
#else
   typedef quad INT_PTR;
#endif

' An 8-bit signed integer.
'typedef signed char INT8;
typedef sbyte INT8;

' A 16-bit signed integer.
typedef signed short INT16;

' A 32-bit signed integer. The range is -2147483648 through 2147483647 decimal.
typedef signed int INT32;

' A 64-bit signed integer. The range is 9223372036854775808 through 9223372036854775807 decimal.
'typedef signed __int64 INT64;
typedef quad INT64;

' A language identifier.
typedef word LANGID;

' A locale identifier. For more information, see Locale Identifiers.
typedef dword LCID;

' A locale information type.
typedef dword LCTYPE;

' A language group identifier.
typedef dword LGRPID;

' A 32-bit signed integer. The range is 2147483648 through 2147483647 decimal.
typedef long LONG;

' A 64-bit signed integer. The range is 9223372036854775808 through 9223372036854775807 decimal.
'typedef __int64 LONGLONG;
typedef quad LONGLONG;

' A signed long type for pointer precision.
' Use when casting a pointer to a long to perform pointer arithmetic.
'#if defined(_WIN64)
' typedef __int64 LONG_PTR;
'#else
' typedef long LONG_PTR;
'#endif
#ifndef mode64bit
   typedef long LONG_PTR;
#else
   typedef quad LONG_PTR;
#endif

' A 32-bit signed integer. The range is 2147483648 through 2147483647 decimal.
typedef signed int LONG32;

' A 64-bit signed integer. The range is 9223372036854775808 through 9223372036854775807 decimal.
'typedef __int64 LONG64;
typedef quad LONG64;

' A message parameter.
typedef LONG_PTR LPARAM;

' A pointer to a BOOL.
typedef bool *LPBOOL;

' A pointer to a BYTE.
typedef byte *LPBYTE;

' A pointer to a COLORREF value.
typedef dword *LPCOLORREF;

' A pointer to a constant null-terminated string of 8-bit Windows (ANSI) characters.
'typedef __nullterminated CONST CHAR *LPCSTR;
'typedef __nullterminated CONST CHAR *LPCSTR;
typedef char *LPCSTR;

' A pointer to a constant null-terminated string of 16-bit Unicode characters.
'typedef CONST WCHAR *LPCWSTR;
typedef wchar *LPCWSTR;

' An LPCWSTR if UNICODE is defined, an LPCSTR otherwise.
'#ifdef UNICODE
' typedef LPCWSTR LPCTSTR;
'#else
' typedef LPCSTR LPCTSTR;
'#endif
#ifdef UNICODE
 typedef LPCWSTR LPCTSTR;
#else
 typedef LPCSTR LPCTSTR;
#endif

' A pointer to a constant of any type.
' typedef CONST void *LPCVOID;
typedef void *LPCVOID;

' A pointer to a DWORD.
typedef dword *LPDWORD;

' A pointer to a HANDLE.
typedef HANDLE *LPHANDLE;

' A pointer to an INT.
typedef int *LPINT;

' A pointer to a LONG.
typedef long *LPLONG;

' A pointer to a null-terminated string of 8-bit Windows (ANSI) characters.
typedef char *LPSTR;

' A pointer to a null-terminated string of 16-bit Unicode characters.
typedef wchar *LPWSTR;

' An LPWSTR if UNICODE is defined, an LPSTR otherwise.
#ifdef UNICODE
 typedef LPWSTR LPTSTR;
#else
 typedef LPSTR LPTSTR;
#endif

' A pointer to any type.
typedef void *LPVOID;

' A pointer to a WORD.
typedef word *LPWORD;

' Signed result of message processing.
typedef LONG_PTR LRESULT;

' A pointer to a BOOL.
typedef bool *PBOOL;

' A pointer to a BOOLEAN.
typedef boolean *PBOOLEAN;

' A pointer to a BYTE.
typedef byte *PBYTE;

' A pointer to a CHAR.
typedef char *PCHAR;

' A pointer to a constant null-terminated string of 8-bit Windows (ANSI) characters.
'typedef CONST CHAR *PCSTR;
typedef char *PCSTR;

' A PCWSTR if UNICODE is defined, a PCSTR otherwise.
#ifdef UNICODE
 typedef LPCWSTR PCTSTR;
#else
 typedef LPCSTR PCTSTR;
#endif

' A pointer to a constant null-terminated string of 16-bit Unicode characters.
'typedef CONST WCHAR *PCWSTR;
typedef wchar *PCWSTR;

' A pointer to a DWORD.
typedef dword *PDWORD;

' A pointer to a DWORDLONG.
typedef DWORDLONG *PDWORDLONG;

' A pointer to a DWORD32.
typedef DWORD32 *PDWORD32;

' A pointer to a DWORD64.
typedef DWORD64 *PDWORD64;

' A pointer to a FLOAT.
typedef float *PFLOAT;

' A pointer to a HALF_PTR.
typedef HALF_PTR *PHALF_PTR;

' A pointer to a HANDLE.
typedef HANDLE *PHANDLE;

' A pointer to an HKEY.
typedef HKEY *PHKEY;

' A pointer to an INT.
typedef int *PINT;

' A pointer to an INT_PTR.
typedef INT_PTR *PINT_PTR;

' A pointer to an INT8.
typedef INT8 *PINT8;

' A pointer to an INT16.
typedef INT16 *PINT16;

' A pointer to an INT32.
typedef INT32 *PINT32;

' A pointer to an INT64.
typedef INT64 *PINT64;

' A pointer to an LCID.
typedef PDWORD PLCID;

' A pointer to a LONG.
typedef LONG *PLONG;

' A pointer to a LONGLONG.
typedef LONGLONG *PLONGLONG;

' A pointer to a LONG_PTR.
typedef LONG_PTR *PLONG_PTR;

' A pointer to a LONG32.
typedef LONG32 *PLONG32;

' A pointer to a LONG64.
typedef LONG64 *PLONG64;

' A 32-bit pointer. On a 32-bit system, this is a native pointer.
' On a 64-bit system, this is a truncated 64-bit pointer.
'#if defined(_WIN64)
'#define POINTER_32 __ptr32
'#else
'#define POINTER_32
'#endif
' A 64-bit pointer. On a 64-bit system, this is a native pointer.
' On a 32-bit system, this is a sign-extended 32-bit pointer.
' Note that it is not safe to assume the state of the high pointer bit.
'#if (_MSC_VER >= 1300)
'#define POINTER_64 __ptr64
'#else
'#define POINTER_64
'#endif
' A signed pointer.
'#define POINTER_SIGNED __sptr
' An unsigned pointer.
'#define POINTER_UNSIGNED __uptr

' A pointer to a SHORT.
typedef short *PSHORT;

' A pointer to a null-terminated string of 8-bit Windows (ANSI) characters.
typedef char *PSTR;

' A PWSTR if UNICODE is defined, a PSTR otherwise.
#ifdef UNICODE
 typedef LPWSTR PTSTR;
#else
 typedef LPSTR PTSTR;
#endif

' A pointer to a UINT.
typedef uint *PUINT;

' A pointer to any type.
typedef void *PVOID;

' A pointer to a WCHAR.
typedef wchar *PWCHAR;

' A pointer to a WORD.
typedef word *PWORD;

' A pointer to a null-terminated string of 16-bit Unicode characters.
typedef wchar *PWSTR;

' A 64-bit unsigned integer.
'typedef unsigned __int64 QWORD;
typedef quad QWORD;

' A handle to a service control manager database.
typedef HANDLE SC_HANDLE;

' A lock to a service control manager database.
typedef LPVOID SC_LOCK;

' A handle to a service status value.
typedef HANDLE SERVICE_STATUS_HANDLE;

' A 16-bit integer. The range is 32768 through 32767 decimal.
typedef short SHORT;

' A WCHAR if UNICODE is defined, a CHAR otherwise.
#ifdef UNICODE
 typedef wchar TBYTE;
#else
 typedef unsigned char TBYTE;
#endif

' A pointer to a TBYTE.
' This type is declared in WinNT.h as follows:
typedef TBYTE *PTBYTE;

' A WCHAR if UNICODE is defined, a CHAR otherwise.
#ifdef UNICODE
 typedef wchar TCHAR;
#else
 typedef char TCHAR;
#endif

' A pointer to a TCHAR.
' This type is declared in WinNT.h as follows:
typedef TCHAR *PTCHAR;

' An unsigned CHAR.
typedef unsigned char UCHAR;

' A pointer to a UCHAR.
typedef UCHAR *PUCHAR;

' An unsigned HALF_PTR. Use within a structure that contains a pointer and two small fields.
'#ifdef _WIN64
' typedef unsigned int UHALF_PTR;
'#else
' typedef unsigned short UHALF_PTR;
'#endif
#ifndef mode64bit
 typedef unsigned short UHALF_PTR;
#else
 typedef unsigned int UHALF_PTR;
#endif

' A pointer to a UHALF_PTR.
typedef UHALF_PTR *PUHALF_PTR;

' An unsigned INT. The range is 0 through 4294967295 decimal.
typedef unsigned int UINT;

' An unsigned INT_PTR.
'#if defined(_WIN64)
' typedef unsigned __int64 UINT_PTR;
'#else
' typedef unsigned int UINT_PTR;
'#endif
#ifndef mode64bit
 typedef unsigned int UINT_PTR;
#else
 typedef quad UINT_PTR;
#endif

' A pointer to a UINT_PTR.
typedef UINT_PTR *PUINT_PTR;

' An unsigned INT8.
typedef unsigned char UINT8;

' A pointer to a UINT8.
typedef UINT8 *PUINT8;

' An unsigned INT16.
typedef unsigned short UINT16;

' A pointer to a UINT16.
typedef UINT16 *PUINT16;

' An unsigned INT32. The range is 0 through 4294967295 decimal.
typedef unsigned int UINT32;

' A pointer to a UINT32.
typedef UINT32 *PUINT32;

' An unsigned INT64. The range is 0 through 18446744073709551615 decimal.
'typedef usigned __int 64 UINT64;
typedef quad UINT64;

' A pointer to a UINT64.
typedef UINT64 *PUINT64;

' An unsigned LONG. The range is 0 through 4294967295 decimal.
'typedef unsigned long ULONG;

' A pointer to a ULONG.
typedef ulong *PULONG;

' A 64-bit unsigned integer. The range is 0 through 18446744073709551615 decimal.
typedef quad ULONGLONG;

' A pointer to a ULONGLONG.
typedef ULONGLONG *PULONGLONG;

' An unsigned LONG_PTR.
#ifndef mode64bit
 typedef unsigned long ULONG_PTR
#else
 typedef quad ULONG_PTR;
#endif

' A pointer to a ULONG_PTR.
typedef ULONG_PTR *PULONG_PTR;

' An unsigned long type for pointer precision.
' Use when casting a pointer to a long type to perform pointer arithmetic.
' (Also commonly used for general 32-bit parameters that have been extended to 64 bits in 64-bit Windows.)
'typedef ULONG_PTR DWORD_PTR;
typedef ULONG_PTR DWORD_PTR;

' A pointer to a DWORD_PTR.
typedef DWORD_PTR *PDWORD_PTR;

' The maximum number of bytes to which a pointer can point.
typedef ULONG_PTR SIZE_T;

' A signed version of SIZE_T.
typedef LONG_PTR SSIZE_T;

' A pointer to a SIZE_T.
typedef SIZE_T *PSIZE_T;

' A pointer to a SSIZE_T.
typedef SSIZE_T *PSSIZE_T;

' An unsigned LONG32. The range is 0 through 4294967295 decimal.
typedef unsigned int ULONG32;

' A pointer to a ULONG32.
typedef ULONG32 *PULONG32;

' An unsigned LONG64. The range is 0 through 18446744073709551615 decimal.
'typedef unsigned __int64 ULONG64;
typedef quad ULONG64;

' A pointer to a ULONG64.
typedef ULONG64 *PULONG64;

' An unsigned SHORT. The range is 0 through 65535 decimal.
typedef unsigned short USHORT;

' A pointer to a USHORT.
typedef USHORT *PUSHORT;

' A Unicode string.
typedef struct _UNICODE_STRING {
  USHORT  Length;
  USHORT  MaximumLength;
  PWSTR  Buffer;
} UNICODE_STRING;
typedef UNICODE_STRING *PUNICODE_STRING;
'typedef const UNICODE_STRING *PCUNICODE_STRING;

' An update sequence number (USN).
typedef LONGLONG USN;

' Any type.
#define VOID void

' A 16-bit Unicode character. For more information, see Character Sets Used By Fonts.
'typedef wchar_t WCHAR;

' A 16-bit unsigned integer. The range is 0 through 65535 decimal.
typedef unsigned short WORD;

' A message parameter.
typedef UINT_PTR WPARAM;
Title: Re: AfxWin - a start
Post by: on October 10, 2018, 08:10:30 PM
Including WTypes.inc, we can use the C declares with O2 without having to change some data types.

Code: [Select]
uses Afx\wTypes

extern lib "user32.dll"
int MessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
int MessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType);
end extern

MessageBoxW 0, "Hello World", "declare", 0

I don't like the alternative syntax

Code: [Select]
! MessageBoxA

because it does not do automatic conversions of strings and literals and there is not parameter checking.
Title: Re: AfxWin - a start
Post by: JRS on October 10, 2018, 08:55:23 PM
That's great news and hopefully a time saver getting reliable include files going with O2.
Title: Re: AfxWin - a start
Post by: on October 10, 2018, 09:22:38 PM
One thing that I don't like at all is that if you use a wrong data type, e.g.

int MessageBoxW(HWND hWnd, xLPCWSTR lpText, LPCWSTR lpCaption, UINT uType);

it compiles, although, of course, doesn't work correctly.

One thing is the strict checking of some languages and another not checking at all. This can cause many hard to find bugs. It should display a message saying that xLPCWSTR is an unknown data type.

How are we going to have realiable include files if mistakes such as the above one aren't caught or ignored?

Title: Re: AfxWin - a start
Post by: Aurel on October 10, 2018, 10:30:41 PM
Quote
it compiles, although, of course, doesn't work correctly.

yeah that is the FUN part...  :D
just try to include SendMessage in C style...
Title: Re: AfxWin - a start
Post by: Arnold on October 10, 2018, 11:08:59 PM
There is /inc/C.inc which will make the code more compatible to the C-language. On the other hand I think that this will restrict the flexibility of Oxygenbasic a bit.

Regarding C-Headers: probably it is possible to use them, but probably not without modifications, which is also necessary with Freebasic, Powerbasic and probably Scriptbasic. Otherwise it would only be another C-compiler like Tiny CC. And I suppose if not thought out carefully, it will restrict the benefits of using Oxygen as a JIT compiler.
Title: Re: AfxWin - a start
Post by: on October 11, 2018, 12:24:32 AM
> There is /inc/C.inc which will make the code more compatible to the C-language.

The purpose of all these typedefs is to use the C declares without having to translate them. I don't need options like #case sensitive, although I have tried the include file with this option to make sure that there are no conflicts if somebody uses it.

I'm not talking of using C .h files, but to make simple to adapt them for use with O2 just keeping the declares, structure, equates... without changes (although we need to wrap the declares between extern/end extern) and discarding what it isn't useful. The typedefs simply create aliases, so when HANDLE, HWND, etc., are found, the compiler will replace it with sys (same with other data types).
Title: Re: AfxWin - a start
Post by: José Roca on October 11, 2018, 01:24:40 AM
> just try to include SendMessage in C style...

No problem using WTypes.inc.

Code: [Select]
extern lib "user32.dll"
LRESULT SendMessageA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
LRESULT SendMessageW(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
end extern
Title: Re: AfxWin - a start
Post by: Arnold on October 11, 2018, 02:12:32 AM
Quote from reply 18:

> int MessageBoxW(HWND hWnd, xLPCWSTR lpText, LPCWSTR lpCaption, UINT uType);

I assume Oxygen tries to read an ansi string. But indeed there should be an error message. I thought this would be the case since 'autodim off' is applied.

I tried:
MessageBoxW 0, "Hello World",  "declare", 0, oops

and now I will get an error message
Title: Re: AfxWin - a start
Post by: Aurel on October 11, 2018, 03:36:05 AM
Jose
maybe i say it on wrong way
there is no problem to add into awinh.inc include file but i have
so damn problems when i tried to execute SendMessage
problems are with types no mather what i do when i try to execute this api i get error
so i give up and use bind just only for this api function and one of more important  ::)
Title: Re: AfxWin - a start
Post by: Aurel on October 11, 2018, 03:51:14 AM
Jose
From your experience which type should be
wParam and lParam ?

from MSDN forum it looks like this:

typedef UINT_PTR WPARAM;  - unsigned integer pointer ..right?
typedef LONG_PTR LPARAM; - long pointer ?
Title: Re: AfxWin - a start
Post by: on October 11, 2018, 04:17:01 AM
Despite the misleading "_PTR" part in their names, they are no pointers.

An UINT_PTR is a DWORD in 32-bit and an unsigned QUAD in 64-bit, but as O2 does not natively support unsigned QUADs, we will have to use QUAD (signed).

A LONG_PTR is a LONG in 32-bit and a QUAD in 64-bit.

In the C headers they are defined as

Code: [Select]
#if defined(_WIN64)
  typedef __int64 LONG_PTR;
#else
  typedef long LONG_PTR;
#endif

#if defined(_WIN64)
  typedef unsigned __int64 UINT_PTR;
#else
  typedef unsigned int UINT_PTR;
#endif

If you're treating them as pointers then I'm not surprised that you are having problems.

BTW I have made an small change in WTypes.inc and reuploaded the file.

Using it and the following declares

Code: [Select]
uses Afx\wTypes

extern lib "user32.dll"
LRESULT SendMessageA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
LRESULT SendMessageW(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
end extern

I don't have any problems in using SendMessage, e.g.

Code: [Select]
dim s as string = "Test string"
SendMessageA hEdit, WM_SETTEXT, 0, strptr(s)

in both 32 and 64-bit.
Title: Re: AfxWin - a start
Post by: Aurel on October 11, 2018, 04:49:43 AM
So as you say  in 32bit
wParam should be DWORD
lParam should be   LONG  - somewhere is stated as ANY ?

Directly there is no problem but when is function declared in include then
problems jumps out ...
so that is why I say that i am forced to use bind in my own awinh.inc
Title: Re: AfxWin - a start
Post by: Aurel on October 11, 2018, 04:55:41 AM
so
wParam dword
lParam long ...somewhere stated that should be ANY

so i must use bind in my awinh.inc what really sucks:

bind user32
(
SendMessage SendMessageA
)

and this not work (in 32bit)

!SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hWnd As INT, ByVal dwMsg As INT, ByVal wParam As INT, lParam As Long) As INT

in older version work

Title: Re: AfxWin - a start
Post by: José Roca on October 11, 2018, 05:04:35 AM
You're missing a ByVal in your declaration:

!SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hWnd As INT, ByVal dwMsg As INT, ByVal wParam As INT, ByVal lParam As Long) As INT
Title: Re: AfxWin - a start
Post by: Arnold on October 11, 2018, 05:45:31 AM
Regarding WTypes.inc (Reply 15): Many of these constants are of type sys in Oxygenbasic, which is a 32-bit value in Win32 and a 64-bit value in Win64. Maybe it is possible to add some of these typedefs directly into Oxygen? I assume Charles has already managed somehow to do this with some structs. I often use: MSG msg in my message loop and I am surprised that this works.
Title: Re: AfxWin - a start
Post by: Aurel on October 11, 2018, 10:29:39 AM
Yes i see
but no mather with or without byVal still not work
I tried all possible combination and nothing.
I almost give up because of this from o2
Title: Re: AfxWin - a start
Post by: Aurel on October 11, 2018, 10:33:46 AM
Quote
MSG msg in my message loop and I am surprised that this works.
Yeah ..that's true and some things are not documented and some are not explained
i even look into source code to try to find what might be wrong and i found some strange
declaration so I sespect there are inbuilt into o2 and cose similar troubles.
Title: Re: AfxWin - a start
Post by: JRS on October 11, 2018, 12:03:50 PM
José is on the right path using C headers as a base. We should support those efforts for maintainable includes.
Title: Re: AfxWin - a start
Post by: on October 11, 2018, 01:36:30 PM
Yes i see
but no mather with or without byVal still not work
I tried all possible combination and nothing.
I almost give up because of this from o2

If it doesn't work for you it must be that you have a wrong declare, or that you aren't passing the parameters correctly, or both.
Title: Re: AfxWin - a start
Post by: on October 11, 2018, 01:45:17 PM
Using the typedefs means that you can use the C declare directly in the source code

Code: [Select]
int MessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);

and what the compiler sees is

Code: [Select]
int MessageBoxA(sys hWnd, char* lpText, char* lpCaption, uint uType)

The advantage is that you don't need to change anything, so much less work and no mistakes. I wish I could have been able to do it this way when I translated the headers to Power Basic.

> Maybe it is possible to add some of these typedefs directly into Oxygen?

It is up to Charles to consider if its worthwile to add these aliases to the language or not.
Title: Re: AfxWin - a start
Post by: JRS on October 11, 2018, 02:16:39 PM
Quote
The advantage is that you don't need to change anything, so much less work and no mistakes. I wish I could have been able to do it this way when I translated the headers to Power Basic.

Your docs and this direction with includes compensates for all the pain we inflicted on each other chasing the light.
Title: Re: AfxWin - a start
Post by: Arnold on October 11, 2018, 11:56:36 PM
I am not against the idea of using typedef. During my experiments to port BCX code to Oxygenbasic I tried this myself (and gave up due to my lack of experience). I just want to point out if it is possible to avoid naming conflicts like HWND hwnd, HFONT hfont etc. Charles uses typedefs with OpenGl too. To overcome some difficulties in one of the NeheTutorials (NeheTut08.o2bas) I had to use #case capital, typedef sys SYS, typedef char CHAR to run the app. If it is possible to avoid misinterpretations, then helper files like WTypes.inc would be of an invaluable help.
Title: Re: AfxWin - a start
Post by: on October 12, 2018, 12:29:09 AM
With typedefs there are not name conflicts. As I said, using WTpes.inc,

Code: [Select]
int MessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);

becomes

Code: [Select]
int MessageBoxA(sys hWnd, char* lpText, char* lpCaption, uint uType)

You would have conflicts if you will use #define or macros, because then it will become

Code: [Select]
int MessageBoxA(sys sys, char* lpText, char* lpCaption, uint uType)

Like #define and macros, typedefs do text substitution, but only if it is a data type, not the name of a variable.

Its usefulness is that you don't need to translate/adapt the C declares, structures, etc., but you can copy and paste them and the typedefs will do the substitution. If Charles implements them in the compiler, it would be a welcome addition to the O2 support for C headers.

Title: Re: AfxWin - a start
Post by: JRS on October 12, 2018, 08:46:36 AM
I would love to see Charles finish his C header feature filling in the holes so you can get your wrappers created.
Title: Re: AfxWin - a start
Post by: JRS on October 12, 2018, 02:34:21 PM
José,

Are you saying you can live with your WTypes.inc as a crutch until O2 becomes more C header file friendly?

I think the C header feature O2 offers makes it much more attractive than FB or PB compilers.
Title: Re: AfxWin - a start
Post by: José Roca on October 12, 2018, 03:05:57 PM
> Are you saying you can live with your WTypes.inc as a crutch until O2 becomes more C header file friendly?

Of course.

> I think the C header feature O2 offers makes it much more attractive than FB or PB compilers.

It makes much easier to adapt the C headers, but parameter checking must be improved.
Title: Re: AfxWin - a start
Post by: JRS on October 12, 2018, 03:22:51 PM
It is very self motivating to watch you work.  You define commitment. We need more folks like Charles, you, Roland and Mike driving this project home.
Title: Re: AfxWin - a start
Post by: JRS on October 12, 2018, 04:05:59 PM
Quote
It makes much easier to adapt the C headers, but parameter checking must be improved.

Can you explain that to me in more detail?
Title: Re: AfxWin - a start
Post by: José Roca on October 12, 2018, 04:11:55 PM
I think that I already have made it clear:

See:
https://www.oxygenbasic.org/forum/index.php?topic=1778.msg19367#msg19367
Title: Re: AfxWin - a start
Post by: JRS on October 12, 2018, 04:40:06 PM
Thanks for the refresher course.  :)
Title: Re: AfxWin - a start
Post by: JRS on October 12, 2018, 05:52:11 PM
I've always wondered what should come next, documentation or error checking?

The resent most online numbers for the O2 forum remind me of good old days on the PowerBASIC forum. I think José's effort can account for most of the increased activity.
Title: Re: AfxWin - a start
Post by: Charles Pegge on October 13, 2018, 01:06:32 AM
I've fixed error trapping for undefined type parameters in C style headers.

Also L"..." string literals and UTF-8/UTF-16 source code are now supported :). Quite complex.
Title: Re: AfxWin - a start
Post by: José Roca on October 13, 2018, 01:39:15 AM
These are great news.

Regarding COM, writing prototyped headers for the whole COM subsystem would be too much work and very difficult because they are very interwitned. For example the IDispatch interface references the VARIANT data type, and the VARIANT data type references the IDispatch interface.

Is there a way in O2 to solve it?
Title: Re: AfxWin - a start
Post by: Charles Pegge on October 13, 2018, 02:45:54 AM
If they are only references, there is no problem with recursive definitions.

And you can use a dummy type to break circularity.

Code: [Select]
type yy{} 'dummy type

type xx
  yy*a
end type

type yy
  xx*b
end type


This solves the definitions problem. Gaining access to recursive members has to be done indirectly though.