1

Тема: Свої іконки в тулбарі

Підкажіть що я не доробив. Не замінює іконку на тулбарі. Все інше працює нормально. В ресурсі вона точно є.
Перепробував вже декілька методів завантаження іконок, міняв послідовність дзвінків, але результату немає.

Свої
HINSTANCE  hInst;
HIMAGELIST hImageList = NULL;

HWND CreateToolbar(HWND hWndParent) {

    const int ImageListID = 0;
    const int numButtons  = 1;
    const int bitmapSize  = 64;

    const DWORD buttonStyles = BTNS_AUTOSIZE;

    HWND hWndToolbar = CreateWindowW(TOOLBARCLASSNAME, NULL, WS_CHILD | TBSTYLE_WRAPABLE | TBSTYLE_LIST | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT, 0, 0, 0, 0, hWndParent, nullptr, hInst, nullptr);
    if (!hWndToolbar) return FALSE;

    hImageList = ImageList_Create(bitmapSize, bitmapSize, ILC_COLOR32 | ILC_MASK, numButtons, 0);
    if (!hImageList) return FALSE;

    HICON hIcon{};
    hIcon = (HICON)LoadImageW(hInst, MAKEINTRESOURCEW(IDI_EXIT), IMAGE_ICON, bitmapSize, bitmapSize, LR_COPYFROMRESOURCE);
    ImageList_ReplaceIcon(hImageList, 0, hIcon);
    DestroyIcon(hIcon);

    TBBUTTON tbButtons[numButtons] =
    {
        { MAKELONG(IDI_EXIT, ImageListID), IDM_EXIT, TBSTATE_ENABLED, buttonStyles, {0}, 0, (INT_PTR)L"Exit"}
    };

    SendMessageW(hWndToolbar, TB_SETIMAGELIST, (WPARAM)ImageListID, (LPARAM)hImageList);
    SendMessageW(hWndToolbar, TB_SETMAXTEXTROWS, 0, 0);
    SendMessageW(hWndToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
    SendMessageW(hWndToolbar, TB_ADDBUTTONS, (WPARAM)numButtons, (LPARAM)&tbButtons);
    SendMessageW(hWndToolbar, TB_AUTOSIZE, 0, 0);
    ShowWindow(hWndToolbar, TRUE);

    return hWndToolbar;
}

З системними іконками все працює як треба:

Системні
HINSTANCE  hInst;
HIMAGELIST hImageList = NULL;

HWND CreateToolbar(HWND hWndParent) {

    const int ImageListID = 0;
    const int numButtons  = 3;
    const int bitmapSize  = 24;

    const DWORD buttonStyles = BTNS_AUTOSIZE;

    HWND hWndToolbar = CreateWindowW(TOOLBARCLASSNAME, NULL, WS_CHILD | TBSTYLE_WRAPABLE | TBSTYLE_FLAT, 0, 0, 0, 0, hWndParent, nullptr, hInst, nullptr);
    if (!hWndToolbar) return FALSE;

    hImageList = ImageList_Create(bitmapSize, bitmapSize, ILC_COLOR32 | ILC_MASK, numButtons, 0);
    if (!hImageList) return FALSE;

    SendMessageW(hWndToolbar, TB_SETIMAGELIST, (WPARAM)ImageListID, (LPARAM)hImageList);
    SendMessageW(hWndToolbar, TB_LOADIMAGES, (WPARAM)IDB_STD_LARGE_COLOR, (LPARAM)HINST_COMMCTRL);

    TBBUTTON tbButtons[numButtons] =
    {
        { MAKELONG(STD_FILENEW,  ImageListID), IDM_DBUPLOAD, TBSTATE_ENABLED, buttonStyles},
        { MAKELONG(STD_FILEOPEN, ImageListID), IDM_DBUNLOAD, TBSTATE_ENABLED, buttonStyles},
        { MAKELONG(STD_DELETE,   ImageListID), IDM_EXIT,     TBSTATE_ENABLED, buttonStyles}
    };

    SendMessageW(hWndToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
    SendMessageW(hWndToolbar, TB_ADDBUTTONS, (WPARAM)numButtons, (LPARAM)&tbButtons);
    SendMessageW(hWndToolbar, TB_AUTOSIZE, 0, 0);
    ShowWindow(hWndToolbar, TRUE);

    return hWndToolbar;
}

Гадаю щось з дзвінками. А там хто знає.

2

Re: Свої іконки в тулбарі

"Дзвінками", я так розумію, ви звете виклики (англ. call)?
Гляньте примітки в описі ImageList_ReplaceIcon на MSDN - може, не варто знищувати hIcon?

3

Re: Свої іконки в тулбарі

Отримати іконку можна і простіше:

ImageList_ReplaceIcon(hImageList, 0, LoadIconW(hInst, MAKEINTRESOURCEW(IDI_EXIT)));

Я ж кажу вже багато варіантів перепробував.
І так теж:

ImageList_ReplaceIcon((HIMAGELIST)&hImageList, 0, LoadIconW(hInst, MAKEINTRESOURCEW(IDI_EXIT)));

Але все не те.
Вони точно читаються, але або не перезаписуються, або список не чіпляється.

4

Re: Свої іконки в тулбарі

Все, питання знято. Я розібрався.

ImageList_ReplaceIcon() повертала помилку -1, тому що у ImageList_Create() 3-й параметр на довжину списку не впливає.
Вона точно працює, але не створює масив з заданої кількості елементів. Тому елементи треба додавати, якщо ImageList_ReplaceIcon() то з другим параметром -1. Але і це ще не все. Навіть не думав і не очикував що мелкософт таке начаклує.

Список іконок має починатися обов'язково з 0. Тобто ресурсу IDC_MYICON в resource.h одразу можна задавати 0, та використовувати його замість змінної ImageListID. Це одне й те саме. Ресурс IDC_MYICON більше ніде не фігурує, тобто він формальний, але мелкософт вірогідно його використовує для себе. Тому і додає в проект по замовченюю.
Далі в файлі список іконок має продовжуватись (з 1!) та не розриватись. Першою іконкою треба ставити головну яка відображає іконку програми. Якщо цього не зробити, то системна іконка (16x16) створеної програми буде містити саме ту що стоїть першою. (В мене там одна іконка замість двох, одну з яких small воно саме робить).
Далі краще додати іконку яка буде використовуватись як заповнювач для розділювача BTNS_SEP, бо його все одно треба мати.
Далі з продовженням послідовної нумерації розташовуємо опис своїх іконок.

Потім в програмі робимо заповнення масиву. В нас попереду 3 елемента які треба заповнити:
1 - місто для іконки програми (яку я так розумію wcex.hIconSm потім і використовує як першу в ресурсі-списку IDC_MYICON),
2 - місто для іконки пустушки (яка в мене IDI_EMPTY і вона існує як файл (в мене Empty.ico) і прикріплена до проекту),
3 - місто для розділювача (не плутати з ресурсом номер 3)!
Тобто 3 рази:

ImageList_ReplaceIcon(hImageList, -1, LoadIconW(hInst, MAKEINTRESOURCEW(IDI_EMPTY)));

Весь блок:

    for (size_t i{}; i < 3; ++i) {
        ImageList_ReplaceIcon(hImageList, -1, LoadIconW(hInst, MAKEINTRESOURCEW(IDI_EMPTY)));
    }

    for (size_t i{}; i < numButtons; ++i) {
        ImageList_ReplaceIcon(hImageList, -1, LoadIconW(hInst, MAKEINTRESOURCEW(IDI_OPEN + i)));
    }

IDI_OPEN це ресурс з номером 3, з якого наприклад може починається блок основних іконок.

Отак це працює.

Ще є проблеми з підкладкою. Окантовка іконок на прозорому фоні які я використовую мають чорний фон на кнопках.

Подякували: koala1