How to get tab control's header height in an empty control - winapi

My app's main window contains a Rebar control which contains a menubar band, a toolbar band, and a tab control band. When adding those bands using RB_INSERTBAND I have to pass a minimum height for the band in the cyMinChild member field of the REBARBANDINFO structure. Otherwise the Rebar control doesn't layout its bands correctly.
I can easily calculate the cyMinChild for the menubar and toolbar bands by simply using the TB_GETBUTTONSIZE message to find out the height of the menubar and toolbar.
For the tab control, however, things are more difficult. In fact, I'm unable to find any way of determining the tab control's header height. The problem is that initially, the tab control doesn't have any entries. If the tab control had some entries, I could just use TCM_GETITEMRECT to find out the header size but when I create the tab control and add it into the Rebar control, it doesn't have any entries yet.
So how should I find out the cyMinChild height for my tab control? Do I have to insert a dummy entry, grab the height using TCM_GETITEMRECT, and instantly remove the dummy entry again to achieve that? Or is there a nicer solution?
Note that I'm not using any toolkits. Everything is done in pure C so any solution should also be in plain Win32 API.
Thanks!

Related

How to create consistent toolbar buttons with icons

Desired look
I wish to make a toolbar for my app that will contain some simple buttons, each with a single monochromatic icon. Here is an example of some toolbar buttons similar to I'm trying to achieve, from Mail's compose window:
Notice these buttons have a consistent size, inner padding, padding, and shading. This is a pretty consistent style across macOS, present in Mail, Safari, Finder, etc. This leads me to suspect there's a standardized UI component for creating such buttons.
If I use a segmented control, each button looks correct, with each icon being correctly padded:
Now I would like to add individual buttons that match the style.
Attempt 1
My first attempt was to add a "Push Button" (NSButton) to the toolbar:
This resulted in a wide button that's a bit too short, and not lined up with the segmented control:
Attempt 2
My second attempt was to use a segmented control, with only 1 segment.
This resulted in a button that's the right shape, size, etc., but it was off center relative to its label.
Naturally, I can manually adjust the button to match the goal, but I feel like I'm missing something. What's the proper way to create these standard buttons?
This is actually quite easy to do and you were close already.
You can use NSButton for that. Note that it has different styles (defined in NSButton.BezelStyle) to choose from. The default one is the one to use inside windows and modals. But for toolbars, to match the style of segmented controls and search bars, you can choose the style .texturedRounded.
You can also set the style via Interface Builder. Note that you have to select the button itself, not the toolbar item around it.
To get the correct size, you seem to set the icon within the toolbar item, not the button itself.
Here is my result:

How to make NSSearchField take up whole width of toolbar

I am trying to make a NSSearchField taking up the whole width of a toolbar in a NSWindowController.
I created a new NSWindowController using Xcode storyboard, add a toolbar to it, when add search field to the toolbar.
I drag the search field from allowed toolbar items to default toolbar items
Set toolbar item's max width to a large number say 1000
I build the app and run. The search field shrinks when window width shrinks, but does not expand beyond a certain width when window width expands.
The question is how to make search field expand and take up all remaining space of the toolbar?
It doesn't sound to me like the toolbar is really what you want to use here. The purpose of the toolbar is to allow multiple UI elements to be included in a user-configurable way. If you want to force one element that takes up the entire width, I suggest just putting it in the window's content view and setting up the layout constraints to pin to both the left and right sides. If you set the "Textured" check box in Interface Builder, it should look roughly the same as it would have looked using the toolbar.

NSTableView with +/- buttons like in System Preferences using only Interface Builder

Apple commonly places +/- buttons below tables (NSTableView), e.g. in the System Preferences for Network or User & Groups. See image below:
How can I place identical buttons below my tables directly in Interface Builder without manipulating any interface elements in my code or subclassing any element classes?
If the table has a fixed width, the easiest way is to just use a segmented control NSSegmentedControl. First add it to your view or window:
Change its Style to Small Square, the Mode to Select None and increase the number of Segments to 4 (or keep it at 3 if you only need + and -):
The +, - and other buttons are predefined images of the AppKit framework (NSAddTemplate and NSRemoveTemplate) and directly available in Interface Builder. E.g. you could setup the first three segments as follows:
For demonstration purposes I made the - segment disabled. Unlike most other buttons, disabling a segment of a segmented control only dims the image/text, it does not change the button background. Only disabling the whole segmented control changes the background (and of course disables all segments).
Of course, the last segment should always be disabled, otherwise it would be clickable and change its background when being clicked. As it contains no image or text, it still looks the same after it has been disabled.
Switch to the size setup and uncheck the Fixed checkbox for all segments, except for the last one, make sure it is checked for the last one:
Unchecking Fixed makes the segment width dynamic, that means it will always match the minimum width required for the content.
Finally place the control directly below the table and resize it to match the table width. Here's the result:
Almost perfect, don't you think?
Things get more difficulty if the table width is dynamic (e.g. the table resizes together with the window resizing). A segmented control doesn't support autoresizing, that means you would have to programmatically change the width of its last segment each time the table is resized. Of course, that is not too hard to do and requires only little code but there is one alternative solution that requires no single line of code.
Decrease the number of segments by one and replace the last segment with a gradient button (NSButton) without title:
Its background looks exactly the same as a segmented control, yet it does support autoresizing to always match the size of the table. There is just one problem: It is clickable and this time disabling it doesn't work as this would change the background. Instead just change its Type to Momentary Change (which means the app wants to control the UI change itself when the button is clicked):
And after the button has been placed correctly and made resizable, the result looks as good as before but this time the table can be resizable and the buttons on the bottom will always fit perfectly.

NSTableView with Plus and Minus buttons

How can I do something like that?
I didn't find any appropriate object in the Interface Builder library.
Any thoughts?
The best way that i found is to use NSSegmentedControl.
after you dragged it on the canvas, you should configure its style:
Style: Small Square
Mode: Select Momentary
looks better. Now use "image" field to set NSAddTemplate and NSRemoveTemplate. Make sure that label field is empty.
Ok, we have "+", "-" and one empty segment. To prevent the latest one to be selected by the user, select it from Segment: pop up and turn off Enabled check box (located next to State: label).
And lastly, what we have to do is set width of first two segments to make them square.
Go to Size inspector
Select Segment 0
Turn off "Fixed" checkbox (segment should immediately autoresize to fit image)
Select Segment 1 and repeat number 3
Now as you resize control, only last segment will change width
Put it at the bottom of your table view and resize as well.
Enjoy ;)
Update for OSX Yosemite
I tried to achieve the same look as Mail.app has in the Accounts view (right window on my screenshot).
I did achieve the desired result by following the steps below:
Add a NSSegmentedControl
Add two segments and set the image to each:
NSAddTemplate for the + button
NSRemoveTemplate for the - button
Set the size of the segments to fixed and set the value to 32 pixels
The rectangle next to the buttons is a NSButton with the style Gradient.
The Button is enabled but Refuses First Responder is set to true so that it is not clickable.
Use a NSButton with a gradient style, and for the images use the system provided NSAddTemplate and NSRemoveTemplate.
One answer here suggests using gradient buttons, however these buttons cannot be disabled as this causes the background to change and thus breaks the look. Another one suggested using a segmented control, which is almost perfect but segmented controls don't support autoresizing, e.g. if the table width is dynamic. My suggestion is a combination of both. Use a segmented control for the actual buttons and a gradient button to fill the rest of the table width that now can also be dynamic if the button width is dynamic as well.
See my answer to a similar question (with screenshots):
https://stackoverflow.com/a/22586314/15809

What Qt4 widgets should I use and how to approximate a ribbon-style interface?

I am trying to create an interface for my application using Qt Designer. I want it to have a tabbed, ribbon-style set of controls at the top, and a MDI-style area with docked windows which I plan to show and hide depending on which tab of the ribbon is currently selected. I am just beginning with Qt Designer as well as Qt4 itself for that matter so I'm not quite sure how to setup the window, which widgets and layouts should I use etc.
It's quite obvious there should be a QTabWidget at the top, but I'm not sure about the bottom. Should I use a QFrame? A QMdiArea? A dock widget? What layouts can I use to make sure the tab widget has a fixed height, occupies the whole width of the window at all times and the bottom area scales as the window is resized?
I've read in the manual that splitter layouts allow for manual adjustment of the size of the widgets they contain, but I can't drag the box size of a widget after I place them inside a splitter. Thus I'm unable to setup the area below the ribbon. Anyone, help?
You should look into the QMainWindow and check the multiple utilities it can provide you (Toolbar, StatusBar, DockWidgets, CentralWidget, etc...).
The way I understood your case is that you will always have the MDI Area visible, and that the tab bar will only be used to change the dockWidgets. Here's how I would do it.
The centralWidget of the mainWindow would be a QWidget with a QVBoxLayout containing a QTabBar widget first (up) and a QMdiArea under it. The sizes should be handled automatically.
This will allow the user (or you) to dock widgets on the left, bottom, top or right areas of the mainWindow's central widget. Keep pointers to the dockWidgets to be able to move and show/hide them at will.
Hope this helps.
VTK Designer, which is built on Qt, has a Ribbon-ish interface. You might take a look at the source code for reference.

Resources