Я видел другие темы по этой теме, но ни одна из них не работает с MFC 2.5 с тех пор.
CButton::ModifyStyle()
и CButton::SetBitmap()
не существуют в MFC 2.5.
Я создаю диалоговое приложение, используя редактор ресурсов, чтобы создать диалоговое окно с несколькими кнопками. В редакторе для кнопок установлено значение «Рисование владельцем». Я использую следующий код:
void CMainDialog::OnInitDialog()
{
// to do: initialization
CBitmapButton m_Processor;
m_Processor.AutoLoad( IDC_CPU, this );
return TRUE;
}
Приведенный выше код должен был автоматически загрузить ресурс растрового изображения, который я создал как IDB_CPU
. Однако при компиляции расположение кнопки просто показывает пустое пространство, а не загружает растровое изображение.
Я также попробовал этот код:
void CMainDialog::OnInitDialog()
{
// to do: initialization
CBitmapButton m_Processor;
m_Processor.LoadBitmaps( IDB_CPU, NULL, NULL, NULL );
return TRUE;
}
Но он дает тот же результат, только с пустым пространством. Я знаю, что изображение существует в растровом формате (например, я могу открыть его с помощью Paint), и я проверил, что идентификатор ресурса для IDB_CPU
правильно установлен в файле resources.h.
Любая помощь приветствуется!
Вы можете вызвать LoadBitmap()
хотя бы с первым набором аргументов. И в этом случае имена ресурсов не обязательно должны соответствовать вышеупомянутой спецификации. Возможно, вам придется использовать MAKEINTRESOURCE()
для использования идентификатора ресурса. Экземпляр класса CBitmapButton
нельзя удалять (поэтому его также не следует определять в функции), он должен существовать на протяжении всего срока службы диалога. Таким образом, он должен быть определен в классе, связанном с идентификатором ресурса с DDX_Control()
в DoDataExchange()
, и вы должны вызвать LoadBitmaps()
в OnInitDialog()
(после вызова OnInitDialog()
базового класса).
Похоже, m_Processor
является (или, по крайней мере, должен быть) членом класса CMainDialog
.
Префикс m_
намекает, что такой участник у вас действительно есть, а если нет, то его следует добавить.
Однако эта строка внутри CMainDialog::OnInitDialog()
:
CBitmapButton m_Processor;
Объявляет локальную переменную. Он затеняет участника с таким же именем (если существует).
Растровое изображение загружается в эту локальную переменную и отбрасывается, когда оно выходит за пределы области действия при возврате метода, а не в элемент диалога, который отображается в графическом интерфейсе (при условии, что такой элемент существует).
Поэтому вам следует удалить эту строку.
Это дало мне намек на то, что я делаю это неправильно, будучи n00b и все такое. Мне удалось выяснить, как сделать m_Processor
членом класса CMainDialog
, но мастер Class Express позволял мне создавать только тип CButton
, а не CBitmapButton
. Для меня довольно странно, если компилятор поддерживает типы CBitmapButton
. Мне придется поискать в Google и посмотреть, смогу ли я выяснить, как изменить тип.
@CharlieDobson Я не уверен, как это сделать, надеюсь, вы найдете это с помощью Google. Вы можете опубликовать новый вопрос по этой проблеме. Но я совершенно уверен, что то, что я написал, является ответом на ваш текущий вопрос в том виде, в котором он опубликован.
Попробуйте просто изменить тип переменной с CButton
на CBitmapButton
в определении класса.
Мне пришлось объединить оба ваших предложения, чтобы заставить его работать. Мне нужно было удалить локальную переменную в CMainDialog::OnInitDialog()
, а также вручную изменить тип класса с CButton
на CBitmapButton
. Мне также пришлось не использовать мастер для добавления переменной-члена, а добавить ее под спецификатором protected:
в классе диалога.
Это не самый распространенный способ связать элементы управления Win32 с переменными класса MFC. Вместо этого вы можете использовать мастер классов, чтобы добавить переменные-члены в класс диалога.
Что касается вашей проблемы (использование старой версии MFC без метода CButton::SetBitmap()
), можно было бы сказать, используйте последнюю версию VS/MFC, но это не всегда легко. Обходной путь — вместо этого использовать сообщение Win32 BM_SETIMAGE. MFC по большей части представляет собой оболочку MFC (и довольно «тонкую», я бы сказал). И это именно то, что на самом деле делает MFC. Ниже приведена реализация CButton::SetBitmap()
в файле afxwin2.inl, строка 640:
_AFXWIN_INLINE HBITMAP CButton::SetBitmap(HBITMAP hBitmap)
{ ASSERT(::IsWindow(m_hWnd)); return (HBITMAP)::SendMessage(m_hWnd, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap); }
То есть он просто отправляет BM_SETIMAGE
элементу управления. Вы можете сделать то же самое в своем приложении:
SendDlgItemMessage(IDC_MYBUTTON, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);
ИЛИ
SendDlgItemMessage(IDC_MYBUTTON, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)(HBITMAP)m_Bitmap);
В классе CBitmap
есть оператор HBITMAP
, поэтому вы можете передать переменную экземпляра CBitmap
там, где ожидается HBITMAP
; однако SendMessage()/SendDlgItemMessage()
принимает LPARAM
в качестве последнего аргумента, поэтому здесь необходимо дополнительное приведение (HBITMAP)
.
Сообщения BM_SETIMAGE
и IMAGE_BITMAP
, похоже, не поддерживаются Win16 API. Я попробовал следующий код, но мой компилятор сказал, что оба неопознаны: BOOL CMainDialog::OnInitDialog() { CDialog::OnInitDialog() // to do: initialization CBitmap h_bitmap; h_bitmap.LoadBitmap( IDB_CPU ); ::SendDlgItemMessage( IDC_PROCESSR, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)(HBITMAP)h_bitmap ); h_bitmap.DeleteObject(); return TRUE; }
Извините за плохое форматирование выше. У меня закончилось время редактирования, прежде чем я смог это исправить.
Если единственная проблема в том, что эти символы не определены, это легко: BM_SETIMAGE
— это 0x00F7
, а IMAGE_BITMAP
— 0. Вопрос в том, поддерживаются ли они библиотекой управления ОС. Попробуйте это с вышеуказанными константами. Из заголовочных файлов видно, что они поддерживаются начиная с Win NT 4.0, но попробовать можно. Я бы не стал удалять растровое изображение (лучше создать экземпляр объекта CBitmap
в своем классе, а не в OnInitDialog()
, поскольку он выделен в стеке, и деструктор все равно его удалит), по крайней мере, пока я не удостоверюсь, что он больше не нужен (после звоню BM_SETIMAGE
).
Забыл упомянуть, чтобы кнопка работала, она не должна быть нарисована владельцем.
"OK"
) плюс буквальный суффикс"U"
,"D"
,"F"
и"X"
для состояний вверх/вниз/фокус/отключено. Чтобы это работало, ваш сценарий ресурсов должен определить эти растровые изображения с именем. В любом случае, если ваши кнопки отображаются пустыми, проблема, скорее всего, связана с вашим кодом отрисовки владельца (который мы не видим). Требуется минимально воспроизводимый пример.