Page 2 of 2

Posted: Thu Apr 03, 2008 7:48 pm
by Fluid Byte
I was 20 minutes behind you Fluid Byte.
I read too fast and just saw the "3" at right of the time. Image
I would never ignore you Fluid Byte. It's been a pleasure to see your nice side around here latelty :)
Yeah, I'm trying to watch my temper more often. I hope ... Image
Just tried this on my laptop running Vista and unfortunately Sparkies code doesn't seem to do anything other than have a button with a nice background, no droptext, no moving or highlighting.
It does work, but randomly. I pasted the code and it ran without a problem. Then I closed the program did something else and ran it again and it failed. I compiled it like 20 more times but it didn't do a thing. After closing and starting the IDE again it worked well. No clue why it's doing that.

Posted: Thu Apr 03, 2008 8:07 pm
by Derek
Just had a brain ripple (not quite a brain wave), checked to see if I had XP skin support on and I have, turned it off and Sparkies code works fine but doesn't look so nice.

Posted: Thu Apr 03, 2008 10:09 pm
by Sparkie
@srod: ME...busy....pffff :P

@Fluid BYte: Good job on the temper control. It gets easier as you get older. 8)

@Derek: I'll have a look when I get home to my Vista laptop.

Posted: Fri Apr 04, 2008 12:14 am
by Sparkie
Just tested my code on my Vista laptop and it works just as well as it does on my XP box. Maybe it's an Aero issue. My laptop video doesn't support it so I have no way to test that here.

As for the XP skins issue, I think I can fix that. 8)

Posted: Fri Apr 04, 2008 4:54 pm
by Sparkie
IMO, I say that as of Win XP, BS_OWNERDRAW is not the best choice, as hottracking is not active by default. Therefore, I put this next piece of code together for XP or later only. Still some minor details to take care of but it works fine for me on both XP and Vista (sans Aero).

Enable XP skins before running code.

Code: Select all

UseJPEGImageDecoder() 
#Button1 = 1
#Button2 = 2
#DrawFrame = 1
#DrawFocus = 2
Structure MYBRUSHES
  hotBrush.l
  defaultBrush.l
  frameBrush.l
  disabledBrush.l
EndStructure
Procedure myWindowCallback(hwnd, msg, wParam, lParam) 
  result = #PB_ProcessPureBasicEvents 
  Select msg 
    Case #WM_NOTIFY 
      *nmhdr.NMHDR = lParam 
      If *nmhdr\code = #NM_CUSTOMDRAW And *nmhdr\idFrom = #Button1
        DrawFocusRect = #False 
        pressed = #False
        *nmcd.NMCUSTOMDRAW = lParam
        *buttonBrushes.MYBRUSHES = GetGadgetData(*nmhdr\idFrom) 
        Select *nmcd\dwDrawStage 
          Case #CDDS_PREERASE 
            result = #CDRF_NOTIFYPOSTERASE 
          Case #CDDS_PREPAINT 
            iState = *nmcd\uItemState &~ #CDIS_SHOWKEYBOARDCUES
            Select iState
              Case #CDIS_DISABLED
                ;... Button is diaabled
                drawDetail = 0
                SetTextColor_(*nmcd\hdc, #Gray)
                brush = *buttonBrushes\disabledBrush
              Case #CDIS_FOCUS
                ;... Button has keyboard focus, button has been clicked
                drawDetail = #DrawFocus
                brush = *buttonBrushes\defaultBrush
                doFlags = #DFCS_HOT | #DFCS_BUTTONPUSH 
              Case #CDIS_FOCUS | #CDIS_HOT | #CDIS_SELECTED
                ;... Button has keyboard, mouse is over button, button is being clicked
                drawDetail = #DrawFocus | #DrawFrame
                brush = *buttonBrushes\defaultBrush
                doFlags = #DFCS_HOT | #DFCS_BUTTONPUSH | #DFCS_PUSHED 
              Case #CDIS_FOCUS | #CDIS_HOT
                ;... Button has keyboard focus, mouse is over button, button has been clicked
                drawDetail = #DrawFocus  | #DrawFrame 
                brush = *buttonBrushes\hotBrush
                doFlags = #DFCS_HOT
              Case #CDIS_HOT
                ;... Button does not have keyboard focus, mouse is over button, button has not been clicked
                drawDetail = #DrawFrame
                brush = *buttonBrushes\hotBrush
                doFlags = #DFCS_HOT | #DFCS_BUTTONPUSH 
              Default
                drawDetail = 0
                brush = *buttonBrushes\defaultBrush
                doFlags = #DFCS_BUTTONPUSH
                DrawFocusRect = #False
                DrawFrame = #False
            EndSelect
            SetBkMode_(*nmcd\hdc, #TRANSPARENT) 
            DrawFrameControl_(*nmcd\hdc, *nmcd\rc, #DFC_BUTTON, doFlags) 
            FillRect_(*nmcd\hdc, *nmcd\rc, brush) 
            Select drawDetail
              Case #DrawFrame
                brush = *buttonBrushes\frameBrush
                DrawText_(*nmcd\hdc, GetGadgetText(*nmhdr\idFrom), Len(GetGadgetText(*nmhdr\idFrom)), *nmcd\rc, #DT_CENTER | #DT_SINGLELINE | #DT_VCENTER) 
                FrameRect_(*nmcd\hdc, *nmcd\rc, brush)
              Case #DrawFocus
                brush = *buttonBrushes\frameBrush
                DrawText_(*nmcd\hdc, GetGadgetText(*nmhdr\idFrom), Len(GetGadgetText(*nmhdr\idFrom)), *nmcd\rc, #DT_CENTER | #DT_SINGLELINE | #DT_VCENTER) 
                *nmcd\rc\left + 1
                *nmcd\rc\top + 1
                *nmcd\rc\right - 1
                *nmcd\rc\bottom - 1
                DrawFocusRect_(*nmcd\hdc, *nmcd\rc) 
              Case #DrawFocus | #DrawFrame
                brush = *buttonBrushes\frameBrush
                DrawText_(*nmcd\hdc, GetGadgetText(*nmhdr\idFrom), Len(GetGadgetText(*nmhdr\idFrom)), *nmcd\rc, #DT_CENTER | #DT_SINGLELINE | #DT_VCENTER) 
                FrameRect_(*nmcd\hdc, *nmcd\rc, brush)
                *nmcd\rc\left + 1
                *nmcd\rc\top + 1
                *nmcd\rc\right - 1
                *nmcd\rc\bottom - 1
                DrawFocusRect_(*nmcd\hdc, *nmcd\rc) 
              Default
                DrawText_(*nmcd\hdc, GetGadgetText(*nmhdr\idFrom), Len(GetGadgetText(*nmhdr\idFrom)), *nmcd\rc, #DT_CENTER | #DT_SINGLELINE | #DT_VCENTER) 
            EndSelect
            result = #CDRF_SKIPDEFAULT 
        EndSelect 
      EndIf 
  EndSelect 
  ProcedureReturn result 
EndProcedure 

Procedure.l DoBrushes(gad)
  ;... Store brush data
  *bBrushes.MYBRUSHES = AllocateMemory(SizeOf(MYBRUSHES))
  ;... Create default button background brush 
  *bBrushes\defaultBrush = CreatePatternBrush_(CatchImage(0, ?myImage)) 
  ;... Create hot button background brush 
  GrabImage(0, 1, 0, 0, 100, 100)
  StartDrawing(ImageOutput(1))
  For x = 0 To ImageWidth(1)
    For y = 0 To ImageHeight(1)
      Plot(x, y, Point(x, y) + RGB(25, 25, 25))
    Next y
  Next x
  StopDrawing()
  *bBrushes\hotBrush = CreatePatternBrush_(ImageID(1)) 
  ;... Create button frame color brush 
  *bBrushes\frameBrush = CreateSolidBrush_(#Yellow)
  ;... Create disabled button background brush 
  *bBrushes\disabledBrush = GetStockObject_(#LTGRAY_BRUSH)
  FreeImage(0) 
  FreeImage(1) 
  ProcedureReturn *bBrushes
EndProcedure

If OpenWindow(0, 100, 100, 230, 120, "Custom Button", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0)) 
  SetWindowCallback(@myWindowCallback()) 
  ButtonGadget(#Button1, 10, 10, 100, 100, "Customdrawn") 
  *brushes.MYBRUSHES = DoBrushes(#Button1)
  SetGadgetData(#Button1, *brushes) 
  ButtonGadget(#Button2, 120, 10, 100, 100, "Normal") 
  
  Repeat 
    event = WaitWindowEvent() 
  Until event = #PB_Event_CloseWindow 
  DeleteObject_(*brushes\defaultBrush) 
  DeleteObject_(*brushes\hotBrush)
  DeleteObject_(*brushes\frameBrush)
EndIf 
End 
DataSection 
myImage: 
Data.b $FF,$D8,$FF,$E0,$00,$10,$4A,$46,$49,$46,$00,$01,$01,$01,$00,$60 
Data.b $00,$60,$00,$00,$FF,$DB,$00,$43,$00,$28,$1C,$1E,$23,$1E,$19,$28 
Data.b $23,$21,$23,$2D,$2B,$28,$30,$3C,$64,$41,$3C,$37,$37,$3C,$7B,$58 
Data.b $5D,$49,$64,$91,$80,$99,$96,$8F,$80,$8C,$8A,$A0,$B4,$E6,$C3,$A0 
Data.b $AA,$DA,$AD,$8A,$8C,$C8,$FF,$CB,$DA,$EE,$F5,$FF,$FF,$FF,$9B,$C1 
Data.b $FF,$FF,$FF,$FA,$FF,$E6,$FD,$FF,$F8,$FF,$C0,$00,$0B,$08,$00,$64 
Data.b $00,$64,$01,$01,$11,$00,$FF,$C4,$00,$17,$00,$01,$01,$01,$01,$00 
Data.b $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$02,$01,$00,$03,$FF 
Data.b $C4,$00,$1A,$10,$01,$01,$01,$01,$01,$01,$01,$00,$00,$00,$00,$00 
Data.b $00,$00,$00,$00,$00,$01,$11,$02,$12,$21,$31,$FF,$DA,$00,$08,$01 
Data.b $01,$00,$00,$3F,$00,$EA,$59,$AD,$39,$5B,$06,$A6,$A6,$B6,$A6,$B6 
Data.b $B1,$4F,$8C,$5E,$4B,$92,$1A,$E7,$D0,$DA,$96,$A6,$AC,$AB,$0A,$16 
Data.b $36,$3A,$79,$1A,$A9,$5C,$EC,$1B,$11,$11,$61,$F2,$E9,$21,$48,$56 
Data.b $8B,$35,$F8,$36,$0D,$83,$60,$D8,$D8,$B2,$1C,$98,$71,$D2,$0D,$69 
Data.b $19,$A8,$54,$4B,$13,$16,$72,$53,$93,$9C,$EA,$F9,$C6,$2B,$C8,$5F 
Data.b $83,$E9,$35,$64,$6C,$6B,$12,$43,$9C,$9F,$92,$9C,$AF,$91,$F2,$B5 
Data.b $CB,$B7,$2E,$92,$53,$94,$A2,$B1,$73,$0D,$A5,$2D,$F8,$C1,$6B,$9F 
Data.b $6E,$3D,$0C,$28,$7C,$D3,$BF,$83,$A5,$3A,$2F,$49,$E8,$B9,$E8,$B4 
Data.b $77,$E3,$9F,$55,$CB,$A1,$C5,$91,$D3,$95,$B4,$2D,$59,$D3,$7A,$69 
Data.b $5D,$25,$2D,$0B,$46,$D1,$A8,$B1,$65,$5B,$42,$A5,$A9,$29,$F2,$E9 
Data.b $17,$41,$2D,$0B,$59,$4A,$35,$14,$C5,$90,$A2,$EB,$68,$DA,$35,$0A 
Data.b $45,$65,$FD,$16,$D6,$D6,$95,$75,$75,$2A,$34,$56,$66,$4A,$8A,$2B 
Data.b $09,$FF,$D9 
EndDataSection 

Posted: Fri Apr 04, 2008 5:47 pm
by Fluid Byte
Nice snippet Sparkman but the problem remains. Sometimes it works, sometimes it doesn't. I think it's because of the focus rectangle issue. Applications compiled with XP skin sometimes show the focus rectangle, sometimes they don't. I think there was a thread about this as well as a workaround.

Posted: Fri Apr 04, 2008 6:45 pm
by Derek
Works on mine every time, it does show the focus rectangle after the first click but it does respond to every click, no matter how fast you click.

Posted: Fri Apr 04, 2008 6:56 pm
by Sparkie
Thanks guys :)

Like Derek, it works each and every time for me as well. :?

Here's another one that works fine for me on Xp and Vista...

Code: Select all

UseJPEGImageDecoder()

Structure SPARKEDBUTTONINFO
  iNum.l
  iId.l
EndStructure

Procedure.l SparkedButtonGadget(gad, x, y, w, h, text$, imageNum, imageId, icoW, icoH) 
  originalImage = GrabImage(imageNum, #PB_Any, 0, 0, ImageWidth(imageNum), ImageHeight(imageNum))
  StartDrawing(ImageOutput(imageNum)) 
  DrawImage(imageId, 0, 0, w, h) 
  DrawingFont(GetStockObject_(#DEFAULT_GUI_FONT)) 
  DrawingMode(#PB_2DDrawing_Transparent)
  DrawText((w - TextWidth(text$))/2, (h - TextHeight(text$))/2, text$, #Black) 
  StopDrawing() 
  gadId = ButtonImageGadget(gad, x, y, w, h, ImageID(imageNum)) 
  *sbi.SPARKEDBUTTONINFO = AllocateMemory(SizeOf(SPARKEDBUTTONINFO))
  *sbi\iNum = imageNum
  *sbi\iId = ImageID(originalImage)
  SetGadgetData(gad, *sbi)
  ProcedureReturn gadId 
EndProcedure 

Procedure.l SetSparkedButtonGadgetText(gad, text$)
  *currentImageInfo.SPARKEDBUTTONINFO = GetGadgetData(gad)
  StartDrawing(ImageOutput(*currentImageInfo\iNum)) 
  DrawImage(*currentImageInfo\iId, 0, 0, ImageWidth(*currentImageInfo\iNum), ImageHeight(*currentImageInfo\iNum)) 
  DrawingFont(GetStockObject_(#DEFAULT_GUI_FONT)) 
  DrawingMode(#PB_2DDrawing_Transparent)
  DrawText((ImageWidth(*currentImageInfo\iNum) - TextWidth(text$))/2, (ImageHeight(*currentImageInfo\iNum) - TextHeight(text$))/2, text$, #Black) 
  StopDrawing() 
  SetGadgetState(gad, ImageID(*currentImageInfo\iNum)) 
EndProcedure

If OpenWindow(0, 0, 0, 230, 120, "Test", #PB_Window_SystemMenu|#PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0)) 
  SparkedButtonGadget(0, 10, 10, 100, 100, "*********", 0, CatchImage(0, ?myImage), 100, 100) 
  SparkedButtonGadget(1, 120, 10, 100, 100, "*****", 1, CatchImage(1, ?myImage), 100, 100) 
  Repeat 
    event = WaitWindowEvent() 
    If EventType() = #PB_EventType_LeftClick And EventGadget() = 0
      SetSparkedButtonGadgetText(1, "Rocks")
    EndIf
    If EventType() = #PB_EventType_LeftClick And EventGadget() = 1
      SetSparkedButtonGadgetText(0, "PureBasic")
    EndIf
  Until event = #PB_Event_CloseWindow 
EndIf 
End 
DataSection 
myImage: 
Data.b $FF,$D8,$FF,$E0,$00,$10,$4A,$46,$49,$46,$00,$01,$01,$01,$00,$60 
Data.b $00,$60,$00,$00,$FF,$DB,$00,$43,$00,$28,$1C,$1E,$23,$1E,$19,$28 
Data.b $23,$21,$23,$2D,$2B,$28,$30,$3C,$64,$41,$3C,$37,$37,$3C,$7B,$58 
Data.b $5D,$49,$64,$91,$80,$99,$96,$8F,$80,$8C,$8A,$A0,$B4,$E6,$C3,$A0 
Data.b $AA,$DA,$AD,$8A,$8C,$C8,$FF,$CB,$DA,$EE,$F5,$FF,$FF,$FF,$9B,$C1 
Data.b $FF,$FF,$FF,$FA,$FF,$E6,$FD,$FF,$F8,$FF,$C0,$00,$0B,$08,$00,$64 
Data.b $00,$64,$01,$01,$11,$00,$FF,$C4,$00,$17,$00,$01,$01,$01,$01,$00 
Data.b $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$02,$01,$00,$03,$FF 
Data.b $C4,$00,$1A,$10,$01,$01,$01,$01,$01,$01,$01,$00,$00,$00,$00,$00 
Data.b $00,$00,$00,$00,$00,$01,$11,$02,$12,$21,$31,$FF,$DA,$00,$08,$01 
Data.b $01,$00,$00,$3F,$00,$EA,$59,$AD,$39,$5B,$06,$A6,$A6,$B6,$A6,$B6 
Data.b $B1,$4F,$8C,$5E,$4B,$92,$1A,$E7,$D0,$DA,$96,$A6,$AC,$AB,$0A,$16 
Data.b $36,$3A,$79,$1A,$A9,$5C,$EC,$1B,$11,$11,$61,$F2,$E9,$21,$48,$56 
Data.b $8B,$35,$F8,$36,$0D,$83,$60,$D8,$D8,$B2,$1C,$98,$71,$D2,$0D,$69 
Data.b $19,$A8,$54,$4B,$13,$16,$72,$53,$93,$9C,$EA,$F9,$C6,$2B,$C8,$5F 
Data.b $83,$E9,$35,$64,$6C,$6B,$12,$43,$9C,$9F,$92,$9C,$AF,$91,$F2,$B5 
Data.b $CB,$B7,$2E,$92,$53,$94,$A2,$B1,$73,$0D,$A5,$2D,$F8,$C1,$6B,$9F 
Data.b $6E,$3D,$0C,$28,$7C,$D3,$BF,$83,$A5,$3A,$2F,$49,$E8,$B9,$E8,$B4 
Data.b $77,$E3,$9F,$55,$CB,$A1,$C5,$91,$D3,$95,$B4,$2D,$59,$D3,$7A,$69 
Data.b $5D,$25,$2D,$0B,$46,$D1,$A8,$B1,$65,$5B,$42,$A5,$A9,$29,$F2,$E9 
Data.b $17,$41,$2D,$0B,$59,$4A,$35,$14,$C5,$90,$A2,$EB,$68,$DA,$35,$0A 
Data.b $45,$65,$FD,$16,$D6,$D6,$95,$75,$75,$2A,$34,$56,$66,$4A,$8A,$2B 
Data.b $09,$FF,$D9 
EndDataSection 

Posted: Fri Apr 04, 2008 7:03 pm
by Derek
Great bit of code Sparkie, works brilliantly now, no focus rectangle showing up now and very responsive. :)

Posted: Fri Apr 04, 2008 7:38 pm
by Fluid Byte
Confirmed. Image

Posted: Fri Apr 04, 2008 8:33 pm
by Sparkie
Fluid Byte wrote:Applications compiled with XP skin sometimes show the focus rectangle, sometimes they don't. I think there was a thread about this as well as a workaround.
Thanks for reminding me of that one Fluid Byte. :)

I applied a fix to the code in post http://www.purebasic.fr/english/viewtop ... 143#239143 if you'd like to try it again.

Posted: Thu Apr 24, 2008 9:36 pm
by mrjiles
Started coding before I reviewed Sparkie's code. Mine is very similar but it appears he has some fancy footwork going on (not sure what everything does either!). Here's my Imagebutton + Text. It uses a 16x16 icon.

Code: Select all

#Window = 1
#Button = 2

Procedure ButtonImageTextGadget(Gadget, x, y, Width, Height, Text$, ImageID)
	hImage = CreateImage(#PB_Any, Width, Height)
	clrBack = GetSysColor_(#COLOR_3DFACE)
	StartDrawing(ImageOutput(hImage))
		Box(0, 0, Width, Height, clrBack)
		DrawImage(ImageID, 8, 7)
		DrawText(40, 7, Text$, 0, clrBack)
	StopDrawing()
	
	ButtonImageGadget(Gadget, x, y, Width, Height, ImageID(hImage))
EndProcedure



OpenWindow(#Window, 0, 0, 300, 300, "ImageButton + Text", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
CreateGadgetList(WindowID(#Window))

ButtonImageTextGadget(#PB_Any, 10, 10, 100, 30, "Test", ImageID(LoadImage(#PB_Any, "c:\test.ico")))


Repeat
	Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
End

Posted: Thu Apr 24, 2008 10:06 pm
by Rook Zimbabwe
This is very useful and extremely cool! Great Job Sparkie, and Mr. Jiles...

@Jiles: Take a look at my nerd pickup lines... it will help with the sequel to your avatar (and wear a cup! ) :wink: (I am teasing!(except about the cup!))