[Implemented] JPG Image Display
-
- PureBasic Guru
- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
[Implemented] JPG Image Display
Restored from previous forum. Originally posted by ebs.
My #1 feature request:
PLEASE! make PB Image commands support JPG images as well as BMP and ICO. Most of my image-handling requires JPG images, and converting to BMP format isn't a possibility. PB already supports reading and displaying JPG images as sprites; would it be difficult to allow them to be displayed in the standard ImageGadget? Am I missing something obvious that can be done with a sprite to display it in a standard Windows app?
Thanks for listening!
Regards,
Eric
My #1 feature request:
PLEASE! make PB Image commands support JPG images as well as BMP and ICO. Most of my image-handling requires JPG images, and converting to BMP format isn't a possibility. PB already supports reading and displaying JPG images as sprites; would it be difficult to allow them to be displayed in the standard ImageGadget? Am I missing something obvious that can be done with a sprite to display it in a standard Windows app?
Thanks for listening!
Regards,
Eric
-
- PureBasic Guru
- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by El_Choni.
Hi,
UPDATE: updated code for 3.20.
This is just for testing purposes, not a complete app, and you'll notice there are lots of features missing; but it loads and shows jpeg and gif files. Enjoy it;
Bye,
El_Choni
Edited by - El_Choni on 01 July 2002 01:16:43
Hi,
UPDATE: updated code for 3.20.
This is just for testing purposes, not a complete app, and you'll notice there are lots of features missing; but it loads and shows jpeg and gif files. Enjoy it;
Code: Select all
;
; Picture View for PB Windows
;
; Written in PureBasic by El_Choni
;
; Thanks: Rings for helping me to deal with bitmaps in memory
;
version.s = "0.1"
Structure ImageData
width.l
height.l
colors.l
chars.l
bits.b
EndStructure
Global IData.ImageData, BmpSize, BmpImage, FileSize, loaded.b, WindowWidth, WindowHeight, ImgWidth, ImgHeight, MenuHeight, xImg, yImg, ParentHandle, ptMinTrackSizex, aspect.f, hDC
*BmpFile.BITMAPFILEHEADER
*BmpInfo.BITMAPINFOHEADER
bmp.BITMAP
#BI_RGB = 0
Global File.s, gpPicture
gpPicture = 0
pstm = 0
#E_POINTER = $80000005
#E_NOINTERFACE = $80000004
#E_OUTOFMEMORY = $80000002
#IPicture_Release = 8
#IPicture_Get_Width = 24
#IPicture_Get_Height = 28
#IPicture_Render = 32
Global lphmwidth, lphmheight
ptMinTrackSizex = 320
Global nwidth, nheight, hmheight, hmwidth, rc.RECT
Procedure UpdateImage()
If loaded
ImgHeight = WindowHeight
ImgWidth = ImgHeight*aspect
If ImgWidth>WindowWidth
ImgWidth = WindowWidth
ImgHeight = ImgWidth/aspect
EndIf
If WindowWidth=ptMinTrackSizex And ImgWidth> 16
UpdateImage()
If loaded
SetWindowText_(ParentHandle, "Picture View - "+File+" "+StrF(((ImgWidth/IData\width)*100), 2)+"%")
EndIf
EndIf
Case #WM_PAINT
result = UpdateImage()
EndSelect
ProcedureReturn result
EndProcedure
Main:
tab.s = Chr(9)
open.s = tab+"Ctrl+O"
save.s = tab+"Ctrl+S"
tabquit.s = tab+"Ctrl+Q"
cien.s = tab+"Ctrl+Alt+0"
zoomin.s = tab+"+"
zoomout.s = tab+"-"
copy.s = tab+"Ctrl+C"
paste.s = tab+"Ctrl+V"
#Open = 0
#Save = 1
#Quit = 2
#Actual = 3
#Zoom_In = 4
#Zoom_Out = 5
#Copy = 6
#Paste = 7
OleInitialize_(0)
If OpenWindow(0, 100, 100, 480, 320, #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_SizeGadget, "Little Image Tool")
ParentHandle = WindowID()
If CreateMenu(0, ParentHandle)
MenuTitle("&File")
MenuItem(#Open, "&Open"+open)
MenuBar()
MenuItem(#Save, "&Save as..."+save)
MenuBar()
MenuItem(#Quit, "&Quit"+tabquit)
MenuTitle("&Tools")
MenuItem(#Actual, "100%"+cien)
MenuItem(#Zoom_In, "Zoom in"+zoomin)
MenuItem(#Zoom_Out, "Zoom out"+zoomout)
MenuBar()
MenuItem(#Copy, "&Copy"+copy)
MenuItem(#Paste, "Paste"+paste)
EndIf
DragAcceptFiles_(ParentHandle, #TRUE)
MenuHeight = GetSystemMetrics_(#SM_CYCAPTION)+GetSystemMetrics_(#SM_CYMENU)+8
Brush.LOGBRUSH\lbColor = 0
SetClassLong_(ParentHandle, #GCL_HBRBACKGROUND, CreateBrushIndirect_(Brush))
If CreateGadgetList(ParentHandle)
CreateImage(0, WindowWidth(), WindowHeight())
ImageGadget = ImageGadget(0, 0, MenuHeight, WindowWidth(), WindowHeight()+MenuHeight, UseImage(0))
hDC = GetDC_(ImageGadget)
WindowWidth = WindowWidth()
WindowHeight = WindowHeight()
SetWindowCallback(@ResizeCallback())
File = ProgramParameter()
Gosub OpenFile
SetForegroundWindow_(ParentHandle)
AddKeyboardShortcut(0, #PB_Shortcut_O|#PB_Shortcut_Control, #Open)
AddKeyboardShortcut(0, #PB_Shortcut_S|#PB_Shortcut_Control, #Save)
AddKeyboardShortcut(0, #PB_Shortcut_Q|#PB_Shortcut_Control, #Quit)
AddKeyboardShortcut(0, #PB_Shortcut_Pad0|#PB_Shortcut_Alt|#PB_Shortcut_Control, #Actual)
AddKeyboardShortcut(0, #PB_Shortcut_Add, #Zoom_In)
AddKeyboardShortcut(0, #PB_Shortcut_Subtract, #Zoom_Out)
AddKeyboardShortcut(0, #PB_Shortcut_C|#PB_Shortcut_Control, #Copy)
AddKeyboardShortcut(0, #PB_Shortcut_V|#PB_Shortcut_Control, #Paste)
Repeat
Select WaitWindowEvent()
Case #PB_EventMenu
Select EventMenuID()
Case #Open
Gosub Open
Case #Save
Gosub Save
Case #Quit
Quit = 1
Case #Actual
Gosub ActualPixels
Case #Zoom_In
Gosub ZoomIn
Case #Zoom_Out
Gosub ZoomOut
Case #Copy
Gosub Copy
Case #Paste
Gosub Paste
EndSelect
Case #WM_DROPFILES
AllocateMemory(3, 256, 0)
hDrop = EventwParam()
DragQueryFile_(hDrop, 0, MemoryID(), 256)
File = PeekS(MemoryID())
FreeMemory(3)
DragFinish_(hDrop)
Gosub OpenFile
Case #PB_EventCloseWindow
Quit = 1
EndSelect
Until Quit
EndIf
EndIf
OleUninitialize_()
End
;
; Actual pixels (100%)
;
ActualPixels:
If loaded
ResizeWindow(nwidth, nheight+MenuHeight)
SetWindowText_(ParentHandle, "Picture View - "+File+" 100%")
EndIf
Return
;
; Zoom out
;
ZoomOut:
If loaded
ResizeWindow(ImgWidth/2, (ImgHeight/2)+MenuHeight)
delayed = 0
EndIf
Return
;
; Zoom in
;
ZoomIn:
If loaded
ResizeWindow(ImgWidth*2, (ImgHeight*2)+MenuHeight)
delayed = 0
EndIf
Return
;
; Open image directly
;
OpenFile:
extension.s = LCase(Right(File, 4))
If extension=".gif" Or extension=".jpe" Or extension=".jpg" Or extension=".bmp"
Gosub OpenPicture
Gosub ShowImage
Gosub ActualPixels
EndIf
Return
;
; Open image request
;
Open:
File = OpenFileRequester("Open image file","","Windows BMP Image (*.bmp)|*.bmp|GIF Image (*.gif)|*.gif|Jpeg Image (*.jpg)|*.jpe;*.jpg", 0)
extension.s = LCase(Right(File, 4))
If extension=".gif" Or extension=".jpe" Or extension=".jpg" Or extension=".bmp"
Gosub OpenPicture
Gosub ShowImage
Gosub ActualPixels
EndIf
Return
;
; Save
;
Save:
If loaded
File = SaveFileRequester("Save image file","","Windows BMP Image (*.bmp)|*.bmp", 0)
If Len(File)>0
SaveImage(0, File)
EndIf
EndIf
Return
;
; Copy image to clipboard
;
Copy:
If loaded
SetClipboardData(#PB_ClipboardImage, ImageID())
EndIf
Return
;
; Paste image
;
Paste:
OpenClipboard_(ParentHandle)
If IsClipboardFormatAvailable_(#CF_BITMAP)
If loaded
DeleteObject_(iHwnd)
FreeMemory(0)
Else
FreeImage(0)
EndIf
ciHwnd = GetClipboardData_(#CF_BITMAP)
GetObject_(ciHwnd, SizeOf(BITMAP), @bmp)
SelectObject_(hDC, ciHwnd)
IData\width = bmp\bmWidth
IData\height = bmp\bmHeight
IData\bits = bmp\bmBitsPixel*bmp\bmPlanes
pad = (bmp\bmWidthBytes-IData\width)*IData\height
iHwnd = CreateCompatibleBitmap_(hDC, IData\width, IData\height)
loaded = 1
aspect = IData\width/IData\height
RGBQuad = 0
If IData\bits>3))+pad
BmpImage = AllocateMemory(0, BmpSize, 0)
*BmpInfo = BmpImage+SizeOf(BITMAPFILEHEADER)
*BmpInfo\biSize = SizeOf(BITMAPINFOHEADER)
*BmpInfo\biWidth = IData\width
*BmpInfo\biHeight = IData\height
*BmpInfo\biPlanes = 1
*BmpInfo\biBitCount = IData\bits
*BmpInfo\biCompression = #BI_RGB; Currently supports only uncompressed images
GetDIBits_(hDC, ciHwnd, 0, IData\height, BMPImage+SizeOf(BITMAPFILEHEADER)+SizeOf(BITMAPINFOHEADER)+2+RGBQuad, BMPImage+SizeOf(BITMAPFILEHEADER), #DIB_RGB_COLORS)
CopyMemory(*BmpInfo, BmpImage+SizeOf(BITMAPFILEHEADER), SizeOf(BITMAPINFOHEADER)+RGBQuad+2)
FreeMemory(1)
*BmpFile = BmpImage
*BmpFile\bfType = 19778
*BmpFile\bfOffBits = SizeOf(BITMAPFILEHEADER)+SizeOf(BITMAPINFOHEADER)+RGBQuad+2
*BmpFile\bfSize = BmpSize
*BmpFile\bfReserved1 = 0
*BmpFile\bfReserved2 = 0
SetDIBits_(hDC, iHwnd, 0, IData\height, BmpImage+*BmpFile\bfOffBits, BmpImage+SizeOf(BITMAPFILEHEADER), 0)
ResizeWindow(IData\width, IData\height+MenuHeight)
EndIf
CloseClipboard_()
Return
;
; Open image file
;
OpenPicture:
If ReadFile(0, File)
LoadLibrary_("OLEPRO32.DLL")
LoadLibrary_("ADVAPI32.DLL")
LoadLibrary_("OLEAUT32.DLL")
FileSize = FileSize(File)
If loaded
FreeMemory(0)
EndIf
hGlobal = GlobalAlloc_(#GMEM_MOVEABLE, FileSize);
pvData = GlobalLock_(hGlobal)
ReadData(pvData, FileSize)
CloseFile(0)
GlobalUnlock_(hGlobal)
CreateStreamOnHGlobal_(hGlobal, #TRUE, @pstm)
If gpPicture
CallCOM(#IPicture_Release, gpPicture)
EndIf
Select OleLoadPicture_(pstm, FileSize, #FALSE, ?IID_IPicture, @gpPicture)
Case #E_POINTER
Error = 222
Case #E_NOINTERFACE
Error = 223
Case #E_OUTOFMEMORY
Error = 224
Default
Error = 0
EndSelect
CallCOM(#IPicture_Release, pstm)
GlobalFree_(hGlobal)
xscreenpixels = GetDeviceCaps_(hDC, #LOGPIXELSX)
yscreenpixels = GetDeviceCaps_(hDC, #LOGPIXELSY)
CallCOM(#IPicture_Get_Width, gpPicture, @hmwidth)
CallCOM(#IPicture_Get_Height, gpPicture, @hmheight)
nwidth = (hmwidth*xscreenpixels)/2540
nheight = (hmheight*yscreenpixels)/2540
ResizeGadget(0, 0, 0, nwidth, nheight)
ResizeWindow(nwidth, nheight+MenuHeight)
rc.RECT
GetClientRect_(ImageGadget, @rc)
ps.PAINTSTRUCT
ps\hdc = hDC
ps\fErase = 1
ps\rcPaint = @rc
aspect = nwidth/nheight
loaded = 1
UpdateImage()
EndIf
Return
;
; Save Bmp file
;
SaveBmp:
If CreateFile(0, File)
WriteData(BmpImage, *BmpFile\bfSize)
CloseFile(0)
EndIf
Return
;
; Show image
;
ShowImage:
Return
If BmpImage
If loaded
DeleteObject_(iHwnd)
Else
FreeImage(0)
EndIf
ResizeWindow(IData\width, IData\height+MenuHeight)
iHwnd = CreateCompatibleBitmap_(GetDC_(ParentHandle), IData\width, IData\height)
DestroyWindow_(ImageGadget)
ImageGadget = ImageGadget(0, 0, MenuHeight, IData\width, IData\height, iHwnd)
hDC = GetDC_(ImageGadget)
SetDIBits_(hDC, iHwnd, 0, IData\height, BmpImage+*BmpFile\bfOffBits, BmpImage+SizeOf(BITMAPFILEHEADER), 0)
loaded = 1
aspect = IData\width/IData\height
SetForegroundWindow_(ParentHandle)
UpdateImage()
EndIf
Return
![section .data]
IID_IPicture:
!dd $07bf80980
!dw $0bf32, $0101a
!db $08b, $0bb, 0, $0aa, 0, $030, $0c, $0ab
El_Choni
Edited by - El_Choni on 01 July 2002 01:16:43
-
- PureBasic Guru
- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
-
- PureBasic Guru
- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by ebs.
I get the same compile error. It's odd, since the definition of *gpPicture is given as:
Global *gpPicture.IPictureMethods
and IPictureMethods is a stucture.
Eric
I get the same compile error. It's odd, since the definition of *gpPicture is given as:
Global *gpPicture.IPictureMethods
and IPictureMethods is a stucture.
Eric
I get an error on this line:
call *gpPicture\Release
PureBASIC error message:
Line 69 This variable doesn't have a 'Structure'
elecTRONics DOCtor
{registeredPB}P150 32Mb w98/DOS/Linux NO DirX NO IE![]()
-
- PureBasic Guru
- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
-
- PureBasic Guru
- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by TronDoc.
OOPS! Thanks Fred. I think I made that mistake once before.
elecTRONics DOCtor
{registeredPB}P150 32Mb w98/DOS/Linux NO DirX NO IE
EDIT:
ooow. now it's worse! I get Purebasic36523192 error:
This program has performed an illegal operation and will be shut down.
If the problem persists, contact the program vendor.
{DETAILS:PUREBASIC36523192 caused a stack fault in module KERNEL32.DLL at 015f:bff742a3.}
And the PureBASIC - Debugger windows says Error at line 226:
InitKeyboard() must be called before use the keyboard commands.
I see that InitKeyboard() is a DirectX command. Oh well.
Edited by - TronDoc on 30 June 2002 21:13:27
Edited by - TronDoc on 30 June 2002 21:15:34
OOPS! Thanks Fred. I think I made that mistake once before.
elecTRONics DOCtor
{registeredPB}P150 32Mb w98/DOS/Linux NO DirX NO IE

EDIT:
ooow. now it's worse! I get Purebasic36523192 error:
This program has performed an illegal operation and will be shut down.
If the problem persists, contact the program vendor.
{DETAILS:PUREBASIC36523192 caused a stack fault in module KERNEL32.DLL at 015f:bff742a3.}
And the PureBASIC - Debugger windows says Error at line 226:
InitKeyboard() must be called before use the keyboard commands.
I see that InitKeyboard() is a DirectX command. Oh well.
Edited by - TronDoc on 30 June 2002 21:13:27
Edited by - TronDoc on 30 June 2002 21:15:34
-
- PureBasic Guru
- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by ebs.
TronDoc,
When I enabled Inline ASM as Fred said, the program compiled and ran fine for me (Win XP Pro).
Eric
TronDoc,
When I enabled Inline ASM as Fred said, the program compiled and ran fine for me (Win XP Pro).
Eric
OOPS! Thanks Fred. I think I made that mistake once before.
elecTRONics DOCtor
{registeredPB}P150 32Mb w98/DOS/Linux NO DirX NO IE
EDIT:
ooow. now it's worse! I get Purebasic36523192 error:
This program has performed an illegal operation and will be shut down.
If the problem persists, contact the program vendor.
{DETAILS:PUREBASIC36523192 caused a stack fault in module KERNEL32.DLL at 015f:bff742a3.}
And the PureBASIC - Debugger windows says Error at line 226:
InitKeyboard() must be called before use the keyboard commands.
I see that InitKeyboard() is a DirectX command. Oh well.
Edited by - TronDoc on 30 June 2002 21:13:27
Edited by - TronDoc on 30 June 2002 21:15:34
-
- PureBasic Guru
- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by ebs.
El_Choni,
Thanks for the JPG display code. Since I don't have a prayer of understanding it completely, I have a question. When I load an image, if I move the window so part of it is off-screen (or move another window in front of it), the covered part of the image disappears. Is there any way to make sure the image remains displayed?
Thanks again,
Eric
El_Choni,
Thanks for the JPG display code. Since I don't have a prayer of understanding it completely, I have a question. When I load an image, if I move the window so part of it is off-screen (or move another window in front of it), the covered part of the image disappears. Is there any way to make sure the image remains displayed?
Thanks again,
Eric
Hi,
This is just for etsting purposes, not a complete app, and you'll notice there are lots of features missing; but it loads and shows jpeg and gif files. Enjoy it;
Bye,
El_Choni
-
- PureBasic Guru
- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
-
- PureBasic Guru
- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by PB.
> When I enabled Inline ASM as Fred said, the program compiled and ran fine for me (Win XP Pro).
Fred: Is it okay to leave Inline ASM turned on for all apps, even if they don't
use any assembly code? Does it have any side-effects? Seems to me that it would
solve a lot of these "can't compile" problems...?
PB - Registered PureBasic Coder
> When I enabled Inline ASM as Fred said, the program compiled and ran fine for me (Win XP Pro).
Fred: Is it okay to leave Inline ASM turned on for all apps, even if they don't
use any assembly code? Does it have any side-effects? Seems to me that it would
solve a lot of these "can't compile" problems...?
PB - Registered PureBasic Coder
-
- PureBasic Guru
- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
-
- PureBasic Guru
- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by ebs.
El_Choni,
Thanks for all your hard work! The new code works much better on PB 3.2. I will try to incorporate it into my application, if that is OK with you. How big do you want your name on the scrolling credit screen???
Fred,
Is built-in JPG support in a future version of PB likely?
Thanks,
Eric
El_Choni,
Thanks for all your hard work! The new code works much better on PB 3.2. I will try to incorporate it into my application, if that is OK with you. How big do you want your name on the scrolling credit screen???
Fred,
Is built-in JPG support in a future version of PB likely?
Thanks,
Eric
Anyway, the updated code doesn't use DX (but it must use Asm to store the CLSID).
Bye,
El_Choni
-
- PureBasic Guru
- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by ebs.
El_Choni,
As usual(!), I have a question about your JPG display code. I noticed that when an image is displayed, the program uses over 90% of the CPU time. I believe this is because of the call to "UpdateImage()" whenever a #WM_PAINT message is received in the "ResizeCallback()" routine. It seems that #WM_PAINT messages are constantly coming in, even when there is no activity on the window - no mouse movement, no other windows moving, just idle. This doesn't make sense to me; I thought a window was repainted only when necessary. In any case, do you have any suggestions as to how to eliminate the unnecessary repaints and decrease the CPU time when no activity is occurring?
BTW - I really like your file drag and drop code! I didn't realize it was that simple. Of course, EVERYTHING is easy when you know how!
Thanks,
Eric
El_Choni,
As usual(!), I have a question about your JPG display code. I noticed that when an image is displayed, the program uses over 90% of the CPU time. I believe this is because of the call to "UpdateImage()" whenever a #WM_PAINT message is received in the "ResizeCallback()" routine. It seems that #WM_PAINT messages are constantly coming in, even when there is no activity on the window - no mouse movement, no other windows moving, just idle. This doesn't make sense to me; I thought a window was repainted only when necessary. In any case, do you have any suggestions as to how to eliminate the unnecessary repaints and decrease the CPU time when no activity is occurring?
BTW - I really like your file drag and drop code! I didn't realize it was that simple. Of course, EVERYTHING is easy when you know how!
Thanks,
Eric
-
- PureBasic Guru
- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by El_Choni.
Hi,
You're right about the CPU problem, but repainting must be done at some moment, and I don't know how to solve this, sorry.
Of course, you can use any part of the code or the whole of it. No need for acknowledgements, almost all is made from copy/paste from Internet.
Feel free to ask for any help. Have a nice day,
El_Choni
Hi,
You're right about the CPU problem, but repainting must be done at some moment, and I don't know how to solve this, sorry.
Of course, you can use any part of the code or the whole of it. No need for acknowledgements, almost all is made from copy/paste from Internet.
Feel free to ask for any help. Have a nice day,
El_Choni
-
- PureBasic Guru
- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by ebs.
El_Choni,
I don't think the problem is redrawing the JPG image when a #WM_PAINT message is received - that's the right time! The problem seems to be that the window CONSTANTLY receives #WM_PAINT messages, even when nothing is happening on the screen. A standard window with an ImageGadget gets #WM_PAINT messages only when part of the window has been covered (by another window, moving offscreen, etc.). Do you have any idea why this happens when using the IPicture COM object?
Fred,
Please consider extending PB's ImageGadget to support reading and displaying (maybe even saving) JPG images. It would be GREAT to have all the ImageGadget features (automatic resizing, etc.) and be able to use JPG images.
How 'bout it?
Regards,
Eric
El_Choni,
I don't think the problem is redrawing the JPG image when a #WM_PAINT message is received - that's the right time! The problem seems to be that the window CONSTANTLY receives #WM_PAINT messages, even when nothing is happening on the screen. A standard window with an ImageGadget gets #WM_PAINT messages only when part of the window has been covered (by another window, moving offscreen, etc.). Do you have any idea why this happens when using the IPicture COM object?
Fred,
Please consider extending PB's ImageGadget to support reading and displaying (maybe even saving) JPG images. It would be GREAT to have all the ImageGadget features (automatic resizing, etc.) and be able to use JPG images.
How 'bout it?
Regards,
Eric
Hi,
You're right about the CPU problem, but repainting must be done at some moment, and I don't know how to solve this, sorry.
Of course, you can use any part of the code or the whole of it. No need for acknowledgements, almost all is made from copy/paste from Internet.
Feel free to ask for any help. Have a nice day,
El_Choni