"продвинутое рисование на форме"
"продвинутое рисование на форме"
дано:
VS 2005 NET CF
нужно:
каждую секунду рисовать много-много всего на экране и так, чтобы не моргало.
идея:
если просток каждую секунду перерисоваывать, будут тормоза и моргания экрана. а ведь можно и так: каждую секунду начинаем рисовать, но не по форме, а по какому нибудь битмапу (пусть на это уйдет даже 0.1с) потом мгновенно меняем изображение на экране на наш битмап и получаем то что хотели (нет моргания)
вопрос: как это сделать?
VS 2005 NET CF
нужно:
каждую секунду рисовать много-много всего на экране и так, чтобы не моргало.
идея:
если просток каждую секунду перерисоваывать, будут тормоза и моргания экрана. а ведь можно и так: каждую секунду начинаем рисовать, но не по форме, а по какому нибудь битмапу (пусть на это уйдет даже 0.1с) потом мгновенно меняем изображение на экране на наш битмап и получаем то что хотели (нет моргания)
вопрос: как это сделать?
Акуеннограмматный ответ! Жаль, что я так не могу! =)ВадимП писал(а):плохая идея
В который раз уже убеждаюсь, что от этого товарисча не бывает толковых ответов - умен больно, блин, не для нашего уровня!
А по твоему вопросу, я бы хотел добавить, что под .Net ничего нельзя писать критичного по времени - уж больно много у нее прослоек (сюда же входит и без нее не быстрый GDI), пока до железа дойдет - пройдет столько времени, что даже человеку заметно.
Для организации backbuffer я бы посоветовал GAPI или на худой конец BITMAP из GDI, хотя полседний так же очень медленный, что бы через него рисовать быстро на экране.
про тормознутость я знаю, но она меня вполне устраивает.Ginger писал(а): А по твоему вопросу, я бы хотел добавить, что под .Net ничего нельзя писать критичного по времени - уж больно много у нее прослоек (сюда же входит и без нее не быстрый GDI), пока до железа дойдет - пройдет столько времени, что даже человеку заметно.
Для организации backbuffer я бы посоветовал GAPI или на худой конец BITMAP из GDI, хотя полседний так же очень медленный, что бы через него рисовать быстро на экране.
ну и пусть медленно рисует, мне нужно чтобы быстро меняло.
времени изучать GAPI совсем нету (я пробежался и понял, что там много всего всего).
с битмапом вроде попроще работать будет?
только вот мне на нем не отдельные пиксели ставить, а фигуры рисовать с заливкой, писать самому эти функции понятное дело подходит.
много кода нужно для реализации двойной буферизации?
научите пожалуйста! я в программировании под КПК совсем новичек, справку VS, MSDN читать на англ. не напрягает, но вот разбираться с новой технологией времени вообще нет.
Насколько я понял первоначальное предложение, речь шла о формировании изображения в некотором буфере в системной памяти, которое затем обычной memcpy() копируется в кадровый буфер видеокарты (который у большинства КПК также находится в системной памяти).sshd писал(а):а почему ты тогда сказал "плохая идея"?
он вроде и описал двойную буферизацию:
"рисовать на битмапе, а потом выводить на экран"
Этот процесс, синхронизированный по времени с сигналом вертикального обратного хода луча (луча, правда, в LCD-мониторах давно нет, но сигнал остался), тоже иногда называли раньше двойной буферизацией.
Но сейчас этот термин всё-таки больше закрепился за тем, что в стародавние времена обзывали "page flipping":
И я не вижу абсолютно никаких преимуществ в первом предложенном варианте - напротив, только недостатки в частности за счет дополнительных потерь времени на копирование.Double Buffering means that there are two display buffers. This means that the next image can be drawn in the page of the display buffer, which is initially invisible. This image is displayed once it is ready and the next image is prepared in the other page of the buffer. Animation's and games can be made to look more realistic with this technique than in simple single buffer mode.
Переключать буфера на мой взгляд гораздо удобнее и проще.
(никаких проблем с созданием необходимого числа буферов и свободным переключением между ними, по крайней мере, на Linux-КПК нет - начало отображаемой части видеопамяти определяется указателем screen_base, который используется низкоуровневым драйвером кадрового буфера).
Про CF не скажу так ли это делается или нет, но для GDI выглядит все просто:
hDC - как понимаешь, тот DC в котором должен быть виден конечный результат пользователю.
Все теперь можешь рисовать на memDC, а результат будет храниться в memBM.
Когда заканчиваешь рисовать, то BitBlt копируешь memDC на тот DC который у тебя на экране. все.
Код: Выделить всё
HDC memDC = CreateCompatibleDC ( hDC );
HBITMAP memBM = CreateCompatibleBitmap ( hDC, nWidth, nHeight );
SelectObject ( memDC, memBM );
Все теперь можешь рисовать на memDC, а результат будет храниться в memBM.
Когда заканчиваешь рисовать, то BitBlt копируешь memDC на тот DC который у тебя на экране. все.
мне на другом форуме подсказали:
. только вот DrawImage тормозит. можно побыстрее сделать?
работаетartko писал(а):2 *apachik*:
ну вы даете. а доки читали?
class my_control : Control
{
....
protected override OnPaint(PaintEventArgs e)
{
Bitmap bmp_buffer = new Bitmap(this.Width, this.Height);
Graphics gr_buffer = Graphics.FromImage(bmp_buffer);
... рисуем по gr_buffer....
e.Graphics.DrawImage(bmp_buffer, 0, 0);
}
}

тоесть ты предлагаешь перерисовывать _весь_ экран????ВадимП писал(а):И я не вижу абсолютно никаких преимуществ в первом предложенном варианте - напротив, только недостатки в частности за счет дополнительных потерь времени на копирование.
Переключать буфера на мой взгляд гораздо удобнее и проще.
(никаких проблем с созданием необходимого числа буферов и свободным переключением между ними, по крайней мере, на Linux-КПК нет - начало отображаемой части видеопамяти определяется указателем screen_base, который используется низкоуровневым драйвером кадрового буфера).
во-первых на покете это вроде бы нельзя делать, во-вторых я так понял, что нужно рисовать в окошке.
page flipping вообще какая-то древняя технология. на спектруме была.
Samsung GT-S8500 + MicroSD 8Gb
sshd писал(а): во-вторых я так понял, что нужно рисовать в окошке.
page flipping вообще какая-то древняя технология. на спектруме была.
Да-да, совсем древняя... Вся трехмерная графика (во всяком случае OpenGL) именно на ней и построена - Вы же пишете при инициализации окна glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA);
а потом по мере надобности glutSwapBuffers();
(для краткости привожу примеры с использованием библиотеки GLUT, но идея от этого не меняется - могу переписать то же самое на чистом GLX. Только длиннее будет)
Создаём область видеопамяти с двойной буферизацией:
Код: Выделить всё
Display *dpy;
Screen *scr;
int scrnum;
int attrib[] = { GLX_RGBA,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_DOUBLEBUFFER,
GLX_DEPTH_SIZE, 1,
None };
XVisualInfo *visinfo;
scrnum = XScreenNumberOfScreen(scr);
root = XRootWindow(dpy, scrnum);
visinfo = glXChooseVisual( dpy, scrnum, attrib );
А потом, после окончания формирования изображения на экране, пишем glXSwapBuffers(dpy, win);
Кстати, независимо от того, перерисовываем ли мы весь экран или небольшой его кусочек - для этого существуют такие инструменты как ножницы (scissors) и трафаретный буфер (stencil buffer).
(трехмерные игры-то спокойно запускаются в окне и двойная буферизация в видеопамяти этому не мешает)
Я конечно понимаю, что исходный вопрос не имел никакого отношения к трехмерной графике и что видеоподсистемы КПК не обеспечивают, увы, необходимой аппаратной поддержки для реализации подобных средств (хотя последнее-то как раз и не имеет особого значения - библиотеки при необходимости эмулируют недостающие возможности программно). Я просто хотел поддержать уважаемого sshd в том, что подобная техника - это несомненно самый что ни на есть каменный век и всяким там doom'ам 3 и quake'ам 4 если и осталось место, то именно на Spectrum'ах!

мне нужно перерисовывать почти весь экран - кроме нижней строки с меню и верхней информационной строки (там всякие лэйблы). строка с заголовком окна убрана нах.sshd писал(а):тоесть ты предлагаешь перерисовывать _весь_ экран????
во-первых на покете это вроде бы нельзя делать, во-вторых я так понял, что нужно рисовать в окошке.
page flipping вообще какая-то древняя технология. на спектруме была.
вот что я нашел
http://www.codeproject.com/bitmap/drawi ... licker.asp
Explanation of Double Buffering
If you have to draw repeatedly to the screen in a short period of time, then when you keep drawing step by step to the DC, it updates the Window again and again which makes the screen flicker.
To avoid this, we first draw to a DC in memory (see the CDC MemDC and CBitmap MemBitmap declarations), and we store the resultant drawing in a memory bitmap. After all the drawing has been completed, we move the bitmap from the memory to the screen in a fast single bitblt call. Thus, we only need to draw once to the screen which avoids flickering totally. This principle is called Double Buffering.
Example code
This example assumes that you are going to draw filled rectangles onto the screen. It generates random shades of green to fill that rectangle.
Use this code in your view class's OnDraw() function if you are using Doc/View architecture or if you are using a dialog based application, then you can add this code in the OnPaint Function.
Note 1 : Gets the coordinates of the bounding rectangle.
Note 2 : Creates a brush with random shades of green. The rand()%255 generates a value between 0 and 255 randomly.
Note 3 : Copies the bitmap from the memory dc to the pdc using a fast bitblt function call.
но это все для С++
http://www.codeproject.com/bitmap/drawi ... licker.asp
Explanation of Double Buffering
If you have to draw repeatedly to the screen in a short period of time, then when you keep drawing step by step to the DC, it updates the Window again and again which makes the screen flicker.
To avoid this, we first draw to a DC in memory (see the CDC MemDC and CBitmap MemBitmap declarations), and we store the resultant drawing in a memory bitmap. After all the drawing has been completed, we move the bitmap from the memory to the screen in a fast single bitblt call. Thus, we only need to draw once to the screen which avoids flickering totally. This principle is called Double Buffering.
Example code
This example assumes that you are going to draw filled rectangles onto the screen. It generates random shades of green to fill that rectangle.
Use this code in your view class's OnDraw() function if you are using Doc/View architecture or if you are using a dialog based application, then you can add this code in the OnPaint Function.
Код: Выделить всё
CRect rcClient;
GetClientRect(rcClient); // See Note 1
CDC MemDC,*pDC;
CBitmap MemBitmap;
pDC = this->GetDC() // Get Current DC
MemDC.CreateCompatibleDC(pDC);
MemBitmap.CreateCompatibleBitmap(pDC,rcClient.right,rcClient.bottom);
CBitmap *pOldBitmap = MemDC.SelectObject(&MemBitmap);
CBrush bkBrush(HS_FDIAGONAL,RGB(0,rand()%255,0)); // See Note 2
MemDC.FillRect(rcClient,&bkBrush);
pDC->BitBlt(0,0,rcClient.right,rcClient.bottom,&MemDC,0,0,SRCCOPY); //See Note 3
MemDC.SelectObject(pOldBitmap);
Note 2 : Creates a brush with random shades of green. The rand()%255 generates a value between 0 and 255 randomly.
Note 3 : Copies the bitmap from the memory dc to the pdc using a fast bitblt function call.
но это все для С++