Windows工具栏 - 控制按钮大小和填充

Dab*_*ler 5 c++ windows winapi bitmap padding

我试图了解Windows工具栏的行为 - 特别是以下值如何交互:

  • 使用的位图图像的大小
  • 工具栏按钮的有效大小
  • 图像和按钮边缘之间的填充
  • 工具栏的高度

按钮显示的文本与我的情况无关.

我真正想要做的是为用户提供一个选项,这样他就可以从几个工具栏按钮大小中选择(显示16x16,32x32或48x48像素的位图),并在选项值更改后相应地重新显示工具栏.这是通过销毁工具栏的图像列表并使用适当的位图重建它们来实现的.我目前遇到的问题是,当从大小16切换到48并返回到大小16时,工具栏看起来与以前略有不同.

这是应用程序启动时工具栏的样子(正确):

在切换工具栏大小之前

一旦我切换到48号并再次返回,它看起来像这样(错误):

切换到更大的尺寸后返回

所有按钮都比以前更高,每个下拉按钮在其位图及其下拉箭头周围都有额外的空间.

(出于测试目的,工具栏已经足够高,可以容纳所有按钮大小,而不需要增加高度.这是为了排除按钮大小的变化源于可能的工具栏调整大小的必要性,需要暂时切换到大小48.)

看起来好像在按钮位图和按钮边缘之间呈现了额外的填充 - 好像用较大的位图/按钮重建工具栏会导致Windows内部增加填充(这是有意义的),但是当我随后重建时不会减少它具有较小位图/按钮的工具栏.但是,发送TB_GETPADDING始终返回0x00060007,这表示16x16位图的标准(正确)填充已到位.

为了通过自己设置填充来解决问题,我在所有非分隔符按钮上设置TBSTYLE_AUTOSIZE样式(这是为了应用填充所必需的).使用这种样式,甚至没有调用TB_SETPADDING,切换到48后再返回,工具栏如下所示:

切换到更大的尺寸并返回后,使用TBSTYLE_AUTOSIZE

在这种情况下,按钮高度也是错误的.

问题是:在重建图像列表后,导致按钮显示的原因什么?

一些备注:

  • 在构建工具栏时,我调用TB_SETBITMAPSIZE,但是既没有TB_SETBUTTONSIZE也没有TB_SETPADDING,因为位图大小是我所拥有的,并且我假设按钮大小将从中正确导出.
  • 我知道我可以简单地从头开始构建整个工具栏窗口(不仅仅是图像列表),但是我想避免这种情况,所以我可以继续使用相同的工具栏窗口句柄.
  • 我知道CCS_NORESIZE工具栏样式(它当前已设置)和TB_AUTOSIZE消息,但使用它们进行的实验并没有带来任何见解.

γηρ*_*όμε 4

我不能说问题是什么(问题中没有代码),但很可能是破坏图像列表的解决方案导致了这种情况。您不需要销毁列表,而是删除按钮然后添加新按钮。下面的代码工作正常:

创建工具栏

if((toolBarHwnd = CreateWindowEx(
                0,
                TOOLBARCLASSNAME,,
                NULL,
                WS_VISIBLE | WS_CHILD | TBSTYLE_WRAPABLE,
                0,
                0, //820,
                0,
                0,
                winHwnd, //main window
                (HMENU)IDC_TOOLBAR,
                hThisInstance,
                NULL
            )) == NULL){/*Error*/}
Run Code Online (Sandbox Code Playgroud)

为您的图像创建ImageList

HIMAGELIST g_hImageListSmall = NULL, g_hImageListMedium = NULL, g_hImageListLarge = NULL;
int numButtons = 3
g_hImageListSmall = ImageList_Create(16, 16,   // Dimensions of individual bitmaps.
                                ILC_COLOR16 | ILC_MASK,   // Ensures transparent background.
                                numButtons, 0);
g_hImageListMedium = ImageList_Create(32, 32,
                                ILC_COLOR16 | ILC_MASK,
                                numButtons, 0);
g_hImageListLarge = ImageList_Create(48, 48,
                                ILC_COLOR16 | ILC_MASK,
                                numButtons, 0);
Run Code Online (Sandbox Code Playgroud)

将图像添加到列表中:

HBITMAP hBitmapImageSmall = NULL, hBitmapImageMedium = NULL, hBitmapImageLarge = NULL;
hBitmapImageSmall = LoadImage(NULL, L"....YourBitmap.bmp", IMAGE_BITMAP, 16, 16, 0x10);
ImageList_Add(g_hImageListSmall , hBitmapImageSmall, NULL);
ImageList_Add(g_hImageListSmall , hBitmapImageSmall, NULL);
ImageList_Add(g_hImageListSmall , hBitmapImageSmall, NULL); //I am using the same image

hBitmapImageMedium = LoadImage(NULL, L"....YourBitmap.bmp", IMAGE_BITMAP, 32, 32, 0x10);
ImageList_Add(g_hImageListSmall , hBitmapImageMedium , NULL);
ImageList_Add(g_hImageListSmall , hBitmapImageMedium , NULL);
ImageList_Add(g_hImageListSmall , hBitmapImageMedium , NULL);
Run Code Online (Sandbox Code Playgroud)

与大号相同(48x48)

g_hImageListSmall添加到工具栏以启动:

//Set the image list.
SendMessage(toolBarHwnd, TB_SETIMAGELIST, (WPARAM)0, (LPARAM)g_hImageListSmall);

// Initialize button info.
// IDM_NEW, IDM_OPEN, and IDM_SAVE are application-defined command constants.
TBBUTTON tbButtons[numButtons] = 
{
    { 0, IDM_NEW,  TBSTATE_ENABLED, BTNS_AUTOSIZE, {0}, 0, (INT_PTR)NULL },
    { 1, IDM_OPEN, TBSTATE_ENABLED, BTNS_AUTOSIZE, {0}, 0, (INT_PTR)NULL},
    { 2, IDM_SAVE, TBSTATE_ENABLED, BTNS_AUTOSIZE, {0}, 0, (INT_PTR)NULL}
};

// Add buttons.
SendMessage(toolBarHwnd, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
SendMessage(toolBarHwnd, TB_ADDBUTTONS, (WPARAM)numButtons, (LPARAM)&tbButtons);

// Resize the toolbar
SendMessage(toolBarHwnd, TB_AUTOSIZE, 0, 0);
Run Code Online (Sandbox Code Playgroud)

这是第一步。

写两个函数:

void RemoveButtons(void){
    int nCount, i;

    // Remove all of the existing buttons, starting with the last one.
    nCount = SendMessage(toolBarHwnd, TB_BUTTONCOUNT, 0, 0);

    for(i = nCount - 1; i >= 0; i--){ SendMessage(toolBarHwnd, TB_DELETEBUTTON, i, 0); }

    return;
}

enum{SMALL, MEDIUM, LARGE};

void AddButtons(int sizeButtons){
    if(sizeButtons == SMALL){
        SendMessage(toolBarHwnd, TB_SETIMAGELIST, (WPARAM)0, (LPARAM)g_hImageListSmall);
    }
    else if(sizeButtons == MEDIUM){
        SendMessage(toolBarHwnd, TB_SETIMAGELIST, (WPARAM)0, (LPARAM)g_hImageListMedium);
    }
    else{
        SendMessage(toolBarHwnd, TB_SETIMAGELIST, (WPARAM)0, (LPARAM)g_hImageListLarge);
    }

    // Add buttons.
    SendMessage(toolBarHwnd, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
    SendMessage(toolBarHwnd, TB_ADDBUTTONS, (WPARAM)numButtons, (LPARAM)&tbButtons);

    // Resize the toolbar
    SendMessage(toolBarHwnd, TB_AUTOSIZE, 0, 0); 

    return;
}
Run Code Online (Sandbox Code Playgroud)

当您想要更改ToolBar中按钮的大小时:

RemoveButtons();
AddButtons(LARGE); //or SMALL, MEDIUM
Run Code Online (Sandbox Code Playgroud)

参考:

如何创建工具栏
如何自定义工具栏