![]() |
|
Модераторы: feodorv, GremlinProg, xvr, Fixin |
![]()
|
|
| GremlinProg |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: 99 Всего: 106 |
если я правильно понимаю: emf, wmf? подойдет, конечно, только пользы от него конкретно в данной задаче будет 0, поскольку отрисовка такого файла будет идти не в потоке, а все в том же WM_PAINT (в потоке будет просто сформирован набор команд) лучше всего подойдет простой растр -------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
|||
|
||||
| feodorv |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 9 Всего: 45 |
План не обширный, а всего лишь подробный))) А фиг его знает, для чего эти законы, но если они действуют, то приходится с ними считаться)))) Потому и олинклюзив))) Ок! Плохо, что автор темы пропал куда-то... -------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
|||
|
||||
| wallstreet |
|
||||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 153 Регистрация: 11.8.2011 Репутация: нет Всего: нет |
Честно признаться не знаю как сформировать мой массив в виде растового изображения. Поэтому без вашей помощи буду месяц разбираться((
ну почему же пропал, просто времени мало в последнее время на самообучение((( а так процесс идет!! ;) Это сообщение отредактировал(а) wallstreet - 22.3.2012, 13:11 |
||||
|
|||||
| GremlinProg |
|
||||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: 99 Всего: 106 |
Width, Height - размерв растра PaintArray - метод отрисовки растра hMemBitmap - сам растр p.s.:код писал в браузере, контроль ошибок не вел -------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
||||
|
|||||
| wallstreet |
|
||||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 153 Регистрация: 11.8.2011 Репутация: нет Всего: нет |
Благодарю за ответ, но вопросов появилось еще больше((
Правильно ли я понимаю, что:
т.е. фактически делаем PrintScreen экрана?
По поводу метода отрисовки растра. Честно говоря у меня вообще ни одной мысли нет как я могу это сделать. Думал что растовая графика работает исключительно с имеющимися уже изображениями. А как создавать изображение ума не приложу. Т.е. насколько я понимаю растовая графика это просто разложение по пикселам изображения. А вот как превратить текст или число в изображение не могу даже представить. Тем более не могу понять зачем нам принт скрин рабочего стола(((( Короче в голове каша полная.. Огромная просьба разъясните что к чему. Это сообщение отредактировал(а) wallstreet - 27.3.2012, 16:31 |
||||
|
|||||
| GremlinProg |
|
||||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: 99 Всего: 106 |
нет, фактически - "получаем вожжи" для его управления, но в данном случае нам он нужен только для того, чтобы создать растр, который имеет с ним аналогичные характеристики, чтобы его можно было отобразить на экране с помощью этой функции создают контекст изображения, совместимый с заданным, т.е. имеющий с ним совместимый формат
с помощью этой функции создают растр, совместимый с заданным контекстом, т.е. имеющий с ним совместимый формат, т.е. растр, который можно выбрать и манипулировать им в аналогичном контексте
ты это уже сделал (см. первый пост): цикл с TextOut, просто вместо hdc нужно указать hMemDC -------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
||||
|
|||||
| wallstreet |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 153 Регистрация: 11.8.2011 Репутация: нет Всего: нет |
Вобщем сделал первый очень сырой вариант без таймера.
Основная задача для меня была сделать управление и научиться создавать растр. Ну и выводить его на экран когда надо. Не со всем удалось справиться, далеко не со всем. Итак вопросы: 1) Не могу понять почему после запуска всех потоков по очереди, в конце третьего не срабатывает InvalidateRect() Т.е. картинка создается, но не отображается. Стоит хоть чуть чуть изменить размеры окна, как она сразу отрисовывается. 2) Где нужно удалять массив, что бы при увеличении его размера не было выхода за пределы. Когда в скроллбаре выбираю размерность 10 к примеру, соответственно отрисуется массив 10х10, если после этого выбираю меньшую размерность все норм, но если большую, то сразу же работа прерывается. 3) массив нормально заполняется размерностью 10х10 если поставить больше, то начинают отображаться символы. По всей видимости где-то что-то не расчитал с типом данных(((( Так вот если подскажите где, буду признателен очень! Вот собственно ссылка на файл сырой проект Заранее благодарю за помощь в обучении. |
|||
|
||||
| GremlinProg |
|
||||||||||||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: 99 Всего: 106 |
1. возвращаемся в самое начало:
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. соответственно, не видно работы с критической секцией (ну раз ее нет, значит и не видно, но не видно даже попыток снхронизировать доступ к массиву)
InvalidateRect срабатывает, см. п. 5
это будет происходить через раз (с учетом исправления п.1), т.к. в HDC чередуется выборка hMemBitmap, см. п. 5
в потоке 1, он же занимается изменением размера массива
все что после этого, уже не имеет значения, т.к. потоков уже нет, см. п.1
пока так же не имеет значения, см. п.1 -------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
||||||||||||
|
|||||||||||||
| wallstreet |
|
||||||||||||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 153 Регистрация: 11.8.2011 Репутация: нет Всего: нет |
мое незнание как реализовать ваши советы, завели меня в тупик.((
Но все по порядку:
Не могу понять как зациклить все потоки что бы они отрабатывали не один раз? Т.е. по срабатываюнию кнопки я освобождаю семафорХ, потом первый освобождает семафорУ, второй освобождает семафорZ а тот в свою очередь опять освобождает семафорХ или каким-то образом необходимо запускать поток через _beginthreadex()? 2. убрал булева переменную x_section (лепил горбатого к стенке, сам не понимаю зачем) Сейчас все потоки с первого по третий защитил критической секцией, для синхронизированной работы с непосредственной отрисовкой в WM_PAINT, которую тоже защищаю критической секцией. Все остальные потоки будут гарантированно выполняться в нужной последовательности за счет последовательного освобождения семафоров.
А как тогда я зациклю потоки что бы они не отображались всего один раз? 3. Те же вопросы с зацикливанием потоков.. Я просто не знаю, как это сделать, не понимаю принцип(. 4. Если делать с вектором то чем тогда займется первый поток ведь он, вектор, должен быть глобальным? 5. Пытаюсь делать так:
а растр вообще перестает отрисовываться. Кстати советуют удалять дескрптор контекста, который создавался функцией GetDC(), с помощью ReleaseDC(). Так вот Вы специально выбрали первый вариант (DeleteDC)? Если нет, то какой хендл (первый аргумент в ReleaseDC) использовать? 6. Вот что у меня получилось:
Опять же понять не могу, как он отрисует раст, если он тут еще не нарисован?!?!?! Ведь я же удалил дескриптор контекста растра еще в 3м потоке. 7.
а синхронизировать что конкретно, отрисовку? Т.е. пока создаем растр, не допускать к отрисовке в WM_PAINT? В данном случае я оградил от отрисовки все потки критической секцией, т.е. отрисовка не начнется пока все не закончат свою работу. 8. Так и поступил, только если сделать hMemBitmap типа BITMAP то будут проблемы вот тут:
поэтому она у меня HGDIOBJ типа. 9. Вроде бы сейчас попытался Сори, что так много вопросов, наверняка со многими из них я бы разобрался за ближайшие лет пять. Так, что спасибо за очередную попытку завести мой мозг с толкача Ссылка на проект Это сообщение отредактировал(а) wallstreet - 4.4.2012, 00:18 |
||||||||||||
|
|||||||||||||
| GremlinProg |
|
||||||||||||||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: 99 Всего: 106 |
надо просто завести в потоках цикл (пусть он пока будет бесконечный):
потом можно будет его ограничить глобальным событием hAbort, чтобы по его включении все потоки спокойно завершали свою работу если это та же секция, то получится, что: 1. либо любая отрисовка окна будет блокировать потоки, которые используют массив 2. либо любой поток, который уже начал обработку массива, будет блокировать отрисовку окна, пока не завершит работу, т.е. приложение будет на это время тупо висеть (ты потом сам это увидишь, когда будешь задавать большие размерности массива) пока я бы не рекомендовал защищать WM_PAINT, это пока не такая страшная ошибка
циклом во всех потоках(см. выше)
пусть вектор будет глобальным, в чем проблема? в старом коде ты использовал в WM_PAINT HDC, созданный в потоке, поэтому растр и не рисуется, в WM_PAINT нужно создать свой HDC и выбрать в него битмап (в 6 почти все правильно, только ты забыл обратно выбрать растр и освободить контекст, т.е. тут сохраняется ошибка п.5)
конечно
не понял у меня для GetDC вызывается ReleaseDC, и в первом параметре тот же дескриптор, что и в первом параметре GetDC, т.е. HWND_DESKTOP или NULL, т.е. - "экран", DeleteDC вызывается только для CreateCompatibleDC
путаешь, ты удалил не растр, а контекст 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, не желаешь присоединиться? ты же можешь, я знаю -------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
||||||||||||||
|
|||||||||||||||
| wallstreet |
|
||||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 153 Регистрация: 11.8.2011 Репутация: нет Всего: нет |
Делаю вот так:
Поток3
Отрисовка данных:
Где в части создания и отрисовки растра я допускаю ошибку? Проект Это сообщение отредактировал(а) wallstreet - 4.4.2012, 16:16 |
||||
|
|||||
| GremlinProg |
|
||||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: 99 Всего: 106 |
установка и использование hMemSharedBitmap неправильная,
не надо для нее создавать растр (CreateCompatibleBitmap), ей надо просто присвоить значение hMemBitmap:
Enter и Leave здесь, соответственно, вход и выход из эксклюзивного участка кода, x и shared - сами синхронизаторы: x - защищает модификацию и чтение массива, а shared защишает доступ к переменной hMemSharedBitmap -------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
||||
|
|||||
| feodorv |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 9 Всего: 45 |
Прошу прощения, что ушёл с сумрак, дела зовут... GremlinProg Правки супер! То, что надо))) Только два момента, замеченных при беглом просмотре: 1/ что такое cx и cy в Thread3 и в WM_PAINT? Как я понимаю, в Thread3 мы должны высчитывать размер битмапа исходя из начальных данных (то есть buf[count_row][count_column] должен порождать cx и cy путём подсчёта места, необходимого под TextOut... Если же сx и cy высчитывать исходя из размера окна, то при ресайзе этого самого окна могут возникнуть неприятные артефакты. 2/ рисовать стОит только тогда, когда hMemSharedBitmap не NULL. wallstreet Очень прошу обратить внимание на
То есть нужны 2 критические секции, а не одна: x - синхронизирует доступ к buf в Thread1, Thread2, Thread3, а shared - к hMemSharedBitmap в Thread3 и WM_PAINT основного потока. Ну и опять же, хочется весь проект с правками... Это сообщение отредактировал(а) feodorv - 5.4.2012, 11:17 -------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
|||
|
||||
| wallstreet |
|
||||||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 153 Регистрация: 11.8.2011 Репутация: нет Всего: нет |
Всем доброго дня.
Благодарю за разъяснения, теперь ясно как никогда. Подровнял я проект под ваши советы, даже вектор прикрутил. Но следуя сложившейся традиции где-то что-то напортачил и матрица отображается криво. А точнее одна ее строка только ито не с самого начала. Что касается:
я инициализировал переменные ширины и высоты битмапа значением выбраным пользователем в скроллбаре умноженным на 30 (ширина между цифрами в битмапе в пикселях) при нажатии кнопки "ОК". Выглядело это вот так:
но можно задать высоту и ширину во втором потоке, сразу после заполнения матрицы значениями. вот так:
Благодарю за участие, вот, собственно, ссылка для скачивания проекта: Ссылка на проект Это сообщение отредактировал(а) wallstreet - 6.4.2012, 18:30 |
||||||
|
|||||||
| feodorv |
|
||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 9 Всего: 45 |
Посмотрел код одним глазом и... ужаснулся((( Как же можно допускать такое нагромождение операторов, переменных... Про начало не знаю, но то, что одна строка:
Ну как минимум count_column во втором форе нужно переинициализировать в 0. Вообще, все векторные прибомбасы стоило отложить на самый конец, имхо. Как максимум нужно разобраться с итераторами (что выводит TextOut?). По замечаниям: 1/ мы с GremlinProg договорились не использовать грязных трюков с захватом критической секции в одном потоке и освобождением в другом. Надо исправить 2/ откуда взялась и что защищает критическая секция csX? 3/ cx и cy - есть характеристики битмапа hMemSharedBitmap. Менять их нужно только в тот момент, в который изменяется значение hMemSharedBitmap, а не в любой произвольный момент. Переменные hMemSharedBitmap, cx, cy защищаются критической секцией csShared. Соответственно, ::scrlh - есть характеристика вектора (в прошлом - буфера), менять значение этой переменной стоит тогда, когда мы изменяем размер вектора (или буфера). Вектор и ::scrlh защищаются критической секцией cs. 4/ Что делает этот код:
??? 5/ таймер больше не используется? 6/ какое отношение имеет инициализация семафоров и запуск потоков к Dialog1??? Что будет, если Dialog1 вызвать более одного раза? Сколько будет потоков? Сколько семафоров? Зачем InvalidateRect(hDlg, FALSE, TRUE); в Dialog1() при WM_COMMAND IDOK? 7/ зачем нам теперь глобальные переменные
8/ зачем семафоры, когда хорошо жили при событиях? Чего-то я ещё заметил, но уже забыл.... Это сообщение отредактировал(а) feodorv - 8.4.2012, 18:16 -------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
||||||
|
|||||||
![]()
|
| Правила форума "C/C++: Системное программирование и WinAPI" | |
|
|
На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы . Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |