Краткая справка: у меня есть TreeView, который я создал с помощью вызовов Windows API в C ++ (Visual Studio 2008, хотя это не должно иметь значения):
hTreeview = CreateWindowEx(0, WC_TREEVIEW, L"My Treeview", WS_CHILD | WS_VISIBLE | TVS_INFOTIP | TVS_NOHSCROLL | TVS_SHOWSELALWAYS | TVS_EDITLABELS | TVS_SINGLEEXPAND, m_tx, m_ty, m_tw, m_th, hWindow, (HMENU)2, hInstance, NULL);
Я успешно назначил ему ImageList, используя:
m_hImageList = ImageList_Create(cx, cy, ILC_COLOR24, n, n);
TreeView_SetImageList(hTreeview, m_hImageList, TVSIL_NORMAL);
где cx
, cy
, а также n
все указаны (в данном случае 18, 18 и 5 соответственно). Все это прекрасно работает, как я вижу, потому что теперь рядом с моими предметами для изображения выделено место.
То, что я пытаюсь сделать, это скопировать подраздел другого растрового изображения (из файла). Код, который я пробовал (но не работает):
HBITMAP hSkin = (HBITMAP)LoadImage(NULL, szPathBmp, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
for (long i = 0; i < n; i++)
{
HDC dcDest = CreateCompatibleDC(NULL);
HBITMAP hIcon = CreateCompatibleBitmap(dcDest, cx, cy);
HDC dcSrc = CreateCompatibleDC(NULL);
SelectObject(dcSrc, hSkin);
BitBlt(dcDest, 0, 0, cx, cy, dcSrc, x, y, SRCCOPY);
*pIcon = ImageList_Add(m_hImageList, hIcon, NULL);
DeleteObject(hIcon);
DeleteDC(dcSrc);
DeleteDC(dcDest);
}
DeleteObject(hSkin);
Я упустил код проверки ошибок для краткости, и можно предположить, что все перечисленные переменные были установлены где-то еще в программе (простите, что я не предоставляю рабочий исходный файл, но это очень большой проект, и я попытался включить только те части, которые имеют отношение к делу).
Все, что я получаю в древовидном представлении, это черные квадраты (цвет фона древовидного представления), поэтому я предполагаю, что что-то не так с последним блоком кода — тем, который загружает скин и пытается BitBlt a часть его в новое растровое изображение для сохранения в ImageList. Может ли кто-нибудь сказать мне, что я делаю неправильно, или предложить мне лучший способ выполнить то, что я пытаюсь сделать?
Я использую C ++ и Windows API исключительно, нет .NET, MFC или Windows Form Designer.
Заранее благодарю за помощь, и если я что-то пропустил, прошу прощения; это один из моих первых постов.
Есть несколько проблем с вашим кодом.
Во-первых, когда вы создаете новый DC, он начинается с монохромного растрового изображения, поэтому ваш CreateCompatibleBitmap
вызов также будет производить монохромный. Вместо этого вы, вероятно, хотите создать растровое изображение на основе окна или экрана DC.
Во-вторых, вы никогда не выбираете растровое изображение в dcDest
так что ничто не будет втянуто в hIcon
тем не мение.
В-третьих, ImageList_Add
потерпит неудачу, если растровое изображение в данный момент выбрано в контексте устройства, поэтому необходимо отменить выбор hIcon
от dcDest
прежде чем добавить значок в список изображений.
Наконец, вы также пренебрегаете сохранением исходных растровых изображений и их восстановлением, поэтому это также приведет к утечке GDI.
Попробуйте что-то вроде этого:
HDC hdcWindow = GetDC(hWnd);
HDC dcDest = CreateCompatibleDC(hDCWindow);
HBITMAP hIcon = CreateCompatibleBitmap(hDCWindow, cx, cy);
HDC dcSrc = CreateCompatibleDC(NULL);
HGDIOBJ hOldSourceBmp = SelectObject(dcSrc, hSkin);
HGDIOBJ hOldDestBmp = SelectObject(dcDest, hIcon);
BitBlt(dcDest, 0, 0, cx, cy, dcSrc, x, y, SRCCOPY);
SelectObject(dcDest, hOldDestBmp);
SelectObject(dcSrc, hOldSourceBmp);
*pIcon = ImageList_Add(m_hImageList, hIcon, NULL);
DeleteObject(hIcon);
DeleteDC(dcSrc);
DeleteDC(dcDest);
ReleaseDC(hWnd, hDCWindow);
Других решений пока нет …