Text over ImageButton()

Just starting out? Need help? Post your questions and find answers here.
User avatar
Rook Zimbabwe
Addict
Addict
Posts: 4322
Joined: Tue Jan 02, 2007 8:16 pm
Location: Cypress TX
Contact:

Text over ImageButton()

Post by Rook Zimbabwe »

OK Aside from creating the picture with the text already in it... is there a way to use an imagebutton and have TEXT floating over the top that could be changed? Easily? :D You know... by some lazy idiot like me?
Binarily speaking... it takes 10 to Tango!!!

Image
http://www.bluemesapc.com/
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Post by Fluid Byte »

Use ownerdraw buttons.
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
User avatar
Rook Zimbabwe
Addict
Addict
Posts: 4322
Joined: Tue Jan 02, 2007 8:16 pm
Location: Cypress TX
Contact:

Post by Rook Zimbabwe »

A search for ownerdrawn has not shown me very much in the way of insight... Anyone know if a thread?
Binarily speaking... it takes 10 to Tango!!!

Image
http://www.bluemesapc.com/
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

Post by Mistrel »

Why don't you draw text onto the image that's displayed on the gadget?
Sparkie
PureBatMan Forever
PureBatMan Forever
Posts: 2307
Joined: Tue Feb 10, 2004 3:07 am
Location: Ohio, USA

Post by Sparkie »

This may be a little more than you need Rook, but it should help you get started. ;)

http://www.purebasic.fr/english/viewtop ... 458#227458
What goes around comes around.

PB 5.21 LTS (x86) - Windows 8.1
Sparkie
PureBatMan Forever
PureBatMan Forever
Posts: 2307
Joined: Tue Feb 10, 2004 3:07 am
Location: Ohio, USA

Post by Sparkie »

Here's an abbreviated version for you Rook.

Code: Select all

UseJPEGImageDecoder()
Procedure myWindowCallback(hwnd, msg, wParam, lParam) 
  result = #PB_ProcessPureBasicEvents 
  Select msg 
    Case #WM_DRAWITEM 
      *dis.DRAWITEMSTRUCT = lParam 
      If *dis\CtlType = #ODT_BUTTON 
        buttonBrush = GetGadgetData(0)
        buttonNum = *dis\CtlID 
        SetBkMode_(*dis\hdc, #TRANSPARENT) 
        doFlags = #DFCS_BUTTONPUSH | #DFCS_ADJUSTRECT 
        DrawFocusRect = #False
        Select *dis\itemState 
          Case #ODS_DISABLED 
            SetTextColor_(*dis\hdc, RGB(125, 125, 125)) 
          Case #ODS_FOCUS 
            DrawFocusRect = #True
          Case #ODS_FOCUS | #ODS_SELECTED 
            doFlags = #DFCS_BUTTONPUSH | #DFCS_PUSHED | #DFCS_ADJUSTRECT 
        EndSelect 
      EndIf 
      DrawFrameControl_(*dis\hdc, *dis\rcItem, #DFC_BUTTON, doFlags) 
      FillRect_(*dis\hdc, *dis\rcItem, buttonBrush) 
      DrawText_(*dis\hdc, GetGadgetText(buttonNum), Len(GetGadgetText(buttonNum)), *dis\rcItem, #DT_CENTER | #DT_SINGLELINE | #DT_VCENTER) 
      If DrawFocusRect
        DrawFocusRect_(*dis\hdc, *dis\rcItem)
      EndIf
  EndSelect 
  ProcedureReturn result 
EndProcedure 

If OpenWindow(0, 100, 100, 500, 400, "Custom Button", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0)) 
  SetWindowCallback(@myWindowCallback()) 
  ButtonGadget(0, 10, 10, 100, 100, "Ownerdrawn") 
  ButtonGadget(1, 120, 10, 100, 100, "Normal") 
  bStyle = GetWindowLong_(GadgetID(0), #GWL_STYLE) 
  SetWindowLong_(GadgetID(0), #GWL_STYLE, bStyle &~#BS_PUSHBUTTON | #BS_OWNERDRAW) 
  ;... Create button background brush 
  buttonBrush = CreatePatternBrush_(CatchImage(0, ?myImage)) 
  SetGadgetData(0, buttonBrush) 
   
  Repeat 
    event = WaitWindowEvent() 
  Until event = #PB_Event_CloseWindow 
EndIf 
DeleteObject_(buttonBrush) 
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
What goes around comes around.

PB 5.21 LTS (x86) - Windows 8.1
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

Nice job, Sparkie! Very compact and functional.

I did see one difference in the way your ownerdrawn button performs compared to the standard one. If you click it a lot quickly, the standard one presses and releases as fast as you can work the mouse while the ownerdrawn version is quite "speed limited". Try it, see what I mean?

It took me a while to pinpoint this one, but I came to the conclusion eventually that faster clicks are being taken as doubleclick events from the button and are thus ignored as buttons don't natively process doubleclicks. The two single clicks get eaten up. So:

Code: Select all

Procedure ButtonCallback(hwnd, msg, wparam, lparam)
  oldproc = GetProp_(hwnd, "oldproc")
  Select msg
    Case #WM_NCDESTROY
      RemoveProp_(hwnd, "oldproc")
    Case #WM_LBUTTONDBLCLK
      PostMessage_(hwnd, #WM_LBUTTONDOWN,0,0)
  EndSelect
  ProcedureReturn CallWindowProc_(oldproc, hwnd, msg, wparam, lparam)
EndProcedure

;
;button creation here
;
SetProp_(GadgetID(0),"oldproc", SetWindowLong_(GadgetID(0),#GWL_WNDPROC,@ButtonCallback()))
Adding this bit of code makes your ownerdrawn button perform like the standard one in this regard, here at least.

The only other thing would be that you could lower the text a pixel or two for the pushed state, then it's pretty much perfect.
BERESHEIT
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Nice tip. Thanks. 8)
I may look like a mule, but I'm not a complete ass.
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Post by Fluid Byte »

Actually you can just remove the class style using this line:

Code: Select all

SetClassLong_(hWnd,#GCL_STYLE,GetClassLong_(hWnd,#GCL_STYLE) ! #CS_DBLCLKS)
Here's a little demo for you:

Code: Select all

Procedure WindowCallback(hWnd,uMsg,wParam,lParam)
    Select uMsg
        Case #WM_DRAWITEM
       *lpdis.DRAWITEMSTRUCT = lParam
       
       SetBkMode_(*lpdis\hDC,#TRANSPARENT)
       
       If *lpdis\itemState & #ODS_SELECTED
          SelectObject_(*lpdis\hDC,GetStockObject_(#BLACK_BRUSH))         
          SetTextColor_(*lpdis\hDC,#White)
       Else
          SelectObject_(*lpdis\hDC,GetStockObject_(#WHITE_BRUSH))          
          SetTextColor_(*lpdis\hDC,0)      
       EndIf
       
       Rectangle_(*lpdis\hDC,0,0,*lpdis\rcItem\right,*lpdis\rcItem\bottom)
       DrawText_(*lpdis\hDC,GetGadgetText(0),-1,*lpdis\rcItem,#DT_CENTER | #DT_VCENTER | #DT_SINGLELINE)
       
       ProcedureReturn 0
    EndSelect
     
    ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

OpenWindow(0,0,0,320,240,"void",#PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CreateGadgetList(WindowID(0))
ButtonGadget(0,5,5,150,25,"OWNERDRAW BUTTON",#BS_OWNERDRAW)

SetClassLong_(GadgetID(0),#GCL_STYLE,GetClassLong_(GadgetID(0),#GCL_STYLE) ! #CS_DBLCLKS)

SetWindowCallback(@WindowCallback())

While WaitWindowEvent() ! #PB_Event_CloseWindow : Wend
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
Sparkie
PureBatMan Forever
PureBatMan Forever
Posts: 2307
Joined: Tue Feb 10, 2004 3:07 am
Location: Ohio, USA

Post by Sparkie »

Thanks netmaestro, I never even noticed that doubleclick issue before. In addition to your fix, you can also removes the CS_DBLCLKS from the button. The only drawback is you won't be able to trap doubleclicks from any and all buttons in your app.

Here's the modified code using my fix and adding netmaesto's drop-text effect. It's no better than what netmaestro posted, it's just an alternative for you to choose from. ;)

Code: Select all

UseJPEGImageDecoder() 

Procedure myWindowCallback(hwnd, msg, wParam, lParam) 
  result = #PB_ProcessPureBasicEvents 
  Select msg 
    Case #WM_DRAWITEM 
      *dis.DRAWITEMSTRUCT = lParam 
      If *dis\CtlType = #ODT_BUTTON 
        buttonBrush = GetGadgetData(0) 
        buttonNum = *dis\CtlID 
        SetBkMode_(*dis\hdc, #TRANSPARENT) 
        doFlags = #DFCS_BUTTONPUSH | #DFCS_ADJUSTRECT 
        DrawFocusRect = #False 
        Select *dis\itemState 
          Case #ODS_DISABLED 
            SetTextColor_(*dis\hdc, RGB(125, 125, 125)) 
          Case #ODS_FOCUS 
            DrawFocusRect = #True 
            pressed = #False
          Case #ODS_FOCUS | #ODS_SELECTED 
            DrawFocusRect = #True
            pressed = #True
            doFlags = #DFCS_BUTTONPUSH | #DFCS_PUSHED | #DFCS_ADJUSTRECT 
        EndSelect 
      EndIf 
      DrawFrameControl_(*dis\hdc, *dis\rcItem, #DFC_BUTTON, doFlags) 
      FillRect_(*dis\hdc, *dis\rcItem, buttonBrush) 
      If DrawFocusRect And pressed
        DrawFocusRect_(*dis\hdc, *dis\rcItem) 
        *dis\rcItem\top + 2
        *dis\rcItem\left + 2
        DrawText_(*dis\hdc, GetGadgetText(buttonNum), Len(GetGadgetText(buttonNum)), *dis\rcItem, #DT_CENTER | #DT_SINGLELINE | #DT_VCENTER) 
      ElseIf DrawFocusRect And Not pressed
        DrawFocusRect_(*dis\hdc, *dis\rcItem) 
        DrawText_(*dis\hdc, GetGadgetText(buttonNum), Len(GetGadgetText(buttonNum)), *dis\rcItem, #DT_CENTER | #DT_SINGLELINE | #DT_VCENTER) 
      Else
        DrawText_(*dis\hdc, GetGadgetText(buttonNum), Len(GetGadgetText(buttonNum)), *dis\rcItem, #DT_CENTER | #DT_SINGLELINE | #DT_VCENTER) 
      EndIf 
  EndSelect 
  ProcedureReturn result 
EndProcedure 

If OpenWindow(0, 100, 100, 500, 400, "Custom Button", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0)) 
  SetWindowCallback(@myWindowCallback()) 
  ButtonGadget(0, 10, 10, 100, 100, "Ownerdrawn") 
  ButtonGadget(1, 120, 10, 100, 100, "Normal") 
  bStyle = GetWindowLong_(GadgetID(0), #GWL_STYLE) 
  SetWindowLong_(GadgetID(0), #GWL_STYLE, bStyle &~#BS_PUSHBUTTON | #BS_OWNERDRAW | #BS_NOTIFY) 
  ;... Create button background brush 
  buttonBrush = CreatePatternBrush_(CatchImage(0, ?myImage)) 
  SetGadgetData(0, buttonBrush) 
  SetClassLong_(GadgetID(0), #GCL_STYLE, GetClassLong_(GadgetID(0), #GCL_STYLE) &(~#CS_DBLCLKS))
  
  Repeat 
    event = WaitWindowEvent() 
  Until event = #PB_Event_CloseWindow 
EndIf 
DeleteObject_(buttonBrush) 
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 
*Edit* Thanks Fluid BYte, you post faster than I type. GMTA :)
What goes around comes around.

PB 5.21 LTS (x86) - Windows 8.1
User avatar
Rook Zimbabwe
Addict
Addict
Posts: 4322
Joined: Tue Jan 02, 2007 8:16 pm
Location: Cypress TX
Contact:

Post by Rook Zimbabwe »

Thanks guys! This is all incredible!!! :D

Now to test and see if this will work with the 121 buttons I redraw each time a new menupage button is selected... 8) Single Clicks are what I wanted to insure as well... that tip was great!

I just wish this wasn't API so I could use it on MAC and Linux as well!

8)
Binarily speaking... it takes 10 to Tango!!!

Image
http://www.bluemesapc.com/
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Post by Fluid Byte »

I thought Sparkman ignored me but we posted in the same minute. Image
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
Sparkie
PureBatMan Forever
PureBatMan Forever
Posts: 2307
Joined: Tue Feb 10, 2004 3:07 am
Location: Ohio, USA

Post by Sparkie »

I was 20 minutes behind you Fluid Byte. I had my post ready to go when I got sidetracked (at work). Then I come back to my computer to post and see you had already snuck in there with your code. :P

I would never ignore you Fluid Byte. It's been a pleasure to see your nice side around here latelty :)
What goes around comes around.

PB 5.21 LTS (x86) - Windows 8.1
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

You must be very busy at work sparks! :wink:
I may look like a mule, but I'm not a complete ass.
Derek
Addict
Addict
Posts: 2354
Joined: Wed Apr 07, 2004 12:51 am
Location: England

Post by Derek »

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.

Fluid Bytes code does work and flashes the colour of the button whenever clicked on.

I'm guessing this is a Vista issue as I haven't tried it on my XP computer but it seems to be working for others. :?

Unless of course there isn't supposed to be any indication that the button was pressed, in which case just ignore me. :wink:
Post Reply