Simple tutorial to create first Windows applications

Windows specific questions.
cl4551f13d
Posts: 5
Joined: Jun 01, 2020 1:22

Simple tutorial to create first Windows applications

Postby cl4551f13d » Jun 08, 2020 5:27

Hi.

I have looked at some examples of simple applications for windows, I have compiled them, but although I come from VisualBasic 6, I have not been able to make my first program for Windows.

Can someone give me a link to a step-by-step tutorial?
Xusinboy Bekchanov
Posts: 349
Joined: Jul 26, 2018 18:28

Re: Simple tutorial to create first Windows applications

Postby Xusinboy Bekchanov » Jun 08, 2020 6:19

There are many GUI libraries here:
viewtopic.php?f=17&t=28510

For a simple try this (Sorry, this is in Russian, found a quick search):

Code: Select all

#include "windows.bi"
#include "win\commctrl.bi"
Dim msg As MSG 'структурированная переменная MSG
Dim As WNDCLASSEX wc 'структурированная переменная WNDCLASSEX
Dim As String NameClass="MyClass" ' переменная имени класса
Dim As HINSTANCE Hinst=GetModuleHandle(0) ' хендл модуля
' функция класса
Function wndproc(hwnd As HWND, msg As UInteger,_
    wparam As WPARAM, lparam As LPARAM) As Integer
    Static As HWND edit1,edit2,edit3,edit4,button
    Select Case msg
        Case WM_CREATE
            edit1=CreateWindowEx(0,"edit","Простой Edit с горизонтальным автоскролом",WS_VISIBLE Or WS_CHILD Or ES_AUTOHSCROLL,10,10,130,20,hwnd,Cast(HMENU,1),0,0)
            edit2=CreateWindowEx(0,"edit","Ввод с клавиатуры только чисел",WS_VISIBLE Or ES_NUMBER Or WS_CHILD,10,40,230,20,hwnd,Cast(HMENU,2),0,0)
            edit3=CreateWindowEx(0,"edit","Пароль",WS_VISIBLE Or ES_PASSWORD Or WS_CHILD,10,70,80,20,hwnd,Cast(HMENU,3),0,0)
            edit4=CreateWindowEx(0,"edit","Многострочный Edit" ,WS_VISIBLE Or ES_MULTILINE Or ES_AUTOVSCROLL Or WS_CHILD,10,100,100,100,hwnd,Cast(HMENU,4),0,0)
            button=CreateWindowEx(0,"button","вставить текст" ,WS_VISIBLE  Or WS_CHILD,130,100,100,20,hwnd,Cast(HMENU,5),0,0)
        Case WM_COMMAND
            If LoWord(wparam)=3 Then
                Dim As ZString*256 text
                GetWindowText(Edit3,@text,256)
                SetWindowText(Edit4,@text)
            ElseIf LoWord(wparam)=5 Then
                Dim As ZString*256 text
                GetWindowText(Edit2,@text,256)
                SendMessage(Edit4,EM_REPLACESEL,1,Cast(Lparam,@text))
            EndIf
        Case WM_DESTROY
            PostQuitMessage(0)
    End Select
    Return DefWindowProc(hwnd,msg,wparam,lparam)
End Function
' Заполнение структуры WNDCLASSEX
With wc
    .cbSize=SizeOf(WNDCLASSEX)
    .style=CS_HREDRAW Or CS_VREDRAW
    .lpfnWndProc=@wndproc
    .hInstance=Hinst
    .hIcon=LoadIcon(0,IDI_QUESTION)
    .hCursor=LoadCursor(0,IDC_ARROW)
    .hbrBackground=Cast(HBRUSH,COLOR_WINDOW)
    .lpszClassName=StrPtr(NameClass)
    .hIconSm=.hIcon
End With
' Регистрация класса окна
If RegisterClassEx(@wc)=0 Then
    Print "Register error, press any key"
    Sleep
    End
EndIf
InitCommonControls
'Создание окна
CreateWindowEx(0,NameClass,"Главное окно",_
WS_VISIBLE Or WS_OVERLAPPEDWINDOW,10,10,300,300,0,0,Hinst,0)
' Цикл сообщений
While GetMessage(@msg,0,0,0)
    TranslateMessage(@msg)
    DispatchMessage(@msg)
Wend
BasicCoder2
Posts: 3671
Joined: Jan 01, 2009 7:03
Location: Australia

Re: Simple tutorial to create first Windows applications

Postby BasicCoder2 » Jun 08, 2020 6:53

jj2007
Posts: 1924
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Simple tutorial to create first Windows applications

Postby jj2007 » Jun 08, 2020 7:47

A template with a menu, a WM_PAINT handler and an edit control. The last line starts the program

Code: Select all

#Include "windows.bi"   ' JJ 18.4.2020
Dim Shared as Handle hEdit
Function WndProc(hWnd As HWND, msg As  UINT, wParam As WPARAM, lParam As LPARAM) As LRESULT
  Dim As RECT rc
  Dim As PAINTSTRUCT ps
  Dim As HANDLE PtDC
  Dim As HMENU hMenu, hPopup, hEsi
  Select Case msg
  Case WM_CREATE
   hMenu=CreateMenu()               ' create the main menu
   hPopup=CreatePopupMenu()               ' create a sub-menu
   AppendMenu(hMenu, MF_POPUP, hPopup, "&File")      ' add it to the main menu
   AppendMenu(hPopup, MF_STRING, 101, "&Open")       ' one more main item
   hEsi=CreatePopupMenu()               ' create a sub-menu
   AppendMenu(hEsi, MF_STRING, 121, "&sources")      ' fill it
   AppendMenu(hEsi, MF_STRING, 122, "&includes")      ' with various
   AppendMenu(hEsi, MF_STRING, 123, "&DLLs")         ' options
   AppendMenu(hPopup, MF_POPUP, hEsi, "&Dir")      ' and add it to the main menu as "Dir"
   AppendMenu(hPopup, MF_STRING, 102, "&Save")       ' one more main item
   AppendMenu(hPopup, MF_STRING, 103, "E&xit")       ' one more main item
   SetMenu(hWnd, hMenu)               ' attach menu to main window
   hEdit=CreateWindowEx(WS_EX_CLIENTEDGE, "edit", "Hello, I am an edit control",_
   WS_CHILD Or WS_VISIBLE or ES_MULTILINE, 0, 0, 100, 100, hWnd, 100, 0, 0)
  Case WM_COMMAND
   Select Case wParam
       Case 101: MessageBox(hWnd, "Open not implemented", 0, MB_OK)
       Case 102: MessageBox(hWnd, "Save not implemented", 0, MB_OK)
       Case 121: MessageBox(hWnd, "No *.bas files found", 0, MB_OK)
       Case 122: MessageBox(hWnd, "No *.inc files found", 0, MB_OK)
       Case 123: MessageBox(hWnd, "No *.dll files found", 0, MB_OK)
       Case 103: SendMessage(hWnd, WM_CLOSE, 0, 0)
   End Select
  Case WM_PAINT
   PtDC=BeginPaint(hWnd, @ps)
   TextOut(PtDC, 3, 3, "TextOut in the WM_PAINT handler", 31)
   EndPaint(hWnd, @ps)
  Case WM_KEYDOWN
     if wParam=VK_ESCAPE then SendMessage(hWnd, WM_CLOSE, 0, 0)
  Case WM_SIZE
   GetClientRect(hWnd, @rc)
   MoveWindow(hEdit, 3, 28, rc.right-6, rc.bottom-30, 0)
  Case WM_DESTROY
      PostQuitMessage(0)
  End Select
  return DefWindowProc(hwnd, msg, wParam, lParam)
End Function

Function WinMain(hInstance As HINSTANCE, hPrevInstance As HINSTANCE, lpCmdLine As LPSTR, nShowCmd As Integer) As Integer
  Dim As WNDCLASSEX wc
  Dim As MSG msg
  Dim As string classname="FbGui"
  Dim As HANDLE hIconLib, hDll
  type pCall as function (xy as any ptr) as long
  Dim As pCall pGetVersion
  type DLLVERSIONINFO
   cbSize as long
   dwMajorVersion as long
   dwMinorVersion as long
   dwBuildNumber as long
   dwPlatformID as long
  end type
  Dim As DLLVERSIONINFO dvi
  dvi.cbSize=sizeof(DLLVERSIONINFO)
  hIconLib=LoadLibrary("shell32")
  wc.hIcon = LoadIcon(hIconLib, 239)   ' get the butterfly icon
  FreeLibrary(hIconLib)
  hDll=LoadLibrary("ComCtl32")
  pGetVersion=GetProcAddress(hDll, "DllGetVersion")
  pGetVersion(@dvi)
  if @dvi.dwMajorVersion then print "Using common controls version ";str(dvi.dwMajorVersion);".";str(dvi.dwMinorVersion)
  FreeLibrary(hDll)
  wc.cbSize = sizeof(WNDCLASSEX)
  wc.hbrBackground = COLOR_BTNFACE+1
  wc.hCursor = LoadCursor(0, IDC_ARROW)
  wc.hIconSm = wc.hIcon
  wc.hInstance = hInstance
  wc.lpfnWndProc = @WndProc
  wc.lpszClassName = StrPtr(classname)
  wc.style = CS_HREDRAW Or CS_VREDRAW
  RegisterClassEx(@wc)
  if CreateWindowEx(0, wc.lpszClassName, "Hello World",_
   WS_OVERLAPPEDWINDOW Or WS_VISIBLE, (GetSystemMetrics(SM_CXSCREEN) / 2) - 150,_
   (GetSystemMetrics(SM_CYSCREEN) / 2) - 150, 300, 300, 0, 0, hInstance, 0)=0 then
          MessageBox(0, "Creating hMain failed miserably", 0, MB_OK)
          return 0
  End If

  While GetMessage(@msg, 0, 0, 0)
      TranslateMessage(@msg)
      DispatchMessage(@msg)
  Wend

  return msg.wParam
End Function
WinMain(GetModuleHandle(NULL), NULL, COMMAND(), SW_NORMAL)
dodicat
Posts: 6790
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Simple tutorial to create first Windows applications

Postby dodicat » Jun 08, 2020 10:09

Really neat jj2007.
You packed a lot in there.
The warnings can be suppressed by doing things like
wc.hbrBackground = cast(HBRUSH__ PTR,(COLOR_BTNFACE+1))
and
wc.hIcon = LoadIcon(hIconLib, cptr(any ptr,239)) ' get the butterfly icon

etc
etc

(To conform to freebasic's windows.bi)
But I shall probably refer to your template now and then, thank you.
jj2007
Posts: 1924
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Simple tutorial to create first Windows applications

Postby jj2007 » Jun 08, 2020 10:37

dodicat wrote:Really neat jj2007
Thanks, dodicat. I hesitate to apply the cast acrobatics because IMHO FB should deal better with the requirements of the Windows API - there is nothing worth a warning, it's all correct. Btw which common controls version do you see? I get 6.16, but that depends on the commandline including a resource file, and the manifest in that rc file.
Tourist Trap
Posts: 2958
Joined: Jun 02, 2015 16:24

Re: Simple tutorial to create first Windows applications

Postby Tourist Trap » Oct 18, 2020 14:09

jj2007 wrote:Btw which common controls version do you see? I get 6.16.

Just for info it's 5.82 here. Works fine whatever.
jj2007
Posts: 1924
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Simple tutorial to create first Windows applications

Postby jj2007 » Oct 18, 2020 20:45

5.82 gives you ugly pre-XP look. Try to specify a manifest file in a resource file as follows:

Code: Select all

32512 ICON "SomeFile.ico"
1 24 "XpManifest.xml"
This is XpManifest.xml:

Code: Select all

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<description>MasmBasic</description>
<dependency>
   <dependentAssembly>
   <assemblyIdentity
      type="win32"
      name="Microsoft.Windows.Common-Controls"
      version="6.0.0.0"
      processorArchitecture="*"
      publicKeyToken="6595b64144ccf1df"
   />
   </dependentAssembly>
</dependency>
</assembly>
Your batch file or commandline should contain something similar:

Code: Select all

set rcfile=
if exist rsrc.rc set rcfile=rsrc.rc
fbc.exe %options% %rcfile% %1
Macq
Posts: 4
Joined: Feb 18, 2021 4:01
Location: Queensland, Australia

Re: Simple tutorial to create first Windows applications

Postby Macq » Feb 23, 2021 0:23

I'm learning windows programming too, so I thought I'd post some code here in the hope that it may help someone.

This is from a book released in 1990 for windows 3.0. Old but still informative. It demonstrates the use of child windows.
Every time you click on a child window, its state is inverted.
Change the value of DIVISIONS for a ridiculous number of tiny windows.

Code: Select all

'
' checker3  from Programming Windows 3.0 (c) 1990 Charles Petzold
'
' Demonstrates child windows, childWndProc(), mouse use, line drawing
'
#include once "windows.bi"
#define DIVISIONS 8

const szAppName    = "Checker3"
const szChildClass = "Checker3_Child"
dim shared hInst as HINSTANCE ' global copy of hInstance from WinMain()

' This is just an empty declaration.  See below for the definition of this fuction
' Without this, WinMain() is not called automatically, and nothing happens...
Declare Function        WinMain     ( ByVal hInstance As HINSTANCE, _
                                      ByVal hPrevInstance As HINSTANCE, _
                                      szCmdLine As String, _
                                      ByVal iCmdShow As Integer ) As Integer
   End WinMain( GetModuleHandle( null ), null, Command, SW_NORMAL )

Function WndProc ( ByVal hw As HWND, _
                   ByVal message As UINT, _
                   ByVal wParam As WPARAM, _
                   ByVal lParam As LPARAM ) As LRESULT

    static hwndChild(DIVISIONS,DIVISIONS) as hwnd ' holds all the handles to all the child windows
    dim as short  cxBlock, cyBlock, x, y
    select case(message)
        case WM_CREATE
            for x = 0 to DIVISIONS-1 step 1
                for y = 0 to DIVISIONS-1 step 1
                    'hwndChild(x,y) = CreateWindow(szChildClass,Null,_ ' Compiler bug with handling comments after _
                    hwndChild(x,y) = CreateWindowEx(WS_EX_CLIENTEDGE,szChildClass,Null,_
                    WS_CHILDWINDOW OR WS_VISIBLE,_
                    0,0,0,0,_
                    hw,_
                    cptr(HMENU,(y shl 8) or x),_
                    hInst,_
                    0)
                next y
            next x
            exit function ' return (0)
       
        case WM_SIZE
            cxBlock = LoWord(lParam) / DIVISIONS 'width of parent window divided by number of child windows per line
            cyBlock = Hiword(lParam) / DIVISIONS 'height of parent window ...
            for x = 0 to DIVISIONS-1 step 1
                for y = 0 to DIVISIONS-1 step 1
                    MoveWindow(hwndChild(x,y),x*cxBlock,y*cyBlock,cxBlock,cyBlock,TRUE)
                next y
            next x
            exit function

        case WM_LBUTTONDOWN
            MessageBeep(0) ' Beep if we get a click in the display area of the main window.
            exit function  ' There may be a small area at the bottom that is not covered by children
           
        case WM_DESTROY
            PostQuitMessage(0)
            exit function
    end select
    ''
    '' The message doesn't concern us so we send it to the default handler and return the result
    '' You MUST call DefWindowProc() for all messages that your window proceedure does not process
    Function = DefWindowProc( hw, message, wParam, lParam )   
   
End Function ' exit WndProc() and return a value

function ChildWndProc ( ByVal hw As HWND, _
                   ByVal message As UINT, _
                   ByVal wParam As WPARAM, _
                   ByVal lParam As LPARAM ) As LRESULT
    dim as HDC hdc
    Dim as PAINTSTRUCT ps
    dim as RECT rect
   
    select case(message)
        case WM_CREATE
            if(rnd > 0.5) then SetWindowWord(hw,0,1) else  SetWindowWord(hw,0,0)' On/Off flag
            exit function ' return 0
        case WM_LBUTTONDOWN
            SetWindowWord(hw,0,1 xor GetWindowWord(hw,0))
            InvalidateRect(hw,null,false)
            exit function
        case WM_PAINT
            hdc = BeginPaint(hw,@ps)
            GetClientRect(hw,@rect)
            Rectangle(hdc,0,0,rect.right,rect.bottom) ' This paints the entire child-window with the default brush
            if(GetWindowWord(hw,0)) then: ' Draw an X in the child window on every odd numbered click
                SelectObject(hdc,GetStockObject(LTGRAY_BRUSH))
                Ellipse(hdc,0,0,rect.right,rect.bottom)
                MoveToEx(hdc,0,0,null)
                LineTo(hdc,rect.right,rect.bottom)
                MoveToEx(hdc,0,rect.bottom,null)
                LineTo(hdc,rect.right,0)
            :end if
            EndPaint(hw,@ps)
            exit function
    end select
    Function = DefWindowProc( hw, message, wParam, lParam )
end function

Function WinMain ( ByVal hInstance As HINSTANCE, _
                   ByVal hPrevInstance As HINSTANCE, _
                   szCmdLine As String, _
                   ByVal iCmdShow As Integer ) As Integer   

    Dim hWin As HWND
    Dim msg As MSG
    Dim wndclass As WNDCLASS   
    Dim As HANDLE hIconLib
    hInst = hInstance ' for use when creating child windows, in WndProc()
    hIconLib = LoadLibrary("shell32")
    randomize
   
    if(not hPrevInstance) then:
        with wndclass
            .Style              = CS_HREDRAW or CS_VREDRAW
            .lpfnWndProc        = @WndProc
            .cbClsExtra         = 0
            .cbWndExtra         = 0
            .hInstance          = hInstance
            .hIcon              = LoadIcon(hIconLib,cptr(any ptr,173)) ' 173-yellow star. 239-butterfly
            .hCursor            = LoadCursor( NULL, IDC_ARROW )
            .hbrBackground      = GetStockObject(LTGRAY_BRUSH)
            .lpszMenuName       = null
            .lpszClassName      = strptr(szAppName)
        end with
        RegisterClass(@wndclass)    ' register a class for the main window
        with wndclass
            .lpfnWndProc        = @ChildWndProc
            .cbWndExtra         = sizeof(word)
            .hIcon              = null ' Child windows have no Icon
            .lpszClassName      = strptr(szChildClass)
        end with
        RegisterClass(@wndclass)    ' register a class for the child windows
    :endif

    hWin = CreateWindow(szAppName,"Checker3 Mouse Hit-Test Demo",_
        WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,_
        NULL,NULL,hInstance,null)
    ShowWindow(hWin,iCmdShow )
    UpdateWindow(hWin)
 
     While( GetMessage( @msg, NULL, 0, 0 ) <> FALSE )   
        TranslateMessage( @msg )
        DispatchMessage( @msg )
    Wend
    ''
    '' Program has ended
    ''
    Function = msg.wParam

End Function
jj2007
Posts: 1924
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Simple tutorial to create first Windows applications

Postby jj2007 » Feb 23, 2021 1:27

Dear MacQ,
Unfortunately, your code fails for all 4 of my frequently used compiler options. Two don't compile, two fail at CreateWindow (btw we use CreateWindowEx nowadays, as shown above). In particular, it's a good idea to do some error checking, see last line:

Code: Select all

    hWin = CreateWindow(szAppName,"Checker3 Mouse Hit-Test Demo",_
        WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,_
        NULL,NULL,hInstance,null)
        if hWin=0 Then MessageBox(0, "bad luck", "CwEx:", MB_OK) : ExitProcess(1)
srvaldez
Posts: 2635
Joined: Sep 25, 2005 21:54

Re: Simple tutorial to create first Windows applications

Postby srvaldez » Feb 23, 2021 1:42

@Macq
compiles and runs OK with -gen gas/gas64 but not with -gen gcc
jj2007
Posts: 1924
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Simple tutorial to create first Windows applications

Postby jj2007 » Feb 23, 2021 11:50

gcc version 8.1.0 (2018)
FreeBASIC Compiler - Version 1.07.1 (2019-09-27)
TmpFb.c:342:30: error: wrong type argument to bit-complement
if( (struct $11HINSTANCE__*)~HPREVINSTANCE$1 == (struct $11HINSTANCE__*)0u ) goto label$100;
dodicat
Posts: 6790
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Simple tutorial to create first Windows applications

Postby dodicat » Feb 23, 2021 12:14

line ~116
use
if( hPrevInstance=0) then:
bla
bla
(not hPrevInstance doesnt work in gcc).
You should be careful using not at any time.

OR
You should
if(not cint(hPrevInstance)) then:
bla
bla
If you must use not.(see the help file for not)
jj2007
Posts: 1924
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Simple tutorial to create first Windows applications

Postby jj2007 » Feb 23, 2021 19:14

dodicat wrote:line ~116
use
if( hPrevInstance=0) then:
That did the trick, plus
#define Unicode
#include once "windows.bi"
#define DIVISIONS 8

Apparently, Macq has a setting in his IDE that defines Unicode via the commandline (?) instead of doing it in the source.
Macq
Posts: 4
Joined: Feb 18, 2021 4:01
Location: Queensland, Australia

Re: Simple tutorial to create first Windows applications

Postby Macq » Feb 24, 2021 0:11

Sorry guys. I didn't mean to create such a stir. I'm using WinFBE Version 2.1.8 (64-bit). I haven't changed any compiler options.

Thanks for the input about not using not.

If I
#define Unicode

then I get

.lpszClassName = Strptr(szAppName) <-- Warning: Suspicious pointer assignment

The executable sits in the background and doesn't open a window.

Return to “Windows”

Who is online

Users browsing this forum: No registered users and 4 guests