Posts: 2,458
Threads: 248
Joined: Apr 2022
Reputation:
125
I'm rethinking the use of hardware acceleration in SCREEN 0. The reason is the very high CPU readings. A lot of times business apps just sit open all day, and I can't imagine burning up the insides of a computer by refreshing hardware images all the time the system sits idle. This leave us with solutions like the old days of using a timed screensaver. I don't miss those days. Another, and more complex method, would be checking for idle time and making a copy of the current page, calling up a graphics screen, and using that to display the image while routing everything else to the mouse/keyboard subroutine. When some action is detected, the process would have to reconstruct the current screen in SCREEN 0... and that could be a real PITA.
For pure graphics uses for speed in gaming, moving multiple objects around the screen, even for complex screen scrolling events, you can't beat hardware acceleration, but mixing it with SCREEN 0 does come at a hefty CPU price, which has me leaning in the direction of graphics conversion for a few apps I want to update.
So I'm curious, what have those of you who have tried this feature think?
Pete
Posts: 2,849
Threads: 340
Joined: Apr 2022
Reputation:
250
I... have no idea what the BLEEP you're talking about.
Code: (Select All)
tempScreen = _NewImage(640, 400, 32)
Cls , &HFFFF0000, tempScreen
hardwareScreen = _CopyImage(tempScreen, 33)
Do
Cls
k = _KeyHit
Select Case k
Case 27: System
Case Is > 27: toggle = Not toggle
End Select
If toggle Then _PutImage (0, 0)-(640, 400), hardwareScreen
_Display
_Limit 30
Loop
I run this and it uses 0.1% CPU.
I hit any key (except ESC which ends the program) and start using hardware images. I use... 0.1% CPU.
There's almost no CPU usage at all here....
So, to test something else, I turn off the _LIMIT and remark it out.
I run this with no limit and, like expected, it goes high with CPU usage being in an endless loop -- 9% CPU.
I then hit any key (again, except ESC) and the hardware image goes into play -- 11% CPU.
Even in a limitless loop, the addition of hardware images only increases my CPU usage by 2%. That's hardly an issue.
I've seen you mention several times about "hardware images uses a lot of CPU", but I've never noticed that. Do you got some code examples of the issue? Is it something you're doing different than what I'm doing here?
Share the simplest set of code that you can, that might highlight the issue. This is about as simple of a toggle as I can think of for testing -- one is NO HARDWARE, hit a key and then the other IS HARDWARE. And I'm just not seeing any real CPU usage either way here, when a reasonable _Limit is in place. Even without a limit, the increase is... 2-3% more perhaps?
It's generally not enough to make my fans turn on and sound like an airplane engine. Whenever THAT happens, then I *know* I'm straining the CPU.
Posts: 404
Threads: 25
Joined: May 2022
Reputation:
74
Not a single part of SCREEN 0 in QB64 is hardware accelerated. The video mode is entirely emulated in software, and the final "rendered" frame is handed over to OpenGL.
Most of us design our SCREEN 0 applications using a "game loop" style. In this approach, events/input are handled, and the entire screen is cleared and redrawn at a fixed number of frames/second. While this method works well for applications that need constant refreshing, it's not ideal for maintaining thermal and power efficiency. One could dynamically adjust the _LIMIT in the main loop to reduce unnecessary redraws, but you might still end up redrawing the whole screen more than necessary.
For a SCREEN 0 TUI application, my idea is to design a retained-mode TUI framework. This approach updates the screen, or just parts of it, only when they are "dirty" – essentially when they need to be repainted. Each GUI object can trigger a "repaint" event when needed. This method can be further optimized by culling objects that are not visible. A z-order for every GUI object can be used to determine the object stack.
Posts: 2,458
Threads: 248
Joined: Apr 2022
Reputation:
125
02-18-2025, 10:35 PM
(This post was last modified: 02-18-2025, 10:44 PM by Pete.)
What I've noticed is a high increase in CPU with multiple hardware accelerated button images sent to SCREEN 0.
Code: (Select All)
_Dest overlay
Line (8 * (x(k) - 1) + 2, 16 * (y(k) - 1) + 7 + 2)-((j + 2) * 8 + 8 * (x(k) - 1) - 2, 16 * 2 + 16 * (y(k) - 1) + 7 - 2), _RGB32(155, 155, 155), B
Line (8 * (x(k) - 1), 16 * (y(k) - 1) + 7)-((j + 2) * 8 + 8 * (x(k) - 1), 16 * 2 + 16 * (y(k) - 1) + 7), _RGB32(fb.BHybBdr1, fb.BHybBdr1, fb.BHybBdr1), B
Line (8 * (x(k) - 1) + 8, 16 * (y(k) - 1) + 15)-((j + 1) * 8 + 8 * (x(k) - 1), y(k) * 16 + 15), _RGB32(fb.BHybBdr2, fb.BHybBdr2, fb.BHybBdr2), B
Overlay_Hardware = _CopyImage(overlay, 33)
_PutImage (0, 0), Overlay_Hardware
_FreeImage Overlay_Hardware
_Dest 0
Or for an image...
Code: (Select All)
_Dest overlay
Overlay_Hardware = _CopyImage(overlay, 33)
_PutImage (0, 0), Overlay_Hardware
img& = _LoadImage(button$(k) + "-hover.png", 32)
_PutImage ((x(k) - 1) * 8 + 4, (y(k) - 1) * 16), img&
_FreeImage img&
_FreeImage Overlay_Hardware
For just a single button, it's not much increase. Without using acceleration I get a single text button in SCREEN 0 at 6 to 9 percent PU. A single graphics or image button raises it to between 20 - 24 percent, but with the button demo I have in the WIP section, 6 hardware accelerated images boost CPU between 55 - 60 percent.
This smaller snippet that I used in part to Ken's request for soundless message boxes shows the difference with single buttons. Input 1 or 2 and it is strictly all SCREEN 0. Input 3 or 4 and the hardware acceleration is placed into use to create graphics in SCREEN 0. You will be albe to see the CPU usage climb with buttons 3, 4, or 5 (If you have downloaded my "Activate-static.png" button from the WIP post).
Code: (Select All)
Dim Shared overlay, demo As Integer
Dim As Single lb, mb, rb, mw, my, mx
ReDim Shared fld$(0), button$(0), mRow$(0)
ReDim Shared x(0), y(0), y1(0), y2(0), x1(0), x2(0), fnx(0), btnmap(0), FType(0)
Type fields_and_buttons
a As String
initiate As Integer
tabmax As Integer
tb As Integer
SimClick As Integer
fld As Integer
nof As Integer
nob As Integer
mapping As Integer
style As Integer
BSelect As Integer
Bg As Integer ' Begin button colors.
BBdr As Integer
BBdrHover As Integer
BBdrFlash As Integer
BFg As Integer
BBg As Integer
BBg1 As Integer
BHvrFg As Integer
BHvrBk As Integer
BFgFlash As Integer
BBgFlash As Integer
BHybFg As Integer
BHybBg1 As Integer
BHybBg2 As Integer
BHybBdr1 As Integer
BHybBdr2 As Integer
End Type
Dim fb As fields_and_buttons
fb.BBdr = 8: fb.BBdrHover = 1: fb.BBdrFlash = 9: fb.BFg = 15: fb.BBg = 3: fb.BBg1 = 1: fb.BHvrFg = 3: fb.BHvrBk = 1: fb.BFgFlash = 1: fb.BBgFlash = 3
fb.Bg = 5: fb.BHybBg1 = 6: fb.BHybFg = 6: fb.BHybBg2 = 7: fb.BHybBdr1 = 0: fb.BHybBdr2 = 255
If fb.style = 0 Then fb.style = 2
Input "Input 1 to 5, but only 5 if you downloaded the button in the WIP post: ", fb.style
If fb.style > 5 Or fb.style < 1 Then Beep: End
Palette 5, 63
Palette 6, 56
Palette 7, 63
Color 0, 7: Cls
Randomize Timer
dice$ = "7" ' 'Cause we're feeling lucky!
msg$ = "Your roll: " + dice$: GoSub pete
Run
pete:
popup 6, 19, 9, 32 ' Top, Left, Height, Width.
Locate 7, 19 - 1 + (32 - Len(msg$)) \ 2: print_array msg$
If fb.style = 5 Then
fb.a = "Activate": fb_text_buttons fb, 11, 30
Else
fb.a = " OK ": fb_text_buttons fb, 10, 30
End If
Do
MyMouse_and_Keyboard lb, mb, rb, my, mx, mw, shift%, AltStatus%, AltToggle%, alt%, ctrl%, clkcnt, drag, k&, b$, autokey$
fb_main fb, b$, button$(), mx, my, lb
If fb.BSelect Then Exit Do
Loop
_AutoDisplay
PCopy 1, 0
Palette 7, 63
fb.initiate = 0
fb.tb = 0: fb.tabmax = 0: fb.nof = 0: fb.nob = 0
ReDim fld$(0), button$(0), mRow$(0)
ReDim x(0), y(0), y1(0), y2(0), x1(0), x2(0), fnx(0), btnmap(0), FType(0)
Return
Sub print_array (a$)
s1 = CsrLin: s2 = Pos(0)
Print a$;
Locate s1, s2
End Sub
Sub MyMouse_and_Keyboard (lb, mb, rb, my, mx, mw, shift%, AltStatus%, AltToggle%, alt%, ctrl%, clkcnt, drag, k&, b$, autokey$)
Dim As Integer oldmw
Static As Integer oldmy, oldmx, mwy, oldmwy
Static z1 As Single
_Limit 60
If AltStatus% Then AltStatus% = 0
If Len(autokey$) Then
b$ = Mid$(autokey$, 1, InStr(autokey$ + ",", ",") - 1)
autokey$ = Mid$(autokey$, InStr(autokey$ + ",", ",") + 1)
Exit Sub
Else
k& = _KeyHit
If k& = 100307 Or k& = 100308 Then
AltStatus% = -1
AltToggle% = 1 - AltToggle%
Exit Sub
End If
If k& > 0 Then
b$ = MKI$(k&)
If Mid$(b$, 2, 1) = Chr$(135) Then b$ = "" ' Keys like like Shift, Ctrl, and Alt.
If Right$(b$, 1) = Chr$(0) Then b$ = Left$(b$, 1)
Else
b$ = ""
End If
End If
If z1 Then If Abs(Timer - z1) > .25 Then z1 = 0: clkcnt = 0
If lb > 0 Then
If lb = 1 Then
lb = -1
Else
lb = 0
End If
End If
If rb > 0 Then If rb = 1 Then rb = -1 Else rb = 0
If mb > 0 Then If mb = 1 Then mb = -1 Else mb = 0
While _MouseInput
mwy = mwy + _MouseWheel
Wend
my = _MouseY
mx = _MouseX
If lb = -1 Then
If oldmy And oldmx <> mx Or oldmy And oldmy <> my Then
If mx <> oldmx Then drag = Sgn(mx - oldmx) ' Prevent zero which can occur if mouse moves off row when being dragged horizontally.
End If
End If
If drag = 0 Then
If mwy <> oldmw Then
mw = Sgn(mwy - oldmwy): mwy = 0
Else
mw = 0
End If
oldmwy = mwy
If _KeyDown(100303) Or _KeyDown(100304) Then shift% = -1 Else If shift% Then shift% = 0
If _KeyDown(100305) Or _KeyDown(100306) Then ctrl% = -1 Else If ctrl% Then ctrl% = 0
If _KeyDown(100307) Or _KeyDown(100308) Then alt% = -1 Else If alt% Then alt% = 0
End If
If lb = -1 And _MouseButton(1) = 0 Then
lb = 2: drag = 0: hover = 0
ElseIf rb = -1 And _MouseButton(2) = 0 Then
rb = 2
ElseIf mb = -1 And _MouseButton(3) = 0 Then
mb = 2
End If
If _MouseButton(1) Then
If lb = 0 Then
lb = 1: z1 = Timer
clkcnt = clkcnt + 1
End If
ElseIf _MouseButton(2) And rb = 0 Then
rb = 1
ElseIf _MouseButton(3) And mb = 0 Then
mb = 1
End If
oldmy = my: oldmx = mx
End Sub
Sub fb_main (fb As fields_and_buttons, b$, button$(), mx, my, lb)
Static prev_fld, HtmlBtn
s1 = CsrLin: s2 = Pos(0)
b_hover = 0: fb.fld = 0: fb.BSelect = 0
If fb.mapping Then
If Len(mRow$(my)) Then
i = Asc(Mid$(mRow$(my), mx, 1))
If i > 96 Then
fb.fld = i - 96
If FType(fb.fld) = 5 Then b_hover = btnmap(fb.fld)
End If
End If
Else
For i = 1 To fb.nof ' number of fields.
If my >= y1(i) And my <= y2(i) And mx >= x1(i) And mx <= x2(i) Then
Select Case FType(i)
Case 1
fb.fld = i
Case 5
fb.fld = i
b_hover = btnmap(fb.fld)
Exit For
End Select
End If
Next
End If
If lb = 2 And FType(fb.fld) = 1 Then
If FType(fb.tb) = 5 Then h = 1: fb_button_tab fb, h, HtmlBtn ' Unhighlight a tab highighted button.
If FType(fb.tb) = 1 Then
If demo Then Locate , Pos(0) + 2, 1, 7, 1: s1 = CsrLin: s2 = Pos(0)
End If
fb.tb = fb.fld - 1
b$ = Chr$(9)
End If
If prev_fld And prev_fld <> fb.fld Then ' Remove button hover effect when present.
s1 = CsrLin: s2 = Pos(0)
c1 = _DefaultColor: c2 = _BackgroundColor
i = prev_fld
j = Len(button$(btnmap(i)))
Select Case fb.style
Case 1 'Single line button with blank border.
Color fb.BBg1, fb.Bg
Locate y1(i) - 1, x1(i): Print String$(j, 220);
Locate y1(i) + 1, x1(i): Print String$(j, 223);
Color fb.BFg, fb.BBg1
Locate y1(i), x1(i): Print button$(btnmap(i));
Case 2 ' Text button with line border.
Color fb.BBdr, fb.Bg
Locate y1(i), x1(i): Print Chr$(218) + String$(j, 196) + Chr$(191)
Locate , x1(i): Print Chr$(179);: Locate , Pos(0) + j: Print Chr$(179)
Locate , x1(i): Print Chr$(192) + String$(j, 196) + Chr$(217);
Case 3 ' Text hybrid button with graphics line border.
j = Len(button$(btnmap(i)))
k = btnmap(i)
_Dest overlay
Line (8 * (x(k) - 1) + 2, 16 * (y(k) - 1) + 7 + 2)-((j + 2) * 8 + 8 * (x(k) - 1) - 2, 16 * 2 + 16 * (y(k) - 1) + 7 - 2), _RGB32(155, 155, 155), B
Line (8 * (x(k) - 1), 16 * (y(k) - 1) + 7)-((j + 2) * 8 + 8 * (x(k) - 1), 16 * 2 + 16 * (y(k) - 1) + 7), _RGB32(fb.BHybBdr1, fb.BHybBdr1, fb.BHybBdr1), B
Line (8 * (x(k) - 1) + 8, 16 * (y(k) - 1) + 15)-((j + 1) * 8 + 8 * (x(k) - 1), y(k) * 16 + 15), _RGB32(fb.BHybBdr2, fb.BHybBdr2, fb.BHybBdr2), B
Overlay_Hardware = _CopyImage(overlay, 33)
_PutImage (0, 0), Overlay_Hardware
_FreeImage Overlay_Hardware
_Dest 0
Color fb.BHybFg, fb.BHybBg2
Locate y1(i) + 1, x1(i) + 1: Print button$(btnmap(i));
End Select
prev_fld = 0
force = -1 ' Local variable to force any tab button field to remain highlighted.
Color c1, c2
Locate s1, s2
End If
If fb.tabmax And b$ = Chr$(9) Then
If fb.tb = fb.tabmax Then ' Redo cycle.
If FType(fb.tb) = 5 Then
h = 1: fb_button_tab fb, h, HtmlBtn ' Remove tab highlighted button in last field.
End If
fb.tb = 0: HtmlBtn = 0
Else
If FType(fb.tb + 1) = 5 Then
If FType(fb.tb) = 5 Then
h = 1: fb_button_tab fb, h, HtmlBtn
End If
fb.tb = fb.tb + 1 ' Note: Button will be highlighted at end of subroutine.
HtmlBtn = 0
force = 1: ' Local variable to force any tab button field to remain highlighted.
Else
fb.tb = fb.tb + 1 ' Increase tab field for text / non-button fields.
i = Val(Mid$(fld$(fb.tb), 6, 5))
j = Val(Mid$(fld$(fb.tb), 16, 5)) + 1
Locate y1(fb.tb), fnx(fb.tb)
If demo Then Locate , Pos(0) + 2, 1, 7, 1
s1 = CsrLin: s2 = Pos(0)
End If
End If
End If
If fb.tb Then
If b$ = Chr$(13) Then
If FType(fb.tb) = 5 Then
fb.SimClick = 1 ' Simulate a left button click.
End If
End If
If FType(fb.tb) = 1 Then
Locate , , 1
Else
Locate , , 0
End If
End If
If b_hover Or fb.SimClick Then ' Add hover effect.
If fb.SimClick Then
h = fb.SimClick
If h = -1 Then h = 0
l = btnmap(fb.tb)
q = fb.tb
Else
prev_fld = fb.fld
h = lb
q = fb.fld
l = b_hover
End If
If demo Then
Select Case l
Case 1, 2: fb.style = 1
Case 3, 4: fb.style = 2
Case 5, 6: fb.style = 3
Case 7, 8: fb.style = 4
Case 9, 10: fb.style = 5
End Select
End If
Select Case h
Case 0, -1, 1 ' Static or color change if button clicked.
s1 = CsrLin: s2 = Pos(0)
c1 = _DefaultColor: c2 = _BackgroundColor
j = Len(button$(l))
Select Case fb.style
Case 1 'Single line button with blank border remover hover.
If Abs(h) = 1 Then Color fb.BBgFlash, fb.Bg Else Color fb.BHvrFg, fb.Bg
Locate y1(q) - 1, x1(q): Print String$(j, 220);
Locate y1(q) + 1, x1(q): Print String$(j, 223);
If Abs(h) = 1 Then Color fb.BFgFlash, fb.BBgFlash Else Color fb.BFg, fb.BBg
Locate y1(q), x1(q): Print button$(l);
Case 2 ' Text button with line border remove hover.
If Abs(h) = 1 Then Color fb.BBdrFlash, fb.Bg Else Color fb.BBdrHover, fb.Bg
Locate y1(q), x1(q): Print Chr$(218) + String$(j, 196) + Chr$(191)
Locate , x1(q): Print Chr$(179);: Locate , Pos(0) + j: Print Chr$(179)
Locate , x1(q): Print Chr$(192) + String$(j, 196) + Chr$(217);
Rem Locate y1(q) + 1, x1(q) + 1: Print button$(l);
Case 3 ' Text hybrid button with graphics line border remove hover.
j = Len(button$(l))
k = btnmap(q)
If Abs(h) = 1 Then Color fb.Bg, fb.BHybFg Else Color fb.BHybFg, fb.BHybBg2
Locate y1(q) + 1, x1(q) + 1: Print button$(l);
_Dest overlay
Line (8 * (x(k) - 1) + 2, 16 * (y(k) - 1) + 7 + 2)-((j + 2) * 8 + 8 * (x(k) - 1) - 2, 16 * 2 + 16 * (y(k) - 1) + 7 - 2), _RGB32(0, 155, 155), B
Overlay_Hardware = _CopyImage(overlay, 33)
_PutImage (0, 0), Overlay_Hardware
_FreeImage Overlay_Hardware
_Dest 0
End Select
Color c1, c2
Locate s1, s2
Case 2 ' Button selection completed.
fb.BSelect = l
fb.SimClick = 0
End Select
If fb.SimClick = -1 Then fb.SimClick = 2
If fb.SimClick = 1 Then fb.SimClick = -1
End If
If demo Or fb.style = 4 Then
If demo Then i2 = 7: i3 = 8 Else i2 = 1: i3 = fb.nob
For k = i2 To i3
j = Len(button$(k)): a$ = " " + button$(k) + " "
HTMLBStatic = fb_gfx_hyb_hw(j * 8, 2 * 16, 170, 170, 170, -9, -9, -1, Mid$(a$, 1, j))
HTMLBHover = fb_gfx_hyb_hw(j * 8, 2 * 16, 200, 200, 200, -8, -7, -1, Mid$(a$, 1, j))
HTMLBPress = fb_gfx_hyb_hw(j * 8, 2 * 16, 200, 200, 200, -1, -1, -1, Mid$(a$, 1, j))
Overlay_Hardware = _CopyImage(overlay, 33)
_PutImage (0, 0), Overlay_Hardware
If HtmlBtn = k And lb = 0 Then
_PutImage ((x(k) - 1) * 8, (y(k) - 1) * 16 + 8), HTMLBHover
Else
If lb = 0 And b_hover = k Then
_PutImage ((x(k) - 1) * 8, (y(k) - 1) * 16 + 8), HTMLBHover
ElseIf Abs(lb) = 1 And b_hover = k Then
_PutImage ((x(k) - 1) * 8, (y(k) - 1) * 16 + 8), HTMLBPress
Else
_PutImage ((x(k) - 1) * 8, (y(k) - 1) * 16 + 8), HTMLBStatic
End If
End If
_FreeImage HTMLBHover
_FreeImage HTMLBPress
_FreeImage HTMLBStatic
_FreeImage Overlay_Hardware
Next
_Dest 0
End If
If demo Or fb.style = 5 Then
If demo Then i2 = 9: i3 = 10 Else i2 = 1: i3 = fb.nob
For k = i2 To i3
_Dest overlay
Overlay_Hardware = _CopyImage(overlay, 33)
_PutImage (0, 0), Overlay_Hardware
If HtmlBtn = k And lb = 0 Then
img& = _LoadImage(button$(k) + "-hover.png", 32)
_PutImage ((x(k) - 1) * 8 + 4, (y(k) - 1) * 16), img&
Else
If lb = 0 And b_hover = k Then
img& = _LoadImage(button$(k) + "-hover.png", 32)
_PutImage ((x(k) - 1) * 8 + 4, (y(k) - 1) * 16), img&
ElseIf Abs(lb) = 1 And b_hover = k Then
img& = _LoadImage(button$(k) + "-active.png", 32)
_PutImage ((x(k) - 1) * 8 + 4, (y(k) - 1) * 16), img&
Else
img& = _LoadImage(button$(k) + "-static.png", 32)
_PutImage ((x(k) - 1) * 8 + 4, (y(k) - 1) * 16), img&
End If
End If
_FreeImage img&
_FreeImage Overlay_Hardware
Next
_Dest 0
End If
If prev_fld <> b_hover And prev_fld = fb.fld Or force Then
If FType(fb.tb) = 5 Then
If b_hover = 0 Or force Then h = 2: fb_button_tab fb, h, HtmlBtn
End If
End If
If demo Then
q1 = CsrLin: q2 = Pos(0)
Color 15, 0
Locate 2, 66 - 7: Print b_hover;: Locate 4, 71 - 5
If b_hover Then Print fb.style; Else j = 0: Print j;
Locate 6, 63 - 6: Print fb.tb;
Color 0, 5
Locate q1, q2
End If
Locate s1, s2
_Display
End Sub
Sub fb_button_tab (fb As fields_and_buttons, h, HtmlBtn)
Dim As Integer i, j, k
s1 = CsrLin: s2 = Pos(0)
temp = fb.style
If demo Then
Select Case btnmap(fb.tb)
Case 1, 2: fb.style = 1
Case 3, 4: fb.style = 2
Case 5, 6: fb.style = 3
Case 7, 8: fb.style = 4
Case 9, 10: fb.style = 5
End Select
End If
i = fb.tb
j = Len(button$(btnmap(i)))
k = btnmap(i)
Select Case h
Case 1: ' Remove tab button highlighting.
Select Case fb.style
Case 1 ' Single line button with blank border.
Color fb.BBg1, fb.Bg
Locate y1(i) - 1, x1(i): Print String$(j, 220);
Locate y1(i) + 1, x1(i): Print String$(j, 223);
Color fb.BFg, fb.BBg1
Locate y1(i), x1(i): Print button$(btnmap(fb.tb));
Case 2 ' Text button with line border.
Color fb.BBdr, fb.Bg
Locate y1(i), x1(i): Print Chr$(218) + String$(j, 196) + Chr$(191)
Locate , x1(i): Print Chr$(179);: Locate , Pos(0) + j: Print Chr$(179)
Locate , x1(i): Print Chr$(192) + String$(j, 196) + Chr$(217);
Case 3 ' Text hybrid button with graphics line border.
_Dest overlay
Line (8 * (x(k) - 1) + 2, 16 * (y(k) - 1) + 7 + 2)-((j + 2) * 8 + 8 * (x(k) - 1) - 2, 16 * 2 + 16 * (y(k) - 1) + 7 - 2), _RGB32(155, 155, 155), B
Line (8 * (x(k) - 1), 16 * (y(k) - 1) + 7)-((j + 2) * 8 + 8 * (x(k) - 1), 16 * 2 + 16 * (y(k) - 1) + 7), _RGB32(fb.BHybBdr1, fb.BHybBdr1, fb.BHybBdr1), B
Line (8 * (x(k) - 1) + 8, 16 * (y(k) - 1) + 15)-((j + 1) * 8 + 8 * (x(k) - 1), y(k) * 16 + 15), _RGB32(fb.BHybBdr2, fb.BHybBdr2, fb.BHybBdr2), B
Overlay_Hardware = _CopyImage(overlay, 33)
_PutImage (0, 0), Overlay_Hardware
_FreeImage Overlay_Hardware
_Dest 0
Color fb.BHybFg, fb.BHybBg2
Locate y1(i) + 1, x1(i) + 1: Print button$(btnmap(fb.tb));
Case 4 ' Graphics hybrid button.
HTMLBStatic = fb_gfx_hyb_hw(j * 8, 2 * 16, 170, 170, 170, -9, -9, -1, Mid$(a$, 1, j))
Overlay_Hardware = _CopyImage(overlay, 33)
_PutImage (0, 0), Overlay_Hardware
_PutImage ((x(k) - 1) * 8, (y(k) - 1) * 16 + 8), HTMLBStatic
_FreeImage HTMLBStatic
_FreeImage Overlay_Hardware
Case 5 ' HTML button.
_Dest overlay
Overlay_Hardware = _CopyImage(overlay, 33)
_PutImage (0, 0), Overlay_Hardware
img& = _LoadImage(button$(btnmap(i)) + "-static.png", 32)
_PutImage ((x(k) - 1) * 8 + 4, (y(k) - 1) * 16), img&
_FreeImage img&
_FreeImage Overlay_Hardware
_Dest 0
End Select
Case 2 ' Tab button highlighting.
Select Case fb.style
Case 1 ' Tab highlight single line button with blank border.
Color fb.BHvrFg, fb.Bg
Locate y1(i) - 1, x1(i): Print String$(j, 220);
Locate y1(i) + 1, x1(i): Print String$(j, 223);
Color fb.BFg, fb.BBg
Locate y1(i), x1(i): Print button$(btnmap(fb.tb));
Case 2 ' Tab highlight text button with line border.
Color fb.BBdrHover, fb.Bg
Locate y1(i), x1(i): Print Chr$(218) + String$(j, 196) + Chr$(191)
Locate , x1(i): Print Chr$(179);: Locate , Pos(0) + j: Print Chr$(179)
Locate , x1(i): Print Chr$(192) + String$(j, 196) + Chr$(217);
Case 3 ' Text hybrid button with graphics line border.
Color fb.BHybFg, fb.BHybBg2
Locate y1(i) + 1, x1(i) + 1: Print button$(btnmap(fb.tb));
_Dest overlay
Line (8 * (x(k) - 1) + 2, 16 * (y(k) - 1) + 7 + 2)-((j + 2) * 8 + 8 * (x(k) - 1) - 2, 16 * 2 + 16 * (y(k) - 1) + 7 - 2), _RGB32(0, 155, 155), B
Overlay_Hardware = _CopyImage(overlay, 33)
_PutImage (0, 0), Overlay_Hardware
_FreeImage Overlay_Hardware
_Dest 0
Case 4, 5
HtmlBtn = btnmap(fb.tb)
End Select
End Select
Locate s1, s2
fb.style = temp
End Sub
Sub fb_text_buttons (fb As fields_and_buttons, y, x)
Static btnnbr
If fb.initiate = 0 Then
fb.initiate = 1
btnnbr = 0
If demo Or fb.style >= 3 Then
overlay = _NewImage(_Width * _FontWidth, _Height * _FontHeight, 32)
End If
End If
s1 = CsrLin: s2 = Pos(0)
c1 = _DefaultColor: c2 = _BackgroundColor
j = Len(fb.a)
fb.nof = fb.nof + 1: fb.nob = fb.nob + 1: fb.tabmax = fb.tabmax + 1
ReDim _Preserve fld$(fb.nof), FType(fb.nof), btnmap(fb.nof)
FType(fb.nof) = 5
btnnbr = btnnbr + 1
btnmap(fb.nof) = btnnbr
fld$(fb.nof) = Space$(25)
ReDim _Preserve y1(fb.nof), x1(fb.nof), y2(fb.nof), x2(fb.nof), button$(fb.nof)
button$(btnnbr) = String$(j, 0) ' Fill any spaces with the null character.
Mid$(button$(btnnbr), 1 + (j - Len(_Trim$(fb.a))) \ 2) = _Trim$(fb.a)
Select Case fb.style
Case 1 ' Single line button with blank border.
y = Abs(y)
Color fb.BFg, fb.BBg1: Locate y, x: fb.a = button$(btnnbr): fb_map fb, 5
Color fb.BBg1, fb.Bg: Locate y - 1, x: fb.a = String$(j, Chr$(220)): fb_map fb, 0
Locate y + 1, x: fb.a = String$(j, Chr$(223)): fb_map fb, 0
Case 2 ' Text button with line border.
Color fb.BBdr, fb.Bg
Locate y - 1, x - 1: fb.a = Chr$(218) + String$(j, 196) + Chr$(191): fb_map fb, 6
Locate y, x - 1: fb.a = Chr$(179): fb_map fb, 0
Locate , Pos(0) + j: fb.a = Chr$(179): fb_map fb, 0
Locate y + 1, x - 1: fb.a = Chr$(192) + String$(j, 196) + Chr$(217): fb_map fb, 7
Locate y, x: fb.a = button$(btnnbr): fb_map fb, 0
Case 3 ' Text hybrid button with graphics line border.
i = btnnbr
j = Len(fb.a)
k = btnnbr
ReDim _Preserve x(btnnbr), y(btnnbr), button$(btnnbr)
y(k) = y - 1: x(k) = x - 1
button$(i) = String$(j, 0)
Mid$(button$(i), 1 + (j - Len(_Trim$(fb.a))) / 2) = _Trim$(fb.a)
Locate y - 1, x - 1: Color fb.BHybBg1, fb.Bg: fb.a = String$(j + 2, "Ü"): fb_map fb, 6
Locate y, x - 1: Color fb.Bg, fb.BHybBg1: fb.a = String$(j + 2, 0): fb_map fb, 0
Locate y + 1, x - 1: Color fb.BHybBg1, fb.Bg: fb.a = String$(j + 2, "ß"): fb_map fb, 7
Locate y, x: Color fb.BHybFg, fb.BHybBg2: fb.a = button$(i): fb_map fb, 0
_Dest overlay
Line (8 * (x(k) - 1) + 2, 16 * (y(k) - 1) + 7 + 2)-((j + 2) * 8 + 8 * (x(k) - 1) - 2, 16 * 2 + 16 * (y(k) - 1) + 7 - 2), _RGB32(155, 155, 155), B
Line (8 * (x(k) - 1), 16 * (y(k) - 1) + 7)-((j + 2) * 8 + 8 * (x(k) - 1), 16 * 2 + 16 * (y(k) - 1) + 7), _RGB32(fb.BHybBdr1, fb.BHybBdr1, fb.BHybBdr1), B
Line (8 * (x(k) - 1) + 8, 16 * (y(k) - 1) + 15)-((j + 1) * 8 + 8 * (x(k) - 1), y(k) * 16 + 15), _RGB32(fb.BHybBdr2, fb.BHybBdr2, fb.BHybBdr2), B
Overlay_Hardware = _CopyImage(overlay, 33)
_PutImage (0, 0), Overlay_Hardware
_FreeImage Overlay_Hardware
_Dest 0
Case 4 ' Graphics hybrid button.
j = Len(fb.a)
ReDim _Preserve x(btnnbr), y(btnnbr), button$(btnnbr)
y(btnnbr) = y - 1: x(btnnbr) = x - 1
button$(btnnbr) = String$(j + 2, 0)
Mid$(button$(btnnbr), 1 + (j - Len(_Trim$(fb.a))) / 2) = _Trim$(fb.a)
fb.a = button$(btnnbr)
Locate y - 1, x - 1: fb_map fb, 8
Locate y, x - 1: fb_map fb, -1
Locate y + 1, x - 1: fb_map fb, 9
Case 5 ' HTML button.
img& = _LoadImage("activate-static.png", 32)
i = _Height(img&)
j = _Width(img&)
If j Mod 8 Then j = j \ 8 + 1 Else j = j \ 8
If i Mod 16 Then i = i \ 16 + 1 Else i = i \ 16
If i / 2 <> i \ 2 Then i = i + 1
If j / 2 <> j \ 2 Then j = j + 1
_FreeImage img&
button$(btnnbr) = _Trim$(fb.a)
fb.a = String$(j, i)
ReDim _Preserve x(btnnbr), y(btnnbr), button$(btnnbr)
y(btnnbr) = y - 1: x(btnnbr) = x - 1
Locate y - 1, x - 1: fb_map fb, 10
For k = 0 To i - 2
Locate y + k, x - 1: fb_map fb, -1
Next
End Select
Color c1, c2
Locate s1, s2
End Sub
Function fb_gfx_hyb_hw (wide, tall, r, g, b, rc, gc, bc, caption$)
' Button function courtesy of the Amazing Steve.
Dim k As _Unsigned Long
Dest = _Dest
t = _NewImage(wide, tall, 32)
_Dest t
For i = 0 To 10
rm = rm + rc
gm = gm + gc
bm = bm + bc
k = _RGB32(r + rm, g + gm, b + bm)
Line (x + i, y + i)-(x + wide - i, y + tall - i), k, B
Next
Paint (x + i, y + i), k
Color _RGB32(r, g, b), 0
_PrintString (x + (wide - _PrintWidth(caption$)) / 2, y + (tall - _FontHeight) / 2), caption$
fb_gfx_hyb_hw = _CopyImage(t, 33)
_FreeImage t
_Dest Dest
End Function
Sub fb_map (fb As fields_and_buttons, mapid)
Static mapfld As Integer
If UBound(mRow$) = 0 Then
ReDim mRow$(_Height)
mapfld = 96
End If
If fb.mapping And mRow$(CsrLin) = "" Then mRow$(CsrLin) = Space$(_Width)
Select Case mapid
Case 1 ' Simple text field.
mapfld = mapfld + 1 ' Advance.
y1(mapfld - 96) = CsrLin
x1(mapfld - 96) = Pos(0)
y2(mapfld - 96) = CsrLin
x2(mapfld - 96) = Pos(0) + Len(fb.a)
Case 5 ' Single line button with blank padding.
mapfld = mapfld + 1 ' Advance.
y1(mapfld - 96) = CsrLin
x1(mapfld - 96) = Pos(0)
y2(mapfld - 96) = CsrLin
x2(mapfld - 96) = Pos(0) + Len(fb.a)
Case 6 ' Text or hybrid button top.
mapfld = mapfld + 1 ' Advance.
y1(mapfld - 96) = CsrLin: x1(mapfld - 96) = Pos(0)
Case 7 ' Text or hybrid button bottom.
y2(mapfld - 96) = CsrLin: x2(mapfld - 96) = Pos(0) + Len(fb.a)
Case 8 ' Graphics hybrid button top.
mapfld = mapfld + 1 ' Advance.
y1(mapfld - 96) = CsrLin
x1(mapfld - 96) = Pos(0)
Case 9 ' Graphics hybrid button bottom.
y2(mapfld - 96) = CsrLin
x2(mapfld - 96) = Pos(0) + Len(fb.a)
Case 10 ' HTML button.
mapfld = mapfld + 1 ' Advance.
y1(mapfld - 96) = CsrLin
x1(mapfld - 96) = Pos(0)
y2(mapfld - 96) = CsrLin + Asc(Mid$(fb.a, 1, 1))
x2(mapfld - 96) = Pos(0) + Len(fb.a)
End Select
If fb.mapping Then Mid$(mRow$(CsrLin), Pos(0)) = String$(Len(fb.a), Chr$(mapfld))
If mapid < 8 And mapid > -1 Then Print fb.a;
End Sub
Sub popup (m.top, m.left, m.height, m.width)
pop = 1
c.MenuBdrFg = 0
c.MenubrdBg = 5
c.MenuSdwFg = 6
c.MenuSdwBg = 0
c.MenuFg = 0
c.MenuBg = 5
spacing = 1
PCopy 0, 1
Palette 7, 7
Locate m.top - pop, m.left - pop
For h = 1 To m.height
If h = 1 Then
Color c.MenuBdrFg, c.MenubrdBg
Print Chr$(218) + String$(m.width - 2, 196) + Chr$(191)
j = CsrLin
For i = 1 To m.height - 2
If CsrLin < _Height Then Locate j, m.left - pop Else Locate , m.left - pop
Color c.MenuBdrFg, c.MenubrdBg: Print Chr$(179);
Color c.MenuBdrFg, c.MenubrdBg: Print Space$(m.width - 2);
Color c.MenuBdrFg, c.MenubrdBg: Print Chr$(179);
j = j + 1
Next
Locate j, m.left - pop
Color c.MenuBdrFg, c.MenubrdBg: Print Chr$(192) + String$(m.width - 2, 196) + Chr$(217);
If pop Then ' Shadow effect.
Color c.MenuSdwFg, c.MenuSdwBg ' Shadow below.
Locate CsrLin + 1, m.left - pop + 2
For i = 1 To m.width
j = Screen(CsrLin, Pos(0))
Print Chr$(j);
Next
Locate m.top - pop + 1 ' Shadow to the right.
For i = 1 To m.height - 1
Locate , m.left - pop + m.width
j = Screen(CsrLin, Pos(0))
Print Chr$(j);
j = Screen(CsrLin, Pos(0))
Print Chr$(j)
Next
End If
End If
Color c.MenuFg, c.MenuBg
Locate m.top - pop + h + (h - 1) * spacing, m.left - pop + 2 - 1
Next h
End Sub
To see a demo with multiple buttons displayed: https://qb64phoenix.com/forum/showthread...8#pid31798
That's the one that boosts the CPU over 50%.
Pete
Posts: 2,849
Threads: 340
Joined: Apr 2022
Reputation:
250
Even using the one that you say jumps your CPU usage up to 50%, I'm just not seeing it. I follow the link, copy the code, run it...
And use 2 -3% CPU at max.
If I had to guess at the issue you're having, however, I'd say it's the way you're doing things.
Take a look at this code snippet: Code: (Select All) For k = i2 To i3
j = Len(button$(k)): a$ = " " + button$(k) + " "
HTMLBStatic = fb_gfx_hyb_hw(j * 8, 2 * 16, 170, 170, 170, -9, -9, -1, Mid$(a$, 1, j))
HTMLBHover = fb_gfx_hyb_hw(j * 8, 2 * 16, 200, 200, 200, -8, -7, -1, Mid$(a$, 1, j))
HTMLBPress = fb_gfx_hyb_hw(j * 8, 2 * 16, 200, 200, 200, -1, -1, -1, Mid$(a$, 1, j))
Overlay_Hardware = _CopyImage(overlay, 33)
_PutImage (0, 0), Overlay_Hardware
If HtmlBtn = k And lb = 0 Then
_PutImage ((x(k) - 1) * 8, (y(k) - 1) * 16 + 8), HTMLBHover
Else
If lb = 0 And b_hover = k Then
_PutImage ((x(k) - 1) * 8, (y(k) - 1) * 16 + 8), HTMLBHover
ElseIf Abs(lb) = 1 And b_hover = k Then
_PutImage ((x(k) - 1) * 8, (y(k) - 1) * 16 + 8), HTMLBPress
Else
_PutImage ((x(k) - 1) * 8, (y(k) - 1) * 16 + 8), HTMLBStatic
End If
End If
_FreeImage HTMLBHover
_FreeImage HTMLBPress
_FreeImage HTMLBStatic
_FreeImage Overlay_Hardware
Next
You make 4 software images. You then convert those to 4 hardware images. You free the software image. You put the hardware to the screen. You free the hardware image.
And you do this inside a FOR loop inside your DO loop... and... OMG!! How many times is that memory being allocated and freed repeated in this process???
I think what you need to do here is:
1) Step back and rebuild so that the screen only updates when needed.
DO
updateScreen = _FALSE
k = _KEYHIT
IF k THEN updateScreen = _TRUE 'a key was hit, let's set the flag to update the screen!
'more junk
IF updateScreen THEN
'do the draw routines
_DISPLAY
END IF
LOOP
If the screen isn't changed, you don't need to redraw it over and over; just leave it as it was until the user interacts with it somehow.
^This change would make a HUGE difference in things.
2) Make the conversion over from software to hardware ONCE, and be done with it, if you possibly can. Create those buttons in advance, don't bother to _FREEIMAGE them. Free the software versions, but save the hardware versions for use elsewhere in the program as needed. Don't create and free them on the fly like that repeatedly. Make 'em, save 'em, use 'em. Only when you're certain you're done with them, THEN free them.
The issue isn't so much the hardware image itself; it's "the creation of the software image, the copy to the hardware, the freeing of the software, the display of the hardware, the freeing of the hardware"....
If you can change it to just "display of the hardware", can't you see how much more efficient that would end up being? << And then make it so it only does that when the screen itself HAS to be updated??
This is a case where the problem isn't in the commands. It's in how you're implementing and trying to use those commands.
Posts: 2,849
Threads: 340
Joined: Apr 2022
Reputation:
250
Even IF you can't (for some odd reason) create those images once, you can still clean up the code and processes a TON with just some simple changes.
Examine the code in the post above, which I copied from your link.
Then, compare to this simple set of changes:
Code: (Select All)
Overlay_Hardware = _CopyImage(overlay, 33)
For k = i2 To i3
j = Len(button$(k)): a$ = " " + button$(k) + " "
_PutImage (0, 0), Overlay_Hardware
If HtmlBtn = k And lb = 0 Then
HTMLBHover = fb_gfx_hyb_hw(j * 8, 2 * 16, 200, 200, 200, -8, -7, -1, Mid$(a$, 1, j))
_PutImage ((x(k) - 1) * 8, (y(k) - 1) * 16 + 8), HTMLBHover
_FreeImage HTMLBHover
Else
If lb = 0 And b_hover = k Then
HTMLBHover = fb_gfx_hyb_hw(j * 8, 2 * 16, 200, 200, 200, -8, -7, -1, Mid$(a$, 1, j))
_PutImage ((x(k) - 1) * 8, (y(k) - 1) * 16 + 8), HTMLBHover
_FreeImage HTMLBHover
ElseIf Abs(lb) = 1 And b_hover = k Then
HTMLBPress = fb_gfx_hyb_hw(j * 8, 2 * 16, 200, 200, 200, -1, -1, -1, Mid$(a$, 1, j))
_PutImage ((x(k) - 1) * 8, (y(k) - 1) * 16 + 8), HTMLBPress
_FreeImage HTMLBPress
Else
HTMLBStatic = fb_gfx_hyb_hw(j * 8, 2 * 16, 170, 170, 170, -9, -9, -1, Mid$(a$, 1, j))
_PutImage ((x(k) - 1) * 8, (y(k) - 1) * 16 + 8), HTMLBStatic
_FreeImage HTMLBStatic
End If
End If
Next
_FreeImage Overlay_Hardware
The overlay doesn't change inside the loop, so there's no reason to create it and free it constantly. At most, create it ONCE before the loop, free it after the loop.
Then you're creating three software images. Copying them to hardware images. Freeing the three software images. Using ONE hardware image based on those IF statements. And then freeing all those hardware images.
I've changed it so you.. Create 1 software, copy it, free it, display the hardware, free it.
That's only using ONE image without ever even having to deal with the other two at all... And, since we're not copying and freeing the overlay, we're now basically making ONE hardware image in the loop instead of FOUR.
I think you can see where even a small change to things, such as this, would *really* affect your CPU usage.
Posts: 2,458
Threads: 248
Joined: Apr 2022
Reputation:
125
02-18-2025, 11:45 PM
(This post was last modified: Yesterday, 12:38 AM by Pete.)
Cool, we are on the same page here, because that's just what I was looking into when you made this post. Certainly the usage will be more with hardware acceleration in SCREEN 0 than just utilizing pure graphics, but as long as it isn't alarmingly elevated, it still may be worth pursuing.
I'll have a look at your code and update my demo accordingly. I'll let you guys know the improvement when the results are in...
Edit...
NEAT! Dramatic improvement from 55% to 35% just by making it so the overlay image copy is only made once and freed once per sub loop.
So the difference in testing the original, do you think it's the difference in our hardware? The desktop you are using is infinitely more powerful than this 12 year old laptop I'm coding on.
Edit #2:
I ran with your idea on the graphic/hybrid buttons. I had to tweak the code a bit more and a bit differently, but yep, you were correct, it also helped reduce CPU, now down to 23%.
You know I did try the system idle approach a few days ago, but it wouldn't display the non-text items. I think I didn't revert to _autodisplay. I'm going to retry that, next...
Pete
Posts: 2,849
Threads: 340
Joined: Apr 2022
Reputation:
250
Question: What is all this crapola?
j = Len(button$(k)): a$ = " " + button$(k) + " "
Mid$(a$, 1, j))
Isn't this just adding a space in front of the button$(k) and removing one letter off the right of button$(k)?
Why not: a$ = " " + LEFT$(button$(k), LEN(button$(k) -1)
Then you can get rid of the variable j, and simplify those MID$ statements to just a$.
Posts: 2,849
Threads: 340
Joined: Apr 2022
Reputation:
250
@Pete your code gives me headaches. It's the old school style of programming with single variable names and things not being declared and arrrghhh!!!
Explain a few things to me:
You only make Overlay once in the program. Right?
And at no point do you ever CLS the Overlay?
And yet, you draw on this same Overlay a bazillion times...
Code: (Select All) Color fb.BHybFg, fb.BHybBg2
Locate y1(q) + 1, x1(q) + 1: Print button$(l);
_Dest overlay
Line (8 * (x(k) - 1) + 2, 16 * (y(k) - 1) + 7 + 2)-((j + 2) * 8 + 8 * (x(k) - 1) - 2, 16 * 2 + 16 * (y(k) - 1) + 7 - 2), _RGB32(0, 155, 155), B
Overlay_Hardware = _CopyImage(overlay, 33)
_PutImage (0, 0), Overlay_Hardware
_FreeImage Overlay_Hardware
_Dest 0
When does those drawings ever get erased? Do they ever get erased? If they don't get erased, then why are you redrawing them repeatedly?
Look as I might, I just don't see where that screen is ever getting cleared or erased.
What am I overlooking here? All this seems to be one overly complex way to do things to me.
Why not go with a much simpler approach like:
TYPE button_type
handle as LONG
wide as LONG
tall as LONG
END TYPE
REDIM button(0) AS button_type
Then when you assign button$(k) = "whatever the caption might be", you instead:
temp = _newimage(8, 16 * "whatever the caption might be" , 32)
_DEST temp
CLS ,whatever_background_color_wanted
Lines 'draw the border as wanted
LOCATE 1, 1: PRINT button$(k); 'print the caption
button(index).handle = _COPYIMAGE(temp, 33) 'make a copy of the button in hardware
button(index).wide = 16 * "whatever the caption might be"
button(index).tall = 8 'or _FONTHEIGHT
_FREEIMAGE temp
Now you have that hardware image already created of that button. You don't have to recreate it over and over. You don't need to PRINT the caption back on the screen or anything else. You just _PUTIMAGE that already created button on the screen where you want it, and be done with it.
Note that this also has the added effect of making each button the size of a button and not just a drawing on the whole screen. You're not going for an overlay of the whole screen; you're just making a button to display over the screen where needed.
Posts: 2,849
Threads: 340
Joined: Apr 2022
Reputation:
250
For a quick demo of what I'm talking about, see here:
Code: (Select All)
Dim buttons(1) 'just two simple buttons for the demo
button(0) = MakeButton("Hello World")
button(1) = MakeButton("STEVE!")
x = 100 'just for moveable button
Cls , 4 'a red screen for a background
Do
_PutImage (x, 100), button(0)
_PutImage (200, 200), button(1)
k = _KeyHit
Select Case k 'left/right arrow to move that button
Case 19200: x = x - 3: If x < 0 Then x = 0
Case 19712: x = x + 3: If x > _Width * _FontWidth - 100 Then x = _Width * _FontWidth - 100
Case Is > 0: System 'any other key to end
End Select
_Display
_Limit 30
Loop
Function MakeButton (caption$)
d = _Dest
temp = _NewImage(_FontWidth * Len(caption$) + 4, _FontHeight + 4, 32)
_Dest temp
Color &HFFFFFFFF&&, 0 ' bright white text with no background
Cls , &HFF0000FF&& 'dark blue background for this button
Line (0, 0)-(_Width - 1, _Height - 1), &HFFFFFFFF, B 'white trim around the edges
Line (1, 1)-(_Width - 2, _Height - 2), &HFFFFFFFF, B '2 pixel trim
_PrintString (3, 3), caption$ 'print the caption
MakeButton = _CopyImage(temp, 33) 'make the hardware button
_Dest d 'restore the destination
_FreeImage temp 'free the temp image
End Function
|