C/C++ to FreeBASIC

Started by Bernard Kunzy, February 12, 2025, 02:37:47 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Bernard Kunzy

Hello José

I wanted to convert this plain C/C++ SDK code from Patrice Terrier to FreeBASIC for comparison purpose.

//+--------------------------------------------------------------------------+
//|                                                                          |
//|                                 MINI                                     |
//|                                                                          |
//|               Example to create very small binary window                 |
//|                    using only the core SDK flat API                      |
//|             and the Tiny C Runtime library from Matt Pietrek.            |
//|                                                                          |
//+--------------------------------------------------------------------------+
//|                                                                          |
//|                         Author Patrice TERRIER                           |
//|                            www.objreader.com                             |
//|                           objreader@gmail.com                            |
//|                                                                          |
//+--------------------------------------------------------------------------+
//|                  Project started on : 01-04-2001 (MM-DD-YYYY)            |
//|                        Last revised : 07-04-2024 (MM-DD-YYYY)            |
//+--------------------------------------------------------------------------+

#include <windows.h>

constexpr auto CLIENT_WIDTH   = 640;
constexpr auto CLIENT_HEIGHT  = 480;

struct PROP {
    HWND        hMain;
    long        minTrackSizeW;
    long        minTrackSizeH;
};

static PROP gP;

static long rWidth(IN RECT &r) {
    return r.right - r.left;
}

static long rHeight(IN RECT &r) {
    return r.bottom - r.top;
}

static LRESULT CALLBACK WndProc(IN HWND hWnd, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam) {
    LRESULT nRet = -1;
    MINMAXINFO* pMM;
    switch (uMsg) {
    case WM_CREATE:
        break;

    case WM_GETMINMAXINFO:
        pMM = (MINMAXINFO*)lParam;
        pMM->ptMinTrackSize.x = gP.minTrackSizeW;
        pMM->ptMinTrackSize.y = gP.minTrackSizeH;
        break;

    case WM_SIZE:
        InvalidateRect(hWnd, NULL, TRUE);
        nRet = 0;
        break;

    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hDC = BeginPaint(hWnd, &ps);
            // Paint the window content here
            EndPaint(hWnd, &ps);
            nRet = 0;
        }
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        nRet = 0;
        break;
    }

    if (nRet == -1) nRet = DefWindowProc(hWnd, uMsg, wParam, lParam);
    return nRet;
}

int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) {
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    int nRet = 0;
    WCHAR szClass[] = L"MINI";

    // Detect process without using a Mutex
    HWND hFound = FindWindow(szClass, NULL);
    if (hFound) {
        if (IsIconic(hFound)) { ShowWindow(hFound, SW_RESTORE); }
        SetForegroundWindow(hFound);
        return nRet;
    }

    WNDCLASSEX wcx = { 0 };
    wcx.cbSize = sizeof(wcx);
    long IsInitialized = GetClassInfoEx(hInstance, szClass, &wcx);
    if (!IsInitialized) {
        wcx.style         = CS_HREDRAW | CS_VREDRAW;
        wcx.lpfnWndProc   = WndProc;
        wcx.cbClsExtra    = 0;
        wcx.cbWndExtra    = 0;
        wcx.hInstance     = hInstance;
        wcx.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
        wcx.hCursor       = LoadCursor(NULL, IDC_ARROW);
        wcx.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;
        wcx.lpszMenuName  = 0;
        wcx.lpszClassName = szClass;
        wcx.hIconSm       = wcx.hIcon;
        if (RegisterClassEx(&wcx)) { IsInitialized = -1; }
    }

    if (IsInitialized) {
        DWORD dwExStyle = 0;
        DWORD dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
        RECT lpr = { 0 }; SetRect(&lpr, 0, 0, CLIENT_WIDTH, CLIENT_HEIGHT);
        AdjustWindowRectEx(&lpr, dwStyle, FALSE, dwExStyle);
        gP.minTrackSizeW = rWidth(lpr);
        gP.minTrackSizeH = rHeight(lpr);
        long x = max((GetSystemMetrics(SM_CXSCREEN) - gP.minTrackSizeW) / 2, 0);
        long y = max((GetSystemMetrics(SM_CYSCREEN) - gP.minTrackSizeH) / 2, 0);

        gP.hMain = CreateWindowEx(dwExStyle, szClass, szClass, dwStyle, x, y, gP.minTrackSizeW, gP.minTrackSizeH, 0, 0, hInstance, NULL);
        if (gP.hMain) {

            ShowWindow(gP.hMain, nCmdShow);
            SetForegroundWindow(gP.hMain); // Slightly Higher Priority

            MSG msg = { 0 };
            while (GetMessage(&msg, NULL, 0, 0)) {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
            nRet = (int) msg.wParam;
        }
        UnregisterClass(wcx.lpszClassName, hInstance);
    }
    return nRet;
}

The resulting C/C++ binary size is only 6 Kb, while the FreeBASIC version is 28160 Kb, but the binary doesn't work.

Here is the fbc64 code I am using (translated by ChatGPT)

#Include "windows.bi"

Const CLIENT_WIDTH  = 640
Const CLIENT_HEIGHT = 480

Type PROP
    hMain As HWND
    minTrackSizeW As Long
    minTrackSizeH As Long
End Type

Dim Shared gP As PROP

Function rWidth(ByRef r As RECT) As Long
    Return r.right - r.left
End Function

Function rHeight(ByRef r As RECT) As Long
    Return r.bottom - r.top
End Function

Function WndProc(ByVal hWnd As HWND, ByVal uMsg As UINT, ByVal wParam As WPARAM, ByVal lParam As LPARAM) As LRESULT
    Dim nRet As LRESULT = -1
    Dim pMM As MINMAXINFO Ptr
   
    Select Case uMsg
    Case WM_CREATE
        ' Initialization can go here if needed.

    Case WM_GETMINMAXINFO
        pMM = Cast(MINMAXINFO Ptr, lParam)
        pMM->ptMinTrackSize.x = gP.minTrackSizeW
        pMM->ptMinTrackSize.y = gP.minTrackSizeH

    Case WM_SIZE
        InvalidateRect(hWnd, NULL, TRUE)
        nRet = 0

    Case WM_PAINT
        Dim ps As PAINTSTRUCT
        Dim hDC As HDC = BeginPaint(hWnd, @ps)
        ' Paint window content here
        EndPaint(hWnd, @ps)
        nRet = 0

    Case WM_DESTROY
        PostQuitMessage(0)
        nRet = 0
    End Select

    If nRet = -1 Then nRet = DefWindowProc(hWnd, uMsg, wParam, lParam)
    Return nRet
End Function

Function WinMain(ByVal hInstance As HINSTANCE, ByVal hPrevInstance As HINSTANCE, ByVal lpCmdLine As WString Ptr, ByVal nCmdShow As Integer) As Integer
    Dim nRet As Integer = 0
    Dim szClass As WString * 10 = "MINI"

    ' Detect process without using a Mutex
    Dim hFound As HWND = FindWindowW(StrPtr(szClass), NULL)
    If hFound <> NULL Then
        If IsIconic(hFound) Then ShowWindow(hFound, SW_RESTORE)
        SetForegroundWindow(hFound)
        Return nRet
    End If

    Dim wcx As WNDCLASSEX
    wcx.cbSize = Len(wcx)
    Dim IsInitialized As Long = GetClassInfoEx(hInstance, StrPtr(szClass), @wcx)

    If IsInitialized = 0 Then
        wcx.style         = CS_HREDRAW Or CS_VREDRAW
        wcx.lpfnWndProc   = @WndProc
        wcx.cbClsExtra    = 0
        wcx.cbWndExtra    = 0
        wcx.hInstance     = hInstance
        wcx.hIcon         = LoadIcon(NULL, IDI_APPLICATION)
        wcx.hCursor       = LoadCursor(NULL, IDC_ARROW)
        wcx.hbrBackground = Cast(HBRUSH, COLOR_BTNFACE + 1) ' Fix: Windows expects a valid brush
        wcx.lpszMenuName  = NULL
        wcx.lpszClassName = StrPtr(szClass) ' ? FIXED: Correct pointer type
        wcx.hIconSm       = wcx.hIcon
       
        If RegisterClassEx(@wcx) <> 0 Then IsInitialized = -1
    End If

    If IsInitialized Then
        Dim dwExStyle As DWORD = 0
        Dim dwStyle As DWORD = WS_OVERLAPPEDWINDOW Or WS_CLIPSIBLINGS Or WS_CLIPCHILDREN
        Dim lpr As RECT
        SetRect(@lpr, 0, 0, CLIENT_WIDTH, CLIENT_HEIGHT)
        AdjustWindowRectEx(@lpr, dwStyle, FALSE, dwExStyle)

        gP.minTrackSizeW = rWidth(lpr)
        gP.minTrackSizeH = rHeight(lpr)

        Dim x As Long = Max((GetSystemMetrics(SM_CXSCREEN) - gP.minTrackSizeW) \ 2, 0)
        Dim y As Long = Max((GetSystemMetrics(SM_CYSCREEN) - gP.minTrackSizeH) \ 2, 0)

        gP.hMain = CreateWindowExW(dwExStyle, StrPtr(szClass), StrPtr(szClass), dwStyle, x, y, gP.minTrackSizeW, gP.minTrackSizeH, NULL, NULL, hInstance, NULL)

        If gP.hMain <> NULL Then
            ShowWindow(gP.hMain, nCmdShow)
            SetForegroundWindow(gP.hMain) ' Slightly Higher Priority

            Dim msg As MSG
            While GetMessage(@msg, NULL, 0, 0)
                TranslateMessage(@msg)
                DispatchMessage(@msg)
            Wend
            nRet = msg.wParam
        End If

        UnregisterClassW(StrPtr(szClass), hInstance)
    End If

    Return nRet
End Function

End WinMain(GetModuleHandle(NULL), NULL, NULL, SW_SHOWDEFAULT)

Are you able to produce a working 64-bit version of that code?



José Roca

Sure.

#Include "windows.bi"

Const CLIENT_WIDTH  = 640
Const CLIENT_HEIGHT = 480

Type PROP
    hMain As HWND
    minTrackSizeW As Long
    minTrackSizeH As Long
End Type

Dim Shared gP As PROP

Function rWidth(ByRef r As RECT) As Long
    Return r.right - r.left
End Function

Function rHeight(ByRef r As RECT) As Long
    Return r.bottom - r.top
End Function

Function WndProc(ByVal hWnd As HWND, ByVal uMsg As UINT, ByVal wParam As WPARAM, ByVal lParam As LPARAM) As LRESULT
    Dim nRet As LRESULT = -1
    Dim pMM As MINMAXINFO Ptr
   
    Select Case uMsg
    Case WM_CREATE
        ' Initialization can go here if needed.

    Case WM_GETMINMAXINFO
        pMM = Cast(MINMAXINFO Ptr, lParam)
        pMM->ptMinTrackSize.x = gP.minTrackSizeW
        pMM->ptMinTrackSize.y = gP.minTrackSizeH

    Case WM_SIZE
        InvalidateRect(hWnd, NULL, TRUE)
        nRet = 0

    Case WM_PAINT
        Dim ps As PAINTSTRUCT
        Dim hDC As HDC = BeginPaint(hWnd, @ps)
        ' Paint window content here
        EndPaint(hWnd, @ps)
        nRet = 0

    Case WM_DESTROY
        PostQuitMessage(0)
        nRet = 0
    End Select

    If nRet = -1 Then nRet = DefWindowProc(hWnd, uMsg, wParam, lParam)
    Return nRet
End Function

Function WinMain(ByVal hInstance As HINSTANCE, ByVal hPrevInstance As HINSTANCE, ByVal lpCmdLine As WString Ptr, ByVal nCmdShow As Integer) As Integer
    Dim nRet As Integer = 0
    Dim szClass As ZString * 10 = "MINI"

    ' Detect process without using a Mutex
    Dim hFound As HWND = FindWindow(szClass, NULL)
    If hFound <> NULL Then
        If IsIconic(hFound) Then ShowWindow(hFound, SW_RESTORE)
        SetForegroundWindow(hFound)
        Return nRet
    End If

    Dim wcx As WNDCLASSEX
    wcx.cbSize = Len(wcx)
    Dim IsInitialized As Long = GetClassInfoEx(hInstance, szClass, @wcx)

    If IsInitialized = 0 Then
        wcx.style         = CS_HREDRAW Or CS_VREDRAW
        wcx.lpfnWndProc   = @WndProc
        wcx.cbClsExtra    = 0
        wcx.cbWndExtra    = 0
        wcx.hInstance     = hInstance
        wcx.hIcon         = LoadIcon(NULL, IDI_APPLICATION)
        wcx.hCursor       = LoadCursor(NULL, IDC_ARROW)
        wcx.hbrBackground = Cast(HBRUSH, COLOR_BTNFACE + 1) ' Fix: Windows expects a valid brush
        wcx.lpszMenuName  = NULL
        wcx.lpszClassName = @szClass
        wcx.hIconSm       = wcx.hIcon
       
        If RegisterClassEx(@wcx) <> 0 Then IsInitialized = -1
    End If

    If IsInitialized Then
        Dim dwExStyle As DWORD = 0
        Dim dwStyle As DWORD = WS_OVERLAPPEDWINDOW Or WS_CLIPSIBLINGS Or WS_CLIPCHILDREN
        Dim lpr As RECT
        SetRect(@lpr, 0, 0, CLIENT_WIDTH, CLIENT_HEIGHT)
        AdjustWindowRectEx(@lpr, dwStyle, FALSE, dwExStyle)

        gP.minTrackSizeW = rWidth(lpr)
        gP.minTrackSizeH = rHeight(lpr)

        Dim x As Long = Max((GetSystemMetrics(SM_CXSCREEN) - gP.minTrackSizeW) \ 2, 0)
        Dim y As Long = Max((GetSystemMetrics(SM_CYSCREEN) - gP.minTrackSizeH) \ 2, 0)

        gP.hMain = CreateWindowEx(dwExStyle, szClass, szClass, dwStyle, x, y, gP.minTrackSizeW, gP.minTrackSizeH, NULL, NULL, hInstance, NULL)

        If gP.hMain <> NULL Then
            ShowWindow(gP.hMain, nCmdShow)
            SetForegroundWindow(gP.hMain) ' Slightly Higher Priority

            Dim msg As MSG
            While GetMessage(@msg, NULL, 0, 0)
                TranslateMessage(@msg)
                DispatchMessage(@msg)
            Wend
            nRet = msg.wParam
        End If

        UnregisterClassW(szClass, hInstance)
    End If

    Return nRet
End Function

End WinMain(GetModuleHandle(NULL), NULL, NULL, SW_SHOWDEFAULT)

The ChatGpt translation don't work because it mixes ansi and unicode and several misuses of STRPTR.

Bernard Kunzy

Thank you for the translation, the gcc.exe code works the same than the cl.exe except for the resulting binary size, and perhaps direct use of native unicode.

José Roca

Patrice is using a tiny C runtime, whereas the Basic compilers use a lot of conde in the runtime to manipulate strings, arrays and other things. IMO these comparisons aren't worthwile.

Bernard Kunzy

#4
Without using Tiny C lib, the resulting cl.exe code is twice bigger than the gcc.exe.
I wonder why more PowerBASIC didn't jump to FreeBASIC, perhaps because they have been spoiled by DDT.
Moreover the FreeBASIC syntax is much closer to the the BASIC original than PureBASIC...


Charles Pegge

I tried this in OxygenBasic, making minimal changes to Patrice's C++ code.
Both 32bit and 64bit binaries are 14Kbytes.

It was good experience but I had to scrutinize every line.

'01:33 13/02/2025
'CP
'
'#include <windows.h>
% filename "t.exe"
'uses RTL64 'or uses RTL32
uses corewinW

'constexpr auto CLIENT_WIDTH   = 640;
'constexpr auto CLIENT_HEIGHT  = 480;
% CLIENT_WIDTH   = 640;
% CLIENT_HEIGHT  = 480;

typedef long lresult

struct PROP {
    sys         hMain;
    long        minTrackSizeW;
    long        minTrackSizeH;
};

static PROP gP;

long rWidth(RECT *r) {
    return r.right - r.left;
}

long rHeight(RECT *r) {
    return r.bottom - r.top;
}

int WndProc(sys hWnd, dword uMsg, sys wParam, sys lParam) callback  {

    typedef struct tagMINMAXINFO {
      POINT ptReserved;
      POINT ptMaxSize;
      POINT ptMaxPosition;
      POINT ptMinTrackSize;
      POINT ptMaxTrackSize;
    } MINMAXINFO, *PMINMAXINFO, *LPMINMAXINFO;

    int nRet = -1;
    MINMAXINFO* pMM;
    switch uMsg {

    case WM_CREATE:
        break;

    case 0X0024 'WM_GETMINMAXINFO:
        @pMM = lParam;
        pMM->ptMinTrackSize.x = gP.minTrackSizeW;
        pMM->ptMinTrackSize.y = gP.minTrackSizeH;
       break;

    case WM_SIZE:
        InvalidateRect(hWnd, NULL, TRUE);
        nRet = 0;
        break;

    case WM_PAINT:
            PAINTSTRUCT ps;
            sys hDC = BeginPaint(hWnd, ps);
            // Paint the window content here
            EndPaint(hWnd, ps);
            nRet = 0;
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        nRet = 0;
        break;
    }

    if (nRet == -1)
      nRet = DefWindowProc(hWnd, uMsg, wParam, lParam);
    endif
    return nRet;
}

int wWinMain(sys hInstance, sys hPrevInstance, sys lpCmdLine, int nCmdShow) {
    'UNREFERENCED_PARAMETER(hPrevInstance);
    'UNREFERENCED_PARAMETER(lpCmdLine);

    int nRet = 0;
    WCHAR szClass[] = L"MINI";
    // Detect process without using a Mutex
    sys hFound = FindWindow(szClass, NULL);
    if hFound {
        if IsIconic(hFound) {
          ShowWindow(hFound, SW_RESTORE);
        }
        SetForegroundWindow(hFound);
        return nRet;
     }

    WNDCLASSEX wcx ' = { 0 };

    long IsInitialized = GetClassInfoEx(hInstance, szClass, wcx);
    if not IsInitialized {
        wcx.cbSize        = sizeof(wcx);
        wcx.style         = CS_HREDRAW | CS_VREDRAW;
        wcx.lpfnWndProc   = @WndProc;
        wcx.cbClsExtra    = 0;
        wcx.cbWndExtra    = 0;
        wcx.hInstance     = hInstance;
        wcx.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
        wcx.hCursor       = LoadCursor(NULL, IDC_ARROW);
        wcx.hbrBackground = 16 'COLOR_BTNSHADOW;
        wcx.lpszMenuName  = 0;
        wcx.lpszClassName = strptr(szClass);
        wcx.hIconSm       = wcx.hIcon;
       if RegisterClassEx(wcx) then IsInitialized = -1;
    }

    if (IsInitialized) {
        DWORD dwExStyle = 0;
        DWORD dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
        RECT lpr '= { 0 };
        SetRect(lpr, 0, 0, CLIENT_WIDTH, CLIENT_HEIGHT);
        AdjustWindowRectEx(lpr, dwStyle, FALSE, dwExStyle);
        gP.minTrackSizeW = rWidth(lpr);
        gP.minTrackSizeH = rHeight(lpr);
        'long x = max((GetSystemMetrics(SM_CXSCREEN) - gP.minTrackSizeW) / 2, 0);
        'long y = max((GetSystemMetrics(SM_CYSCREEN) - gP.minTrackSizeH) / 2, 0);

        macro max as int(r  a,b)
        if a>b then r=a else r=b
        end macro

        long x=(GetSystemMetrics(SM_CXSCREEN)-gP.minTrackSizeW)/2;
        long y=(GetSystemMetrics(SM_CYSCREEN)-gP.minTrackSizeH)/2;
        x=max(x,0);
        y=max(y,0);

        gP.hMain = CreateWindowEx(dwExStyle, szClass, szClass, dwStyle,
                x, y, gP.minTrackSizeW, gP.minTrackSizeH, 0, 0, hInstance, NULL);
        if gP.hMain {
            ShowWindow(gP.hMain, nCmdShow);
            SetForegroundWindow(gP.hMain); // Slightly Higher Priority
            MSG mg '= { 0 };
            while GetMessage(mg, NULL, 0, 0) {
                TranslateMessage(mg);
                DispatchMessage(mg);
            }
            nRet = mg.wParam;
        }
       UnregisterClass(wcx.lpszClassName, hInstance);
    }
    return nRet;
}
wWinmain( GetModuleHandle(0),0,GetCommandLine(),SW_SHOWDEFAULT);

Charles Pegge

I translated José's FreeBasic translation to OxygenBasic. Again with minimal changes.

Some of the alterations were due to missing equates in corewinW.inc.

'02:52 13/02/2025
'CP
'
'#Include "windows.bi"
% filename "t.exe"
'uses RTL64 'or uses RTL32
uses corewinW


Const CLIENT_WIDTH as long  = 640
Const CLIENT_HEIGHT as long = 480

Type PROP
    hMain As sys 'HWND
    minTrackSizeW As Long
    minTrackSizeH As Long
End Type

alias int as LRESULT

Dim gP As PROP

Function rWidth(ByRef r As RECT) As Long
    Return r.right - r.left
End Function

Function rHeight(ByRef r As RECT) As Long
    Return r.bottom - r.top
End Function

Function WndProc(ByVal hWnd As sys, ByVal uMsg As UINT, ByVal wParam As sys, ByVal lParam As sys) callback As LRESULT
    Dim nRet As LRESULT = -1
    Dim pMM As MINMAXINFO Ptr
   
    Select Case uMsg
    Case WM_CREATE
        ' Initialization can go here if needed.

    Case 0x0024 'WM_GETMINMAXINFO
        @pMM = lParam
        pMM->ptMinTrackSize.x = gP.minTrackSizeW
        pMM->ptMinTrackSize.y = gP.minTrackSizeH

    Case WM_SIZE
        InvalidateRect(hWnd, NULL, TRUE)
        nRet = 0

    Case WM_PAINT
        Dim ps As PAINTSTRUCT
        Dim hDC As sys = BeginPaint(hWnd, @ps)
        ' Paint window content here
        EndPaint(hWnd, @ps)
        nRet = 0

    Case WM_DESTROY
        PostQuitMessage(0)
        nRet = 0
    End Select

    If nRet = -1 Then nRet = DefWindowProc(hWnd, uMsg, wParam, lParam)
    Return nRet
End Function

Function WinMain(ByVal hInstance As sys, ByVal hPrevInstance As sys, ByVal lpCmdLine As sys, ByVal nCmdShow As Integer) As Integer
    Dim nRet As Integer = 0
    Dim szClass[10] As wchar ="MINI" 'zString * 10 = "MINI"

    ' Detect process without using a Mutex
    Dim hFound As sys = FindWindow(szClass, NULL)
    If hFound <> NULL Then
        If IsIconic(hFound) Then ShowWindow(hFound, SW_RESTORE)
        SetForegroundWindow(hFound)
        Return nRet
    End If

    Dim wcx As WNDCLASSEX
    wcx.cbSize = sizeof(wcx) 'not len
    Dim IsInitialized As Long = GetClassInfoEx(hInstance, szClass, @wcx)
    If IsInitialized = 0 Then
        wcx.style         = CS_HREDRAW Or CS_VREDRAW
        wcx.lpfnWndProc   = @WndProc
        wcx.cbClsExtra    = 0
        wcx.cbWndExtra    = 0
        wcx.hInstance     = hInstance
        wcx.hIcon         = LoadIcon(NULL, IDI_APPLICATION)
        wcx.hCursor       = LoadCursor(NULL, IDC_ARROW)
        wcx.hbrBackground = 16 'COLOR_BTNFACE + 1) ' Fix: Windows expects a valid brush
        wcx.lpszMenuName  = NULL
        wcx.lpszClassName = strptr(szClass)
        wcx.hIconSm       = wcx.hIcon
       
        If RegisterClassEx(@wcx) <> 0 Then IsInitialized = -1
    End If
    If IsInitialized Then
        Dim dwExStyle As DWORD = 0
        Dim dwStyle As DWORD = WS_OVERLAPPEDWINDOW Or WS_CLIPSIBLINGS Or WS_CLIPCHILDREN
        Dim lpr As RECT
        SetRect(@lpr, 0, 0, CLIENT_WIDTH, CLIENT_HEIGHT)
        AdjustWindowRectEx(@lpr, dwStyle, FALSE, dwExStyle)

        gP.minTrackSizeW = rWidth(lpr)
        gP.minTrackSizeH = rHeight(lpr)

        'Dim x As Long = Max((GetSystemMetrics(SM_CXSCREEN) - gP.minTrackSizeW) \ 2, 0)
        'Dim y As Long = Max((GetSystemMetrics(SM_CYSCREEN) - gP.minTrackSizeH) \ 2, 0)

        macro max as int(r  a,b)
         if a>b then r=a else r=b
        end macro

        dim long x=(GetSystemMetrics(SM_CXSCREEN)-gP.minTrackSizeW)/2
        dim long y=(GetSystemMetrics(SM_CYSCREEN)-gP.minTrackSizeH)/2
        x=max(x,0);
        y=max(y,0);


        gP.hMain = CreateWindowEx(dwExStyle, szClass, strptr(szClass), dwStyle, x, y, gP.minTrackSizeW, gP.minTrackSizeH, NULL, NULL, hInstance, NULL)

        If gP.hMain <> NULL Then
            ShowWindow(gP.hMain, nCmdShow)
            SetForegroundWindow(gP.hMain) ' Slightly Higher Priority

            Dim mg As MSG
            While GetMessage(@mg, NULL, 0, 0)
                TranslateMessage(@mg)
                DispatchMessage(@mg)
            Wend
            nRet = mg.wParam
        End If

        UnregisterClass(szClass, hInstance)
    End If

    Return nRet
End Function

WinMain(GetModuleHandle(NULL), NULL, NULL, SW_SHOWDEFAULT)

Zlatko Vid

Wow..wow..wow
Cpp yeah...i must reinstall Ultimate++  ;D

OK in both programs i get same error on word max

x=max(x,0);

Charles Pegge

Hi Aurel,

I think it is your earlier version of Oxygen.dll that does not support macro functions. But this kind of composite construct is good for neither compiler nor human trying to understand the code.

Original:
        long x = max((GetSystemMetrics(SM_CXSCREEN) - gP.minTrackSizeW) / 2, 0);
        long y = max((GetSystemMetrics(SM_CYSCREEN) - gP.minTrackSizeH) / 2, 0);

de-compounded and easier to understand. (without max)
        long x = (GetSystemMetrics(SM_CXSCREEN) - gP.minTrackSizeW) / 2;
        long y = (GetSystemMetrics(SM_CYSCREEN) - gP.minTrackSizeH) / 2;
        if (x<0) x=0;
        if (y<0) y=0;


Johan Klassen

Quote from: Bernard Kunzy on February 12, 2025, 02:37:47 PMstatic long rWidth(IN RECT &r) {
    return r.right - r.left;
}

could someone enlighten me on this statement ?
static long rWidth(IN RECT &r) {

never seen IN in C++ code before

Zlatko Vid

QuoteI think it is your earlier version of Oxygen.dll that does not support macro functions
Yes Charles i use SC604..then ok  ;)

Theo Gottwald

Quote from: Bernard Kunzy on February 12, 2025, 05:59:04 PMWithout using Tiny C lib, the resulting cl.exe code is twice bigger than the gcc.exe.
I wonder why more PowerBASIC didn't jump to FreeBASIC, perhaps because they have been spoiled by DDT.
Moreover the FreeBASIC syntax is much closer to the the BASIC original than PureBASIC...

The advantage from Purebasic are that it has extensive "ready made" Libraries.
This way you can get from here to there just plugging some library code together.
No other BASIC has so many libraries as of my knowledge.

Bernard Kunzy

#12
QuoteNo other BASIC has so many libraries as of my knowledge.
The syntax is too convoluted for my taste (too far from the standard BASIC language I have learned).
Gadgets...

And dispite their moto, I have never seen a descent 3D application written with it.


Theo Gottwald

Quote from: Bernard Kunzy on February 13, 2025, 03:15:48 PM
QuoteNo other BASIC has so many libraries as of my knowledge.
The syntax is too convoluted for my taste (too far from the standard BASIC language I have learned).
Gadgets...

And dispite their moto, I have never seen a descent 3D application written with it.


For example try to connect to the API from Mistral or OpenAI.
You will need http-COmmands and a JSON Library.
Generally all KI's are very good in Purebasic and providde you witth the nearly "ready-to-run"" code for things like that.
To do all this in good quality with other Basics may take you much longer.