maxscript

Underline a letter on a button in Maxscript


I was looking for a way to do this like in a queryBox where there's the Y and N of Yes and No underlined to indicate that if you press them that's what will get pressed.

enter image description here

Here's the code and the wrong resulting screenshot that I have where I've put an ampersand before Button.

try destroyDialog testRol catch()
rollout testRol "testRol" (
  button btn_test "&Button"
  )
createDialog testRol 100 45

enter image description here


Edit:

Even if I try with \x0332Yes it doesn't work. It does but the underline isn't lined up correctly and when used before a B it looks a mess.

I've used hardcoded underlined letters which work which is not ideal so if anyone knows a solution that would be great to avoid this.

Here's that attempt as it may help you figure this out:

try destroyDialog testRol catch()
rollout testRol "testRol" (
  button btn_yes "Y̲es (Working)" width:120 across:4
  button btn_no "N̲o (Working)" width:120
  button btn_button_not_working "\x0332Button (Not Working)" width:120
  button btn_yes_not_working "\x0332Yes (Kinda Working)" width:120
  )
createDialog testRol 525 45

enter image description here


Solution

  • Depends on your expectations, you could use a .NET button inside a rollout control but you have to style it yourself to match the theme and use a system style to make it look like maxscript button:

    try destroyDialog testRol catch()
    rollout testRol "MXS + .NET"
    (
        dotNetControl btnMakeCylinder "Button" text:"&Make Cylinder" width:120 height:25
        on btnMakeCylinder mouseClick evnt arg do with undo on Cylinder isSelected:on
        on testRol open do btnMakeCylinder.FlatStyle = btnMakeCylinder.FlatStyle.System
    )
    createDialog testRol
    

    Or you can use the MaxForm where the button will inherit the colors but it will still not look like the rest of the UI:

    (
        local form = dotNetObject "MaxCustomControls.MaxForm"
        form.Text = ".NET form"
    
        fn makeCylinder = with undo on Cylinder isSelected:on
    
        local btnMakeCylinder = dotNetObject "Button"
        btnMakeCylinder.Text = "&Make Cylinder"
        dotNet.addEventHandler btnMakeCylinder "MouseClick" makeCylinder
    
        form.Controls.Add btnMakecylinder
        form.ShowModeless()
    )
    

    Or you can use Qt UI that comes with its own set of shortcomings (like having to always explicitly specify undo records) and it's rather verbose:

    (
        local legacy = (python.import "sys").version_info[1] < 3
        local QtGui = python.import "PySide2.QtGui"
        local QtWidgets = python.import "PySide2.QtWidgets"
        local GetQMaxMainWindow = (if legacy then python.import "MaxPlus" else python.import "qtmax").GetQMaxMainWindow
    
        if isProperty ::testQtDialog #close do testQtDialog.close()
        testQtDialog = QtWidgets.QDialog(GetQMaxMainWindow())
        testQtDialog.setWindowTitle "Qt Window"
    
        local dialogLayout = QtWidgets.QVBoxLayout()
    
        fn makeCylinder = with undo on Cylinder isSelected:on
    
        local btnMakeCylinder = QtWidgets.QPushButton "&Make Cylinder"
        btnMakeCylinder.clicked.connect makeCylinder
        dialogLayout.addWidget btnMakeCylinder
    
        testQtDialog.setLayout dialogLayout
        testQtDialog.show()
    )
    

    From 2022 you can also make Qt windows with native max controls this way:

    if isKindOf testQtRol RolloutClass do UIAccessor.closeDialog testQtRol.hwnd
    rollout testQtRol "Qt Rollout"
    (
        QtButton btnMakeCylinder "&Make cylinder" row:0 column:2
        on btnMakeCylinder pressed do with undo on Cylinder isSelected:on
    )
    createQtDialog testQtRol