 |
Bay Six Software Beyond the Basics
|
View previous topic :: View next topic |
Author |
Message |
Mattestion New Member
Joined: 29 Feb 2012 Posts: 4
|
Posted: Feb 29th, 2012, 2:54am Post subject: GUI skin (sort of) |
|
|
I'm trying to use a bmp for the background of a window that will have controls. I've been able to do that but the problem I'm having is I can't close the window without using Ctrl+Alt+Del. Here is the code:
Code: |
nomainwin
open "WMLiberty" for dll as #wmlib
loadbmp "skin", "bmp\skin.bmp"
WindowWidth = 520
WindowHeight = 400
UpperLeftX=int((DisplayWidth-WindowWidth)/2)
UpperLeftY=int((DisplayHeight-WindowHeight)/2)
open "Skinned Window" for window_nf as #skin
#skin "trapclose [QUIT]"
callback lpfn, OnPaint ( ulong, ulong, ulong, ulong ), long
hwndSkin = hwnd(#skin)
calldll #wmlib, "SetWMHandler", _
hwndSkin as ulong, _
_WM_PAINT as ulong, _
lpfn as ulong, _
0 as long, _
ret as long
#skin "hide"
#skin "show"
[LOOP]
scan
calldll #kernel32, "Sleep", _ 'Minimize CPU usage
50 as long, _
ret as void
goto [LOOP]
[QUIT]
close #skin
close #wmlib
end
function OnPaint(hwnd, uMsg, wParam, lParam)
hdc = GetDC(hwnd)
dcSkin = CreateCompatibleDC(hdc)
r = SelectObject(dcSkin, hbmp("skin"))
r = BitBlt(hdc, 0,0,520,400, dcSkin, 0, 0, _SRCCOPY)
r = DeleteDC(dcSkin)
r = ReleaseDC(hwnd, hdc)
r = DeleteObject(hbmp("skin"))
end function
function GetDC(h)
calldll #user32, "GetDC",_
h as ulong,_ 'graphicbox handle
GetDC as ulong 'returns handle to device context
end function
function ReleaseDC(h, hdc)
calldll #user32, "ReleaseDC",_
h as ulong,_ 'window handle
hdc as ulong,_ 'device context
ReleaseDC as long
end function
function DeleteDC(hDCM)
calldll #gdi32, "DeleteDC", _
hDCM as ulong, _
DeleteDC as long
end function
function CreateCompatibleDC(hDC)
calldll #gdi32, "CreateCompatibleDC", _
hDC as ulong, _ 'current screen
CreateCompatibleDC as ulong 'handle of memory DC
end function
function SelectObject(hDC,hImage)
calldll #gdi32, "SelectObject", _
hDC as ulong, _
hImage as ulong, _
SelectObject as ulong
end function
function DeleteObject(memBmp)
calldll #gdi32, "DeleteObject", _
memBmp as ulong, _
DeleteObject as long
end function
function BitBlt(hDCdest, xDest, yDest, xWidth, yHeight, hDCsource, xSrc, ySrc, ROP)
CallDll #gdi32, "BitBlt", _
hDCdest as ulong,_ 'The destination DC
xDest as long,_ 'x location on destination
yDest as long,_ 'y location on destination
xWidth as long,_ 'width to transfer
yHeight as long,_ 'height to transfer
hDCsource as ulong,_ 'The source DC
xSrc as long,_ 'x location in source
ySrc as long,_ 'y location in source
ROP as ulong,_ 'The operation to be performed
BitBlt as long 'nonzero if successful
end function
|
Here is a link to download the image: skin.bmp _________________ Just BASIC v1.01 / Liberty BASIC Pro v4.04 / Run BASIC v1.01 / Vista Home Premium SP2 - AMD Athlon 64 X2 Dual Core Processor 5000+ 2.60 GHz - 2GB RAM |
|
Back to top |
|
 |
RichardRussell Full Member
Joined: 28 Jan 2012 Posts: 57 Location: Downham Market, UK
|
Posted: Feb 29th, 2012, 11:23pm Post subject: Re: GUI skin (sort of) |
|
|
Mattestion wrote: | I'm trying to use a bmp for the background of a window that will have controls. |
This may be a silly question, but have you tried the simple approach of using a graphics window? I know the docs say "They are not intended to contain controls" and "some controls do not work properly" but you may find that in practice they work fine. I believe I'm right in saying that in LB Βooster any control which works in a window of type 'Window' will also work in a window of type 'Graphics'.
Richard.
http://lbbooster.com/ |
|
Back to top |
|
 |
Brent Site Admin
Joined: 01 Jul 2005 Posts: 793
|
Posted: Mar 1st, 2012, 12:51am Post subject: Re: GUI skin (sort of) |
|
|
Hello and welcome,
Sorry about the slow response--bad thunderstorms here. Anyway, I think I found a way to do what you want.
Code: | struct ps,_ 'PAINTSTRUCT
hdc as ulong, _
fErase as long, _
rcPaint.left as long, _
rcPaint.top as long, _
rcPaint.right as long, _
rcPaint.bottom as long, _
fRestore as long, _
fIncUpdate as long, _
rgbReserved as char[32]
open "WMLiberty" for dll as #wmlib
loadbmp "skin", "bmp\skin.bmp"
WindowWidth = 520
WindowHeight = 400
UpperLeftX=int((DisplayWidth-WindowWidth)/2)
UpperLeftY=int((DisplayHeight-WindowHeight)/2)
open "Skinned Window" for window_nf as #skin
#skin "trapclose [QUIT]"
callback lpfn, OnPaint ( ulong, ulong, ulong, ulong ), long
hwndSkin = hwnd(#skin)
calldll #wmlib, "SetWMHandler", _
hwndSkin as ulong, _
_WM_PAINT as ulong, _
lpfn as ulong, _
0 as long, _
ret as long
Call EraseWindow hwnd(#skin)
[LOOP]
scan
calldll #kernel32, "Sleep", _ 'Minimize CPU usage
50 as long, _
ret as void
goto [LOOP]
[QUIT]
close #skin
close #wmlib
unloadbmp "skin"
end
function OnPaint(hwnd, uMsg, wParam, lParam)
hSkinBmp = hbmp("skin")
dcSkin = CreateCompatibleDC(0)
hOldBmp = SelectObject(dcSkin, hSkinBmp)
CallDLL #user32, "BeginPaint", hwnd as ulong, ps as struct, ret as long
r = BitBlt(ps.hdc.struct, 0,0,520,400, dcSkin, 0, 0, _SRCCOPY)
CallDLL #user32, "EndPaint", hwnd as ulong, ps as struct, ret as long
ret = DeleteObject(dcSkin)
end function
function GetDC(h)
calldll #user32, "GetDC",_
h as ulong,_ 'graphicbox handle
GetDC as ulong 'returns handle to device context
end function
function ReleaseDC(h, hdc)
calldll #user32, "ReleaseDC",_
h as ulong,_ 'window handle
hdc as ulong,_ 'device context
ReleaseDC as long
end function
function DeleteDC(hDCM)
calldll #gdi32, "DeleteDC", _
hDCM as ulong, _
DeleteDC as long
end function
function CreateCompatibleDC(hDC)
calldll #gdi32, "CreateCompatibleDC", _
hDC as ulong, _ 'current screen
CreateCompatibleDC as ulong 'handle of memory DC
end function
function SelectObject(hDC,hImage)
calldll #gdi32, "SelectObject", _
hDC as ulong, _
hImage as ulong, _
SelectObject as ulong
end function
function DeleteObject(memBmp)
calldll #gdi32, "DeleteObject", _
memBmp as ulong, _
DeleteObject as long
end function
function BitBlt(hDCdest, xDest, yDest, xWidth, yHeight, hDCsource, xSrc, ySrc, ROP)
CallDll #gdi32, "BitBlt", _
hDCdest as ulong,_ 'The destination DC
xDest as long,_ 'x location on destination
yDest as long,_ 'y location on destination
xWidth as long,_ 'width to transfer
yHeight as long,_ 'height to transfer
hDCsource as ulong,_ 'The source DC
xSrc as long,_ 'x location in source
ySrc as long,_ 'y location in source
ROP as ulong,_ 'The operation to be performed
BitBlt as long 'nonzero if successful
end function
Sub EraseWindow hWnd
flags = _RDW_ERASE Or _RDW_INVALIDATE
CallDLL #user32, "RedrawWindow", _
hWnd as ulong, _
_NULL as ulong, _
_NULL as ulong, _
flags as ulong, _
ret as long
End Sub |
_________________ Brent |
|
Back to top |
|
 |
Mattestion New Member
Joined: 29 Feb 2012 Posts: 4
|
Posted: Mar 1st, 2012, 2:18am Post subject: Re: GUI skin (sort of) |
|
|
Thanks, that works perfectly. Could you explain to me why this method works? _________________ Just BASIC v1.01 / Liberty BASIC Pro v4.04 / Run BASIC v1.01 / Vista Home Premium SP2 - AMD Athlon 64 X2 Dual Core Processor 5000+ 2.60 GHz - 2GB RAM |
|
Back to top |
|
 |
STPendl Full Member
Joined: 20 Aug 2007 Posts: 161 Location: Austria
|
Posted: Mar 1st, 2012, 8:32am Post subject: Re: GUI skin (sort of) |
|
|
The EraseWindow API function forces a WM_PAINT message.
You will better succeed, if you get some information about handling GUI windows in plain ANSI C without using any GUI framework. _________________ Stefan
Any code I post can be freely used, just give credit. |
|
Back to top |
|
 |
RichardRussell Full Member
Joined: 28 Jan 2012 Posts: 57 Location: Downham Market, UK
|
Posted: Mar 1st, 2012, 9:43am Post subject: Re: GUI skin (sort of) |
|
|
Mattestion wrote: | Thanks, that works perfectly. |
Yes, it works in LBB too, somewhat to my surprise. What I don't understand, though, is why (in LB) you need this code instead of a simple wait:
Code: | [LOOP]
scan
calldll #kernel32, "Sleep", _ 'Minimize CPU usage
50 as long, _
ret as void
goto [LOOP] |
Substituting a wait appears to cause the program to ignore the trapclose and not to respond to the the close button. In LBB a wait works fine, but that's not surprising because internally it does exactly the same as the above loop (although it sleeps for only 1 ms).
And I still wonder what advantage this approach has over a graphics window. Is it true, as the docs imply, that some controls don't work properly, and if so which ones are they?
Richard. |
|
Back to top |
|
 |
STPendl Full Member
Joined: 20 Aug 2007 Posts: 161 Location: Austria
|
Posted: Mar 1st, 2012, 10:02am Post subject: Re: GUI skin (sort of) |
|
|
The SCAN-loop is a requirement of using WMLiberty, so Brent will surly have the correct answer.
Static text controls do not work in a graphics control and some of the notifications for other controls are eaten by the graphics control, so the controls do not respond to user actions. _________________ Stefan
Any code I post can be freely used, just give credit. |
|
Back to top |
|
 |
RichardRussell Full Member
Joined: 28 Jan 2012 Posts: 57 Location: Downham Market, UK
|
Posted: Mar 1st, 2012, 11:29am Post subject: Re: GUI skin (sort of) |
|
|
STPendl wrote: | Static text controls do not work in a graphics control and some of the notifications for other controls are eaten by the graphics control, so the controls do not respond to user actions. |
Ah, OK. I'll have to add that to the list of advantages of LBB, because it uses exactly the same window class for both GRAPHICS and WINDOW, so should handle control notifications the same way.
Richard. |
|
Back to top |
|
 |
RichardRussell Full Member
Joined: 28 Jan 2012 Posts: 57 Location: Downham Market, UK
|
Posted: Mar 1st, 2012, 4:33pm Post subject: Re: GUI skin (sort of) |
|
|
STPendl wrote: | Static text controls do not work in a graphics control. |
Actually as far as I can see they do work, so long as you force an initial redraw (which you can do for example using a font command):
Code: | statictext #main.st, " Static text ", 40, 40, 240, 60
open "Statictext in a graphics window" for graphics_nsb as #main
#main "down; backcolor blue; boxfilled 320 340; flush"
#main.st "!font Arial 36"
wait |
However you can't change the colour, so that might be one reason why this isn't an acceptable approach.
Richard. |
|
Back to top |
|
 |
RichardRussell Full Member
Joined: 28 Jan 2012 Posts: 57 Location: Downham Market, UK
|
Posted: Mar 1st, 2012, 6:17pm Post subject: Re: GUI skin (sort of) |
|
|
STPendl wrote: | some of the notifications for other controls are eaten by the graphics control. |
I haven't managed to find any notifications that are 'eaten' by the graphics window; this is the program I used:
Code: | nomainwin
array$(1) = "Some"
array$(2) = "items"
array$(3) = "for"
array$(4) = "the"
array$(5) = "Combobox"
array$(6) = "and"
array$(7) = "Listbox"
button #main.button, "Button", Notify, UR, 40, 10
checkbox #main.checkbox, "Checkbox", Notify, Notify, 10, 10, 120, 20
combobox #main.combobox, array$(), Notify, 10, 50, 120, 130
listbox #main.listbox, array$(), Notify, 160, 50, 120, 130
radiobutton #main.radiobutton1, "Radiobutton 1", Notify, Notify, 10, 200, 120, 20
radiobutton #main.radiobutton2, "Radiobutton 2", Notify, Notify, 160, 200, 120, 20
open "Notifications in a graphics window" for graphics_nsb as #main
#main "down; backcolor blue; boxfilled 320 340; flush"
#main "trapclose [Quit]"
wait
[Quit]
close #main
end
sub Notify handle$
notice handle$
end sub |
I wonder if this is yet another example of something which used to be the case in an earlier version of LB but no longer is, but the help file hasn't been updated.
Richard. |
|
Back to top |
|
 |
Brent Site Admin
Joined: 01 Jul 2005 Posts: 793
|
Posted: Mar 1st, 2012, 10:07pm Post subject: Re: GUI skin (sort of) |
|
|
With respect to WAIT not working with callbacks, I can only guess the reason. I seem to recall that when callbacks were added, Carl said the functionality was in a Smalltalk library. It may be that that library makes some assumptions about how callbacks are used. There might be more than one event loop, or maybe there's a flag that the WAIT statement doesn't set which causes LB to ignore events when it is in "callback mode." _________________ Brent |
|
Back to top |
|
 |
RichardRussell Full Member
Joined: 28 Jan 2012 Posts: 57 Location: Downham Market, UK
|
Posted: Mar 3rd, 2012, 11:46am Post subject: Re: GUI skin (sort of) |
|
|
Brent wrote: | Code: | ret = DeleteObject(dcSkin)
end function
|
|
Shouldn't that be DeleteDC rather than DeleteObject?
Code: | ret = DeleteDC(dcSkin)
end function
|
Richard. |
|
Back to top |
|
 |
Brent Site Admin
Joined: 01 Jul 2005 Posts: 793
|
Posted: Mar 3rd, 2012, 6:17pm Post subject: Re: GUI skin (sort of) |
|
|
RichardRussell wrote: | Shouldn't that be DeleteDC rather than DeleteObject? |
http://msdn.microsoft.com/en-us/library/dd183489%28v=vs.85%29.aspx
In CreateCompatibleDC, MSDN wrote: | When you no longer need the memory DC, call the DeleteDC function. We recommend that you call DeleteDC to delete the DC. However, you can also call DeleteObject with the HDC to delete the DC. |
_________________ Brent |
|
Back to top |
|
 |
RichardRussell Full Member
Joined: 28 Jan 2012 Posts: 57 Location: Downham Market, UK
|
Posted: Mar 3rd, 2012, 7:00pm Post subject: Re: GUI skin (sort of) |
|
|
Brent wrote: | In CreateCompatibleDC, MSDN wrote: | We recommend that you call DeleteDC to delete the DC. However, you can also call DeleteObject. |
|
MSDN at its worst! If DeleteDC is recommended why would one ever use anything else? This wording (which is a recent addition) is possibly because current versions of Windows (2000 onwards) have accepted either, whereas earlier ones may have accepted only DeleteDC.
Richard. |
|
Back to top |
|
 |
Alyce Full Member
Joined: 04 Jul 2005 Posts: 91
|
Posted: Mar 4th, 2012, 12:02pm Post subject: Re: GUI skin (sort of) |
|
|
RichardRussell wrote: | If DeleteDC is recommended why would one ever use anything else?
Richard. |
Why not? DeleteObject works on many graphics objects, such as pen, brush, font, bitmap, region, and palette. The programmer only needs to remember the syntax for a single API call. Also, if APIs are wrapped in user-functions, one function is all that is needed and can be called many times.
That argument is off-topic for this thread, however. Brent did not make an error in his code and that is all that is pertinent to the OP.
Regarding Richard's message, "I haven't managed to find any notifications that are 'eaten' by the graphics window; this is the program I used: " I tried the code. I added to it and "setfocus" to the graphics window to trap user events. I added graphics statements to trap mouse events and keypresses. Even with the added focus and traps, the controls appeared to work correctly. It may be that the caveat against putting controls over graphics is no longer needed, but before I'd count on that, I'd try it with a graphicbox instead of a graphics window, and I'd test it on different versions of Windows. I never use a graphics window, other than for short demos. I use a graphicbox inside a regular window, which gives me more control and flexibility. _________________ - Alyce |
|
Back to top |
|
 |
|
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You can download files in this forum
|
|
|