Monday, December 28, 2020

Microsoft Office 365-like Ribbon Control

Merry Christmas! Every year between Christmas and New Year's, I like to work on a fun project, such as learning a new technique or writing some cool utility. Last year, I worked on the open source version of Hacker's Guide to Visual FoxPro. This year, I created an open source Microsoft Office 365-like ribbon control for VFP forms.

Here's a sample form containing the ribbon control that resembles Microsoft Outlook. It has two tabs: Home and Send / Receive. Clicking a tab displays the toolbar for that tab.


Here's the Send / Receive tab:

So far, I've included two themes: Colorful (above) and Dark Grey (below):


Themes are defined as RGB colors in an XML file so it's a simple matter to add another theme.

The ribbon control is 100% VFP code. Please try it out and let me know of any enhancements you'd like by creating issues in the GitHub repository for the project.

9 comments:

  1. Anonymous9:57 PM

    Fantastic!!!
    I loved the layout and the user interface. It's definitely time to make some cosmetic changes to our Apps.
    I performed some basic tests, added some tabs and buttons, and everything is working as expected. Congratulations.
    Seems very easy to implement.

    I hope to go deep into it in the next weeks.

    Thanks for sharing!
    Cesar

    ReplyDelete
  2. Hello,
    Great control...However, I'm more in the Winforms world so I have a beginner's simple and stupid question: is there a chance that I can migrae this superb control to informs?

    Thanks

    Philippe

    ReplyDelete
  3. Google "winforms ribbon control" and you'll find lots of hits.

    Doug

    ReplyDelete
  4. Nigel Gomm9:03 AM

    Doug,
    great stuff - i've just started adding this to a project.

    I added a new property sfribbontoolbarbutton.disabledpicture to my copy

    and this code in sfribbontolbarbutton.enabled_assign

    LPARAMETERS tlEnabled
    DO CASE
    CASE tlEnabled = .F. AND !EMPTY(THIS.DISABLEDPICTURE) AND LEFT(THIS.DISABLEDPICTURE,4) = "‰PNG"
    THIS.imgButton.PICTUREVAL= THIS.DISABLEDPICTURE
    CASE tlEnabled = .F. AND !EMPTY(THIS.DISABLEDPICTURE) AND FILE(THIS.DISABLEDPICTURE)
    THIS.imgButton.PICTUREVAL= FILETOSTR(THIS.DISABLEDPICTURE)
    CASE tlEnabled = .F. AND !EMPTY(THIS.IMAGE) AND FILE(THIS.IMAGE)
    TRY
    WITH _SCREEN.SYSTEM.Drawing
    LOCAL loBitmap AS xfcBitmap
    LOCAL loNewBitmap AS xfcBitmap

    loBitmap = .BITMAP.fromfile(THIS.IMAGE)
    LOCAL lnWidth, lnHeight, X, Y, lnLuma
    LOCAL loColor AS xfcColor

    FOR Y = 0 TO loBitmap.HEIGHT - 1
    FOR X = 0 TO loBitmap.WIDTH - 1
    loColor = loBitmap.GetPixel(m.X,m.Y)
    IF loColor.isknowncolor AND loColor.r != 255 AND loColor.g !=255 AND loColor.b !=255
    loBitmap.SetPixel(m.X, m.Y, .COLOR.FromRgb(RGB(200,200,200)))
    ENDIF
    NEXT
    NEXT


    THIS.DISABLEDPICTURE = loNewBitmap.GetPictureVal(.Imaging.ImageFormat.png)
    THIS.imgButton.PICTUREVAL = THIS.DISABLEDPICTURE
    ENDWITH
    CATCH TO loerr
    THIS.imgButton.PICTUREVAL= FILETOSTR(THIS.IMAGE)
    ENDTRY
    CASE FILE(THIS.IMAGE)
    THIS.imgButton.PICTUREVAL= FILETOSTR(THIS.IMAGE)
    ENDCASE
    DODEFAULT(tlEnabled)


    the .getpixel approach is too slow where there's no filename but i'll try and get a colormatrix to speed things up. Unless you already have some code for that?

    ReplyDelete
  5. Nigel Gomm9:07 AM

    sorry there's a typo in my previous post....

    THIS.DISABLEDPICTURE = loBitmap.GetPictureVal

    n

    ReplyDelete
  6. Thanks, Nigel. I've added a DisabledImage property for consistency with the Image property, and didn't add the GDI+ code.

    ReplyDelete
  7. Nigel Gomm11:49 AM

    Doug,
    i also removed (in my copy) the "if enabled" in sfribbontoolbar.mouseleave()
    because if a button disables itself it remains highlighted otherwise.

    n

    ReplyDelete
  8. Thanks. As an aside, these things are best posted as Issues on the GitHub page rather than as comments here.

    ReplyDelete
  9. Nigel Gomm1:43 PM

    will do (and have done)

    ReplyDelete