|
 2.3 Кб |
|
| Ну ни как у меня не получается это сделать! А это, на сколько я понимаю, то самое, чем пользуются, при отрисовке дизайна Windows-приложений.
Я уже не знаю что ещё сделать. Вот, прикрепляю файл с кодом. Программа компилируется и запускается, но ничего на экран не выводится. | |
|
|
|
|
|
|
|
для: EvgenLog
(24.01.2007 в 00:47)
| | Так не пойдёт - вы должны явно указать в функции LoadBitmap() откуда вы загружаете изображение... Просто NULL указать не получится, придётся передавать дескриптор приложения hInstance, иначе функция не будет знать где брать изображение... Вынесете определение объекта
за пределы функции WinMain(), чтобы объект wc стал глобальным и передавайте в качестве первого параметра функции LoadBitmap() - wc.hInstance | |
|
|
|
|
|
|
|
для: cheops
(24.01.2007 в 02:13)
| | Спасбо, действительно всё заработало. Значит дизайн теперь так строить? Выводить битмапы? С сответствующими координатами....
Вот ещё вопрос. Я правильно понимаю принцип действия?
Вот например мне нужно создать свою кнопку, своей формы и т.д. Для этого мне нужно вывести картинку кнопки в "отжатом" состоянии, а при нажатии на неё обработать сообщение которое сообщает о нажатии левой кнопки мыши? | |
|
|
|
|
|
|
|
для: EvgenLog
(24.01.2007 в 11:11)
| | >С сответствующими координатами....
Не только координатами, если вы пользуетесь готовыми элементами управления, меню, кнопками, то вам нужно будет выводить изображеня на них, т.е. привязываться к контексту... каждый элемент управления представляет собой своебразное мини-окно и координаты у них должны быть свои. Т.е. если захотите меню разукрасить (10 глава Петцольда), то необходимо будет привязываться к меню, а не к основному окну.
>Для этого мне нужно вывести картинку кнопки в "отжатом" состоянии, а при нажатии на неё
>обработать сообщение которое сообщает о нажатии левой кнопки мыши?
Если вы полностью отрисовываете свою собственную кнопку, да именно так. Как правило подготавливают два изображения - в нажатом и отжатом состоянии (иногда, ещё вид кнопки при наведённой на неё мыши). | |
|
|
|
|
|
|
|
для: cheops
(24.01.2007 в 13:37)
| | Т.е. чтобы рисовать на заголовке окна (менять, собственно внешний вид окна в целом) и рамках, нужно делать привязку к контексту окна. В таком случае можно будет удалить с заголовка все стандартные элементы и разместить свои? Но, если создавать свою кнопку, то как опредилить, что пользователь кликнул именно на ДАННОМ обьекте? Ведь сообщение о нажатии мыши отправляется при клике в любом месте.
И ещё, можно-ли кроме Bitmap вывести ещё что-нибудь, содержащее большее количество цветов? Например JPG? Я знаю, что можно добавить в ресурсы, что угодно, но вот какими средствами вывести, не нашёл. Знаю, что существует формат битового изображения 24-bit, но он слишком много весит. | |
|
|
|
|
|
|
|
для: EvgenLog
(24.01.2007 в 13:58)
| | Чтобы рисовать в заголовке - вам нужно открыть окно в режиме, котором вообще ничего нет кроме области окна (как игрушки делают) - и отрисовывать заголовок окна, кнопки свернуть, выключить, на полный экран (если они вообще нужны) самостоятельно... Правда, режим не помню - нужно в справочнике рыться. | |
|
|
|
|
|
|
|
для: cheops
(24.01.2007 в 14:47)
| | Ясно. Спасибо.
А на вопрос про создание своего объкта ответа так и нет. Создать новую тему? С таким вопросом. По сути он к выводу битмапов никак не относится. | |
|
|
|
|
|
|
|
для: EvgenLog
(24.01.2007 в 15:02)
| | Хм... а что-то не вижу... Под новые вопросы лучше всегда заводить новые темы - тогда их сложнее не заметить :))) | |
|
|
|
|
|
|
|
для: cheops
(24.01.2007 в 15:13)
| | Хм... Вот интересно, а почему изображение исчезает с экрана? Просто исчезает. Это происходит, если непрерывно менять размеры окна или таскать по нему что-нибудь, например другое перекрывающее окно. Через несколько секун таких пыток изображение исчезает. И ещё, очень раздражительно мигает картинка, при совершении подобных операций. В чём дело и как от всего этого избавиться? | |
|
|
|
|
|
|
|
для: EvgenLog
(24.01.2007 в 19:43)
| | У вас, я там видел, конекст не закрывается, т.е. свойство WM_PAINT выглядит так
case WM_PAINT :
hDc = BeginPaint(hWnd, &ps);
bmPicture = LoadBitmap(NULL, MAKEINTRESOURCE(IDB_BITMAP2));
DrawBitmap(hDc, bmPicture, 100, 100);
return(0); |
Я когда разбирался с вашим примером, контекст закрывал
case WM_PAINT :
hDc = BeginPaint(hWnd, &ps);
bmPicture = LoadBitmap(wc.hInstance, MAKEINTRESOURCE(IDB_BITMAP2));
DrawBitmap(hDc, bmPicture, 100, 100);
EndPaint(hWnd, &ps);
return 0; |
Сейчас таскаю - у меня ничего не пропадает - попробуйте - наверняка дело в этом. | |
|
|
|
|
|
|
|
для: cheops
(24.01.2007 в 19:49)
| | Я это уже давно и исправил. У меня тоже контекст закрывается.
Вот что я заметил. Если отображать маленьку картинку (размер не более 2 кб), то всё нормально, не удаляется, хотя мигание всё равно присутсвует. Если же отображать картинку потяжелее (примерно 380 кб), то она после издевательств над окном исчезает. Я в виду своей недостаточной образованности в этой области, ничего конкретного сказать не могу, но думай, что нужен буфер. | |
|
|
|
|
|
|
|
для: EvgenLog
(24.01.2007 в 20:12)
| | Мне ещё не нравится, что вы выполняете функцию LoadBitmap() при каждом чихе программы - дело в том, что работая с окном - вы вызываете эту функцию десятки раз за секунду... лучше загрузить LoadBitmap() один раз в WinMain(), а затем использовать в событии WM_PAINT. Однако и это тоже может не помочь, так как Windows API вообще говоря не силён в графике - максимум, что можно сделать, это что-то вроде сапёра или косынки. Для серьёзных графических проектов используют либо OpenGL, либо DirectX. При 380 Кб от мерцания будет очень сложно избавиться. | |
|
|
|
|
|
|
|
для: cheops
(24.01.2007 в 20:50)
| | Хорошо, а каким тогда образом отображаются иконки допустим в обычном окне Windows? Они ведь не мерцают при изменение размеров окна. | |
|
|
|
|
|
|
|
для: EvgenLog
(24.01.2007 в 20:57)
| | Они и 380 Кб не занимают :) | |
|
|
|
|
|
|
|
для: cheops
(24.01.2007 в 21:07)
| | Но они там хотябы не мерцают! :) | |
|
|
|
|
|
|
|
для: EvgenLog
(24.01.2007 в 21:17)
| | Понимаете там... картинка рисуется один раз, после этого, при срабатывании события WM_PAINT, перерисовываются только те участки которые изменились... Грубо говоря тащите вы окно и видите, что наложения других окон нет, размер не изменяется... в этом случае вы ничего не перерисовываете, а если требуется перерисовать - перерисовывайте. WM_PAINT может сотню раз сработать пока окно тащите... попробуйте переместить код отрисовки в события отображения окна WM_SHOWWINDOW и событие изменения его размера WM_SIZE (я тут вызов LoadBitmap() в WinMian() вынес)
switch(iMsg)
{
case WM_SHOWWINDOW:
case WM_SIZE:
hDc = BeginPaint(hWnd, &ps);
DrawBitmap(hDc, bmPicture, 100, 100);
EndPaint(hWnd, &ps);
return 0;
case WM_PAINT :
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
|
В этом случае изображение будет отрисовываться только при отображении окна и при изменени его размера... правда ещё потерю фокуса нужно обработать - иначе перекрытие другими окнами будет затирать окно. | |
|
|
|
|
|
|
|
для: EvgenLog
(24.01.2007 в 21:17)
| | Причём зачастую отрисуют окно и запоминают как оно выглядело, потом подгружают сохранённый образ и редактируют на нём только то, что подверглось изменению, не перерисовывая каждую деталь... Библиотеки MFC и VCL не зря свой хлеб едят, они действительно выполняют множество рутинной работы. | |
|
|
|
|
|
|
|
для: cheops
(24.01.2007 в 22:23)
| | Ясно. Попробую, но мне кажется что не в этом проблема. Когда я окно претаскиваю, то оно не мигает и ничего не исчезает. Глюки как раз таки только при изменение размеров. Ну сейчас попробую. | |
|
|
|
|
|
|
|
для: EvgenLog
(24.01.2007 в 22:32)
| | Странно. Я переместил функцию загрузки изображения в WinMain() и теперь у меня вообще ничего не выводися на экран.
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
static char szAppName[] = "Paint On Window";
HBITMAP bmPicture;
HBRUSH hBrush;
HWND hwnd;
MSG msg;
bmPicture = LoadBitmap(wndclass.hInstance, MAKEINTRESOURCE(IDB_BITMAP1));
wndclass.cbSize = sizeof(wndclass);
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
wndclass.lpszClassName = szAppName;
wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&wndclass);
.
.
.
|
| |
|
|
|
|
|
|
|
для: EvgenLog
(24.01.2007 в 22:37)
| | bmPicture глобальным сделали? | |
|
|
|
|
|
|
|
для: EvgenLog
(24.01.2007 в 22:32)
| | При изменении размеров вообще говоря тоже нужно отслеживать, пересекает область окна изобаржение или нет - если не пересекает, то и перерисовывать его не требуется. | |
|
|
|
|
|
|
|
для: cheops
(24.01.2007 в 22:39)
| | Сделал глобальной (вынес на самый верх), безрезультатно. Отслеживать пересекает или нет... Т.е. нужно использовать область отсечения или InvalidateRect? | |
|
|
|
|
|
|
|
для: EvgenLog
(24.01.2007 в 22:49)
| | Странно - у меня работает - прикрепите файл, в том виде, котором он у вас сейчас. | |
|
|
|
|
 1.4 Кб |
|
|
для: cheops
(24.01.2007 в 23:00)
| | Вот как выглядит файл main.cpp. В архив не включены ресурсы. | |
|
|
|
|
|
|
|
для: EvgenLog
(24.01.2007 в 23:03)
| | Только сейчас заметил - вы используете wndclass.hInstance в LoadBitmap() до того, как он определён парой строчек ниже... поэтому в качестве первого параметра опять передаётся NULL. Поместите LoadBitmap() ниже в WinMain(). | |
|
|
|
|
|
|
|
для: cheops
(24.01.2007 в 23:06)
| | Ха! Да что ты будешь делать!
Переместил
bmPicture = LoadBitmap(wndclass.hInstance, MAKEINTRESOURCE(IDB_BITMAP2));
|
В самый низ WinMain(), опять без результата! Может вы мне вышлите код в таком виде, в котором он у вас работает? | |
|
|
|
|
|
|
|
для: EvgenLog
(24.01.2007 в 23:10)
| | В самый низ нельзя :), так как программа по сути выполняется в цикле
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
} |
Вот так напишите
wndclass.cbSize = sizeof(wndclass);
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
wndclass.lpszClassName = szAppName;
wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
bmPicture = LoadBitmap(wndclass.hInstance, MAKEINTRESOURCE(IDB_BITMAP1)); |
или просто оставьте в начале, но засобачьте вместо wndclass.hInstance - hInstance, вы же в WinMain() находитесь можете использовать оригинальный дескриптор. | |
|
|
|
|
|
|
|
для: EvgenLog
(24.01.2007 в 23:10)
| | Опять нет результата. Я вот подумал правилен-ли вот этот код?
switch(iMsg)
{
case WM_SHOWWINDOW:
case WM_SIZE:
hDc = BeginPaint(hWnd, &ps);
DrawBitmap(hDc, bmPicture, 100, 100);
EndPaint(hWnd, &ps);
return 0;
case WM_PAINT :
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
|
Петзольд пишет, что нельзя вот так делать:
case WM_PAINT :
return 0;
|
| |
|
|
|
|
 14.9 Кб |
|
|
для: EvgenLog
(24.01.2007 в 23:20)
| | Держите мой проект...
PS Тема уже достаточно большая наверное нужно бы новую завести для продолжения... | |
|
|
|
|
|
|
|
для: cheops
(24.01.2007 в 23:25)
| | Хм... Работает... Построчно придётся сравнивать, чтобы докапаться до ошибки. Ну да ладно, этим потом займусь, всё равно для разработки справвочника буду пользоваться графическим интерфейсом. Спасбо за помощь! | |
|
|
|
|
|
|
|
для: cheops
(24.01.2007 в 22:39)
| | Вобщем нужно помечать перекрываемую область как недействительную и перерисовывать только её? | |
|
|
|
|
|
|
|
для: EvgenLog
(24.01.2007 в 22:32)
| | В том и дело, что WM_SIZE тоже очень много возникает - нужно перерисовывать только тогда, когда задевается рисунок, причём, если окно только расширяется и задевает изображение. | |
|
|
|