Форум программистов, компьютерный форум, киберфорум
Наши страницы
Visual C++
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.64/25: Рейтинг темы: голосов - 25, средняя оценка - 4.64
Sheppard
1 / 1 / 0
Регистрация: 27.05.2012
Сообщений: 48
1

Двойная буферизация, присутствует мерцание

05.08.2012, 18:12. Просмотров 4530. Ответов 32
Метки нет (Все метки)

Здравствуйте!
Если форма на C++ (чистый WinAPI), на ней рисуется графика с помощью GDI+.
Форма обновляется каждые 100мс., но вот беда она мерцает.
Код отрисовки:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
VOID OnPaint(HDC hdc)
{
   Graphics     graphics(hdc);
   SolidBrush  brush(Color(255, 0, 0, 255));
   FontFamily  fontFamily(L"Times New Roman");
   Font         font(&fontFamily, 24, FontStyleRegular, UnitPixel);
   PointF         pointF(10.0f, 20.0f);
   Bitmap* picture = Bitmap::FromResource(GetModuleHandle(NULL), MAKEINTRESOURCEW(IDB_BITMAP1));
   graphics.DrawImage(picture, 0, 0);
   if (is_game)
        graphics.DrawString(L"Game is running!", -1, &font, pointF, &brush);
   else graphics.DrawString(L"Game is'nt running!", -1, &font, pointF, &brush);
}
Само рисование формы и применение буферизации:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
case WM_PAINT:
  {
   HDC hdc;
   PAINTSTRUCT ps;
   ULONG_PTR gdiplusToken;
   HDC mdc = CreateCompatibleDC(NULL);
   HBITMAP mbmp =  CreateBitmap(420,320,1,8,NULL);
   HBITMAP moldbmp = (HBITMAP)SelectObject(mdc,mbmp);
   hdc = BeginPaint(hWnd, &ps);
   GdiplusStartupInput gdiplusStartupInput;
   GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
   {
        OnPaint(hdc);
   }
   SelectObject(mdc,moldbmp);
   DeleteObject(mbmp);
   DeleteDC(mdc);
   EndPaint(hWnd, &ps);
  }
  break;
И собственно говоря код, который вызывает обновление:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
case WM_TIMER:
  {
   if (ME->GetProcessByName() != 0)
   {
        is_game = true;
        RECT rect = {0, 0, 420, 320};
        InvalidateRect(hWnd, &rect, false);
   }
   else
   {
        is_game = false;
        RECT rect = {0, 0, 420, 320};
        InvalidateRect(hWnd, &rect, false);
   }
  }
  break;
Как я могу устранить мерцание элементов формы? Может что-то не так с буферизацией?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
05.08.2012, 18:12
Ответы с готовыми решениями:

Двойная буферизация!
Пишу очень облегченное и просто подобие старого Пеинта, но столкнулся с одной...

Двойная буферизация под Win на VC++ (MFC)
Двойная буферизация под Win на VC++(MFC) - кто-нибудь знает - это вообще...

Двойная компиляция
Всем привет! При компиляции на VS2010 происходит двойной запуск программы. ...

Мерцание консоли
Пишу RPG. Но возникла такая проблема: когда персонаж двигается, начинает...

Мерцание при Invalidate
(MFC) Вызываю в OnMouseMove MoveWindow(SetWindowPos (отключаю перерисовку))...

32
castaway
Эксперт С++
4930 / 3037 / 453
Регистрация: 10.11.2010
Сообщений: 11,116
Записей в блоге: 10
Завершенные тесты: 1
05.08.2012, 23:35 21
Цитата Сообщение от Sheppard Посмотреть сообщение
я его исправил как ты и всё, большим изменениям он не подвергался.
Я всегда предполагаю, что человек может меня не так понять и что-то сделать не так, именно поэтому и спрашиваю вновь показать код целиком. Крайне желательно в тэге CUT чтобы он не мозолил глаза лишний раз.
Плюс ко всему, мне намного удобнее будет выявить ошибку видя новый код перед глазами, нежели представлять его в уме.
0
Sheppard
1 / 1 / 0
Регистрация: 27.05.2012
Сообщений: 48
05.08.2012, 23:38  [ТС] 22
Цитата Сообщение от lazybiz Посмотреть сообщение
Я всегда предполагаю, что человек может меня не так понять и что-то сделать не так, именно поэтому и спрашиваю вновь показать код целиком. Крайне желательно в тэге CUT чтобы он не мозолил глаза лишний раз.
C++ source code

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include <Windows.h>
#include <GdiPlus.h>
#include "resource.h"
#include <iostream>
 
#pragma comment (lib, "gdiplus.lib")
using namespace Gdiplus;
 
bool is_game = false;
wchar_t ammo[16];
 
ULONG_PTR gdiplusToken;
GdiplusStartupInput gdiplusStartupInput;
 
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // прототип WndProc
 
VOID OnPaint(HDC hdc)
{
   Graphics    graphics(hdc);
   SolidBrush  brush(Color(255, 0, 0, 255));
   FontFamily  fontFamily(L"Times New Roman");
   Font        font(&fontFamily, 24, FontStyleRegular, UnitPixel);
   PointF      pointF(10.0f, 20.0f);
   PointF      pointF2(10.0f, 45.0f);
   Bitmap* picture = Bitmap::FromResource(GetModuleHandle(NULL), MAKEINTRESOURCEW(IDB_BITMAP1));
   graphics.DrawImage(picture, 0, 0);
   if (is_game)
   {
       graphics.DrawString(L"Game is running!", -1, &font, pointF, &brush);
       graphics.DrawString(ammo, -1, &font, pointF2, &brush);
   }
   else graphics.DrawString(L"Game is'nt running!", -1, &font, pointF, &brush);
}
 
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int CmdShow)
{
    HWND hWnd;
    MSG msg;
    WNDCLASS w;
    memset(&w, 0, sizeof(WNDCLASS)); // зарезервировали место под наш класс окна
    w.style = 0;
    w.lpfnWndProc = WndProc; // задали процессс окна
    w.hInstance = hInstance;
    //w.hbrBackground = (HBRUSH)GetStockObject (WHITE_BRUSH); // задали белый цвет как фон формы
    w.lpszClassName = "Windows Form"; // Задали класс окна
    RegisterClass(&w); // зарегистрировали наше будующее окно
    hWnd = CreateWindow( w.lpszClassName, "Windows Form", WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX,
        CW_USEDEFAULT, CW_USEDEFAULT, 420, 300, NULL, NULL, hInstance, NULL); // создаём форму
    CreateWindow( "button", "Press me!", WS_CHILD | WS_VISIBLE | BS_CENTER,
        40, 90,
        70, 30,
        hWnd, (HMENU)1, hInstance, 0); // создали кнопку
 
    SetTimer(hWnd, NULL, 100, NULL); // сделали таймер
 
    ShowWindow( hWnd, CmdShow); // показываем наше окно
 
    UpdateWindow (hWnd); // обновляем содержимое окна
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
 
    while (GetMessage ( &msg, NULL, 0, 0) )
    {
        TranslateMessage (&msg);
        DispatchMessage(&msg);
    }// настроили отправку сообщений формы, о сообщениях формы можете почитать на MSDN
    return msg.wParam;
}
 
LONG WINAPI WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;
    RECT rect;
    switch (msg)
    {
    case WM_DESTROY:  // обработчик закрытия формы
        PostQuitMessage(0);
    case WM_PAINT:
        {
            hdc = BeginPaint(hWnd, &ps);
            OnPaint(hdc);
            EndPaint(hWnd, &ps);
        }
        break;
 
    case WM_COMMAND: //обработчик разных действий формы, нажатие на кнопку и т.д.
        switch (wParam)
        {
        case 1: // 1 - это HMENU нашей кнопки
            MessageBox(hWnd, "Button pressed", "All right!", MB_OK);
            break;
        }
    case WM_TIMER:
        {
            GetClientRect(hWnd, &rect);
            InvalidateRect(hWnd, &rect, false);
                is_game = true;
                ammo = L"Ammo: 42";
        }
        break;
    default:
        return DefWindowProc (hWnd, msg, wParam, lParam);
    }
    return 0;
}
0
castaway
Эксперт С++
4930 / 3037 / 453
Регистрация: 10.11.2010
Сообщений: 11,116
Записей в блоге: 10
Завершенные тесты: 1
05.08.2012, 23:55 23
А говоришь все поправил.
1. Поставь GdiplusStartup() между 41-й и 42-й строками. UpdateWindow() посылает WM_PAINT, что уже не правильно.
2. После 79-й строки ( PostQuitMessage(0); ) поставь break;
3. Про 97-ю и 98-ю ты меня не послушал. Это не столь критично, но тем не менее.
4. После 94-й должен стоять break;

Кнопка у тебя будет моргать в любом случае, т.к. изображение закрашивает её.
С текстом та же самая фигня, но как это правильно делается в GDI+ понятия не имею.

Кстати, никакой двойной буферизацией у тебя тут даже и не пахнет. Тебе следует использовать CreateCompatibleDC(), для того чтобы создать back-buffer, рисовать в него, а потом с помощью BitBlt() выводить все на hDC, полученный BeginPaint().
Возможно в GDI+ есть какой-то другой вариант, но он мне не известен.
0
Sheppard
1 / 1 / 0
Регистрация: 27.05.2012
Сообщений: 48
06.08.2012, 00:08  [ТС] 24
Цитата Сообщение от lazybiz Посмотреть сообщение
А говоришь все поправил.
1. Поставь GdiplusStartup() между 41-й и 42-й строками. UpdateWindow() посылает WM_PAINT, что уже не правильно.
2. После 79-й строки ( PostQuitMessage(0); ) поставь break;
3. Про 97-ю и 98-ю ты меня не послушал. Это не столь критично, но тем не менее.
4. После 94-й должен стоять break;

Кнопка у тебя будет моргать в любом случае, т.к. изображение закрашивает её.
С текстом та же самая фигня, но как это правильно делается в GDI+ понятия не имею.

Кстати, никакой двойной буферизацией у тебя тут даже и не пахнет. Тебе следует использовать CreateCompatibleDC(), для того чтобы создать back-buffer, рисовать в него, а потом с помощью BitBlt() выводить все на hDC, полученный BeginPaint().
Возможно в GDI+ есть какой-то другой вариант, но он мне не известен.
Знаю что всё в Paint это пихать не надо, но после попытки сделать двойную буферизацию, форма мерцает чёрным цветом.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    case WM_PAINT:
        {
            hdc = BeginPaint(hWnd, &ps);
            HDC memDC = CreateCompatibleDC(NULL);
            HBITMAP hMemBmp = CreateCompatibleBitmap(hdc, 420, 320);
            HGDIOBJ old_object = SelectObject(memDC, hMemBmp);
            BitBlt(hdc, 0, 0, 420, 320, memDC, 0, 0, SRCCOPY);
            OnPaint(hdc);
            SelectObject(memDC, old_object);
            DeleteObject(hMemBmp);
            DeleteDC(memDC);
            EndPaint(hWnd, &ps);
        }
        break;
0
castaway
Эксперт С++
4930 / 3037 / 453
Регистрация: 10.11.2010
Сообщений: 11,116
Записей в блоге: 10
Завершенные тесты: 1
06.08.2012, 00:17 25
Ты меня без ножа режешь...
CreateCompatibleBitmap() тебе не нужна. Убирай. SelectObject() тоже.
Рисовать ты должен в memDC!!! А уже потом BitBlt.
Перенеси все кроме BeginPaint() и EndPaint() в OnPaint().
0
Sheppard
1 / 1 / 0
Регистрация: 27.05.2012
Сообщений: 48
06.08.2012, 00:25  [ТС] 26
Цитата Сообщение от lazybiz Посмотреть сообщение
Ты меня без ножа режешь...
CreateCompatibleBitmap() тебе не нужна. Убирай. SelectObject() тоже.
Рисовать ты должен в memDC!!! А уже потом BitBlt.
Перенеси все кроме BeginPaint() и EndPaint() в OnPaint().
С++ source code
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
VOID OnPaint(HDC hdc)
{
   HDC memDC = CreateCompatibleDC(NULL);
   Graphics    graphics(hdc);
   SolidBrush  brush(Color(255, 0, 0, 255));
   FontFamily  fontFamily(L"Times New Roman");
   Font        font(&fontFamily, 24, FontStyleRegular, UnitPixel);
   PointF      pointF(10.0f, 20.0f);
   PointF      pointF2(10.0f, 45.0f);
   Bitmap* picture = Bitmap::FromResource(GetModuleHandle(NULL), MAKEINTRESOURCEW(IDB_BITMAP1));
   graphics.DrawImage(picture, 0, 0);
   if (is_game)
   {
       graphics.DrawString(L"Game is running!", -1, &font, pointF, &brush);
       graphics.DrawString(ammo, -1, &font, pointF2, &brush);
   }
   else graphics.DrawString(L"Game is'nt running!", -1, &font, pointF, &brush);
   BitBlt(hdc, 0, 0, 420, 320, memDC, 0, 0, SRCCOPY);
   DeleteDC(memDC);
}

Элементы формы уже мерцают не всегда.
Но всё равно мерцают, пробовал рисовать в memDC, но тогда просто чёрная форма получается.
0
castaway
Эксперт С++
4930 / 3037 / 453
Регистрация: 10.11.2010
Сообщений: 11,116
Записей в блоге: 10
Завершенные тесты: 1
06.08.2012, 00:39 27
А как ты пробовал рисовать в memDC ?
Понимаешь, меня интересует код, который я тебе "навязываю", а не который ты исправил на свое усмотрение.
0
Игорь с++
473 / 465 / 63
Регистрация: 26.01.2011
Сообщений: 2,033
06.08.2012, 00:41 28
Цитата Сообщение от Sheppard Посмотреть сообщение
код из "Нет мерцание.rar", не позволяет убрать мерцание, проверял на твоих же исходниках, текст отрисованный GDI+ мерцает.
я не знаю как и чего у тебя там моргает , возьми запусти exe-шник и посмотри , что у тебя будет творится !!!! Есть мерцание ??????
0
castaway
Эксперт С++
4930 / 3037 / 453
Регистрация: 10.11.2010
Сообщений: 11,116
Записей в блоге: 10
Завершенные тесты: 1
06.08.2012, 00:41 29
Как я уже говорил, элементы (контроли) так и будут мерцать, в твоем случае от этого никуда не денешься.
0
Sheppard
1 / 1 / 0
Регистрация: 27.05.2012
Сообщений: 48
06.08.2012, 00:43  [ТС] 30
Цитата Сообщение от lazybiz Посмотреть сообщение
Как я уже говорил, элементы (контроли) так и будут мерцать, в твоем случае от этого никуда не денешься.
Текст мерцает также, но реже
0
castaway
Эксперт С++
4930 / 3037 / 453
Регистрация: 10.11.2010
Сообщений: 11,116
Записей в блоге: 10
Завершенные тесты: 1
06.08.2012, 00:52 31
Цитата Сообщение от Sheppard Посмотреть сообщение
Текст мерцает также
Если ты все сделал так как я тебе говорил, то мне верится в это с трудом. Показывай код в CUT.
0
Sheppard
1 / 1 / 0
Регистрация: 27.05.2012
Сообщений: 48
06.08.2012, 01:00  [ТС] 32
Цитата Сообщение от lazybiz Посмотреть сообщение
Если ты все сделал так как я тебе говорил, то мне верится в это с трудом. Показывай код в CUT.
С++ source code
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
VOID OnPaint(HDC hdc)
{
   HDC memDC = CreateCompatibleDC(NULL);
   Graphics    graphics(hdc);
   SolidBrush  brush(Color(255, 0, 0, 255));
   FontFamily  fontFamily(L"Times New Roman");
   Font        font(&fontFamily, 24, FontStyleRegular, UnitPixel);
   PointF      pointF(10.0f, 20.0f);
   PointF      pointF2(10.0f, 45.0f);
   Bitmap* picture = Bitmap::FromResource(GetModuleHandle(NULL), MAKEINTRESOURCEW(IDB_BITMAP1));
   graphics.DrawImage(picture, 0, 0);
   if (is_game)
   {
       graphics.DrawString(L"Game is running!", -1, &font, pointF, &brush);
       graphics.DrawString(ammo, -1, &font, pointF2, &brush);
   }
   else graphics.DrawString(L"Game is'nt running!", -1, &font, pointF, &brush);
   BitBlt(hdc, 0, 0, 420, 320, memDC, 0, 0, SRCCOPY);
   DeleteDC(memDC);
}

Только не говори, что я что-то перепутал
0
castaway
Эксперт С++
4930 / 3037 / 453
Регистрация: 10.11.2010
Сообщений: 11,116
Записей в блоге: 10
Завершенные тесты: 1
06.08.2012, 01:21 33
Опять ты кое-что перепутал, а точнее не доделал. Кстати, ты заметил что с прошлого раза этот код не изменился!? Обрати на это внимание.

Я спать. Сделай как я говорил, и, если не будет работать выложи код целиком, завтра посмотрим...
0
06.08.2012, 01:21
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
06.08.2012, 01:21

Анимация огня. Мерцание
Собственно само задание выглядит так: Задание я вроде бы выполнил, но...

Постоянное мерцание при прорисовке
создал класс, в котором реализованы методы для рисования графиков. есть маcсив...

Мерцание при перерисовке (MFC)
Господа Программисты! Делаю Тетрис на MFC. При перерисовке игрового поля...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
33
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru