Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Затирание немодального диалогового окна основным, Нужна помощь 
V
    Опции темы
PirateTigo
Дата 20.9.2009, 14:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Я уверен в том, что у меня классическая проблема и разобраться с ней не составит труда опытным программистам WinAPI.

В общем так:

В программе создано несколько диалоговых окон в числе которых существует три немодальных. Программа работает с графическим объектом, который в процессе работы программы видоизменяется. Для поддержки двойной буферизации создан пользовательский обработчик перерисовки клиентской области приложения, который вызывается по сообщению USER_WM, вот его объявление:
Код

enum UserMsg {USER_WM = WM_USER + 1};


в обработчике сообщения WM_PAINT находится следующий код:
Код

case WM_PAINT:        
        DefWindowProc (hWnd, message, wParam, lParam);
        SendMessage (hWnd, USER_WM, 0, 0);
        break;


в обработчике сообщения USER_WM используется совместимый с контекстом окна hdc контекст memdc. Все действия по обработке изображения выполняются в контексте memdc, а затем содержимое контекста копируется в контекст окна hdc с помощью этой функции:
Код

BitBlt (hdc, 0, 0, rect.right, rect.bottom, memdc, 0, 0, SRCCOPY);


В обработчике сообщения WM_CREATE создается немодальное диалоговое окно, использующееся для отображения некоторых параметров графического объекта:
Код

hActVert = CreateDialog (hInst, MAKEINTRESOURCE (IDD_ACTVERT), hWnd, ActVert);


Здесь hActVert  - дескриптор немодального диалогового окна, ActVert - Процедура обработки сообщений для этого окна,
IDD_ACTVERT - шаблон этого окна, hInst - дескриптор экземпляра основного окна приложения.

А теперь вопрос:
Какой код и куда мне нужно поместить, чтобы мое немодальное диалоговое окно не затиралось, а вполне себе успешно отображалось в клиентской области окна приложения в процессе работы программы?

Заранее благодарен.
PM MAIL ICQ Skype   Вверх
GremlinProg
Дата 20.9.2009, 14:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

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



а зачем пересылать из WM_PAINT к USER_WM, когда все можно рисовать прямо в WM_PAINT
Цитата(PirateTigo @  20.9.2009,  16:20 Найти цитируемый пост)
Какой код и куда мне нужно поместить, чтобы мое немодальное диалоговое окно не затиралось, а вполне себе успешно отображалось в клиентской области окна приложения в процессе работы программы?

не совсем понятно, что значит "затиралось", 
тут могут быть разные ситуации:
- рисование немодального диалога (который затирается) не производится на WM_PAINT (при этом затирается не весь диалог, а только пользовательское содержимое)
- процедура окна немодального диалога блокируется каким-либо образом
- производится какое-либо долгосрочное вычисление, мещающее основной работе окна (в диспетчере задач при этом показана 100% загрузка CPU)

и во всех случаях нужно видеть исходный код, чтобы определить причину такого поведения,
а без кода можешь расчитывать только на диалог с самим собой, т.к. все, что за пределами кода - телепатия,
а у нас пока большинство участников бегают со старыми сервис-паками, без апгрейда "телепатия", не обессудь


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
PirateTigo
Дата 20.9.2009, 15:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



На счет WM_PAINT согласен - не подумал.

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

Код

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    static HDC hdc, memdc;
    static HRGN hRgn;
    RECT rect;
    static int X, Y, R;
    static VertName Active;    
    static VertName Iterator;
    static VertName IterAct;
    static float h = 0.;
    static bool bTracking = false;
    static HBITMAP hBmp;
    static HBRUSH hBrush;
    static int count = 0;
    static SimpleGraph<VertexData *, EdgeData>::iterator GIT;
//===================================================================================
    switch (message)
    {
    case WM_CREATE:
        hinst_msimg32 = LoadLibrary(TEXT("msimg32.dll"));        
        if (hinst_msimg32)
        {
            GFill = (bool (WINAPI *)(HDC, TRIVERTEX*, 
                unsigned long, void*, unsigned long, unsigned long))
            GetProcAddress(hinst_msimg32, "GradientFill");
        }    

        LPPNTS = (VertexData **)malloc (sizeof (VertexData *)*100000);
        for (int i=0; i<100000; i++)
            LPPNTS[i] = PNTS+i;

        graphData.V = "10";
        graphData.Directed = false;
        graphData.TP = IDC_L;

        GetClientRect(hWnd, &rect);
        X = (rect.left + rect.right) / 2;
        Y = (rect.bottom + rect.top) / 2;
        R = min (Y/2, X/2);    
        
        hBrush = CreateSolidBrush (RGB (255,255,255));
        hdc = GetDC (hWnd);        
        SetClassLong (hWnd, GCL_HBRBACKGROUND, (LONG)hBrush);
        memdc = CreateCompatibleDC (hdc);
        hBmp = CreateCompatibleBitmap (memdc, rect.right, rect.bottom);        
        SelectObject (memdc, hBmp);
        SetGraphicsMode (memdc, GM_ADVANCED);    
        hRgn = CreateRectRgnIndirect (&rect);
        hActVert = CreateDialog (hInst, MAKEINTRESOURCE (IDD_ACTVERT), hWnd, ActVert);
        hRgn = AdjDlgPlace (hRgn, hActVert);        
        break;



Код

    case WM_SIZE:        
        GetClientRect(hWnd, &rect);                
        X = (rect.left + rect.right) / 2;
        Y = (rect.bottom + rect.top) / 2;
        R = min (Y/2, X/2);
        if (G != NULL) {
            int i=0, j;
            for (multimap<string, int>::iterator iter = NAMES.begin();
                i<G->V(); iter++, i++) {
                    double alpha = i*h*Pi/180.;
                    VertName temp (&((*iter).second),sizeof (int));
                    (**(G->Vertex (temp)->GetData())).SetXY ((int)(X + sin (alpha)*R),(int)(Y - R*cos (alpha)));
                }            
            i=0;
            for (multimap<string, int>::iterator iter1 = NAMES.begin();
                i<G->V(); iter1++, i++) {
                    j=i+1;
                for (multimap<string, int>::iterator iter2 = iter1;
                    j<G->V(); j++) {
                        iter2++;
                        VertName SrcName (&((*iter1).second), sizeof (int));
                        VertName DstName (&((*iter2).second), sizeof (int));
                        Edge<VertName, EdgeData> *temp1 = new Edge<VertName, EdgeData>(
                            SrcName, DstName, NULL, NULL);
                        Edge<VertName, EdgeData> *temp2 = new Edge<VertName, EdgeData>(
                            DstName, SrcName, NULL, NULL);
                        EdgeData *temp1s=NULL, *temp2s=NULL;
                        if ((temp1s=G->Edge (temp1))!=NULL) {
                            temp1s->SetXYSrc (
                                (*(G->Vertex (SrcName)->GetData ()))->x,
                                (*(G->Vertex (SrcName)->GetData ()))->y
                                );
                            temp1s->SetXYDst (
                                (*(G->Vertex (DstName)->GetData ()))->x,
                                (*(G->Vertex (DstName)->GetData ()))->y
                                );
                            delete temp1;
                        }
                        if ((temp2s=G->Edge (temp2))!=NULL) {
                            temp2s->SetXYSrc (
                                (*(G->Vertex (DstName)->GetData ()))->x,
                                (*(G->Vertex (DstName)->GetData ()))->y
                                );
                            temp2s->SetXYDst (
                                (*(G->Vertex (SrcName)->GetData ()))->x,
                                (*(G->Vertex (SrcName)->GetData ()))->y
                                );
                            delete temp2;
                        }                                            
                }    
            }
        }                    
        hBmp = CreateCompatibleBitmap (hdc, rect.right, rect.bottom);
        DeleteObject (SelectObject (memdc, hBmp));
        BitBlt (memdc, 0, 0, rect.right, rect.bottom, hdc, 0, 0, SRCCOPY);        
        break;
//=================================================================================
    case WM_PAINT:        
        DefWindowProc (hWnd, message, wParam, lParam);
        SendMessage (hWnd, USER_WM, 0, 0);
        break;

    case USER_WM:
        {    
            GetClientRect (hWnd, &rect);        
            if (!count) {
                BitBlt (memdc, 0, 0, rect.right, rect.bottom, hdc, 0, 0, SRCCOPY);
                count++;
            }            
            FillRect (memdc, &rect, hBrush);
                
            if (G != NULL) {            
                int i=0, j;
                for (multimap<string, int>::iterator iter = NAMES.begin();
                    i<G->V(); iter++, i++) {
                        int temp = (*iter).second;
                        VertName Name (&temp, sizeof (int));
                        (*(G->Vertex (Name)->GetData ()))->Draw (memdc);
                }

                i=0;
                for (multimap<string, int>::iterator iter1 = NAMES.begin();
                    i<G->V(); iter1++, i++) {
                        j=i+1;
                    for (multimap<string, int>::iterator iter2 = iter1;
                        j<G->V(); j++) {
                            iter2++;
                            VertName SrcName (&((*iter1).second), sizeof (int));
                            VertName DstName (&((*iter2).second), sizeof (int));
                            Edge<VertName, EdgeData> *temp1 = new Edge<VertName, EdgeData>(
                                SrcName, DstName, NULL, NULL);
                            Edge<VertName, EdgeData> *temp2 = new Edge<VertName, EdgeData>(
                                DstName, SrcName, NULL, NULL);
                            EdgeData *temp1s=NULL, *temp2s=NULL;
                            if ((temp1s=G->Edge (temp1))!=NULL | 
                                (temp2s=G->Edge (temp2))!=NULL) {                                    
                                    if (temp1s!=NULL) temp1s->Draw (memdc);
                                    else temp2s->Draw (memdc);
                                    if (temp1s!=NULL) temp1s->DrawDir (memdc);
                                    if (temp2s!=NULL) temp2s->DrawDir (memdc);
                            }    
                            delete temp1, temp2;        
                    }                        
                }                                        
            }        
        }                
        BitBlt (hdc, 0, 0, rect.right, rect.bottom, memdc, 0, 0, SRCCOPY);        
        break;


Под словом "затиралось" я имел в виду то, что при запуске программы окно отображается, но как только я вызываю обработчик сообщения USER_WM окно исчезает (это понятно потому что происходит копирование с контекста памяти memdc на контекст hdc без отсчения регионов)

Из тех вариантов, что вы привели сюда НЕ подходят:
- производится какое-либо долгосрочное вычисление, мещающее основной работе окна (в диспетчере задач при этом показана 100% загрузка CPU)

Ну и по поводу пакета "телепатия". Я и так по-моему достаточно хорошо все описал и изложил суть проблемы. Дело ведь не в том, что я что-то забыл написать в коде, а в том, что я не знаю как это делается в классическом варианте (это я про немодальное диалоговое окно сейчас), так как использую его в таком контексте впервые. А хамить не нужно.
PM MAIL ICQ Skype   Вверх
GremlinProg
Дата 20.9.2009, 15:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

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



Цитата(PirateTigo @  20.9.2009,  16:20 Найти цитируемый пост)

в обработчике сообщения WM_PAINT находится следующий код:
Код

case WM_PAINT:        
        DefWindowProc (hWnd, message, wParam, lParam);
        SendMessage (hWnd, USER_WM, 0, 0);
        break;


так это и есть обработчик на немодальном диалоге, который "затирается"?
если так, то просто убери DefWindowProc, чтобы она не подтверждала регион коррекции
Цитата(PirateTigo @  20.9.2009,  17:07 Найти цитируемый пост)
А хамить не нужно.

в данном случае оно было обоюдным, т.к. просить помощи без разъяснения ситуации - хамство по отношению к участникам форума


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
PirateTigo
Дата 20.9.2009, 16:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Убрал - программа зависла как только я попытался изобразить графический объект.

Добавлено через 5 минут и 1 секунду
Так... Кажется опять не понятно, что я хочу узнать от всех...

Мне в общем код не важен, мне нужен просто принцип. Как это делается? 
А если точнее, то какими средствами можно перерисовать немодальное диалоговое окно. Ну то есть как явно его обновить?
PM MAIL ICQ Skype   Вверх
GremlinProg
Дата 20.9.2009, 16:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

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



Цитата(PirateTigo @  20.9.2009,  18:03 Найти цитируемый пост)
Убрал - программа зависла как только я попытался изобразить графический объект.

да, рисование в USER_WM организовано мягко говоря некорректно,
я расчитывал на более обыденную форму, с BeginPaint и EndPaint

да и инициализацию второго буфера в WM_CREATE привязывать к hWnd не нужно, т.к. до вызова встронного обработчика его координаты еще не определены

на данном этапе, я предлагаю:
1. отвязаться от посылки USER_WM,
2. рисовать все в ответ на WM_PAINT
3. двойной буфер создавать прямо в WM_PAINT
4. пользоваться исключительно BeginPaint и EndPaint
5. если нужно отвязаться от создания второго буфера в WM_PAINT, это можно будет сделать в WM_SIZE, сразу как только будут решены текущие проблемы

на форуме много готовых примеров, выбирай наиболее подходящий: http://forum.vingrad.ru/act-Search/CODE/sh...2580/index.html

Добавлено через 6 минут и 27 секунд
вот такой запрос немного точнее: http://forum.vingrad.ru/act-Search/CODE/sh...2522/index.html


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
PirateTigo
Дата 20.9.2009, 17:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



В общем я нашел решение.

Нужно просто установить для главного окна стиль WS_CLIPCHILDREN, и/или для дочерних окон стиль WS_CLIPSIBLINGS.

Добавлено через 1 минуту и 45 секунд
Ответ найден.
PM MAIL ICQ Skype   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

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


 




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


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

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