3

I created a toolbar with the following styles:

DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS
                | CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE
                | TBSTYLE_FLAT | TBSTYLE_LIST;

Then I fill the toolbar with text-only buttons:

bool InsertButton(int Index, int CmdId, BYTE Style, BYTE State,
                  int TxtIdx, DWORD_PTR lParam)
{
    TBBUTTON tbb = { 0 };
    tbb.idCommand = CmdId;
    tbb.fsStyle = Style;    // == BTNS_AUTOSIZE | BTNS_DROPDOWN
    tbb.fsState = State;
    tbb.iBitmap = I_IMAGENONE;
    tbb.iString = TxtIdx;
    tbb.dwData = lParam;

    return (bool)CToolBarCtrl::InsertButton(Index, &tbb);
}

After the toolbar is filled up, I want to get the actual size of its buttons. But the GetButtonInfo returns zero size.

int GetBtnSize(int Idx) const
{
    TBBUTTONINFO tbbi = { sizeof(tbbi), TBIF_SIZE | TBIF_BYINDEX };
    GetButtonInfo(Idx, &tbbi);
    return tbbi.cx;
}

What am I doing wrong and how can I know the button's actual size?

Barmak Shemirani
  • 30,904
  • 6
  • 40
  • 77
Ilia
  • 425
  • 2
  • 10
  • 1
    What is the return value of `GetButtonInfo`? Where is `GetBtnSize` implemented? It looks like a global function but that cannot be. – Werner Henze Jan 01 '19 at 19:04
  • 2
    That's might be a bug in documentation or API. Or you have to do something else before requesting the value for `cx` (I think calling `SetButtonInfo` with valid `cx` will work, but is not useful). You can use `toolbar.GetItemRect(index, &rc)` as alternative. – Barmak Shemirani Jan 02 '19 at 00:29
  • @WernerHenze, The functions shown in the question are members of my class derived from the CToolBarCtrl. – Ilia Jan 02 '19 at 10:53
  • @BarmakShemirani, `toolbar.GetItemRect(index, &rc)` works and does exactly what I need. Thank you very much! I'm not very experienced in GUI development, and somehow missed this method in the documentation. If you turn your comment into the answer, I could mark it respectively. – Ilia Jan 02 '19 at 11:10

1 Answers1

5

Partial answer:

Use CToolBarCtrl::GetItemRect to find the rectangle for the toolbar button.


CToolBarCtrl::GetButtonInfo (MFC encapsulation for TB_GETBUTTONINFO) should also return the button's width, based on documentation, I don't know why it doesn't.

If the toolbar is created with TBSTYLE_WRAPABLE style, and toolbar button has BTNS_AUTOSIZE flag, then GetButtonInfo will return the right value for TBBUTTONINFO::cx. Example:

BOOL CMyDialog::OnInitDialog()
{
    CDialog::OnInitDialog();
    toolbar.Create(WS_CHILD | WS_VISIBLE | TBSTYLE_WRAPABLE, CRect(0, 0, 0, 0), this, 100);
    toolbar.SendMessage(TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
    toolbar.AddStrings(L"New\0Open\0Save\0\0");

    TBBUTTON tbb[2] = {
         { 0, 1000, TBSTATE_ENABLED, BTNS_AUTOSIZE, {0}, 0, 0},
         { 0, 1001, TBSTATE_ENABLED, BTNS_AUTOSIZE, {0}, 0, 1},
    };
    toolbar.AddButtons(_countof(tbb), tbb);
    toolbar.AutoSize();

    TBBUTTONINFO tbbi = { sizeof(tbbi), TBIF_BYINDEX | TBIF_SIZE };
    toolbar.GetButtonInfo(0, &tbbi);
    TRACE("tbbi.cx = %d", tbbi.cx);
    return TRUE;
}
Barmak Shemirani
  • 30,904
  • 6
  • 40
  • 77
  • I think `GetButtonInfo()` only returns the width explicitly specified by calls to `InsertButton()` or `SetButtonInfo()`. OP zero-initialized the `TBBUTTON::cx` member, so that is what `GetButtonInfo()` returns. – zett42 Jan 02 '19 at 14:58
  • @zett42 That makes sense (although you can't set cx value in `InsertButton`). I managed to get `GetButtonInfo` return the right value for `TBBUTTON::cx` under some circumstances, but not consistently. It's a bit confusing. – Barmak Shemirani Jan 02 '19 at 20:06