Отправляет email-рассылки с помощью сервиса Sendsay

[prg] отправка текста в заголовок диалогового окна

Здравствуйте.

В диалоговом окне запускается еще один поток, в котором циклически
выполняются некоторые команды, изменяющие глабальную переменную. Там же во
втором потоке пытаюсь отправить текстовое значение глобальгной переменной в
заголовок диалогового окна, которое было открыто в первом потоке. Результат
нулевой. Посмотрел примеры синхронизации потоков на msdn, но там все примеры
с использованием функции main, а у меня есть только оконная процедура
диалогового окна и следовательно, не ясно, где разместить цикл,
отслеживающий какое событие сейчас установлено, а создание событий мы
отправим в блок case INITDIALOG.
Отсюда вопрос: можно каким-то образом в первом потоке реализовать механизм
синхронизации без функции WinMain с помощью событий. Разумеется, во втором
потоке ни кто мне не помешает устанавливать и проверять состояние событий,
поэтому загвозка с первым потоком.

Грызунов Александр

Ответить   Fri, 27 Dec 2013 15:41:14 +0400 (#2904778)

 

Ответы:

С наступающим!
Объясните чайнику, как проверить на валидность адрес электронной почты, со
всеми собаками и точками.
Заранее спасибо.

Ответить   Fri, 27 Dec 2013 23:02:46 +1100 (#2905000)

 

Приветствую всех.

Использовать регулярные выражения:
http://www.script-coding.com/WSH/RegExp.html

Успехов. Анатолий.

Ответить   "i_chay" Sat, 28 Dec 2013 03:24:03 +0300 (#2905164)

 

Публикуйте исходный код.
Кроме ошибок в коде, нет других объяснений ваших неудач.

Первый поток как раз и начинает свою работу с функции WinMain (на самом деле,
он начинает работу немного раньше, но сути дела это не меняет), а затем "крутится"
в цикле обработки оконных сообщений до тех пор, пока вы не закроете диалог.
Отличие диалогового окна от обычного, кроме всего прочего, состоит в том, что
цикл обработки сообщений скрыт от программиста.
Если вы хотите, чтобы ваше диалоговое окно отреагировало на какое-то ваше событие,
то из второго потока пошлите ему сообщение WM_USER,
http://www.vsokovikov.narod.ru/New_MSDN_API/Message_queue/notify_wm_user.htm
а в диалоговой процедуре вашего окна предусмотрите обработку этого сообщения.

Но для смены заголовка этого не требуется.

Успехов. Анатолий.

Ответить   "i_chay" Sat, 28 Dec 2013 03:18:51 +0300 (#2905161)

 

Здравствуйте, все и Анатолий в частности.

Код диалогового окна пришлось упростить и сократить, но каркас передаю без
изменений:

Диалог создается из оконной процедуры при обработке назжатой клавиши:
DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG3), hDlg, LoadingBookDlgProc);
// где: hInst - описатель экземпляра программы;
// hDlg - описатель родительского диалогового окна;
// LoadingBookDlgProc - указатель на оконную процедуру для создаваемого
диалогового окна;

листинг файла Dlg3.cpp
#include

HWND hDlg3;
bool bKill;

// объявление оконной процедуры диалога 3
INT_PTR CALLBACK LoadingBookDlgProc(HWND hDlg3, UINT uMsg, WPARAM wParam,
LPARAM lParam);

// определение функции, создающей второй поток
unsigned __stdcall SecondThreadFunc( void* pArguments ) {
bKill=false;
// выполняем действия в цикле
while (!bKill) {
// первоначально заголовок окна "заголовок1"
// задаем текст будущих заголовков
string sTitle0="заголовок0";
string sTitle1="заголовок1";
string sTitle2="заголовок2";
// изменяем заголовок окна
if (SetWindowText(hDlg3, sTitle0.c_str()) == true) continue;
if (SetWindowText(FindWindow(NULL, "заголовок1"), sTitle2.c_str()) ==
true) continue;
if (SetWindowText(FindWindow(NULL, "заголовок2"), sTitle1.c_str()) ==
true) continue;
}
PostMessage(FindWindow(NULL, "заголовок1"), WM_CLOSE, 0, 0);
}

INT_PTR CALLBACK LoadingBookDlgProc(HWND hDlg3, UINT uMsg, WPARAM wParam,
LPARAM lParam) {
switch(uMsg) {
case WM_INITDIALOG: {
_beginthreadex(NULL, 0, &SecondThreadFunc, NULL, 0, 0);
return true;
}
case WM_COMMAND: {
switch(LOWORD(wParam)) {
case IDCANCEL: {
bKill=true;
EndDialog(hDlg3, 0);
return true;
}
}
return TRUE;
}
}
return FALSE;
}

Необходимые пояснения. При урезании кода обнаружил, что с проблемой
описателя диалогового окна я столкнулся еще год назад, когда писал этот код
и именно этим объясняется использование не дискриптора, а функция поиска
top-окна с заданным текстом в заголовке.
Кстати, из трех примеров отправки текста в заголовок работают как раз вторая
и третья функции SetWindowText с использованием поиска текста заголовка. А
первая функция с дискриптором диалогового окна hDlg3 так и не разу не
срабатывает, потому что он после передачи управления во второй поток
становится равным нулю, хотя я объявлял ее как глобальную переменную в
header.h:
extern HWND hDlg3;

Грызунов Александр

Ответить   Mon, 30 Dec 2013 09:58:57 +0400 (#2906193)

 

Приветствую всех и поздравляю с наступающим Новым годом!

0. Примеры кода в том виде, в котором они приведены ниже, не компилировались
и не проверялись.
1. Дескриптор нужного вам диалогового окна вы получаете при первом же вызове
системой вашей диалоговой процедуры. Этот дескриптор не меняется в течение всего
времени существования диалогового окна, поэтому нет необходимости искать это
окно на каждой итерации цикла в потоковой функции. То есть даже если вы используете
FindWindow(), то делать это надо один раз , при условии, что она вернула ненулевой
дискриптор (а лучше вообще не использовать эту функцию).
Но самое главное: где же у вас происходит присваивание значения дескриптора глобальной
переменной hDlg3???
Кроме использования глобальной переменной, есть другой способ передачи значения
дескриптора диалогового окна в потоковую функцию: через её параметр, а в потоковой
функции привести параметр к нужному типу и оперировать с ним, чтобы менять заголовки
окна. Это избавляет от лишней глобальной переменной и делает код более очевидным.
Вот примерные фрагменты кода:
а) Диалоговая процедура (кроме всего прочего, надо ещё проверять значение, которое
возвращает _beginthreadex, чтобы быть уверенным, что поток успешно создан; более
того, это значение нужно где-то хранить, чтобы была возможность контролировать
состояние потока):
INT_PTR CALLBACK LoadingBookDlgProc(HWND hDlg3, UINT uMsg, WPARAM wParam,
LPARAM lParam) {
switch(uMsg) {
case WM_INITDIALOG:
_beginthreadex(NULL, 0, &SecondThreadFunc, (void*)hDlg3, 0, 0);
return true;
........
б) Потоковая функция:
unsigned __stdcall SecondThreadFunc( void* pArguments )
{
HWND hDlg = (HWND)pArguments;
....
Далее SetWindowText() в качестве аргумента передаём hDlg.

2. В потоковой функции объявление строк заголовков нужно вынести за пределы цикла,
чтобы на каждой итерации не тратить память и ресурсы процессора на создание и
уничтожение этих строк. Кроме того, это один из немногих случаев, когда использование
класса string ничем не оправдано и приводит лишь к снижению производительности.
Более эффективным решением будет создать статический локальный массив символьных
указателей, например:
const int MAX_TITLES = 4;
static const char* titles[MAX_TITLES] = {
"title0",
"title1",
"title2",
"title3"
};
int i = 0;
while(!bkill)
{
SetWindowText(hDlg, titles[i]);
if ((++i)>MAX_TITLES) i=0;
// Для наглядности делаем паузу.
Sleep(1000);
...

3. Для работы с bkill корректнее было бы использовать потокобезопасные функции
с именем Interlocked... (например, InterlockedExchange()), соответственно изменив
тип переменной.

Успехов. Анатолий.

Ответить   "i_chay" Tue, 31 Dec 2013 07:57:40 +0300 (#2906768)