Форум программистов, компьютерный форум, киберфорум
Visual C++
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.71/7: Рейтинг темы: голосов - 7, средняя оценка - 4.71
2 / 2 / 0
Регистрация: 30.01.2013
Сообщений: 36
1

Передача в поток указателя на контекст устройства

14.11.2013, 17:28. Просмотров 1309. Ответов 14
Метки нет (Все метки)


Здравствуйте!
С потоками раньше дела не имел вовсе, но случилась необходимость освоить.
Нужно передать в поток указатель на контекст устройства.

C++
1
2
CMyPaintDC dc(this);//получили указатель
AfxBeginThread(proc1, &dc);//передали
В потоке получили:
C++
1
2
3
4
5
UINT CMainWnd::proc1(LPVOID pParam)
{
    CDC *xdc = (CDC*)pParam;
...
}
Но так, естественно, не работает, а я не знаю, как.
Пытался сделать с reinterpret_cast, получается какой-то бред.
Помогите плз, как его [указатель] передать, а потом правильно получить, чтоб можно было рисовать...

Добавлено через 11 часов 33 минуты
Неужели это невозможно?
Или, поставим вопрос по-другому - можно ли рисовать в потоке, а не в основной программе?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
14.11.2013, 17:28
Ответы с готовыми решениями:

Вывод целого в контекст устройства
Вот как вывести целое? Вот, например, для вывода текста служит функция pDC->TextOutW(10,10,t); ...

Как сделать прозрачный контекст устройства??
Рисую кругpDC->Ellipse(...);но никак не могу сделать этот круг прозрачным...Может какие-то флаги...

Как получить контекст устройства Bitmap?
Всем здравствуйте. Хочу рисовать на Bitmap средствами API. От Bitmap переходим к объекту...

Как обрезать картинку выбраную в контекст устройства?
Приветствую. Разбираюсь с GDI. Возник вопрос. Подскажите, как обрезать картинку выбраную в контекст...

__________________
Помогаю в написании студенческих работ здесь.
Записывайтесь на профессиональные курсы C++ разработчиков
14
Заблокирован
14.11.2013, 17:51 2
Цитата Сообщение от SwanSONG Посмотреть сообщение
AfxBeginThread(proc1, &dc);
ну попробуй тут dc к LPVOID привести перед во время передачи. Пробей дебагером, что отсылаешь и что принимаешь - hex в студию
0
2 / 2 / 0
Регистрация: 30.01.2013
Сообщений: 36
14.11.2013, 17:55  [ТС] 3
Немного не понял,привести к LPVOID ДО(!) инициализации потока?
0
Заблокирован
14.11.2013, 17:58 4
AfxBeginThread(proc1, (LPVOID)dc); или как то так

Потом, ты уверен, что поток, откуда ты передаешь свой dc не завершается до того момента, как ты это принимаешь в другом? Если так - то указатель у тебя становится не валидным

Добавлено через 1 минуту
Цитата Сообщение от SwanSONG Посмотреть сообщение
CMyPaintDC dc(this);//получили указатель
AfxBeginThread(proc1, &dc);//передали
вот после этого, ты должен ждать, пока рисуешь поток получит dc и всё отрисует. Потом продолжаешь игру
0
2 / 2 / 0
Регистрация: 30.01.2013
Сообщений: 36
14.11.2013, 18:02  [ТС] 5
C++
1
2
LPVOID *lPtr=reinterpret_cast<LPVOID*>(&dc);
AfxBeginThread(proc1, lPtr);
Так?

Добавлено через 1 минуту
Цитата Сообщение от newbie666 Посмотреть сообщение
Потом, ты уверен, что поток, откуда ты передаешь свой dc не завершается до того момента, как ты это принимаешь в другом?
Да, уверен, потому как передается из основного блока

Добавлено через 1 минуту
Идея состоит в том, чтобы второй поток занимался рисованием сам, в то время, как основная программа занималась своими делами
0
Заблокирован
14.11.2013, 18:03 6
Цитата Сообщение от SwanSONG Посмотреть сообщение
AfxBeginThread(proc1, &dc)
да вот так:
C++
1
AfxBeginThread(proc1, (LPVOID)&dc)
я
Цитата Сообщение от SwanSONG Посмотреть сообщение
Да, уверен, потому как передается из основного блока
это ни о чём не говорит - приведи код, откуда в основном потоке ты вызываешь это, небойсь из оконной процедуры из сообщения WM_PAINT?
0
2 / 2 / 0
Регистрация: 30.01.2013
Сообщений: 36
14.11.2013, 18:14  [ТС] 7
Пример "тестовый"
CMainWnd.h:
Кликните здесь для просмотра всего текста
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
#pragma once
#include "process.h"
 
class CMainWnd:public CFrameWnd
{
public:
    CMainWnd(void);
    ~CMainWnd(void);
 
    void MakeInterface();
 
    //static UINT proc1(LPVOID Param);
    static UINT proc1(LPVOID Param);
 
    CDC *xdc;
 
    afx_msg void OnPaint();
    
private:
    DECLARE_MESSAGE_MAP();
 
    CButton *MyButton1,*MyButton2;
 
protected:
    //afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
};


CMainWnd.cpp:
Кликните здесь для просмотра всего текста
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
//include
#include "afxwin.h"
#include "process.h"
 
#include "CMainWnd.h"
#include "CMyPaintDC.h"
#include "XConst.h"
 
//define
#define bStart 100
#define bFinish 101
 
CMainWnd::CMainWnd(void)
{
    Create(NULL,_T("Справочник"),WS_OVERLAPPEDWINDOW,rectDefault,NULL,NULL);
    CMainWnd::SetWindowPos(&wndTop,50,50,1050,850,SWP_SHOWWINDOW);
    MakeInterface();
}
 
CMainWnd::~CMainWnd(void)
{
}
 
BEGIN_MESSAGE_MAP(CMainWnd, CFrameWnd)
    ON_WM_PAINT()
    ON_WM_KEYDOWN()
END_MESSAGE_MAP()
 
 
 
void CMainWnd::OnPaint()
{
    //CMyPaintDC dc(this);
    CPaintDC dc(this);
 
    dc.MoveTo(0,0);
    dc.LineTo(100,100);
 
    
    srand(time(NULL));
 
    LPVOID *lPtr=reinterpret_cast<LPVOID*>(&dc);
 
    //AfxBeginThread(proc1, &dc);
    AfxBeginThread(proc1, lPtr);
    
 
    /*
    Derived1  derived1;
    Unrelated*  pUnrelated = reinterpret_cast<Unrelated*>(&derived1);
    */
 
 
 
 
}
 
UINT CMainWnd::proc1(LPVOID pParam)
{
    while(1)
    {
        x1=rand()%50;
        y1=rand()%50;
        x2=rand()%850;
        y2=rand()%550;
        
//      xdc->MoveTo(0,0);
        
        
        
        
 
        
        Sleep(1);
    }
}
 
void CMainWnd::MakeInterface()
{
    MyButton1 = new CButton();
    if (MyButton1!=NULL)
        MyButton1->Create(_T("Start"),WS_CHILD|WS_VISIBLE|SS_CENTER,CRect(10,10,110,60),this,bStart);
    MyButton2 = new CButton();
    if (MyButton2!=NULL)
        MyButton2->Create(_T("Finish"),WS_CHILD|WS_VISIBLE|SS_CENTER,CRect(120,10,220,60),this,bFinish);
}


Добавлено через 7 минут
Преобразование ВНУТРИ потока пытаюсь делать так:
C++
1
2
3
4
5
UINT CMainWnd::proc1(LPVOID pParam)
{
    CDC *xdc;
    xdc=static_cast<CDC*>(pParam);
}
0
Заблокирован
14.11.2013, 18:15 8
Цитата Сообщение от SwanSONG Посмотреть сообщение
AfxBeginThread(proc1, lPtr);
С убогим MFC не работал много лет. Но судя по всему, OnPait вызывается по аналогии с чистым WM_PAINT, тоесть просты вызывается эта функция, когда надо перерисовать окно.
Вот и смотри, вызвалась функция OnPaint, в ней создался поток, куда ты передал адрес (тоесть указатель) на девайс контекст AfxBeginThread(proc1, lPtr);, далее - создался твой поток, а он создаётся относительно долго и начал что то делать, но пока он создавался и пока ты в нём обратился к dc, твоя функция OnPaint уже вылетела, тоесть закончилась, она ж в другом потоке и во первых, по скольку твой CPaintDC dc(this); объявлен в функции OnPaint - после того, как она вылетит - указатель станет не валидным и пользоваться им в другом потоке уже нельзя... А во вторых... В общем сначала с первым реши. В данном случа рисовать в другом потоке нет никакого смысла, т.к. тебе надо дождаться после вот этого AfxBeginThread(proc1, lPtr); завершения рисующего потока и никакого профита ты не получишь. Андестенд ?
0
2 / 2 / 0
Регистрация: 30.01.2013
Сообщений: 36
14.11.2013, 18:23  [ТС] 9
Если честно, запутали окончательно. То есть читать-то я умею, но ваш абзац переваривал долго, но так и не переварил :-(
Мне нужно даже не столько рисовать в отдельном потоке, а рисовать (в бесконечном цикле) так, чтобы основное окно откликалось на действия пользователя (чтобы он мог нажимать кнопки, останавливать или запускать рисование). Ничего лучшего потоков не придумал...

Добавлено через 1 минуту
Или при слабых знаниях матчасти про это лучше забыть???
0
Заблокирован
14.11.2013, 18:29 10
А что ты рисуешь? GUI рисуется всегда в одном потоке... Последние версии DirectX что - то выдвигали про MULTITHREADED_RENDERING, но пока это бутафория... Рисуют в разных потоках, точнее не рисуют, а просчитывают, например, сцены в 3ds max... Ты что конкретно рисуешь? Где и чего в таком случае хочешь добиться?

P.S.: например в случае двойной буферизации - ты сначала целиком прорисовываешь кадр как хочешь, а потом меняешь его на передний, ну тоесть именно на экране пиксели загораются в одном потоке
0
2 / 2 / 0
Регистрация: 30.01.2013
Сообщений: 36
14.11.2013, 18:32  [ТС] 11
Имитация звездного неба, около 2000 объектов в списке. Положение и цвет - рандомно меняются.
Проблема в том, что когда запускаешь всю эту машину (while (1){}), пользователь теряет связь с программой.
0
Заблокирован
14.11.2013, 18:43 12
Цитата Сообщение от SwanSONG Посмотреть сообщение
Имитация звездного неба, около 2000 объектов в списке. Положение и цвет - рандомно меняются.
Проблема в том, что когда запускаешь всю эту машину (while (1){}), пользователь теряет связь с программой.
В общем тебе нужно главное окно - это GUI для общения с юзером и обязательно! другое окно, в котором ты будешь рисовать в отдельном потоке. Второе окно может быть чем угодно, отдельным окном - маленьким окошком на форме и тд ... Опиши, как выглядит твой интерфейс, я ушёл - через пару часов за комп сяду ))
0
2 / 2 / 0
Регистрация: 30.01.2013
Сообщений: 36
14.11.2013, 19:14  [ТС] 13
В общем, при конструкции

C++
1
2
3
4
5
6
UINT CMainWnd::proc1(LPVOID pParam)
{
CDC *xdc;
xdc=reinterpret_cast<CDC*>(pParam);
...
}
xdc (в дебагере) состоит из:
[CPaintDC]
CJbject
m_hDC
m_hAttribDC
m_bPrinting

А DC, полученный в основном блоке:
CDC
m_hWnd
m_ps

Это барахло есть в xdc (и с теми же значениями), но зарыто глубоко:
xdc / [CPaintDC] / CDC

Вот я и не могу понять, как до этого CDC добраться

Добавлено через 8 минут
Цитата Сообщение от newbie666 Посмотреть сообщение
Опиши, как выглядит твой интерфейс
А интерфейса как такового и нет. Окно (1000х800) плюс 2 кнопки (запуск анимации и остановка анимации). По крайне мере, так в теории (и моих желаниях). Без 2 кнопок проект работает и сейчас, но из-за закольцованности цикла нет взаимодействия с пользователем. Проект сложный (как для меня) - класс-родитель CMyPoint и несколько наследников. Для упрощения задачи я (для начала!) хотел бы сделать в таком же бесконечном цикле во втором потоке вывод точки с рандомными координатами и цветом. Причем при нажатии кнопки "Start" процесс запускался бы, а при нажатии на "Stop" - останавливался.
Если получится это, получится и все остальное.
В этом и нужна помощь профи - как можно это организовать?
Причем, учитывая мой уровень, объясняйте "как для чайников" (подозреваю, такие просьбы уже в печенках сидят, так что в любом случае, спасибо, что тратите свое время).

Добавлено через 19 минут
При такой конструкции:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
...
CMyPaintDC dc(this);
LPVOID *lPtr=reinterpret_cast<LPVOID*>(&dc);
AfxBeginThread(proc1, lPtr);
... 
 
UINT CMainWnd::proc1(LPVOID pParam)
{
    CDC *xdc;
    CMyPaintDC *xdc1;
    xdc=reinterpret_cast<CDC*>(pParam);
    xdc1=dynamic_cast<CMyPaintDC*>(xdc);
 
    while(1)
    {
...
}}
Я вроде бы добрался до содержимого dc (сравнивал в дебагере), но начала вылетать другая ошибка:
Кликните здесь для просмотра всего текста
---------------------------
Microsoft Visual C++ Runtime Library
---------------------------
Debug Error!

Program: ...documents\visual studio 2012\Projects\XTread\Debug\XTread.exe

R6010
- abort() has been called


(Press Retry to debug the application)

---------------------------
Прервать Повтор Пропустить
---------------------------


Я уж и не знаю, что делать...
0
Заблокирован
14.11.2013, 21:00 14
Я предлагаю для начала, ну как для чайника, делать без MFC.

Скидывай сюда проект - посмотрю что можно сделать

Добавлено через 5 минут
В двух словах в таких случаях делают следующее в главном цикле обработки сообщений:
проверяют, если ли сообщение (GetMessage, PeekMessage) и только в случае - если его нет - вызывается функция Render например. Тоесть прорисовка графики идёт так сказать в idler time...

Добавлено через 11 секунд
тогда ничего не лочится
0
2 / 2 / 0
Регистрация: 30.01.2013
Сообщений: 36
15.11.2013, 19:58  [ТС] 15
Цитата Сообщение от newbie666 Посмотреть сообщение
Скидывай сюда проект - посмотрю что можно сделать
Искреннее спасибо. Вам вроде как это и не нужно, а все равно готовы помочь. Но хочу разобраться сам. Когда до чего-то доходишь сам и когда за тебя делают, - согласитесь, не одно и то же. Мне первое приятнее.
Единственное, о чем попрошу, сделайте микро-проект (по-возможности, разбитый на .h и .cpp файлы), который в отдельном потоке выводит точку с рандомными координатами, а в основной программе есть кнопка, к примеру, "PAUSE", по нажатию на которую вывод точек останавливается, а потом начинается вновь. А со своим проектом (который сейчас крутится в бесконечном while, я после повожусь сам.
Это то, что своими силами сделать не могу - еще год назад я о C++ не имел не малейшего представления, и конструкции вида i*=2 меня страшили Теперь вот страшат потоки.
В общем, спасибо
P.S. если нужно, сброшу голый тестовый проект, на котором сейчас ковыряюсь, но не думаю, что там вы найдете что-то полезное :-)

Добавлено через 20 часов 25 минут
Допер сам!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Решение оказалось на удивление простым:

1. Объявили поток в .h:
C++
1
static UINT MyThread(LPVOID pParam);
2. Описали поток в .cpp:
C++
1
2
3
4
5
6
UINT CMainWnd::MyThread(LPVOID pParam)
{
    CMainWnd *ptr=(CMainWnd*)pParam;
    CDC *dc=ptr->GetDC();
...
}
3.Запустили поток:
C++
1
AfxBeginThread(MyThread,this);
ВСЕ!!!!!!
Моя ошибка была (как я думаю) в том, что я пытался передать указатель на контекст устройства, а надо было указатель на объект класса (?) CMainWnd, из которого уже в самом потоке я и получил контекст устройства
Спасибо всем, тему можно считать закрытой!!!
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
15.11.2013, 19:58

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь или здесь.

Подхватить видео-поток от устройства
Хочу немного расширить область своих знаний - интересно как получать доступ через драйвер...

передача указателя
какой способ передачи указателя наиболее быстрый? int a = 1; int *b= &amp;a;...

Передача указателя
Здравствуйте! Форумчане, очень нужна помощь..:cry: В общем ситуация такова: написана программа,...

Передача указателя на функцию
Есть класс в котором: typedef void(*setChar)(int x, int y, wchar_t c); void...


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

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

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