Модераторы: feodorv, GremlinProg, xvr, Fixin

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> SetWaitableTimer(), как задать период срабатывания таймера 
V
    Опции темы
GremlinProg
Дата 16.3.2012, 07:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(feodorv @  15.3.2012,  18:03 Найти цитируемый пост)
А метафайл никак подойдёт под эту задачу?

если я правильно понимаю: emf, wmf?

подойдет, конечно,
только пользы от него конкретно в данной задаче будет 0,
поскольку отрисовка такого файла будет идти не в потоке, а все в том же WM_PAINT (в потоке будет просто сформирован набор команд)

лучше всего подойдет простой растр


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
feodorv
Дата 16.3.2012, 21:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 9
Всего: 45



Цитата(GremlinProg @  16.3.2012,  08:06 Найти цитируемый пост)
судя по твоему обширному плану

План не обширный, а всего лишь подробный)))

Цитата(GremlinProg @  16.3.2012,  08:06 Найти цитируемый пост)
эти законы не для того, чтобы жить по ним, а для того, чтобы 

А фиг его знает, для чего эти законы, но если они действуют, то приходится с ними считаться)))) Потому и олинклюзив)))

Цитата(GremlinProg @  16.3.2012,  08:26 Найти цитируемый пост)
лучше всего подойдет простой растр

Ок!
Плохо, что автор темы пропал куда-то...


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
wallstreet
Дата 22.3.2012, 13:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 153
Регистрация: 11.8.2011

Репутация: нет
Всего: нет



Цитата

6 и 7 пункт, по хорошему, требует также синхронизации доступа к глобальному растру, решать это можно как секцией, так и простой взаимоблокировкой,

p.s.: если не понятно как реализовать синхронизацию доступа к глобальному растру взаимоблокировкой, могу потом показать


Честно признаться не знаю как сформировать мой массив в виде растового изображения. Поэтому без вашей помощи буду месяц разбираться((


Цитата

Плохо, что автор темы пропал куда-то... 


ну почему же пропал, просто времени мало в последнее время на самообучение(((
а так процесс идет!! ;)

Это сообщение отредактировал(а) wallstreet - 22.3.2012, 13:11
PM MAIL   Вверх
GremlinProg
Дата 22.3.2012, 14:58 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(wallstreet @  22.3.2012,  15:09 Найти цитируемый пост)
Честно признаться не знаю как сформировать мой массив в виде растового изображения. Поэтому без вашей помощи буду месяц разбираться((

Код

hScreenDC = ::GetDC( HWND_DESKTOP );
hMemDC = ::CreateCompatibleDC( hScreenDC );
hMemBitmap = ::CreateCompatibleBitmap( hScreenDC, Width, Height );
::ReleaseDC( HWND_DESKTOP, hdcScreen );
hMemBitmap = ::SelectObject( hMemDC, hMemBitmap );
//
PaintArray( hMemDC );
//
hMemBitmap = ::SelectObject( hMemDC, hMemBitmap );
::DeleteDC( hMemDC );


Width, Height - размерв растра
PaintArray - метод отрисовки растра
hMemBitmap - сам растр

p.s.:код писал в браузере, контроль ошибок не вел


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
wallstreet
Дата 27.3.2012, 16:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 153
Регистрация: 11.8.2011

Репутация: нет
Всего: нет



Благодарю за ответ, но  вопросов появилось еще больше((
Правильно ли я понимаю, что:
Код

hScreenDC = ::GetDC( HWND_DESKTOP ); //получаем дескриптор контекста рабочего стола

т.е. фактически делаем PrintScreen экрана?
Код

hMemDC = ::CreateCompatibleDC( hScreenDC ); // насколько я понимаю с помощью этой функции
                        // создают контекст загруженного изображения, а
                        // у нас только дескриптор но не могу понять чего.
                        // hScreenDC ведь не дескриптор контекста изображения
                        // пока что. Или ошибаюсь?

hMemBitmap = ::CreateCompatibleBitmap( hScreenDC, Width, Height ); // получаем адрес структуры изображения
                                                         // BITMAP. Изображения рабочего стола?
::ReleaseDC( HWND_DESKTOP, hdcScreen );                   // Освобождаем контекст
hMemBitmap = ::SelectObject( hMemDC, hMemBitmap ); // выбираем объект hMemBitmap в контекст hMemDC

По поводу метода отрисовки растра. Честно говоря у меня вообще ни одной мысли нет как я могу это сделать. Думал что растовая графика работает исключительно с имеющимися уже изображениями. А как создавать изображение ума не приложу. Т.е. насколько я понимаю растовая графика это просто разложение по пикселам изображения. А вот как превратить текст или число в изображение не могу даже представить. Тем более не могу понять зачем нам принт скрин рабочего стола(((( Короче в голове каша полная.. Огромная просьба разъясните что к чему.

Это сообщение отредактировал(а) wallstreet - 27.3.2012, 16:31
PM MAIL   Вверх
GremlinProg
Дата 28.3.2012, 07:23 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(wallstreet @  27.3.2012,  18:29 Найти цитируемый пост)
т.е. фактически делаем PrintScreen экрана?

нет, фактически - "получаем вожжи" для его управления,
но в данном случае нам он нужен только для того, чтобы создать растр, который имеет с ним аналогичные характеристики,
чтобы его можно было отобразить на экране
Цитата(wallstreet @  27.3.2012,  18:29 Найти цитируемый пост)

// насколько я понимаю с помощью этой функции
// создают контекст загруженного изображения, а
// у нас только дескриптор но не могу понять чего.
// hScreenDC ведь не дескриптор контекста изображения
// пока что. Или ошибаюсь?

с помощью этой функции создают контекст изображения, совместимый с заданным, т.е. имеющий с ним совместимый формат
Цитата(wallstreet @  27.3.2012,  18:29 Найти цитируемый пост)

//получаем адрес структуры изображения
// BITMAP. Изображения рабочего стола?

с помощью этой функции создают растр, совместимый с заданным контекстом,
т.е. имеющий с ним совместимый формат,
т.е. растр, который можно выбрать и манипулировать им в аналогичном контексте
Цитата(wallstreet @  27.3.2012,  18:29 Найти цитируемый пост)
По поводу метода отрисовки растра. Честно говоря у меня вообще ни одной мысли нет как я могу это сделать

ты это уже сделал (см. первый пост): цикл с TextOut,
просто вместо hdc нужно указать hMemDC


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
wallstreet
Дата 30.3.2012, 00:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 153
Регистрация: 11.8.2011

Репутация: нет
Всего: нет



Вобщем сделал первый очень сырой вариант без таймера. 
Основная задача для меня была сделать управление и научиться создавать растр. Ну и выводить его на экран когда надо.
Не со всем удалось справиться, далеко не со всем.
Итак вопросы:
1) Не могу понять почему после запуска всех потоков по очереди, в конце третьего не срабатывает InvalidateRect()
Т.е. картинка создается, но не отображается. Стоит хоть чуть чуть изменить размеры окна, как она сразу отрисовывается.
2) Где нужно удалять массив, что бы при увеличении его размера не было выхода за пределы.
Когда в скроллбаре выбираю размерность 10 к примеру, соответственно отрисуется массив 10х10, если после этого
выбираю меньшую размерность все норм, но если большую, то сразу же работа прерывается.
3) массив нормально заполняется размерностью 10х10 если поставить больше, то начинают отображаться символы.
По всей видимости где-то что-то не расчитал с типом данных(((( Так вот если подскажите где, буду признателен очень!


Вот собственно ссылка на файл
сырой проект


Заранее благодарю за помощь в обучении.
PM MAIL   Вверх
GremlinProg
Дата 30.3.2012, 09:28 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



1. возвращаемся в самое начало:
Цитата(feodorv @  12.3.2012,  01:08 Найти цитируемый пост)
В коде этого нет. Потоки Thread1, Thread2 и Thread3 отработают один раз и завершатся.

2. булева переменная x_section лишняя, надо избавиться, главный вопрос: где критическая секция x (CRITICAL_SECTION), и зачем здесь hSemaphoreX, видимо тут уже путаница
3. семафоры, которые ожидают потоки не нужно снова включать из этих же потоков, вызывая для них ReleaseSemaphore, их всегда должно включать что-то внешнее:
 - a включает кнопка (основной поток)
 - y включает поток 1
 - z включает поток 2

ну, раз появилась кнопка, значит здесь a - это тот самый синхронизатор, который включает первый поток a, вместо непонятного hSemaphoreX
(на данном этапе это не так важно из-за первых двух ошибок)
4. Thread1 не перераспределяет память buf, он только создает массив (на данном этапе это не важно из-за первых двух ошибок), вобщем-то напрямую память трогать не обязательно, можно использовать какой-нибудь готовый контейнер, STL, например, std::vector
5. после отрисовки растра в потоке не вижу его обратной выборки из HDC и не вижу удаления HDC, если этого не делать будет утечка GDI-ресурсов и hMemBitmap будет хранить системный растр, а не тот, который рисуешь
6. hMemDC на WM_PAINT нужно создать свой, по той же схеме
7. hMemBitmap в таком случае требует синхронизации доступа из основного и 2-го потоков
8. не надо делать глобальными hScreenDC, hMemDC, hMemBitmap (не стоит), глобальным можно сделать например hMemBitmap, или просто другой HBITMAP, чтобы не делать ошибок на пустом месте
9. соответственно, не видно работы с критической секцией (ну раз ее нет, значит и не видно, но не видно даже попыток снхронизировать доступ к массиву)

Цитата(wallstreet @  30.3.2012,  02:06 Найти цитируемый пост)
Не могу понять почему после запуска всех потоков по очереди, в конце третьего не срабатывает InvalidateRect()

InvalidateRect срабатывает, см. п. 5
Цитата(wallstreet @  30.3.2012,  02:06 Найти цитируемый пост)
Стоит хоть чуть чуть изменить размеры окна, как она сразу отрисовывается.

это будет происходить через раз (с учетом исправления п.1), т.к. в HDC чередуется выборка hMemBitmap, см. п. 5
Цитата(wallstreet @  30.3.2012,  02:06 Найти цитируемый пост)
Где нужно удалять массив, что бы при увеличении его размера не было выхода за пределы

в потоке 1, он же занимается изменением размера массива
Цитата(wallstreet @  30.3.2012,  02:06 Найти цитируемый пост)
если после этого выбираю меньшую размерность все норм, но если большую, то сразу же работа прерывается.

все что после этого, уже не имеет значения, т.к. потоков уже нет, см. п.1
Цитата(wallstreet @  30.3.2012,  02:06 Найти цитируемый пост)
массив нормально заполняется размерностью 10х10 если поставить больше, то начинают отображаться символы.

пока так же не имеет значения, см. п.1


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
wallstreet
Дата 4.4.2012, 00:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 153
Регистрация: 11.8.2011

Репутация: нет
Всего: нет



мое незнание как реализовать ваши советы, завели меня в тупик.((
Но все по порядку:
Цитата

1. возвращаемся в самое начало:

Цитата(feodorv @  12.3.2012,  01:08 )
В коде этого нет. Потоки Thread1, Thread2 и Thread3 отработают один раз и завершатся.

Не могу понять как зациклить все потоки что бы они отрабатывали не один раз? Т.е. по срабатываюнию кнопки я освобождаю семафорХ, потом первый освобождает семафорУ, второй освобождает семафорZ а тот в свою очередь опять освобождает семафорХ или каким-то образом необходимо запускать поток через _beginthreadex()?

2. убрал булева переменную x_section (лепил горбатого к стенке, сам не понимаю зачем) Сейчас все потоки с первого по третий защитил критической секцией, для синхронизированной работы с непосредственной отрисовкой в WM_PAINT, которую тоже защищаю критической секцией. Все остальные потоки будут гарантированно выполняться в нужной последовательности за счет последовательного освобождения семафоров.
Цитата

и зачем здесь hSemaphoreX, видимо тут уже путаница

А как тогда я зациклю потоки что бы они не отображались всего один раз?

3. Те же вопросы с зацикливанием потоков.. Я просто не знаю, как это сделать, не понимаю принцип(.

4. Если делать с вектором то чем тогда займется первый поток ведь он, вектор, должен быть глобальным?

5. Пытаюсь делать так:

Код

hMemBitmap = ::SelectObject(hMemDC, hMemBitmap);
::DeleteDC(hMemDC);


а растр вообще перестает отрисовываться. Кстати советуют удалять дескрптор контекста, который
создавался функцией GetDC(), с помощью ReleaseDC(). Так вот Вы специально выбрали первый вариант (DeleteDC)? Если 
нет, то какой хендл (первый аргумент в ReleaseDC) использовать?

6. Вот что у меня получилось:
Код

case WM_PAINT:
        hScreenDC = ::GetDC(HWND_DESKTOP);
        hMemDC = CreateCompatibleDC(hScreenDC);
        ::ReleaseDC(HWND_DESKTOP, hScreenDC);
        hMemBitmap = ::SelectObject(hMemDC, hMemBitmap);
        hdc = BeginPaint(hWnd, &ps);
        EnterCriticalSection(&cs);
        BitBlt(hdc, 0, 0, cx, cy, hMemDC, 0, 0, NOTSRCCOPY); // Отрисовываем раст
        LeaveCriticalSection(&cs);
        EndPaint(hWnd, &ps);
        break;


Опять же понять не могу, как он отрисует раст, если он тут еще не нарисован?!?!?! Ведь я же удалил дескриптор контекста растра еще в 3м потоке.

7. 
Цитата

hMemBitmap в таком случае требует синхронизации доступа из основного и 2-го потоков

а синхронизировать что конкретно, отрисовку? Т.е. пока создаем растр, не допускать к отрисовке в WM_PAINT?
В данном случае я оградил от отрисовки все потки критической секцией, т.е. отрисовка не начнется пока все не закончат свою работу.

8. Так и поступил, только если сделать hMemBitmap типа BITMAP то будут проблемы вот тут: 
Код

hMemBitmap = ::SelectObject(hMemDC, hMemBitmap);

поэтому она у меня HGDIOBJ типа. 

9. Вроде бы сейчас попытался  smile  


Сори, что так много вопросов, наверняка со многими из них я бы разобрался за ближайшие лет пять.
Так, что спасибо за очередную попытку завести мой мозг с толкача smile 

Ссылка на проект

Это сообщение отредактировал(а) wallstreet - 4.4.2012, 00:18
PM MAIL   Вверх
GremlinProg
Дата 4.4.2012, 07:11 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(wallstreet @  4.4.2012,  02:09 Найти цитируемый пост)
Не могу понять как зациклить все потоки что бы они отрабатывали не один раз?

надо просто завести в потоках цикл (пусть он пока будет бесконечный):
Код

unsigned _stdcall Thread1(void *param){
  for( ; ; ){
    ::WaitForSingleObject( ... );
    ...
  }
}

потом можно будет его ограничить глобальным событием hAbort, чтобы по его включении все потоки спокойно завершали свою работу
Цитата(wallstreet @  4.4.2012,  02:09 Найти цитируемый пост)
в WM_PAINT, которую тоже защищаю критической секцией

если это та же секция, то получится, что:
1. либо любая отрисовка окна будет блокировать потоки, которые используют массив
2. либо любой поток, который уже начал обработку массива, будет блокировать отрисовку окна, пока не завершит работу, т.е. приложение будет на это время тупо висеть (ты потом сам это увидишь, когда будешь задавать большие размерности массива)

пока я бы не рекомендовал защищать WM_PAINT, это пока не такая страшная ошибка

Цитата(wallstreet @  4.4.2012,  02:09 Найти цитируемый пост)
А как тогда я зациклю потоки что бы они не отображались всего один раз?

циклом во всех потоках(см. выше)
Цитата(wallstreet @  4.4.2012,  02:09 Найти цитируемый пост)
Если делать с вектором то чем тогда займется первый поток ведь он, вектор, должен быть глобальным?

пусть вектор будет глобальным, в чем проблема?
Цитата(wallstreet @  4.4.2012,  02:09 Найти цитируемый пост)
а растр вообще перестает отрисовываться.

в старом коде ты использовал в WM_PAINT HDC, созданный в потоке, поэтому растр и не рисуется,
в WM_PAINT нужно создать свой HDC и выбрать в него битмап (в 6 почти все правильно, только ты забыл обратно выбрать растр и освободить контекст, т.е. тут сохраняется ошибка п.5)

Цитата(wallstreet @  4.4.2012,  02:09 Найти цитируемый пост)
Кстати советуют удалять дескрптор контекста, которыйсоздавался функцией GetDC(), с помощью ReleaseDC()

конечно
Цитата(wallstreet @  4.4.2012,  02:09 Найти цитируемый пост)
Так вот Вы специально выбрали первый вариант (DeleteDC)? Если нет, то какой хендл (первый аргумент в ReleaseDC) использовать?

не понял  smile 
у меня для GetDC вызывается ReleaseDC, и в первом параметре тот же дескриптор, что и в первом параметре GetDC, т.е. HWND_DESKTOP или NULL, т.е. - "экран",
DeleteDC вызывается только для CreateCompatibleDC
Цитата(wallstreet @  4.4.2012,  02:09 Найти цитируемый пост)
Опять же понять не могу, как он отрисует раст, если он тут еще не нарисован?!?!?! Ведь я же удалил дескриптор контекста растра еще в 3м потоке.

путаешь,
ты удалил не растр, а контекст hMemDC, это разные вещи,
растр находится в hMemBitmap

по хорошему, как я уже говорил, следует синхронизировать обращение к hMemBitmap (но другим синхронизатором),
у тебя в этом плане тут 2 ошибки:
1. синхронизируется только вызов BitBlt, хотя 3-й поток может изменить растр еще на этапе SelectObject
2. в 3-м потоке используется та же переменная, что и в основном, на WM_PAINT - это hMemBitmap (да, в 8 ты об этом правильно подметил), т.е. это означает, что пока 3-й поток рисует массив, доступ к этой переменной должен быть блокирован, поэтому я и рекомендую вместо глобальной hMemBitmap использовать какую-нить другую, например: hMemSharedBitmap, в которую 3-й поток, после завершения отрисовки массива, будет копировать hMemBitmap, и которую будет использовать основной поток в WM_PAINT, вот доступ к этой переменной и надо синхронизировать

ну, и теперь, когда ты зациклишь все потоки, потребуется удалять hMemSharedBitmap, перед очередным ее обновлением в 3-м потоке, чтобы не было утечки GDI-ресурсов, для этого нужно вначале инициироввать ее в значение NULL, и перед любой модификацией проверить на NULL и удалить, в случае, если она не NULL с помощью функции DeleteObject

p.s.: неблагодарное это дело, пальцев не хватит, проще написать код,
feodorv, не желаешь присоединиться?
ты же можешь, я знаю  smile 


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
wallstreet
Дата 4.4.2012, 16:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 153
Регистрация: 11.8.2011

Репутация: нет
Всего: нет



Делаю вот так:
Поток3
Код

HGDIOBJ hMemSharedBitmap;
unsigned _stdcall Thread3(void *param)
{
    HDC hScreenDC, hMemDC;
    HGDIOBJ hMemBitmap;
    int x = 0;
    int y = 0;
    hMemSharedBitmap = NULL;

    while(!done)
    {
        WaitForSingleObject(hSemaphoreZ, INFINITE);
        if(done)
            break;
        hScreenDC = ::GetDC(HWND_DESKTOP);                              // Получаем указатель на контекст рабочего стола
        hMemDC = CreateCompatibleDC(hScreenDC);                         // Создаем в памяти контекст устройства совместимый с hScreenDC
        hMemBitmap = CreateCompatibleBitmap(hScreenDC, cx, cy);         // Инициализируем битовый образ делая его совместимым с hScreenDC
        ::ReleaseDC(HWND_DESKTOP, hScreenDC);                           // Удаляем контекст hScreenDC
        hMemBitmap = ::SelectObject(hMemDC, hMemBitmap);                // Выбираем объект для контекста hMemDC
    
        // Рисуем растр
        for(int count_row=0; count_row<::scrlh; count_row++)
        {
            for(int count_column=0; count_column<::scrlh; count_column++)
            {
                y=count_row*30;
                x=count_column*30;
                _itot(buf[count_row][count_column], str, ::scrlh);
                TextOut(hMemDC, x, y, str, _tcslen(str));
            }
        }
        if(hMemSharedBitmap=NULL)                                        
        {
            hMemSharedBitmap = CreateCompatibleBitmap(hMemDC, cx, cy);   // Инициализируем битовый образ делая его совместимым с hMemDC
        }
        else 
        {
            DeleteObject(hMemSharedBitmap);
        }
        InvalidateRect((HWND)param, FALSE, TRUE);                        // Перерисовываем окно
        LeaveCriticalSection(&cs);                                       // Освобождаем критическую секцию
        ::DeleteDC(hMemDC);                                              // Удаляем дескриптор контекста
    }
    return 0;
}


Отрисовка данных:
Код

case WM_PAINT:
        hScreenDC = ::GetDC(HWND_DESKTOP);                              // Получаем указатель на контекст рабочего стола
        hMemDC = CreateCompatibleDC(hScreenDC);                         // Создаем в памяти контекст устройства совместимый с hScreenDC
        ::ReleaseDC(HWND_DESKTOP, hScreenDC);                           // Удаляем контекст hScreenDC
        hMemSharedBitmap = ::SelectObject(hMemDC, hMemSharedBitmap);    // Выбираем объект для контекста hMemDC
     
        hdc = BeginPaint(hWnd, &ps);
        EnterCriticalSection(&cs);
        BitBlt(hdc, 0, 0, cx, cy, hMemDC, 0, 0, NOTSRCCOPY);             // Отрисовываем раст
        LeaveCriticalSection(&cs);
        EndPaint(hWnd, &ps);

        ::DeleteDC(hMemDC);                                              // Удаляем контекст hMemDC
        break;


Где в части создания и отрисовки растра я допускаю ошибку?

Проект

Это сообщение отредактировал(а) wallstreet - 4.4.2012, 16:16
PM MAIL   Вверх
GremlinProg
Дата 5.4.2012, 06:51 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



установка и использование hMemSharedBitmap неправильная,
не надо для нее создавать растр (CreateCompatibleBitmap),
ей надо просто присвоить значение hMemBitmap:
Цитата(wallstreet @ 4.4.2012,  18:00)

HGDIOBJ hMemSharedBitmap;
unsigned _stdcall Thread3(void *param)
{
    HDC hScreenDC, hMemDC;
    HGDIOBJ hMemBitmap;
    int x = 0;
    int y = 0;
    hMemSharedBitmap = NULL;

    while(!done)
    {
        WaitForSingleObject(hSemaphoreZ, INFINITE);
        if(done)
            break;
        hScreenDC = ::GetDC(HWND_DESKTOP);                              // Получаем указатель на контекст рабочего стола
        hMemDC = CreateCompatibleDC(hScreenDC);                         // Создаем в памяти контекст устройства совместимый с hScreenDC
        hMemBitmap = CreateCompatibleBitmap(hScreenDC, cx, cy);         // Инициализируем битовый образ делая его совместимым с hScreenDC
        ::ReleaseDC(HWND_DESKTOP, hScreenDC);                           // Удаляем контекст hScreenDC
        hMemBitmap = ::SelectObject(hMemDC, hMemBitmap);                // Выбираем объект для контекста hMemDC
    
        // Рисуем растр
        Enter( x );
        for(int count_row=0; count_row<::scrlh; count_row++)
        {
            for(int count_column=0; count_column<::scrlh; count_column++)
            {
                y=count_row*30;
                x=count_column*30;
                _itot(buf[count_row][count_column], str, ::scrlh);
                TextOut(hMemDC, x, y, str, _tcslen(str));
            }
        }
        Leave( x );
        hMemBitmap = ::SelectObject(hMemDC, hMemBitmap);                // Выбираем растр обратно из hMemDC!!!!!!!!!!

        ::DeleteDC(hMemDC);                                              // Удаляем дескриптор контекста
        if(hMemSharedBitmap=NULL)                                        
        {
            hMemSharedBitmap = CreateCompatibleBitmap(hMemDC, cx, cy);   // Инициализируем битовый образ делая его совместимым с hMemDC
        }
        else 
        {
            DeleteObject(hMemSharedBitmap);
        }
        LeaveCriticalSection(&cs);                                       // Освобождаем критическую секцию

        Enter( shared );
        if( hMemSharedBitmap ){
            ::DeleteObject( hMemSharedBitmap );
        }
        hMemSharedBitmap = hMemBitmap;
        Leave( shared );

        InvalidateRect((HWND)param, FALSE, TRUE);                        // Перерисовываем окно
    }
    return 0;
}

Цитата(wallstreet @ 4.4.2012,  18:00)

case WM_PAINT:
        hScreenDC = ::GetDC(HWND_DESKTOP);                              // Получаем указатель на контекст рабочего стола
        hMemDC = CreateCompatibleDC(hScreenDC);                         // Создаем в памяти контекст устройства совместимый с hScreenDC
        ::ReleaseDC(HWND_DESKTOP, hScreenDC);                           // Удаляем контекст hScreenDC
        Enter( shared );
        hMemSharedBitmap = ::SelectObject(hMemDC, hMemSharedBitmap);    // Выбираем объект для контекста hMemDC
     
        hdc = BeginPaint(hWnd, &ps);
        EnterCriticalSection(&cs);
        BitBlt(hdc, 0, 0, cx, cy, hMemDC, 0, 0, NOTSRCCOPY);             // Отрисовываем раст
        LeaveCriticalSection(&cs);
        EndPaint(hWnd, &ps);
        hMemSharedBitmap = ::SelectObject(hMemDC, hMemSharedBitmap);    // Выбираем растр обратно из hMemDC!!!!!!!!!!!!!!!!!!!!!
        Leave( shared );

        ::DeleteDC(hMemDC);                                              // Удаляем контекст hMemDC
        break;

Enter и Leave здесь, соответственно, вход и выход из эксклюзивного участка кода,
x и shared - сами синхронизаторы: x - защищает модификацию и чтение массива, а shared защишает доступ к переменной hMemSharedBitmap


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
feodorv
Дата 5.4.2012, 11:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 9
Всего: 45



Цитата(GremlinProg @  4.4.2012,  08:11 Найти цитируемый пост)
feodorv, не желаешь присоединиться?

Прошу прощения, что ушёл с сумрак, дела зовут...

GremlinProg
Правки супер! То, что надо)))

Только два момента, замеченных при беглом просмотре:
1/ что такое cx и cy в Thread3 и в WM_PAINT? Как я понимаю, в Thread3 мы должны высчитывать размер битмапа исходя из начальных данных (то есть buf[count_row][count_column] должен порождать cx и cy путём подсчёта места, необходимого под TextOut... Если же сx и cy высчитывать исходя из размера окна, то при ресайзе этого самого окна могут возникнуть неприятные артефакты.
2/ рисовать стОит только тогда, когда hMemSharedBitmap не NULL.


wallstreet
Очень прошу обратить внимание на
Цитата(GremlinProg @  5.4.2012,  07:51 Найти цитируемый пост)
x и shared - сами синхронизаторы: x - защищает модификацию и чтение массива, а shared защишает доступ к переменной hMemSharedBitmap 

То есть нужны 2 критические секции, а не одна: x - синхронизирует доступ к buf в Thread1, Thread2, Thread3, а shared - к hMemSharedBitmap в Thread3 и WM_PAINT основного потока.

Ну и опять же, хочется весь проект с правками...


Это сообщение отредактировал(а) feodorv - 5.4.2012, 11:17


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
wallstreet
Дата 6.4.2012, 13:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 153
Регистрация: 11.8.2011

Репутация: нет
Всего: нет



Всем доброго дня.
Благодарю за разъяснения, теперь ясно как никогда.
Подровнял я проект под ваши советы, даже вектор прикрутил. Но следуя сложившейся традиции
где-то что-то напортачил и матрица отображается криво. А точнее одна ее строка только ито не с самого начала.
Что касается:
Цитата

1/ что такое cx и cy в Thread3 и в WM_PAINT? Как я понимаю, в Thread3 мы должны высчитывать размер битмапа исходя из начальных данных (то есть buf[count_row][count_column] должен порождать cx и cy путём подсчёта места, необходимого под TextOut...

я инициализировал переменные ширины и высоты битмапа значением выбраным пользователем в скроллбаре
умноженным на 30 (ширина между цифрами в битмапе в пикселях) при нажатии кнопки "ОК".
Выглядело это вот так:
Код

::cx = scrlh * 30;
::cy = scrlh * 30;

но можно задать высоту и ширину во втором потоке, сразу после заполнения матрицы значениями.
вот так:
Код

::cx = vv.size() * 30;
::cy = vv.size() * 30;



Благодарю за участие, 
вот, собственно, ссылка для скачивания проекта: Ссылка на проект

Это сообщение отредактировал(а) wallstreet - 6.4.2012, 18:30
PM MAIL   Вверх
feodorv
Дата 8.4.2012, 17:48 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 9
Всего: 45



Цитата(wallstreet @  6.4.2012,  14:50 Найти цитируемый пост)
вот, собственно, ссылка для скачивания проекта

Посмотрел код одним глазом и... ужаснулся(((
Как же можно допускать такое нагромождение операторов, переменных...

Цитата(wallstreet @  6.4.2012,  14:50 Найти цитируемый пост)
одна ее строка только ито не с самого начала.

Про начало не знаю, но то, что одна строка:
Код

        // Рисуем растр
        int count_row = 0;
        int count_column = 0;
        for(itVv=vv.begin(); itVv!=vv.end(); itVv++, count_row++)
        {
            for(itV=itVv->begin(); itV!=itVv->end(); itV++, count_column++)
            {
                y=count_row*30;
                x=count_column*30;
                _itot(*itV, str, vv.size());
                TextOut(hMemDC, x, y, str, _tcslen(str));
            }
        }

Ну как минимум count_column во втором форе нужно переинициализировать в 0. Вообще, все векторные прибомбасы стоило отложить на самый конец, имхо.
Как максимум нужно разобраться с итераторами (что выводит TextOut?).

По замечаниям:

1/ мы с GremlinProg договорились не использовать грязных трюков с захватом критической секции в одном потоке и освобождением в другом. Надо исправить smile 

2/ откуда взялась и что защищает критическая секция csX?

3/ cx и cy - есть характеристики битмапа hMemSharedBitmap. Менять их нужно только в тот момент, в который изменяется значение hMemSharedBitmap, а не в любой произвольный момент. Переменные hMemSharedBitmap, cx, cy защищаются критической секцией csShared.
Соответственно, ::scrlh - есть характеристика вектора (в прошлом - буфера), менять значение этой переменной стоит тогда, когда мы изменяем размер вектора (или буфера). Вектор и ::scrlh защищаются критической секцией cs.

4/ Что делает этот код:
Код

unsigned _stdcall Thread3(void *param)
{
 ...
    [color=red]hMemSharedBitmap = NULL;[/color]
...
}

???

5/ таймер больше не используется?

6/ какое отношение имеет инициализация семафоров и запуск потоков к Dialog1??? Что будет, если Dialog1 вызвать более одного раза? Сколько будет потоков? Сколько семафоров? Зачем InvalidateRect(hDlg, FALSE, TRUE); в Dialog1() при WM_COMMAND IDOK?

7/ зачем нам теперь глобальные переменные 
Код

TCHAR str[10];
int **buf;
int x, y,
HGDIOBJ hMemBitmap;


8/ зачем семафоры, когда хорошо жили при событиях?

Чего-то я ещё заметил, но уже забыл....

Это сообщение отредактировал(а) feodorv - 8.4.2012, 18:16


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Страницы: (4) Все 1 [2] 3 4 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0737 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.