-
Windows API `Hello World!`
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]
-
Re: Windows API `Hello World!`
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
-
Re: Windows API `Hello World!`
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 equates :shock: It does make you wonder.
Charles.
-
Re: Windows API `Hello World!`
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? :roll:
-
Re: Windows API `Hello World!`
Quote:
Originally Posted by zlatkoAB
But I recive error message :
Error code 18
Error description Unknown keyword
Line number 262
Line code O2_Basic src
What i do wrong? :roll:
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.
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
-
Re: Windows API `Hello World!`
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
-
Re: Windows API `Hello World!`
Quote:
Originally Posted by Charles Pegge
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.
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 ... :oops: Oh well, not that worried about it. :unguee:
Mark
-
Re: Windows API `Hello World!`
Sorry I think that I make mistake :roll:
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.
Code:
lpfnwndproc as long
So is this thing do .dll included in zip?
Or is this normal thing which can be executed from other
interpreter which support api-s?
Zlatko
-
Re: Windows API `Hello World!`
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
-
Re: Windows API `Hello World!`
Charles you are great,thanks. :D
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
-
Re: Windows API `Hello World!`
You dont often need getCommandline, this works fine :)
[code=thinbasic]
inst=GetModuleHandle 0
WinMain inst,0,0,SW_NORMAL
[/code]
-
Re: Windows API `Hello World!`
Aha...
Ok I will try tomorow,becose i get sleep.
Thanks again... :)
-
Re: Windows API `Hello World!`
Charles i try all posible combination but still refuse to work :(
-
Re: Windows API `Hello World!`
Hi Zlatco
You can run a message box even before entering WinMain and see whether your system returns a plausible module handle. (Zero means it wont give you one.). Messageboxes are one of the best debugging tools when dealing with low level Windows stuff, (As long as they are not used inside a long loop :) )
In O2H:
[code=thinbasic]
cmdline=GetCommandLine
inst=GetModuleHandle 0
print str inst
[/code]
-
Re: Windows API `Hello World!`
Hi Charles...
I know that MessageBox is great tool and i use them alot when i make
some stuff in my interpreter.
but this time I think that is useless I think that CBasic is limited in
current case (Paul told me that is not posibile?)
If you wish I can sand you Pm with source code.
You are expert in this area.
I do everithing but whitout succses,I'm little bit disapointed.
-
Re: Windows API `Hello World!`
Have you looked at FreeBasic, Zlatco? I chose to use it for Oxygen because of its cross-platform capability and compiling down to x86 code, of course. Though I have not explored all of its features, I find it to be very stable,predictable and fast, which are all essential for building higher level software systems.
Charles.
-
Re: Windows API `Hello World!`
Yes Free Basic is good and probably is capable for producing
Window from API becose is compiler.
I already have EBasic which is capable for that.
As i see thinBasic can't produce Window from API directly
without your oxigen module and without .dll included.
Or maby I'm wrong?
Thanks Zlatko
-
Re: Windows API `Hello World!`
ThinBasic can certainly call any DLL directly by using a declaration with a LIB specification. The main issue is can it handle a low level callback for an interpreted Wndproc - Eros would be able to answer this one :)
Charles
-
Re: Windows API `Hello World!`
Yes the main problem is in WinProc.
So how return function directly
Code:
case else
function=DefWindowProc hWnd,wMsg,wParam,lParam
To here:
Code:
lpfnWndProc=&WndProc '#long#long#long#long
This part don't work from CBasic.
Maby thinBasic can do that.
If can ,that would be fantastic.
So Eros what you say it is posible directly from thinBasic open
window with API-s-?
-
Re: Windows API `Hello World!`
Quote:
Originally Posted by zlatkoAB
Paul told me that is not posibile?
Hi Zlatko,
don't believe everything you get told by this guy, especially when he sells a competing commercial product.
There is allways a possibility.
Cheers
Michael
-
Re: Windows API `Hello World!`
Hi Michael...
I don't believe everything what he saying but this time i think
that is true.It looks that is Cbasic limited in this concret problem.
I have source code from VB6 for API Window but I don't try them
yet.As i see thinBasic can do that with oxygen modul and with
oxygen .dll .
Maby it's posible directly - that would be cool.
Zlatko
-
Re: Windows API `Hello World!`
Ok, I thought he ment in general not possible.
-
Re: Windows API `Hello World!`
Hi I must say that is very interesting problematic and like Charles say
i find something very interesting on Free Basic Forum.Look code:
Code:
#Include "windows.bi"
Dim As MSG msg ' Message variable (stores massages)
Dim As HWND hWnd ' Window variable
' Create window
hWnd = CreateWindowEx( 0, "#32770", "Hello", WS_OVERLAPPEDWINDOW Or WS_VISIBLE, 100, 100, 500, 300, 0, 0, 0, 0 )
While GetMessage( @msg, 0, 0, 0 ) ' Get message from window
TranslateMessage( @msg )
DispatchMessage( @msg )
Select Case msg.hwnd
Case hWnd ' If msg is window hwnd: get messages from window
Select Case msg.message
Case 273 ' Get message when 'X' was pressed
End
End Select
End Select
Wend
You must say that look very simple. :roll:
And little bit weird.So i try something similiar on CBasic and work
but not properly.I can open new window,without focus and can not
be closed with closebox button"X".One interesting thing ,window is
like standalone compiled app :shock:
I don't try on thinBasic bacose i don't know shape of APi-s.
Is the same like this or different?
Code:
DECLARE "user32",CreateWindowExA(dwExStyle AS INT,lpClassName AS STRING,lpWindowName AS STRING,dwStyle AS INT,x AS INT,y AS INT,nWidth AS INT,nHeight AS INT,hWndParent AS INT,hMenu AS INT,hInstance AS INT,lpParam AS INT),INT
DECLARE "user32",GetMessageA(lpMsg AS MSG,hwnd AS INT,wMsgFilterMin AS INT,wMsgFilterMax AS INT),INT
DECLARE "user32",TranslateMessage(lpMsg AS MSG),INT
DECLARE "user32",DispatchMessageA(lpMsg AS MSG),INT
DECLARE "user32", PostQuitMessage(nExitCode AS INT)
-
Re: Windows API `Hello World!`
Hi Zlatco,
Try 256 instead of 273. 256 is the WM_KEYDOWN message -
this is what I tried in o2h (wm is the message variable)
[code=thinbasic]
while GetMessage &wm,0,0,0
TranslateMessage &wm
DispatchMessage &wm
'
select wm.hwnd
case hwnd
if wm.message=256 then print `key down` : exit do
end select
'
wend
[/code]
-
Re: Windows API `Hello World!`
Hi Charles...
I always recive error that Argument is wrong type in
Code:
While GetMessageA( wmsg,0, 0, 0 ) :' Get message from window
So which message close window?
Or what argument is wrong ,hmm it looks very tricky.
-
Re: Windows API `Hello World!`
GetMessage needs the address of the message: varptr(msg) &msg or @msg, whatevever syntax Cbasic uses.
I am assuming the Win header files follow the standard C version.
Charles
-
Re: Windows API `Hello World!`
Aha I see ...
So there is the main problem .
CBasic can't pass or see adress so only I can try with pointer.
But i think that is not posible.
Whatever thanks on all answers,Charles.
Zlatko