Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Обмен данными между окнами, --- 
:(
    Опции темы
13dreams
Дата 18.7.2010, 17:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Имеется дочернее диалоговое окно которое вызывается нажатием кнопки главного окна с помощью метода DoModal(). В дочернем окне есть кнопка которой хотелось бы менять иконку на кнопке главного окна. 

В классе дочернего окна я создал объект класса главного окна и через написанную мной функцию пытаюсь передать в главное окно данные.

Всё компилируется нормально, но когда я нажимаю на кнопку, которая должна отправить данные в главное окно, вылетает какое-то сообщение об ошибке.

Что я не так делаю? И как в моём случае организовать эту передачу данных? 
PM MAIL   Вверх
Earnest
Дата 19.7.2010, 08:06 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

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



Цитата(13dreams @  18.7.2010,  18:12 Найти цитируемый пост)
вылетает какое-то сообщение об ошибке.

Замечательное описание ошибки!
Не надо гадать на кофейной гуще - у тебя есть отладчик. Поставь точку прерывания и посмотри, откуда ошибка. 


--------------------
...
PM   Вверх
13dreams
Дата 19.7.2010, 20:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



немного изменил код:
из дочернего окна вызываю функцию главного окна которая меняет только флаг. В главном окне вызываю таймер который в соответствии с этим флагом меняет битмап на кнопке.

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

ps И можно ли считать таймер отдельным потоком? 
PM MAIL   Вверх
Earnest
Дата 20.7.2010, 07:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

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



Цитата(13dreams @  19.7.2010,  21:53 Найти цитируемый пост)
И можно ли считать таймер отдельным потоком?  

Нет, с чего бы вдруг?
Цитата(13dreams @  19.7.2010,  21:53 Найти цитируемый пост)
из дочернего окна вызываю функцию главного окна которая меняет только флаг. В главном окне вызываю таймер который в соответствии с этим флагом меняет битмап на кнопке.

Можно и так. Но, честно сказать, чем тебе прямое сообщение не угодило? Т.е. прямо сообщить главному окну, что нужно менять картинку. Определи пользовательское сообщение и посылай. Только лучше асинхронно (PostMessage).


--------------------
...
PM   Вверх
13dreams
Дата 20.7.2010, 22:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



добил код в котором рабочий поток отправляет сообщение главному окну из класса которого он создан

Код

// SomeDlg.h : файл заголовка
...
CWinThread *m_pThread;
LRESULT OnUpdateControl(WPARAM wParam, LPARAM lParam);   
static UINT ThreadProc(LPVOID param);
...




Код

// SomeDlg.cpp : файл реализации
CSomeDlg::CSomeDlg(CWnd* pParent /*=NULL*/)
    : CDialog(CSomeDlg::IDD, pParent)
    , m_WrStr1(_T(""))
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    m_pThread = 0;
}



BEGIN_MESSAGE_MAP(CSomeDlg, CDialog)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    //}}AFX_MSG_MAP
    ON_MESSAGE(WM_UPDATE_CONTROL, OnUpdateControl)
END_MESSAGE_MAP()



BOOL CSomeDlg::OnInitDialog()
{
    CDialog::OnInitDialog();
...
 HWND *phObjectHandle = new HWND;
  *phObjectHandle = GetSafeHwnd();
    m_pThread=AfxBeginThread(ThreadProc, phObjectHandle);  //Запуск потока
return TRUE;  
}



UINT CSomeDlg::ThreadProc(LPVOID param)  //Создание потоковой функции 
{
    HWND *phObjectHandle = static_cast<HWND *>(param);
    while(1)
    {        CString* ps = new CString("111");
::PostMessage(*phObjectHandle, WM_UPDATE_CONTROL, (WPARAM)ps, (LPARAM)0);
         Sleep(1000);
    }
    delete phObjectHandle;
    return 0;
}



LRESULT CSomeDlg::OnUpdateControl(WPARAM wParam, LPARAM lParam)
{
  static int iCounter = 0;
  CString    strText;

CString *pStr = (CString*)wParam;
GetDlgItem(IDC_THREAD_TEXT)->SetWindowText(pStr->GetBuffer(0));
m_WrStr1=*pStr;
UpdateData(false);
delete pStr;

  return 0;
}


как реализовать отправку сообщения из этого потока в дочернее окно?

я пробовал объявить и написать 
Код

LRESULT CSomeDlg::OnUpdateControl(WPARAM wParam, LPARAM lParam)
{}
в классе дочернего окна но ничего не выходит 
PM MAIL   Вверх
Earnest
Дата 21.7.2010, 07:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

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



Я как-то путаюсь: то у тебя главное окно, то дочернее, кто есть кто в конце концов?
Из кода вижу, что диалог запускает поток, который должен послать ему сообщение. Вроде все нормально, только динамически создавать phObjectHandle совершенно не нужно - HWND вполне влезет в LPARAM. 
Что касается "ничего не выходит", то поясни, что сие значит: ты не видишь результат? Или не попадаешь в обработчик? Второе вряд ли, все вроде верно. Поставь точку прерывания в обработчике и проверь код. Возможно у тебя UpdateData ничего не делает (т.к. не вижу кода, который связывает переменные с контролами, но может ты его просто не привел).

Добавлено через 2 минуты и 42 секунды
Да, кстати, логичнее в потоковую процедуру предать указатель на диалог, а не HWND, а переменную m_WrStr1 устанавливать непосредственно перед отправкой сообщения через соответствующий метод диалога - все эти динамические переменные, создаваемые в одном месте, а освобождаемые в другом, дурно пахнут. А сообщение может быть просто сигналом.


--------------------
...
PM   Вверх
13dreams
Дата 21.7.2010, 08:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Прошу прощения, что так выражаюсь. 

этот код, который я написал выше, работает корректно. Созданный поток отправляет главному окну CString и эта строка отображается в контроле этого главного окна

но есть ещё одно дочернее окно которое вызывается кнопкой из этого главного окна(методом DoModal() ). И я хочу чтоб та же строка CString отсылалась и этому дочернему окну

как это реализовать?
PM MAIL   Вверх
Earnest
Дата 21.7.2010, 11:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

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



Очевидно, нужно ему что-нибудь тоже послать. Вопрос, откуда удобнее это сделать - и тут возможны варианты. Если есть HWND этого дочернего диалога, то нет проблем, не так ли? Значит, надо его получить (HWND). Мне кажется, проще это сделать прямо в обработчике главного окна (если оно по прежнему должно получать это сообщение). Определить HWND можно, например, с помощью функции GetLastActivePopup.
Еще вариант: если главное окно хранит ссылку на дочерний диалог (а не создает его как автоматическую переменную в обработчике, где делается DoModal), то можно сделать обновление не через сообщение, а через функцию дочернего диалога. Только перед вызовом тогда нужно проверять, что окно валидно (т.к. оно валидно только в течении вызова DoModal).
Вариант определения HWND через GetLastActivePopup можно скомбинировать с вызовом функции дочернего диалога (а не посылкой ему сообщения), получив указатель на диалог с помощью функции FromHandlePermanent.
Только этот вызов должен находиться в главном потоке.
Наконец, можно разослать сообщение всем окнам системы через PostMessage (HWND_BROADCAST, ...), только тогда нужно гарантировать, что никто чужой случайно не обработает сообщение WM_UPDATE_CONTROL. Такую гарантию могут дать только зарегистрированные сообщения (RegisterWindowMessage, подключение обработчика - ON_REGISTERED_MESSAGE).


--------------------
...
PM   Вверх
13dreams
Дата 21.7.2010, 18:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Я думаю, что лучше в потоке проверят создано ли дочернее окно и если создано, то отправить ему сообщение

но как правильно использовать GetLastActivePopup?
я пробовал аналогично предыдущему коду
Код

UINT CThreadTestDlg::ThreadProc(LPVOID param)  //Создание потоковой функции 
{
    while(1)
    {    HWND *hPopup = static_cast<HWND *>(param);
        
    CString* ps = new CString("111");

    ::GetLastActivePopup(*hPopup);
    ::PostMessage(*hPopup, WM_UPDATE_CONTROL, (WPARAM)ps, (LPARAM)0);
    
     Sleep(1000);
     delete hPopup;
    }
    
    return 0;
}


и пробовал 

Код

UINT CThreadTestDlg::ThreadProc(LPVOID param)  //Создание потоковой функции 
{
    while(1)
    {    CString* ps = new CString("111");

    HWND *hPopup=new HWND;
    ::GetLastActivePopup(*hPopup);
    ::PostMessage(*hPopup, WM_UPDATE_CONTROL, (WPARAM)ps, (LPARAM)0);
    
     Sleep(1000);
     delete hPopup;
    }
    
    return 0;
}


и чего-то сообщения не доходят 

Это сообщение отредактировал(а) 13dreams - 21.7.2010, 18:53
PM MAIL   Вверх
Earnest
Дата 21.7.2010, 20:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

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



А описание в MSDN посмотреть не судьба?
GetLastActivePopup ВОЗВРАЩАЕТ попап-окно, принадлежащее главному:
Код

HWND hPopup = GetLastActivePopup (hMainWnd);
if (hPopup && hPopup != hMainWnd)
   ...



--------------------
...
PM   Вверх
13dreams
Дата 23.7.2010, 16:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Спасибо! 

Заглянул в МСДН и решил проблему с помощью GetForegroundWindow()  smile

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


 




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


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

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