Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.57/7: Рейтинг темы: голосов - 7, средняя оценка - 4.57
0 / 0 / 0
Регистрация: 19.03.2013
Сообщений: 25

Кнопка из другого потока

28.03.2013, 16:22. Показов 1678. Ответов 10
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
В одном потоке создается окно, и его hwnd записывается в глобальную переменную, а потом из другого потока я пытаюсь добавить кнопку, но кнопка не создается, хотя если использовать тот же самый код в потоке, в котором создается окно, то все ок. Можно ли вообще добавить кнопку из другого потока?
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
28.03.2013, 16:22
Ответы с готовыми решениями:

Управление объектами потока из другого потока
Доброго времени. Есть два потока, один GUI, второй рабочий - делает снапшоты открытых окон, сравнивает их, передаёт потоку GUI...

Узнать информацию из другого потока\процесса
Главная цель: узнать адрес процесса по PID используя только windows.h Допустим я знаю pid процесса "notepad". У меня идея...

Прекратить ReadDirectoryChangesW цикл из другого потока (Windows XP)
Здравствуйте! Значца, у меня есть некоторый класс, который следит за изменениями в директории с помощью ф-ии ReadDirectoryChangesW Этот...

10
Заблокирован
28.03.2013, 16:36
Какую ещё кнопку? Код в студию
0
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
28.03.2013, 17:09
Цитата Сообщение от enderkond Посмотреть сообщение
В одном потоке создается окно, и его hwnd записывается в глобальную переменную, а потом из другого потока я пытаюсь добавить кнопку, но кнопка не создается, хотя если использовать тот же самый код в потоке, в котором создается окно, то все ок. Можно ли вообще добавить кнопку из другого потока?
Вам враздел WinApi, во вторых...

Нужно смотреть моменты с синхронизацией потоков.

В WinApi не силен, но возможно стоит создавать кнопку и основного потока по "пришеставию" сообщения из другого потока.
0
0 / 0 / 0
Регистрация: 19.03.2013
Сообщений: 25
28.03.2013, 17:33  [ТС]
Код:

------Поток------
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
DWORD WINAPI updateLoop(LPVOID LPparam)
{
    window* winPointer = static_cast<window*>(LPparam);
    std::cout << "OLD" << winPointer->hWnd << "\n";
    winPointer->hWnd = CreateWindow(TEXT("Class"), "Calc", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 300, 250, 300, 150, NULL, NULL, GetModuleHandle(0), NULL);
    std::cout << "\nBBB " << winPointer->hWnd << "\n";
    HWND Button = CreateWindow("Button", TEXT("Я тут"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 0, 0, 80, 80, winPointer->hWnd, NULL, GetModuleHandle(0), NULL); // Тут кнопка создается!
    if(!winPointer->hWnd){
        MessageBox(NULL, TEXT("Не удалось создать окно"), TEXT("Ошибка!"), MB_OK);
        exit(-2);
    }
    winPointer->ready = true;
    //Windows.push_back(hWnd);
 
    MSG msg = {0};
    while(true)
    {
        GetMessage(&msg, NULL, NULL, NULL);
        MessageBox(NULL, TEXT("Button"), TEXT("Capt"), MB_OK);
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    std::cout << "2";
    return NULL;
}
---------Добавление вне потока-----------
C++
1
2
3
4
5
6
7
8
void window::addItem(Button* butt)
{
    do
    {
    } while(ready == false);
    std::cout << "Button " << hWnd << std::endl;
    HWND BUtt = CreateWindow("Button", TEXT((butt->text).c_str()), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, butt->x, butt->y, butt->width, butt->height, hWnd, NULL, hInstance, NULL); // Кнопка почему-то не создается ((
}
0
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
28.03.2013, 17:43
Ага как основной поток догадается о существовании кнопки и о том что её нужно перерисовать ....
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33374 / 21499 / 8235
Регистрация: 22.10.2011
Сообщений: 36,894
Записей в блоге: 11
28.03.2013, 18:19
Цитата Сообщение от enderkond Посмотреть сообщение
Можно ли вообще добавить кнопку из другого потока?
Creating Windows in Threads:
Any thread can create a window. The thread that creates the window owns the window and its associated message queue. Therefore, the thread must provide a message loop to process the messages in its message queue.
1
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
28.03.2013, 18:28
UI, Правильно ли я понял:
Создать можно из любого потока.
Но должна быть предусмотренна "обработка" сообщений там же где обработка окна-родителя.
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33374 / 21499 / 8235
Регистрация: 22.10.2011
Сообщений: 36,894
Записей в блоге: 11
28.03.2013, 19:51
Нет, не там же. Сообщения будут приходить в очередь тому потоку, который создал окно (и, соответственно, владеет им). То есть, именно в этом, не основном, потоке и нужно сделать выборку сообщений из очереди и их обработку. Вот а теперь пусть ТС думает, оно надо ему?
0
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
28.03.2013, 20:08
Цитата Сообщение от UI Посмотреть сообщение
Нет, не там же. Сообщения будут приходить в очередь тому потоку, который создал окно (и, соответственно, владеет им). То есть, именно в этом, не основном, потоке и нужно сделать выборку сообщений из очереди и их обработку. Вот а теперь пусть ТС думает, оно надо ему?
Т.е может быть такой случай что один поток обрабатывает окно программы, а другой поток обрабатывает RICHEDIT находящийся на этом окне ?
0
0 / 0 / 0
Регистрация: 19.03.2013
Сообщений: 25
29.03.2013, 20:01  [ТС]
Проблему решил самым долбанутым способом, что мог. Создал стак(#include <stack>) указателей на структуру Button и создал переменную для хранения текущего действия. Теперь все выглядит так:
------Цикл окна------
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
DWORD WINAPI updateLoop(LPVOID LPparam)
{
    window* winPointer = static_cast<window*>(LPparam);
 
    winPointer->hWnd = CreateWindow(TEXT("Class"), "Calc", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 300, 250, 300, 150, NULL, NULL, GetModuleHandle(0), NULL);
    if(!winPointer->hWnd){
        MessageBox(NULL, TEXT("Не удалось создать окно"), TEXT("Ошибка!"), MB_OK);
        exit(-2);
    }
    winPointer->ready = true;
 
    MSG msg = {0};
    while(true)
    {
        if(PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE))
        {
            if(strcmp(winPointer->funcList.c_str(), "")!=0)
            {
                std::cout << winPointer->funcList.c_str() << "\n"; 
                if(strcmp(winPointer->funcList.c_str(), "addButton")==0)
                {
                    if(buttStack.empty())
                        MessageBox(NULL, TEXT("Несоответствие списку аргументов"), TEXT("POP Error"), MB_OK);
                    Button* butt = buttStack.top();
                    HWND Button = CreateWindow("Button", TEXT((butt->text).c_str()), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, butt->x, butt->y, butt->width, butt->height, winPointer->hWnd, NULL, GetModuleHandle(0), nullptr);
                }
                winPointer->funcList = "";
            }
 
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    return NULL;
}
------Добавление элемента------
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Button* butt = new Button;
butt->text = "LOL";
butt->x = 0;
butt->y = 1;
butt->width = 200;
butt->height = 30;
wind.addItem(butt);
 
void window::addItem(Button* butt)
{
    do
    {
    } while(ready == false);
    
    buttStack.push(butt);   
    funcList = "addButton";
}
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33374 / 21499 / 8235
Регистрация: 22.10.2011
Сообщений: 36,894
Записей в блоге: 11
29.03.2013, 22:04
Лучший ответ Сообщение было отмечено volvo как решение

Решение

Цитата Сообщение от Avazart Посмотреть сообщение
Т.е может быть такой случай что один поток обрабатывает окно программы, а другой поток обрабатывает RICHEDIT находящийся на этом окне ?
Вполне.

Изначально вопрос стоял о возможности создания контрола из другого потока - вот пример с созданием кнопки. Одна - создается в основном, а другая - в дополнительном потоке. Обе работают.

Код
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include <windows.h>
 
#define ID_BTN 1000
#define ID_BTN2 1002
 
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
 
HINSTANCE hInst;
 
class WndData
{
public:
    HDC hdc;
    HWND hwnd;
    WndData() : hdc(0), hwnd(0)
    {
    }
};
 
WNDPROC btnProc = 0;
 
void thread_func (WndData *data)
{
 
    MSG msg;
 
    while(!data->hwnd) Sleep(0);
    HWND button = CreateWindowEx(0, TEXT("BUTTON"), TEXT("Other Thread"),
                                 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                                 10, 10, 80, 30, data->hwnd, (HMENU)ID_BTN, hInst, NULL);
    SendMessage(button, WM_SETFONT, WPARAM(GetStockObject(DEFAULT_GUI_FONT)), 1);
 
    while (IsWindow(data->hwnd) && GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}
 
MSG msg;
int WINAPI WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
    hInst = hInstance;
    DWORD dw;
 
    WndData wd;
    CreateThread(0, 0, (unsigned long (__stdcall *) (void *))thread_func, (void *)&wd, 0, &dw);
 
    WNDCLASSEX wc;
    wc.cbSize = sizeof(WNDCLASSEX);
    if (!GetClassInfoEx(hInst, TEXT("MTR_APP"), &wc))
    {
        memset(&wc, 0, sizeof(wc));
        wc.cbSize        = sizeof(WNDCLASSEX);
        wc.style         = 0;
        wc.lpfnWndProc   = WndProc; // DefWindowProc;
        wc.cbClsExtra    = 0;
        wc.cbWndExtra    = 0;
        wc.hIcon         = NULL;
        wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
        wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
        wc.lpszMenuName  = NULL;
        wc.hIconSm       = NULL;
        wc.hInstance     = hInst;
        wc.lpszClassName = TEXT("MTR_APP");
        if (!RegisterClassEx(&wc))
            return false;
    }
    HWND hWnd = CreateWindowEx(0, TEXT("MTR_APP"), TEXT("Threads"),
                            WS_OVERLAPPEDWINDOW, 10, 10, 200, 200,
                            0, NULL, hInst, NULL);
    UpdateWindow(hWnd);
    ShowWindow(hWnd, SW_SHOW);
    wd.hwnd = hWnd;
 
    while (IsWindow(hWnd) && GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return 0;
}
 
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
    case WM_CREATE:
        {
            HWND button = CreateWindowEx(0, TEXT("BUTTON"), TEXT("Main Thread"),
                                         WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                                         10, 50, 80, 30, hwnd, (HMENU)ID_BTN2, hInst, NULL);
            SendMessage(button, WM_SETFONT, WPARAM(GetStockObject(DEFAULT_GUI_FONT)), 1);
        }
        break;
 
    case WM_COMMAND:
        if (LOWORD(wParam) == ID_BTN || LOWORD(wParam) == ID_BTN2)
        {
            if (InSendMessage()) // Сообщение пришло из другого потока?
                ReplyMessage(TRUE);
            MessageBox(hwnd, TEXT("Button Pressed"), TEXT("Caption"), MB_OK);
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
29.03.2013, 22:04
Помогаю со студенческими работами здесь

Как передать сообщение окну из другого потока?
В общем пытаюсь передать сообщение окну из другого потока: Запускаю поток так: std::thread potok_ (klient, &amp;база_Kient_mob,...

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

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

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

Рисовать в окне из другого потока
Добрый день, написал был код, все работало, но из-за сбоев электрики комп. отключился от сети и как раз мой код оно потерло. Начал...


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
Использование SDL3-callbacks вместо функции main() на Android, Desktop и WebAssembly
8Observer8 24.01.2026
Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а привычная функция main(). . .
моя боль
iceja 24.01.2026
Выложила интерполяцию кубическими сплайнами www. iceja. net REST сервисы временно не работают, только через Web. Написала за 56 рабочих часов этот сайт с нуля. При помощи perplexity. ai PRO , при. . .
Модель сукцессии микоризы
anaschu 24.01.2026
Решили писать научную статью с неким РОманом
http://iceja.net/ математические сервисы
iceja 20.01.2026
Обновила свой сайт http:/ / iceja. net/ , приделала Fast Fourier Transform экстраполяцию сигналов. Однако предсказывает далеко не каждый сигнал (см ограничения http:/ / iceja. net/ fourier/ docs ). Также. . .
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь(не выше 3-го порядка) постоянного тока с элементами R, L, C, k(ключ), U, E, J. Программа находит переходные токи и напряжения на элементах схемы классическим методом(1 и 2 з-ны. . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru