Oxygen Basic
Programming => Problems & Solutions => Topic started by: Aurel on March 19, 2012, 09:58:31 AM
-
Hi..
The way how doevents function work is not very good option for gui
programming at all.
It is a good option for games.
Im looking into a way to simplify message loop,
what would be simpliest solution?
creating some sort of callback function in OpenWindow(setwindow) function or
maybe something else.
I also lookin in Xblite option.
any suggestion....?
-
I stuck again with message processing.
Example is translated from xblite example.
Is anyone here who can explain me why message is not translated or dispatched:
Include "awinh.inc"
#lookahead ' for procedures
INT win
INT winstyle
INT button1
INT ed1
INT Lb1
winstyle = WS_MINMAXSIZE or WS_CLIPCHILDREN
'create window
win = SetWindow("Test AwinH",100,100,640,480,winstyle)
print str(win)
'create button
button1 = SetButton(win,200,40,80,24,"button_1",0x50000001,0x200)
'create edit control
ed1 = SetEditBox(win,200,80,80,24,"edit 1",0,0)
'create listbox
Lb1 = SetListBox(win,200,140,180,240,"LB 1",0,0)
'WHILE GetMessage (&wm,0,0,0)<>0
'TranslateMessage &wm
'DispatchMessage &wm
'WEND
sys bRet
'
do while bRet := GetMessage (&wm, 0, 0, 0)
if bRet = -1 then
'show an error message
else
TranslateMessage &wm
DispatchMessage &wm
end if
wend
FUNCTION WndProc(byval win as INT,byval wMsg as INT,byval wParam as INT,byval lParam as INT)as INT callback
SELECT wMsg
'----------------------------
CASE WM_DESTROY
PostQuitMessage 0
'--------------------------------------
CASE WM_COMMAND
controlID = LoWord(wParam)
notifyCode = HiWord(wParam)
SELECT notifyCode
CASE BN_CLICKED
select controlID
case button1
Print str(button1)
end select
END SELECT
CASE ELSE
FUNCTION = DefWindowProc win,wMsg,wParam,lParam
END SELECT
END FUNCTION
-
I search more and almost think that something is wrong because i can't
intercept wMsg then i test message wm_destroy like this:
SELECT wMsg
'----------------------------
CASE WM_DESTROY
PRINT "CLOSED"
PostQuitMessage 0
'--------------------------------------
CASE WM_COMMAND
controlID = LoWord(wParam)
notifyCode = HiWord(wParam)
SELECT notifyCode
CASE BN_CLICKED
select controlID
case button1
Print str(button1)
end select
And it works but why then wm_command don't work is a mistery :-\
it is really weird.
i will try more... ;)
-
Hmmm i finally got to work something but still not as i espected :-\
BN_CLICKED respond but on every control which is created ::)
It looks that don't respond on controlID = LoWord(wParam)
So , i will try check again function LoWord....
-
Hi Aurel,
Could we see AWinh.inc?
Charles
-
yes of course..
nothing special as i say before just derived from peter wFunc ,and i just remove
wndproc function.
I'm not sure but LoWord & HiWord functions looks little bit weird to me.
what is exactly:
and lo,&hffff
shr hi,16
shr->what's that mean ???
another thing which i probably made wrong is when i create control.
Each control is without ID ::)
just return hendle this might couse problem,right?
like:
hButton = CreateWindowEx(_ext,"BUTTON",_btext,_bflag,_bx,_by,_bw,_bh,_bhwnd,0,0,0)
and better will be:
hButton = CreateWindowEx(_ext,"BUTTON",_btext,_bflag,_bx,_by,_bw,_bh,_bhwnd,controlID,0,0)
hmmm....what you mean ?
-
YES...
I finally got it what is wrong ,i add control ID in SetButton() function and work.
'syn : SetButton (hwnd,x,y,w,h,caption$,style,ext,controlID)
Function SetButton(byval _bhwnd as int,byval _bx as int,byval _by as int,byval _bw as int,byval _bh as int, byval _btext as string,byval _bflag as int,byval _ext as int,byval _cID as INT) as int
If _bflag=0
_bflag = 0x50000000
EndIf
_ext = 0
hButton = CreateWindowEx(_ext,"BUTTON",_btext,_bflag,_bx,_by,_bw,_bh,_bhwnd,_cID,0,0)
UpdateWindow _bhwnd
Function = hButton
End Function
Note:this function is inside awinh.inc
So now example code look like this :
Include "awinh.inc"
#lookahead ' for procedures
INT win
INT winstyle
INT button1,button2
INT ed1
INT Lb1
int ed2
INT b1ID,b2ID,b3ID,b4ID,b5ID,b6ID,b7ID
b1ID=100
b1ID=101
b1ID=102
b1ID=103
b1ID=104
b1ID=105
winstyle = WS_MINMAXSIZE or WS_CLIPCHILDREN
'create window
win = SetWindow("Test AwinH",100,100,640,480,winstyle)
'create buttons
button1 = SetButton(win,200,40,80,24,"button_1",0x50000001,0x200,b1ID)
button2 = SetButton(win,300,40,80,24,"button_2",0x50000001,0x200,b2ID)
'create edit control
ed1 = SetEditBox(win,200,80,80,24,"edit 1",0,0)
'create listbox
Lb1 = SetListBox(win,200,140,180,240,"LB 1",0,0)
'WHILE GetMessage (&wm,0,0,0)<>0
'TranslateMessage &wm
'DispatchMessage &wm
'WEND
sys bRet
'
do while bRet := GetMessage (&wm, 0, 0, 0)
if bRet = -1 then
'show an error message
else
TranslateMessage &wm
DispatchMessage &wm
end if
wend
Function WndProc(byval hWnd as long,byval wMsg as long, byval wParam as long,byval lparam as long) as long callback
SELECT wMsg
'----------------------------
CASE WM_DESTROY
PostQuitMessage 0
'-------------------------------------------------------------
CASE WM_COMMAND
controlID = LoWord(wparam) 'get control ID
notifyCode = HiWord(wParam) 'get notification message
Select controlID
Case b1ID
If notifycode=0
Print "Button 1 Clicked!"
End If
Case b2ID
If notifycode=0
Print "Button 2 Clicked!"
End If
End Select
'-----------------------------------------------------
END SELECT
FUNCTION = DefWindowProc hwnd,wMsg,wParam,lParam
END FUNCTION
-
Next step is set default gui font and add string to listbox.
Look into attachment,manifest work fine ;)
Include "awinh.inc"
#lookahead ' for procedures
INT win
INT winstyle
INT button1,button2
INT edit1,edit2,edit3
INT Lbox
INT ed1ID,ed2ID,ed3ID
INT b1ID,b2ID,b3ID,b4ID,b5ID,b6ID,b7ID
INT LboxID=300
b1ID=100
b1ID=101
b1ID=102
b1ID=103
b1ID=104
b1ID=105
ed1ID=200
ed2ID=201
ed3ID=202
winstyle = WS_MINMAXSIZE or WS_CLIPCHILDREN
'create window
win = SetWindow("Test AwinH",100,100,640,480,winstyle)
'create buttons
button1 = SetButton(win,200,40,80,24,"button_1",0x50000000,0x200,b1ID)
button2 = SetButton(win,300,40,80,24,"button_2",0x50000000,0x200,b2ID)
'create edit control
edit1 = SetEditBox(win,200,80,180,24,"edit 1",0x50004000,0x200,ed1ID)
'create listbox
Lbox = SetListBox(win,200,140,180,240,"LB 1",0x50000140,0x200,LboxID)
SendMessage Lbox,LB_ADDSTRING,0,"First Item"
'WHILE GetMessage (&wm,0,0,0)<>0
'TranslateMessage &wm
'DispatchMessage &wm
'WEND
sys bRet
'
do while bRet := GetMessage (&wm, 0, 0, 0)
if bRet = -1 then
'show an error message
else
TranslateMessage &wm
DispatchMessage &wm
end if
wend
Function WndProc(byval hWnd as long,byval wMsg as long, byval wParam as long,byval lparam as long) as long callback
SELECT wMsg
'----------------------------
CASE WM_DESTROY
PostQuitMessage 0
'-------------------------------------------------------------
CASE WM_COMMAND
controlID = LoWord(wparam) 'get control ID
notifyCode = HiWord(wParam) 'get notification message
Select controlID
Case b1ID
If notifycode=0
Print "Button 1 Clicked!"
End If
Case b2ID
If notifycode=0
Print "Button 2 Clicked!"
End If
End Select
'-----------------------------------------------------
END SELECT
FUNCTION = DefWindowProc hwnd,wMsg,wParam,lParam
END FUNCTION
-
SHR
Means Shift right the bits in a value. shr hi,16
A wparam is a 4 byte variable and the two most significant bytes are considered the Hiword of the wparam.
The two least significant bytes are the Loword of the wparam.
To get the value of the Hiword out of the wparam you shift the value 16 bits to the right which places the Hiword in the Loword position and it can be extracted as a word value this way.
-
thanks izzy77 on explanation ;)
-
Small step next...added bitmap button.
'loadbmp
'##########################################
INT bmpB1
bmpB1 = LoadImage(0,"data/xpBopen.bmp",0,76,20,16)
then:
button1 = SetButton(win,200,40,80,24,"",0x50000080,0x200,b1ID)
'set bitmap on button 1
SendMessage button1 , BM_SETIMAGE, 0, bmpB1
-
Just tested and added static control creation.
Here is code:
'create static control
static1 = SetStatic(win,10,20,254,16," This is a STATIC text control with EX_CLIENTEDGE",0,0x200,st1ID)
static2 = SetStatic(win,10,40,254,13," This is a STATIC text control without ex_ClientEdge ",0,0,st1ID)
'crete static control with bitmap
static3 = SetStatic(win,10,60,82,82,"",0x5000030E,0,st3ID)
SendMessage static3 ,370, 0, bmpS1
In attachment is screenshot how look.
-
Looking good!
-
Thanks Kent ;)
-
I try to add function SetText and found some weird problem.
When i try to change edit control text with:
SUB SetControlText
string n$
int n=3
n$ = str(n)
print n$ '....this work properly
SendMessage edit1,WM_SETTEXT,1,n$
but text in control is not changed ???
So i try change variable type to sys n$="new text"
and sometimes work and sometimes not.
-
Infact n$ = str(n) don't work if n$ is defined as string .
which is really weird to me ???
-
Oh my ,oh my i am really confused with all this string types.
It looks that i must use bString instead of just string.
So it looks that this work:
SUB SetControlText
bstring n$
n$=""
n$ = str(10)
SendMessage edit1,WM_SETTEXT,0,n$
'UpdateWindow(edit1)
END SUB
I will try this inside loop... ;)
-
OK,here is part with for loop,and work fine ;)
SUB SetControlText
bstring n$
n$=""
'loop
For i = 0 To 10000
n$ = Str(i)
SendMessage edit1,WM_SETTEXT,0,n$
UpdateWindow(edit1)
Next i
END SUB
-
Hi Aurel
Oxygen ignores % and $ endings, so you were using the same variable when you intended to have 2 different variable types named n.
Bstrings are not garbage collected, so you need to free them when finished.
frees n
But if you prefer to use standard strings with the win64.inc definition of SendMessage: (it has not been given a prototype)
string n
....
SendMessage edit1,WM_SETTEXT,0,*n$
Charles
-
Bstrings are not garbage collected, so you need to free them when finished.
-Hmmm ok,but it looks that don't couse any problems after exiting.
Charles,i even don't look into win64.h as you may see i prefer my own version of header,
by the way i don't think that is something wrong with win64.h.
I mean that win64 is only used for 64bit systems and almost forget about what is it.
my fault...
And one weird thing to me *n$ - it looks like pointer of n.string ,right?
And yeah,i still use 034 version,heh work fine for me,sounds strange maybe...
thanks on reply...
-
If local Bstrings are left to accumulate, they will eventually fill the entire memory space while the program is running. The problem does not usually reveal itself in short-run programs, but task-manager is useful for spotting memory leaks of this kind.
Peter's win64.inc and my MinWin.inc both have some API calls - low level, without prototypes which mean that the parameters have to be a perfect match.
But when functions are declared in the usual way, type matching and byval/byref are automatically handled by the compiler. Then no need for '*'
when passing string n$.
Like PowerBasic strings, OxygenBasic strings are double pointered: they are indirect Bstrings.
Charles
-
If local Bstrings are left to accumulate, they will eventually fill the entire memory space while the program is running. The problem does not usually reveal itself in short-run programs, but task-manager is useful for spotting memory leaks of this kind.
-Ok, i understand what you mean but as is local veriable why is not destroyed when
end sub executed.I see that you say that is not destroyed with garbage colector.
In my case i test 100000 iteration inside edit control and watch mem-footprint in task
manager and footprint is same about cca 2245k which looks fine to me.
Peter's win64.inc and my MinWin.inc both have some API calls - low level, without prototypes which mean that the parameters have to be a perfect match.
- Mine include is not something special just same thing derived from Peter header with
some api calls for creating controls .
But without WndProc.
Here is code:
Include "awinh.inc"
#lookahead ' for procedures
% LR_LOADTRANSPARENT = &H20
% LR_LOADMAP3DCOLORS = &H1000
INT TransparentMap3D = LR_LOADTRANSPARENT or LR_LOADMAP3DCOLORS
INT win
INT winstyle
INT button1,button2
INT edit1,edit2,edit3
INT Lbox,static1,static2,static3
INT ed1ID,ed2ID,ed3ID
INT b1ID,b2ID,b3ID,b4ID,b5ID,b6ID,b7ID
INT LboxID = 300
INT st1ID,st2ID
b1ID=100
b1ID=101
b1ID=102
b1ID=103
b1ID=104
b1ID=105
'-----------------
ed1ID=200
ed2ID=201
ed3ID=202
'----------------
st1ID=350
st2ID=351
st3ID=352
'----------------
'loadbmp
'##########################################
INT bmpB1,bmpS1
bmpB1 = LoadImage(0,"data/xpBopen.bmp",0,76,20,16)
bmpS1 = LoadImage(0,"data/xpStatic.bmp",0,82,82,16)
'##########################################
winstyle = WS_MINMAXSIZE or WS_CLIPCHILDREN
'create window
win = SetWindow("Test AwinH",100,100,640,480,winstyle)
'create buttons
button1 = SetButton(win,280,20,80,24,"",0x50000080,0x200,b1ID)
'set bitmap on button 1
SendMessage button1 , BM_SETIMAGE, 0, bmpB1
button2 = SetButton(win,380,20,80,24,"button_2",0x50000000,0x200,b2ID)
'create edit control
edit1 = SetEditBox(win,200,80,180,24,"edit 1",0x50004000,0x200,ed1ID)
'create listbox
Lbox = SetListBox(win,200,140,180,150,"LB 1",0x50000140,0x200,LboxID)
'create static control
static1 = SetStatic(win,10,20,254,16," This is a STATIC text control with EX_CLIENTEDGE",0,0x200,st1ID)
static2 = SetStatic(win,10,40,254,13," This is a STATIC text control without ex_ClientEdge ",0,0,st1ID)
'crete static control with bitmap
static3 = SetStatic(win,10,60,82,82,"",0x5000030E,0,st3ID)
SendMessage static3 ,370, 0, bmpS1
'---------------------------------------------------------------------
GoSub AddListboxItems
'WHILE GetMessage (&wm,0,0,0)<>0
'TranslateMessage &wm
'DispatchMessage &wm
'WEND
sys bRet
'
Do While bRet := GetMessage (&wm, 0, 0, 0)
If bRet = -1 then
'show an error message
Else
TranslateMessage &wm
DispatchMessage &wm
End If
Wend
Function WndProc(byval hWnd as long,byval wMsg as long, byval wParam as long,byval lparam as long) as long callback
SELECT wMsg
'----------------------------
CASE WM_DESTROY
PostQuitMessage 0
'-------------------------------------------------------------
CASE WM_COMMAND
controlID = LoWord(wParam) 'get control ID
notifyCode = HiWord(wParam) 'get notification message
Select controlID
Case b1ID
If notifycode=0
Beep(1660,50)
Print "Button 1 Clicked!"
End If
Case b2ID
If notifycode=0
Gosub SetControlText
End If
End Select
'-----------------------------------------------------
END SELECT
FUNCTION = DefWindowProc hwnd,wMsg,wParam,lParam
END FUNCTION
'########################################################
SUB AddListboxItems
bstring i$ : i$=""
For n = 0 To 100
i$=Str(n) + "..listbox item"
SendMessage Lbox,LB_ADDSTRING,0,i$
Next n
END SUB
'#########################################################
SUB SetControlText
bstring n$
n$=""
'loop
For i = 0 To 100000
n$ = Str(i)
SendMessage edit1,WM_SETTEXT,0,n$
UpdateWindow(edit1)
Next
END SUB
-
In my case i test 100000 iteration inside edit control and watch mem-footprint in task
manager and footprint is same about cca 2245k which looks fine to me.
Hi Aurel,
I need to explain a little further
In your SetControlText procedure the compiler can see n$ being reused 10000 times, so it frees the previous bstring and creates a new one for each iteration of the loop.
When the routine ends, only one n$ Bstring remains in memory.
So, if you call your SetControlText procedure 10000 times instead, you will end up with 10000 bstrings in system memory. And you should be able to see that in Task Manager.
Charles
-
I ask me, if he understands that.
He still uses Version 034, which is faulty and has extra memory leaks.
Yeah,yeah...o
Ok ,maybe i dont understand and mybe im completely stupid.
But if you don't belive try executable from attachment and you will see that memory not grow up.
On my computer stay on 2540k.
I even test 100x10000 iteration and is still same.
Case b2ID
If notifycode=0
again:
Gosub SetControlText
count=count+1
IF count < 100 then goto again
End If
-
I like the grass Peter, this is how Football pitches are laid.
-
Of course that you get crush even you move mouse,because WM_MOUSEMOVE messasge is sended
and is not intercepted when loop run.
So just clik on buton and leave mouse,and don't tuch anything ;D
Ok i maybe made to much interating ,so i decrease looping to 10x10000 by clicking on button_2.
I think that i must add function like WaitWindowMessages inside long loops which can intercept win
message inside runing loop.
I must look into CB source or DCompiler source and see how is solwed there.
About mem-leak ...nothing ,task.manager display still 2540k of used.
-
But the OPEN BUTTON is fishy
heh,what you mean fishy?
Do you mean on classic control theme button?
This button is classic bitmap button which only can have this style.
I don't know how to create themed (xpstyle button) yet :-\
-
After few hours of searching for a right style i finally add RichEdit control.
'create Rich Edit control
INT reStyle = WS_CHILD|WS_VISIBLE|ES_MULTILINE|ES_WANTRETURN|WS_VSCROLL|WS_HSCROLL|ES_AUTOVSCROLL|ES_AUTOHSCROLL|ES_SUNKEN
'INT reStyle = 0x508010C4
richedit1 = SetRichEdit(win,300,80,200,150,"Text in Richedit...",reStyle ,0x200,reID)
Function from header:
Dim kernel32,user32,gdi32,riched32
kernel32 = LoadLibrary "kernel32.dll"
user32 = LoadLibrary "user32.dll"
gdi32 = LoadLibrary "gdi32.dll"
riched32 = LoadLibrary "riched32.dll"
unction SetRichEdit(byval _ehwnd as int,byval _ex as int,byval _ey as int,byval _ew as int,byval _eh as int, byval _etext as string,byval _eflag as int,byval _ext as int,byval _cID as INT) as int
INT _hfont
If _eflag=0
'0x50800080 single , 0x50B010C4 multiline
_eflag = 0x50800080 or ES_SUNKEN
EndIf
hRichEdit = CreateWindowEx(_ext,"richedit20a",_etext,_eflag,_ex,_ey,_ew,_eh,_ehwnd,_cID,0,0)
_hfont = GetStockObject(17)
SendMessage hRichEdit,WM_SETFONT,_hfont,0
UpdateWindow _ehwnd
Function = hRichEdit
End Function