yudjin
|
|
« : 03-03-2010 07:05 » |
|
День добрый! в С++, а тем более в WinAPI новичек. Возникла такая проблема - необходимо при активации операции рисовать 1 раз сложные объекты в CBitmap'e, а в OnDraw вызывать только перерисовку энтого CBitmap'а. Дело в том, что запускать метод прорисовки фигур в OnDraw слишком дорого - тысячи точек, сложные циклы. Пробовал рисовать сложные фигуры в другой CDC, и потом выводить его (BitBlt) его в OnDraw, но при вызове Invalidate() этот "другой" CDC, точнее, то, что в нем было - вроде бы опустошается. Подскажите технологию, куда копать. Заранее благодарен.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #1 : 03-03-2010 07:34 » |
|
покажи код, как делал ?
|
|
|
Записан
|
|
|
|
yudjin
|
|
« Ответ #2 : 03-03-2010 07:39 » |
|
Код не очень красивый void CDemoZoomView::OnDraw(CDC* pDC) { // TODO: add draw code for native data here if(refresh) { DrawMe(pDC); }
pDC->BitBlt(0,0, 700, 700, memDC,0,0, SRCCOPY);
}
void CDemoZoomView::DrawMe(CDC* pDC) { srand(0); int width = 2000/10; int height = 1000/10; int i = 0; CDC* dcMem = new CDC; dcMem->CreateCompatibleDC(pDC); CBrush backgroundBrush(RGB(221,0,0));
pbmp->CreateCompatibleBitmap(dcMem,700,700);
CBitmap* oldBmp=dcMem->SelectObject(pbmp); CBrush* pOldBrush = dcMem->SelectObject(&backgroundBrush);
{ for (i = 0; i < 10; i++) { dcMem->FillSolidRect(CRect(i * width, i * height, i * width + width, i * height + height), RGB(rand() % 255, rand() % 255, rand() % 255)); } } memDC->CreateCompatibleDC(pDC); memDC=dcMem; dcMem->SelectObject(pOldBrush); //dcMem->SelectObject(oldBmp);
refresh=false; }
|
|
|
Записан
|
|
|
|
yudjin
|
|
« Ответ #3 : 03-03-2010 07:39 » |
|
Это тестовый кусок, сложных выводов графики тут не ищите
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #4 : 03-03-2010 07:52 » |
|
только вечером детально смогу поразбираться, а навскидку - не понимяу OnDraw, у меня всё в WM_PAINT рисуется (OnPaint() )
|
|
|
Записан
|
|
|
|
yudjin
|
|
« Ответ #5 : 03-03-2010 07:53 » |
|
В этом варианте уже не мигает - добавил локальный CDC (блин как-то плохо технологию эту понимаю, тыкаю на угад), правда цвета пропадают - белым по черному рисует. а если раскомментировать операцию //dcMem->SelectObject(oldBmp); - то возникает ошибка, хотя я ж уже настроил указатель глобального memDC на локальный... Глупые вопросы наверное, просто уже пару дней тыкаюсь. В C# или дельфях я бы сделал Bitmap и выводил его, но тут можно только операции BitBlt с устройством производить... Спасибо за идею, попробую в OnPaint() ЗЫ: не нашел кнопки "редактировать", по-этому и пложу сообщения
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #6 : 03-03-2010 08:00 » |
|
можешь пока почитать как раз об этом https://club.shelek.ru/view.php?id=11Создание собственного графического элемента управления с использованием библиотеки MFC. Часть 1,2,3.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #7 : 03-03-2010 08:01 » |
|
а ещё у тебя память течёт
CDC* dcMem = new CDC;
|
|
|
Записан
|
|
|
|
yudjin
|
|
« Ответ #8 : 03-03-2010 08:37 » |
|
Статьи - супер! Претендуют на оригинальные Узнал много интересного, в частности - удалось вылечить свой код и очень полезно про двойную буферизацию, и получить желаемое, за что огромное спасибо, т.к. бился много дней, а спросить толком не у кого. Ну, и код, правда все еще не оптимизированный, так, наброски идеи: void CDemoZoomView::OnDraw(CDC* pDC) { if(refresh) { DrawMe(pDC); } pDC->BitBlt(0,0, 700, 700, memDC,0,0, SRCCOPY); }
void CDemoZoomView::DrawMe(CDC* pDC) { CDC* dcMem = new CDC; dcMem->CreateCompatibleDC(pDC);
pbmp->CreateCompatibleBitmap(pDC,700,700);
CBitmap* oldBmp=dcMem->SelectObject(pbmp); //Не совсем понятна эта функция, но без нее все рисуется на черном фоне. //из msdn понял, что она заливает наш прямоугольник выбранной кистью dcMem->PatBlt(0,0,700,700,PATCOPY); //Рисуем сложные объекты, например, 10 прямоугольников :) for (i = 0; i < 10; i++) dcMem->FillSolidRect(CRect( i * width, i * height, i * width + width, i * height + height), RGB(120,150,70)); memDC=dcMem; //delete memDC; вызываем в деструкторе класса CDemoZoomView
refresh=false; } Блин, я думал, на С++ никто уже не пишет (ЗЫ: Я сам студент, практикуюсь. Со школьных дельфей перешел и полгода работал на C# - понравилось, но C# оказался слишком медленным для такой задачи). Теперь месяц на С++. Читаю сейчас Страуструппа в твердой копии - он советует Гради Бутча, как классику проектирования архитектуры приложений - потому как занялся сложным долгоиграющим проектом. Скажите мне, С++ не умер? Очень не нравятся работы с БД в С++, хотя, возможно, еще пересмотрю этот вопрос. А вообще, ребята, форум классный! Еще раз спасибо, нигде не нашел столько ответов на свои вопросы, как тут.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #9 : 03-03-2010 08:46 » |
|
Претендуют на оригинальные
а они и так ))) Блин, я думал, на С++ никто
хех, а я думал наоборот , что все повально на с++ пишут ) Во всяком случае - многие точно. Не умер и не умрёт ) Ещё раз: 1) CDC* dcMem = new CDC; без delete - это утечка памяти. Тут можно проще: CDC dcMem; 2) но надо (если в OnDraw) GetDC() ... ReleaseDC() 3) а ещё лучше - рисовать в OnPaint.
|
|
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #10 : 03-03-2010 11:27 » |
|
но C# оказался слишком медленным для такой задачи Или ты, например, не знаешь, как в .NET получить низкоуровневый доступ к Bitmap, чтобы писать пикселы по указателю прямо в память.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #11 : 03-03-2010 11:44 » |
|
Dimka, дык покажи - может правда не знает
|
|
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #12 : 03-03-2010 13:35 » |
|
Алексей1153++, дык не спрашивает
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #13 : 03-03-2010 15:31 » |
|
Dimka, ага, подождём ))
|
|
|
Записан
|
|
|
|
yudjin
|
|
« Ответ #14 : 04-03-2010 11:26 » |
|
Спасибо, на самом деле тут спортивный интерес - хочется на С++ поработать хорошо, чую, он погибче До-диеза будет.
|
|
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #15 : 04-03-2010 11:40 » |
|
yudjin, чисто синтаксически как раз наоборот. C# - язык более молодой и более выразительный. Если же речь о всяких WinAPI, то заметная их часть имеется в составе .NET Framework; доступ к прочим системным библиотекам и сторонним библиотекам, написанным на C/C++, возможен, хотя требует несколько больших трудозатрат, нежели в самом C++. MFC же в плане внутреннего дизайна, скажем так, далеко не самый лучший образец. Самое главное, не думай, что если у тебя что-то не получилось на C#, то виноват в этом язык, и на C++ будет проще Скорее наоборот
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
yudjin
|
|
« Ответ #16 : 05-03-2010 07:47 » |
|
Насчет последнего - ни в коем случае! Слушайте, довольно много времени потратил на чтение различных форумов (правда, на здешнем еще не юзал поиск по интересуюущей теме), сравнивая С++ и C#, но в основном шло просто дружное поливание грязью с обоих сторон. Немногие выводы, которые я для себя сделал - код на С++ может быть легко переносим на различные платформы (неужели С# только под Windows иже Framework?), а в C# действительно очень много инструментов в виде библиотек, радует сборщик мусора (читай, работа без указателей), и "внутренний дизайн" (имеется ввиду работа со студией MS Visual C#). Так вот, собственно, вопрос - ссылки на статьи, литературу, где идет объективное сравнение этих двух языков, и можно ли вообще их сравнивать? Я так понимаю, большинство ПО пишется именно на этих языках (быть может, за исключением отдельных специализированных модулей) - или я не прав? - и хочется хорошей критики почитать.
По поводу низкоуровневых операций с дисплеем на С++: мне показалось (возможно, действительно из-за плохого знания языка С#), что на С# вывод сложной 2D графики (под сложной имеется единовременный вывод на видимую область десятков тысяч точечных объектов), теоритически будет медленнее во-первых, из-за оберток над WinAPI, а во-вторых, из-за CRL-машины.
Дело в том, что за полгода практики я понял, что программирование и проектирование ПО - именно то, чем я хочу заниматься, мне нравится моя работа, мои проекты. Но вот возраст не позволяет читать много книг (не просто читать, а переваривать, осозновать), + начинается весна, какое может быть программирование! куда-то меня занесло...
|
|
|
Записан
|
|
|
|
Джон
просто
Администратор
Offline
Пол:
|
|
« Ответ #17 : 05-03-2010 07:54 » |
|
По поводу низкоуровневых операций с дисплеем на С++: мне показалось (возможно, действительно из-за плохого знания языка С#), что на С# вывод сложной 2D графики (под сложной имеется единовременный вывод на видимую область десятков тысяч точечных объектов), теоритически будет медленнее во-первых, из-за оберток над WinAPI, а во-вторых, из-за CRL-машины.
Нет, не из-за этого. Дело в том, что сишарповская графика базируется на библиотеке gdi+, у которой перманентные проблемы с отображением точек. Если ты используешь пусть даже С++ и SDK, но gdi+, и в этом случае у тебя вывод 10 000 тысяч точек будет очень медленным. Например отображение пунктирной линии.
|
|
|
Записан
|
Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома. "Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash "Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman "All science is either physics or stamp collecting." Ernest Rutherford "Wer will, findet Wege, wer nicht will, findet Gründe."
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #18 : 05-03-2010 14:25 » |
|
код на С++ может быть легко переносим на различные платформы Верно. Только к MFC это не относится Нет, не из-за этого. Дело в том, что сишарповская графика базируется на библиотеке gdi+, у которой перманентные проблемы с отображением точек. Если ты используешь пусть даже С++ и SDK, но gdi+, и в этом случае у тебя вывод 10 000 тысяч точек будет очень медленным. Например отображение пунктирной линии. Тогда уж нужно использовать DirectX. Он может быть использован как в C++, так и в C# (да и, по большому счёту, в любом языке программирования, способном использовать внешние библиотеки и COM). теоритически будет медленнее во-первых, из-за оберток над WinAPI, а во-вторых, из-за CRL-машины. MFC - это тоже обёртки. В CLR используется JIT-компилятор, не менее эффективный, чем всякий другой компилятор. идет объективное сравнение этих двух языков, и можно ли вообще их сравнивать? Чтобы сравнить две вещи, логически нужно иметь нечто третье, общее для них. Какова цель сравнения лично для тебя?
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
yudjin
|
|
« Ответ #19 : 10-03-2010 10:56 » |
|
Нет, не из-за этого. Дело в том, что сишарповская графика базируется на библиотеке gdi+, у которой перманентные проблемы с отображением точек. Если ты используешь пусть даже С++ и SDK, но gdi+, и в этом случае у тебя вывод 10 000 тысяч точек будет очень медленным. Например отображение пунктирной линии. Тогда уж нужно использовать DirectX. Он может быть использован как в C++, так и в C# (да и, по большому счёту, в любом языке программирования, способном использовать внешние библиотеки и COM). DirectX для работы с 2D графики? Имеется ввиду DirectDraw? А не выйдет так, что микроскопом гвозди забиваем? идет объективное сравнение этих двух языков, и можно ли вообще их сравнивать? Чтобы сравнить две вещи, логически нужно иметь нечто третье, общее для них. Какова цель сравнения лично для тебя? Область применения. В чем преимущества/недостатки одного перед другим? Если C# оставил гибкость С++ и даже преуспел в этом (как многие пишут), означает ли это, что стоит фокусироваться на нем и платформе .NET? В чем тогда преимущество С++?
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #20 : 10-03-2010 11:24 » |
|
Лично я после недолгого знакомства с C# плевался от его "выразительности" ))) Лично мне C++ больше по нраву. Слишком уж он вкусный )
|
|
« Последнее редактирование: 10-03-2010 12:00 от Алексей1153++ »
|
Записан
|
|
|
|
yudjin
|
|
« Ответ #21 : 10-03-2010 11:43 » |
|
Спасибо, примерно так и думал - это дело каждого (вкусов, привычек) + нужно учитывать постевленную задачу.
|
|
|
Записан
|
|
|
|
Вад
|
|
« Ответ #22 : 10-03-2010 12:05 » |
|
Глобальное преимущество C++ в том же, в чём и его недостаток: универсальность. В принципе, на C++ можно писать почти что угодно и почти подо что угодно. Это даёт ему фору в том смысле, что освоил один язык - и делаешь на нём что хочешь.
Но как только этот универсальный язык сталкивается с нишевым языком в решении задач, к которым лучше приспособлен этот нишевой - универсальный язык начинает проигрывать - в первую очередь, в простоте.
Мне кажется, C# - это язык для прикладного ПО под конкретные платформы (родство его с Java в этом смысле не случайно). Соответственно, писать прикладной софт для Win на C# проще.
Скажем, когда я вижу, что какой-нибудь Samsung наступает на грабли Symbian с попыткой сделать "свой C++ для программирования под смартфоны" (новая платформа Bada именно этим и занимается), я думаю, что они явно простых путей не ищут. Потому что C++ и программирование под смартфоны едва ли совместимы: ультракороткий цикл разработки очень плохо сочетается со сложным языком C++, порождающим сложные логические ошибки, которые сложно искать. Не говоря уж об оверхеде, возникающем на возне с "лишними деталями", от которых другие языки разработчика освобождают (управление временем жизни, работа с ресурсами, и т.п.)
|
|
« Последнее редактирование: 10-03-2010 12:08 от Вад »
|
Записан
|
|
|
|
yudjin
|
|
« Ответ #23 : 01-04-2010 09:22 » |
|
День добрый. Снова проблемы с HDC и всеми вытекающими. По логике вещей всё должно работать. Делаю следующее: 1. Получаю контекст m_hDC = GetDC(m_hWnd); 2. Создаю m_hMemDC=::CreateCompatibleDC(m_hDC); , в нем буду рисовать 3. BitBtl'ом переношуНе выходит. Если в методах StartDrawing и DrawPoint m_hMemDC заменить на m_hDC, то все рисует. void CScreenDisplay::set_hWnd(HWND hWnd) { m_hWnd=hWnd; m_hDC = GetDC(m_hWnd); m_hMemDC=::CreateCompatibleDC(m_hDC); }
HDC CScreenDisplay::GetDCHandle() { return m_hDC; } void CScreenDisplay::StartDrawing(HDC hDC) { LOGBRUSH logBrush; logBrush.lbColor=RGB(0,0,255); logBrush.lbStyle=BS_SOLID;
HBRUSH hBrush = ::CreateBrushIndirect(&logBrush); SelectObject(m_hMemDC,m_hBitmap); //если меняем на hDC SelectObject(m_hMemDC,hBrush); //то все рисует нормально
CRect rect(20,200,100,300/*m_rectBox.left,m_rectBox.bottom,m_rectBox.right,m_rectBox.top*/); rect.DeflateRect(-100,-100); //если меняем на hDC,то все рисует нормально PatBlt(m_hMemDC,rect.left,rect.top,rect.Width(), rect.Height(),PATCOPY/*PATCOPY*/); } void CScreenDisplay::DrawPoint(CVecGeometry* pGeometry) { //если меняем на m_hDC,то все рисует нормально ::Rectangle(m_hMemDC,20,20,100,100); }
void CScreenDisplay::FinishDrawing(void) { ::BitBlt(m_hDC,5,5, 500, 500, m_hMemDC,0,0, SRCCOPY); }
Пользуемся: //... HDC dc= theApp.pMap->ActiveView()->get_ScreenDisplay()->GetDCHandle(); //... //... theApp.pMap->ActiveView()->get_ScreenDisplay()->StartDrawing(dc); theApp.pMap->ActiveView()->get_ScreenDisplay()->DrawPoint(NULL); theApp.pMap->ActiveView()->get_ScreenDisplay()->FinishDrawing(); //...
Подскажите, где я неправ код, как всегда с магическими цифрами - но это для своеобразного удобства тестирования ))
|
|
« Последнее редактирование: 01-04-2010 10:07 от RXL »
|
Записан
|
|
|
|
yudjin
|
|
« Ответ #24 : 01-04-2010 09:32 » |
|
Извеините, разобрался. Всем спасибо.
|
|
« Последнее редактирование: 01-04-2010 09:53 от Джон »
|
Записан
|
|
|
|
yudjin
|
|
« Ответ #25 : 07-04-2010 14:57 » |
|
День добрый. Передаю в некий класс hDC окна, рисую в нем - творчество отображается корректно в окне. Хочу сделать копирование BitBlt с hDC (в котором рисовали) с другими координатами - не выходит. Копировать пытаюсь следующим образом void CMapView::OnDraw(CDC* pDC) { //... hDC= m_pActiveView->WindowDC(); pDC->BitBlt(newX,newY,newX+500,newX+500,CDC::FromHandle(hDC),0,0,SRCCOPY); //... }
Пытался по разному: и через ::BitBlt(pDC->GetSafeDC(),newX,newY,newX+500,newX+500,hDC,0,0,SRCCOPY); и создавал отдельный ЦДС... ничего
|
|
« Последнее редактирование: 07-04-2010 15:00 от yudjin »
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #26 : 07-04-2010 16:07 » |
|
1) что есть метод WindowDC() ? 2) используешь MFC - не смешивай так жёстко с АПИ: void CMapView::OnDraw(CDC* pDC) {
CDC* pAVdc=m_pActiveView->GetWindowDC;//или же GetDC(), если надо только клиентскую часть окна { //newX,newY - относительные координаты для pDC pDC->BitBlt(newX,newY,/*newX+*/500,/*newX+*/500,pAVdc,0,0,SRCCOPY); } ReleaseDC(pAVdc); pAVdc=0; }
|
|
|
Записан
|
|
|
|
yudjin
|
|
« Ответ #27 : 07-04-2010 18:29 » |
|
Ах да, извините. WindowDC() - просто возвращает HDC, на котором все рисовалось. С АПИ приходится жестко связывать - свои заморочки. Про относительные координаты понятно, просто сокращая код, дабы не загромождать, упустил этот момент... m_pActiveView не имеет никакого отношения к CView и производным, это не графический объект. А если без МФС попробовать - как можно событие WM_PAINT обрабатывать? 24 раза в секунду самому перерисовывать?
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #28 : 07-04-2010 18:38 » |
|
С АПИ приходится жестко связывать - свои заморочки
да легко - весь мой код из MFC очень просто переделать в чистый API. Про относительные координаты понятно, просто сокращая код, дабы не загромождать, упустил этот момент...
а ещё с шириной и высотой пролетел - там не надо прибаввлять начальные координаты ) как можно событие WM_PAINT обрабатывать? 24 раза в секунду самому перерисовывать?
не понятен вопрос... Как придёт сообщение - тогда и перерисовать
|
|
|
Записан
|
|
|
|
yudjin
|
|
« Ответ #29 : 08-04-2010 05:59 » |
|
Просто есть класс, предоставляющий услуги (госспади) отрисовки на переданном HDC. Но это пользовательский класс - и в студии я не могу добавить ему обработку события WM_PAINT, да и никакого вообще. Там пусто. Самому карту сообщений создавать?
|
|
|
Записан
|
|
|
|
|