Button response to mouse pointer hover - modern button styles

The IDE (and other programs) have buttons with text that are responsive to the mouse moving over the button. E.g., the [+ Create Topic] button below this little message area.

Is using a flat button with a graphic image of the desired text the only way to do this?

If so, is there a simple what to modify the flat button’s response to the hovering mouse pointer? E.g., the C11 IDE shows a white border around some buttons when the pointer goes over them.

What about dynamic text for a button?

I’m in C9.1 but played around in C11 to see if there were any changes and didn’t notice anything obvious in this area.

Other thoughts for doing more modern button styles?

Maybe look at ActiveImage in your libsrc\win folder. I don’t know about text, but it might do some stuff you want. Never used it.

1 Like

You’ll need to be familiar with subclassing,
CallWindowProcA function (winuser.h) - Win32 apps | Microsoft Learn
but have a look at WM_Notify
WM_NOTIFY message (Winuser.h) - Win32 apps | Microsoft Learn
and BCN_HOTITEMCHANGE
BCN_HOTITEMCHANGE notification code (Commctrl.h) - Win32 apps | Microsoft Learn

This is untested off the top of my head.

Global part of your app

map
module('win32')
CallWindowProcA(long,long,long,long,long),long,PAscal,Name('CallWindowProcA')
end
end
Glo:MyWindowAcceptLoopAddress long !< -- I have to use a global here

In your window with your button

   map    
MySubclassProc Procedure(long phwnd, long pMsg, long pwParam, long plParam)
    End
    WM_Notify Equate(004eh) !These could be global equates
    HICF_ENTERING Equate(0010h)
    HICF_LEAVING Equate(0020h)
    Loc:SubclassAddress Long

NMHDR Group,type
hwnd long
controlfeq ulong
code ulong
       end


Code
Loc:SubclassAddress = address(MySubClass)
Glo:MyWindowAcceptLoopAddress{Prop:WndProc}  !This stores the address of this windows accept loop so your subclass proc can pass on the windows messages.

{Prop:WndProc} = Loc:SubclassAddress  !This now diverts the windows messages to your subclass procedure. You can daisy chain many subclass procedures one after the other, if you wanted to separate code.
Loc:ButtonHandle{PRop:Feq} = ?MyButton
         !Your existing window code and accept loop
        !Local Procedure
        MySubclassProc  Procedure(long phwnd, long pMsg, long pwParam, long plParam)
 loc:NMHDR  &NMHDR 
        Code
        IF pMsg = WM_Notify
            loc:NMHDR &= plParam
         IF loc:NMHDR.controlfeq  =   Loc:ButtonHandle
         IF loc:NMHDR.code  = HICF_ENTERING !Mouse pointer entering button region
         !Do something
        ElsIF loc:NMHDR.code = HICF_LEAVING !Mouse pointer leaving button region
         !Do something else
        Else
         !Shouldnt happen
        End
        End
          Return(CallWindowProc(Glo:MyWindowAcceptLoopAddress ,phwnd, pMsg, pwParam, plParam)

Like I said this is untested. In the debugger its worth having a look at plparam to see if the data in memory (examine memory) fits into the NMHDR structure.
If the compiler complains, change “long plParam” to “NMHDR plParam” in the subclass procedure definition and in the local procedure. This is also why I mentioned the point about its possible to daisy chain subclassed procedures, if you have to change the long plParam to * NHMDR plParam, you’ll want to write the code in this subclassed procedure just for processing passed by address (*) NHMDR group structures.

1 Like

Does “modern button style” mean: a button changes its background and text colors (and maybe a button’s text and icon) when mouse cursor is over the button? And colors and other properties are reset when mouse cursor leaves the button?

2 Likes

I’m mainly aiming for a flat button, but still visible as a button shape with a chosen color and then responsive to the mouse like a flat button. This seems to be fairly common these days and appears both within the Clarion IDE and this website.

As near as I can tell, once FLAT is on, the button shape disappears other than for any text/icon. I’d still like the rectangle, but flat.

Without FLAT, the button is still responsive to the mouse pointer until I pick a COLOR.

Hover functionality can be implemented quite easy, you just handle mouse move and mouse leave messages and change button background and other properties accordingly.
Full custom draw is much more complex. For example, if a button has a standard predefined icon like ICON:Save, you must draw that icon manually. Sounds easy, but pay attention that ICON:Save is not a real image but just an identifier of something somewhere…
FYI: here is the demo I wrote during the weekend, it shows simple hover enabled buttons and custom drawn butons.

2 Likes

Thanks, Mike! I’ll check it out tomorrow.

I have noticed that a generic Clarion button can sometimes exhibit close to the behavior that I’m looking for. I have some apps that the buttons respond to the mouse hover and some that do not. Window previews from the designer show the button responding to the mouse pointer even when the actual program does not in some cases.

I’m still investigating that behavior–I suspect a 3rd party extension is doing something to the button that turns the behavior off or inhibits it.

After some testing with a simple app since I can see responsive buttons in some apps and not others, I believe the gen/make process in C9.1 has a problem.

Starting with an empty generated folder, I get ‘nice’ buttons that respond to the mouse pointer.

Unfortunately, a subsequent make appears to mess things up, sometimes immediately, sometimes after several makes. It looks like the generated manifest file is no longer used at some point and then the buttons revert to ‘not-nice’ and are unresponsive to the mouse pointer.

Comparing good and bad generated folders when the buttons change, the difference appears to be in the .cwproj.FileList.xml file. Specifically, the manifest entry and a number of RSC entries are missing in the bad folder.

Thoughts/ideas? I’ll test C11 next…

I always create my own manifest and add it to the project.

2 Likes

If the problem is a manifest (corrupted or ignored), then I guess you should see all buttons in the app look nice or all buttons look not nice.

Sorry for the off topic: just updated the demo, now it shows not rectangular buttons. Sometimes I can’t stop.

2 Likes

Cool, I will get to your thing, but figured I better sort out why I had buttons looking OK in some apps but not in others. And yes, if an app was OK, then all buttons in that app were OK and vice-versa (subject to the color issue.)

Manually adding the manifest seems to be the workaround for at least C9.1.

Even with the manifest sorted, adding color to the button disables the mouse-pointer responsiveness. Can be the COLOR attribute for the button itself or color for the font. I’m not super surprised but would have been nice.

I had never payed much attention to the manifest other to set my desired options in the app and then ‘assumed’ that the checked-on options to automatically export and link it in always worked. I guess I should know better at this stage.

Your demo is about what I’m looking for. I have the ‘native’ button scheme working now that the manifest issue is sorted, but being able to add the color attributes to the buttons would work for my needs.

Are you using a region occupying the button area to get at the mouse events?

No, I don’t use “region” approach, it is pure button.

1 Like

Hi Mike , can you share the Code for the bottoms demo you did , I really like it . BTW are you a freelancer for clarion I can use your services once in a while .
Thanks

Carlos elextronika .

Hi Carlos,

  • No I can’t share the code.
  • Yes I’m a freelancer.

All I can share is the code which sets the button properties:

  CODE
  OPEN(Window)

  btnSimpleMgr.SetButton(?btnSimple1, COLOR:Gray, COLOR:White)
  btnSimpleMgr.SetButton(?btnSimple2, COLOR:Gray, COLOR:White)
  btnSimpleMgr.SetButton(?btnSimple3, COLOR:Gray, COLOR:White)
  
  !- rectangle button options
  rectangleBtnProps.backColor1 = COLOR:LightGray
  rectangleBtnProps.backColor2 = COLOR:DarkGray
  rectangleBtnProps.hoverBackColor1 = COLOR:DarkGray
  rectangleBtnProps.hoverBackColor2 = COLOR:LightGray
  rectangleBtnProps.textColor = COLOR:BTNTEXT
  rectangleBtnProps.hoverTextColor = COLOR:Blue
  
  btnShapeMgr.SetButton(?btnRect1, ButtonShapeType::Rectangle, rectangleBtnProps)
  btnShapeMgr.SetButton(?btnRect2, ButtonShapeType::Rectangle, rectangleBtnProps)
  btnShapeMgr.SetButton(?btnRect3, ButtonShapeType::Rectangle, rectangleBtnProps)

  !- ellipse button options
  ellipseBtnProps.backColor1 = 00E6D8ADh
  ellipseBtnProps.backColor2 = 00FFBF00h
  ellipseBtnProps.hoverBackColor1 = 00FFBF00h
  ellipseBtnProps.hoverBackColor2 = 00E6D8ADh
  ellipseBtnProps.textColor = 000045FFh
  ellipseBtnProps.hoverTextColor = COLOR:White
  ellipseBtnProps.gradientMode = LinearGradientModeForwardDiagonal
  ellipseBtnProps.outlineFocusColor = COLOR:Red
  ellipseBtnProps.outlineFocusWidth = 2
  ellipseBtnProps.outlineFocusDashStyle = DashStyleDashDot

  btnShapeMgr.SetButton(?btnEllipse1, ButtonShapeType::Ellipse, ellipseBtnProps)
  btnShapeMgr.SetButton(?btnEllipse2, ButtonShapeType::Ellipse, ellipseBtnProps)
  
  ACCEPT
  END
1 Like

Mike,

Is this working for Clarion 8 - Legacy?

Regards Frits.

Yes it works in C6.3 and newer.

Thanks for your Response . Im interested in some coding can i gave you my email or you can give me yours . Thanks
CARLOS