It is amazing how much code it takes to do something so simple. That's why I like BASIC syntax. But, sometimes it is good to remind yourself what all is going on in the background.
Mark
This will be instantly recognisable to any one who has worked direclty with the Windows API.
[code=thinbasic]
' Windows Hello World
' with winmain message loop and wndproc
' Revised 20 Mar 2009
' Charles Pegge
Uses "Oxygen","File"
dim src as string
src="
type WNDCLASS
;40 bytes
STYLE as long
lpfnwndproc as long
cbClsextra as long
cbWndExtra as long
hInstance as long
hIcon as long
hCursor as long
hbrBackground as long
lpszMenuName as long
lpszClassName as long
end type
type point
x as long
y as long
end type
type MSG
; 28 bytes
hwnd as long
message as long
wParam as long
lParam as long
time as long
pt as point
end type
dim kernel32,user32,GDI32 as long
kernel32=LoadLibrary `kernel32.dll`
user32=LoadLibrary `user32.dll`
GDI32=LoadLibrary `GDI32.dll`
bind kernel32
(
GetCommandLine GetCommandLineA ; @0
GetModuleHandle GetModuleHandleA ; @4
ExitProcess ExitProcess ; @4
)
bind user32
(
LoadIcon LoadIconA ; @8
LoadCursor LoadCursorA ; @8
RegisterClass RegisterClassA ; @4
MessageBox MessageBoxA ; @4
CreateWindowEx CreateWindowExA ; @48
ShowWindow ShowWindow ; @8
UpdateWindow UpdateWindow ; @4
GetMessage GetMessageA ; @16
TranslateMessage TranslateMessage ; @4
DispatchMessage DispatchMessageA ; @4
PostQuitMessage PostQuitMessage ; @4
BeginPaint BeginPaint ; @8
EndPaint EndPaint ; @8
GetClientRect GetClientRect ; @8
DrawText DrawTextA ; @20
PostMessage PostMessageA ; @16
DefWindowProc DefWindowProcA ; @16
)
bind GDI32
(
GetStockObject GetStockObject ; @4
)
'
def SW_NORMAL 1
def SW_SHOWDEFAULT 10
dim cmdline,inst as long
cmdline=GetCommandLine
inst=GetModuleHandle 0
declare Function WinMain(byval inst as long ,byval prevInst as long ,byval cmdline as long , byval show as long) as long
declare function WndProc(byval hWnd as long, byval wMsg as long, byval wParam as long, byval lparam as long) as long
WinMain inst,0,cmdline,SW_NORMAL
freelibrary kernel32
freelibrary user32
freelibrary gdi32
terminate
; o2 !10 ; align 16 bytes
;=====================================
% CS_VREDRAW 1
% CS_HREDRAW 2
% IDI_APPLICATION 32512
% IDC_ARROW 32512
% WHITE_BRUSH 0
% MB_ICONERROR 16
def CW_USEDEFAULT 0x80000000
def WS_OVERLAPPEDWINDOW 0x00cf0000
'------------------------------------------------------------
Function WinMain(byval inst as long ,byval prevInst as long,
byval cmdline as long , byval show as long) as long
'===========================================================
'
; window handle
dim a,b,c,hWnd as long
dim wc as WndClass
dim wm as MSG
with wc. '
style=CS_HREDRAW or CS_VREDRAW
lpfnWndProc=&WndProc '#long#long#long#long
cbClsExtra=0
cbWndExtra=0
hInstance=inst
hIcon=LoadIcon 0, IDI_APPLICATION
hCursor=LoadCursor 0,IDC_ARROW
hbrBackground=GetStockObject WHITE_BRUSH '
lpszMenuName=0
lpszClassName=`HelloWin`
end with
if not RegisterClass &wc
MessageBox 0,`Registration failed`,`Problem`,MB_ICONERROR
exit function
end if '
hWnd=CreateWindowEx 0,wc.lpszClassName,`Hello Window`,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,640,480,
0,0,inst,0
if not hWnd then
MessageBox 0,`Unable to create window`,`problem`,MB_ICONERROR
exit function
end if
'
ShowWindow hWnd,show
UpdateWindow hWnd
;
;MESSAGE LOOP
;
while GetMessage &wm,0,0,0
TranslateMessage &wm
DispatchMessage &wm
wend
;
function=wm.wparam
end function ; end of WinMain
type RECT
; 16 bytes
left as long
top as long
right as long
bottom as long
end type
type rgbacolor
red as byte
green as byte
blue as byte
alpha as byte
end type
type PAINTSTRUCT
; 64 bytes
hDC as long
fErase as long
rcPaint as rect
fRestore as long
fIncUpdate as long
rgb as rgbacolor
Reserved as 32
end type
% WM_CREATE 1
% WM_DESTROY 2
% WM_PAINT 15
% WM_CLOSE 16
% WM_KEYDOWN 256
'-----------------------------------------
function WndProc ( byval hWnd as long,
byval wMsg as long, byval wParam as long,
byval lparam as long ) as long callback
'=========================================
dim cRect as rect
dim Paintst as paintstruct
dim hDC as long
select wMsg
'--------------
case WM_CREATE
'=============
'--------------
case WM_DESTROY
'===============
PostQuitMessage 0
'------------
case WM_PAINT
'============
hDC=BeginPaint hWnd,&Paintst
GetClientRect hWnd,&cRect
; style
; 0x20 DT_SINGLELINE
; 0x04 DT_VCENTER
; 0x01 DT_CENTER
; 0x25
DrawText hDC,`Hello World!`,-1,&cRect,0x25
EndPaint hWnd,&Paintst
'--------------
case WM_KEYDOWN
'==============
if wParam=27 then
PostMessage hWnd,WM_CLOSE,0,0
end if
'--------
case else
'========
function=DefWindowProc hWnd,wMsg,wParam,lParam
end select
end function ' WndProc
"
o2_basic src
'File_Save("t.txt",o2_len+$cr+o2_error+"o2h "+o2_prep src ) ': stop
if len(o2_error) then msgbox 0,o2_error : stop
o2_exec
[/code]
It is amazing how much code it takes to do something so simple. That's why I like BASIC syntax. But, sometimes it is good to remind yourself what all is going on in the background.
Mark
Hi Mark,
Yes the Windows API is a ponderous beast - but the program here also incorporates a chunk of the Windows equates which are normally hidden away somewher in header files.
In the 4 port Viewer example, The header files for Opengl, supplied with thinBasic are invoked and they contain about 5000 equatesIt does make you wonder.
Charles.
Hi...
Charles, i'm fascinating with your oxigen compiler.
But why this example dont work on my computer.
I have downloaded last thinBasic release and your TBO2H zip with
.dll?
I do next:
Copy and paste this example in ThinAir and start.
But I recive error message :
Error code 18
Error description Unknown keyword
Line number 262
Line code O2_Basic src
What i do wrong?![]()
I had this same problem when I tried to open it. I replaced the DLL file that comes with TB with the one you downloaded seperately.Originally Posted by zlatkoAB
The DLLs are found in the thinbasic/Lib folder of your TB installation. Put the newsest Oxygen DLL in there. You will probably have to replace it with an older one.
Mark
As this is a prerelease version of Oxygen, the best thing to do is to leave the DLL in the same directory as the scripts that use it. thinBasic will then use this version instead of the original (Assembler only) Oxygen.
Did you manage to capture the full script ZLatko? I know it is a bit lengthy for a posting. There is a copy in the zip file 029.tbasic
Charles
Good thing to know, and the safer way to do it. But, of course, you could make a back up of the original ... which I didn't do ...Originally Posted by Charles Pegge
Oh well, not that worried about it.
Mark
Sorry I think that I make mistake
I don't know that i use tb 1.7.0.0 so I uninstall 1.7.0.0 and just
download 1.7.7.0 .
Then I unpak oxigen.zip in oxygen folder .
Finaly I found this example 029 and work fine.
Great!
I'm little curious,someona told me that is not posible made
window from api with interpreter becose lpfnwndproc can't be
fired from interpreter.
I see that in this example is posible.
So is this thing do .dll included in zip?lpfnwndproc as long
Or is this normal thing which can be executed from other
interpreter which support api-s?
Zlatko
Hi Zlatco,
If your interpreter supports API calls then you can certainly run Windows from it directly
This is the code which you may not see in other compilers. It calls WinMain, and it is what you have to do at the very start of your procedure.
[code=thinbasic]
dim cmdline,inst as long
cmdline=GetCommandLine
inst=GetModuleHandle 0
declare Function WinMain(byval inst as long ,byval prevInst as long ,byval cmdline as long , byval show as long) as long
declare function WndProc(byval hWnd as long, byval wMsg as long, byval wParam as long, byval lparam as long) as long
WinMain inst,0,cmdline,SW_NORMAL
[/code]
But you may encounter timing problems if you try to run the message loop in interpreted code. In some of my early experiments with scripting languages, Some Windows messages seemed to time out. So you will probably need to manage the message loop as an internal operation.
Charles
Charles you are great,thanks.
Yes I see something similiar but without WinMain .
Yes CBasic support API-s.
I have error with
"kernel32",_GetCommandLine ALIAS GetCommandLineA(),STRING
Ok i will try on your way.
Zlatko