使用BCM_SETIMAGELIST为按钮设置图像列表失败,SendMessage返回0且无错误信息
BCM_SETIMAGELIST为按钮设置图像列表失败,SendMessage返回0且无错误信息
我仔细看了你的代码,发现几个关键问题导致BCM_SETIMAGELIST调用失败,咱们一个个拆解解决:
1. 通用控件初始化的致命错误
你代码里的INITCOMMONCONTROLSEX指针完全没分配内存就直接访问成员,这会触发非法内存访问,导致InitCommonControlsEx根本没法正确初始化按钮的扩展控件类。而且你用了ICC_LISTVIEW_CLASSES——这是初始化列表视图控件的标志,咱们要的是按钮扩展功能,得换成ICC_BUTTON_CLASSES。
正确写法应该用栈上的变量,避免野指针:
INITCOMMONCONTROLSEX ComCon; ComCon.dwSize = sizeof(INITCOMMONCONTROLSEX); ComCon.dwICC = ICC_BUTTON_CLASSES; InitCommonControlsEx(&ComCon);
2. 按钮样式不匹配
你给按钮加了BS_BITMAP样式,但BCM_SETIMAGELIST是给新版按钮用的扩展接口,不需要这个旧样式。另外建议加上BS_FLAT,确保和通用控件6.0的风格兼容(有manifest的情况下新版控件才会生效):
HWND ButtonOne = CreateWindowEx(0, WC_BUTTON, "", BS_PUSHBUTTON | BS_FLAT | WS_CHILD | WS_VISIBLE, 40, 10, 50, 50, WindowHandle, (HMENU)(IDC_BUTTON_ONE), GetModuleHandle(nullptr), nullptr);
3. 不必要的动态内存分配(还会泄漏)
你用new创建了BUTTON_IMAGELIST对象,但用完完全没释放,这会造成内存泄漏。其实直接在栈上声明结构就行,简单又安全:
RECT rect = { 0, 0, 50, 50 }; BUTTON_IMAGELIST ButtonImageList = {0}; ButtonImageList.himl = ImageList; ButtonImageList.margin = rect; ButtonImageList.uAlign = BUTTON_IMAGELIST_ALIGN_CENTER; // 现在再调用SendMessage应该就能成功了 LRESULT result = SendMessage(ButtonOne, BCM_SETIMAGELIST, 0, (LPARAM)&ButtonImageList); std::cout << result;
4. 额外的检查建议
调用图像列表相关函数后,最好加个返回值检查,确认每一步都成功:
HANDLE Image = LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BITMAP_SQUARE), IMAGE_BITMAP, 50, 50, LR_DEFAULTCOLOR); if (!Image) { // 处理位图加载失败 } ImageList = ImageList_Create(50, 50, ILC_COLORDDB, 1, 0); if (!ImageList) { // 处理图像列表创建失败 } if (ImageList_Add(ImageList, (HBITMAP)Image, nullptr) == -1) { // 处理图像添加失败 }
把这些修改之后,BCM_SETIMAGELIST应该就能正常返回非0值,按钮也能显示图像列表里的内容了。另外记得确保你的manifest文件正确嵌入,这是系统加载通用控件6.0版本的前提,也是使用BCM_SETIMAGELIST这类扩展接口的必要条件。
备注:内容来源于stack exchange,提问作者Karl Auer
相关产品推荐
相关产品推荐

