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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Класс окна на основе диалога. В ресурсах другого диалога. 
V
    Опции темы
mekhanikus
Дата 2.4.2011, 04:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вольноопределяющийся
*


Профиль
Группа: Участник
Сообщений: 186
Регистрация: 16.6.2008
Где: Спасск-Дальний

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



Попытаюсь обьяснить, чего я хочу.

Имеем диалог из ресурса:
Код

MonthWnd DIALOGEX 114,100,250,146
FONT 10,"Arial",400,0,204
STYLE 0x00C80840
EXSTYLE 0x00000080
BEGIN
  CONTROL "11",W01_MON,"DateWnd",0x50000301,31,32,13,10
  ...
  CONTROL "67",W06_SUN,"DateWnd",0x50000301,106,98,13,10
END

Где "DateWnd" - свой класс окна.

Хочу создать диалог:
Код

YearWnd DIALOGEX 114,100,250,146
FONT 10,"Arial",400,0,204
STYLE 0x00C80840
EXSTYLE 0x00000080
BEGIN
  CONTROL "01",JAN,"MonthWnd",0x50000301,31,32,13,10
  ...
  CONTROL "12",DEC,"MothWnd",0x50000301,106,98,13,10
END

Где "MonthWnd" - диалог из предыдущего примера.

Пока пытаюсь осмыслить метод, предложенный GremlinProg в теме.
PM MAIL   Вверх
GremlinProg
Дата 4.4.2011, 06:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



а я пока не понял проблемы,
что мешает создать диалог на основе второго листинга?

это же обычный ресурс диалога

Добавлено @ 06:46
а, начинаю понимать, т.е. надо первый диалог разместить на втором

Добавлено @ 06:53
так не получится,
нужно у второго перехватить событие WM_INITDIALOG и вызвать CreateDialog с параметрами первого

но если уж очень хочется автоматизировать дизайнерский процесс расстановки компонент на втором диалоге,
то можно временно поставить STATIC на то место, где должен быть размещен первый диалог
и на WM_INITDIALOG получить его координаты, чтобы подставить их в CreateDialog

Это сообщение отредактировал(а) GremlinProg - 4.4.2011, 06:54


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


Вольноопределяющийся
*


Профиль
Группа: Участник
Сообщений: 186
Регистрация: 16.6.2008
Где: Спасск-Дальний

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



Для начала сделал так:
Регистрирую класс окна "MonthWnd"
и в его WM_CREATE создаю дочерний диалог:
Код

LRESULT CALLBACK MONTHWND::MonthProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    MONTHWND* temp = (MONTHWND*)GetWindowLong(hwnd,GWL_USERDATA);
    switch (message)
    {
        case WM_CREATE:
        {
            CREATESTRUCT* cs = (CREATESTRUCT*)lParam;
            temp = new MONTHWND(cs);
            SetWindowLong(hwnd,GWL_USERDATA,(unsigned long)temp);
            temp->MonthDlg = CreateDialogParam(cs->hInstance,
                                               "MonthDlg",
                                               hwnd,
                                               (DLGPROC)&MONTHWND::MonthDlgProc,
                                               (LPARAM)temp->month);


            break;
        }
        case WM_DESTROY:
            delete temp;
        default:
            return DefWindowProc (hwnd, message, wParam, lParam);
    }
    return 0;
}


Чувствую - на тернистый путь встал.
PM MAIL   Вверх
mekhanikus
Дата 10.4.2011, 13:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вольноопределяющийся
*


Профиль
Группа: Участник
Сообщений: 186
Регистрация: 16.6.2008
Где: Спасск-Дальний

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



Регистрирую класс окна:

Код

char MONTHWND::szClassName[] = "MonthWnd";

ATOM MONTHWND::RegMonthWnd()
{
    WNDCLASSEX wc;
    ZeroMemory(&wc,sizeof(wc));
    wc.cbSize = sizeof(WNDCLASSEX);

    GetClassInfoEx(NULL,"#32770",&wc);

    HINSTANCE hi = GetModuleHandle(NULL);

    wc.hInstance = hi;
    wc.lpszClassName = szClassName;
    wc.lpfnWndProc = (WNDPROC)InitMonthDlg;

    return RegisterClassEx (&wc);
}


В процедуре инициализации переназначаю процедуру окна, прописываю USERDATA:

Код

LRESULT CALLBACK MONTHWND::InitMonthDlg(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
    MONTHWND* temp = new MONTHWND();

    SetWindowLong(hwnd,GWL_WNDPROC,(LONG)MONTHWND::MonthDlgProc);
    SetWindowLong(hwnd,GWL_USERDATA,(unsigned long)temp);

    return CallWindowProc(MONTHWND::MonthDlgProc,hwnd,msg,wParam,lParam);
}


В основной процедуре считываю USERDATA, и вызываю DefDlgProc.

Код

LRESULT CALLBACK MONTHWND::MonthDlgProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
    MONTHWND* temp = (MONTHWND*)GetWindowLong(hwnd,GWL_USERDATA);
    return CallWindowProc(DefDlgProc,hwnd,msg,wParam,lParam);//
}


Ресурсы как в первом топике:

Код

MonthWnd DIALOGEX 114,100,250,146
CLASS "MonthWnd"
FONT 10,"Arial",400,0,204
STYLE 0x00C80840
EXSTYLE 0x00000080
BEGIN
  CONTROL "11",W01_MON,"DateWnd",0x50000301,31,32,13,10
  ...
  CONTROL "67",W06_SUN,"DateWnd",0x50000301,106,98,13,10
END


Код

YearWnd DIALOGEX 114,100,250,146
FONT 10,"Arial",400,0,204
STYLE 0x00C80840
EXSTYLE 0x00000080
BEGIN
  CONTROL "01",JAN,"MonthWnd",0x50000301,31,32,13,10
  ...
  CONTROL "12",DEC,"MothWnd",0x50000301,106,98,13,10
END


Диалог "YearWnd" запускается как обычно:

Код

DialogBox(GetModuleHandle(NULL),"YearDlg",hwndDlg,YearDlgProc);


На месте "MonthWnd" рисуются пустые квадратики без контролов.

Что я делаю не так?
PM MAIL   Вверх
GremlinProg
Дата 10.4.2011, 19:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(mekhanikus @  10.4.2011,  15:45 Найти цитируемый пост)
Что я делаю не так?

Цитата(GremlinProg @  4.4.2011,  08:45 Найти цитируемый пост)
так не получится



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


Вольноопределяющийся
*


Профиль
Группа: Участник
Сообщений: 186
Регистрация: 16.6.2008
Где: Спасск-Дальний

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



Цитата(GremlinProg @ 4.4.2011,  06:45)
так не получится

Просто, понятно, лаконично...  smile 

Пойдем другим путем.

Регистрируем класс окна:
Код

char MONTHWND::szClassName[] = "MonthWnd";

ATOM MONTHWND::RegMonthWnd()
{
    WNDCLASSEX wc;
    ZeroMemory(&wc,sizeof(wc));
    wc.cbSize = sizeof(WNDCLASSEX);

    HINSTANCE hi = GetModuleHandle(NULL);

    if(!GetClassInfoEx(hi,szClassName,&wc))
    {
        wc.cbSize = sizeof (WNDCLASSEX);
        wc.hInstance = hi;
        wc.lpszClassName = szClassName;
        wc.lpfnWndProc = (WNDPROC)InitMonthProc;
        wc.style = CS_DBLCLKS;
        wc.hIcon = NULL;
        wc.hIconSm = NULL;
        wc.hCursor = NULL;
        wc.lpszMenuName = NULL;
        wc.cbClsExtra = 0;
        wc.cbWndExtra = 0;
        wc.hbrBackground = NULL
        return RegisterClassEx (&wc);
    }
    return 0;
}

В момент создания окна делаем следующее:
Код

LRESULT CALLBACK MONTHWND::InitMonthProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        case WM_CREATE:
        {
            CREATESTRUCT* cs = (CREATESTRUCT*)lParam;

            //создаем диалог из ресурса
            HWND hDlg = CreateDialogParam(cs->hInstance,
                                               "MonthDlg",
                                               hwnd,
                                               (DLGPROC)&MONTHWND::MonthDlgProc,
                                               (LPARAM)0);

            RECT r;
            GetWindowRect(hDlg,&r);
            MapWindowPoints( HWND_DESKTOP, hDlg, (POINT*)&r, 2 );

            LONG PosX = (cs->cx - r.right)/2;
            LONG PosY = (cs->cy - r.bottom)/2;

            //делаем родителем MonthDlg основное окно диалога YearDlg 
            SetParent(hDlg,GetParent(hwnd));

            //ставим диалог в нужную позицию
            SetWindowPos(hDlg,HWND_TOP,PosX + cs->x,PosY + cs->y,0,0,SWP_NOSIZE);

            return (LRESULT)0;
        }
        default:
            return DefWindowProc (hwnd, message, wParam, lParam);
    }
    return DefWindowProc (hwnd, message, wParam, lParam);
}


Так работает, диалоги появляются.

Теперь надо убить окно инициализации диалога (желательно самоубийство  smile ) и назначить созданый диалог Item'ом YearDlg.

Первый пункт, думаю, освою сам.

А, вот со вторым пунктом пока проблемы, надо листать букварь.
PM MAIL   Вверх
mekhanikus
Дата 12.4.2011, 10:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вольноопределяющийся
*


Профиль
Группа: Участник
Сообщений: 186
Регистрация: 16.6.2008
Где: Спасск-Дальний

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



Со вторым пунктом разобрался:
Код

SetWindowLong(hDlg,GWL_ID,GetWindowLong(hwnd,GWL_ID));

Окно инициализации убиваю на очистке фона:
Код

case WM_ERASEBKGND:
        {
            DestroyWindow(hwnd);
            return (LRESULT)1;
        }

Может быть это правильней делать где-нибудь в другом месте?

Пока все устраивает. smile 
PM MAIL   Вверх
GremlinProg
Дата 12.4.2011, 11:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(mekhanikus @  12.4.2011,  12:53 Найти цитируемый пост)
Может быть это правильней делать где-нибудь в другом месте?

если я правильно понял вопрос,
вот такая обработка WM_CREATE просто не создаст окно,
Цитата(mekhanikus @  11.4.2011,  13:37 Найти цитируемый пост)
return –1;

и не придется его удалять

а место и в самом деле неподходящее, не надо так делать


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


Вольноопределяющийся
*


Профиль
Группа: Участник
Сообщений: 186
Регистрация: 16.6.2008
Где: Спасск-Дальний

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



Попробовал сделать
Код

return -1;

Приложение сразу закрывается.
Цитата(GremlinProg @  12.4.2011,  11:31 Найти цитируемый пост)
не надо так делать 

А как надо?
Интересует именно самоуничтожение.
PM MAIL   Вверх
GremlinProg
Дата 12.4.2011, 12:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(mekhanikus @  12.4.2011,  13:40 Найти цитируемый пост)
Приложение сразу закрывается.

а в какой процедуре обрабатывается WM_ERASEBKGND?
закрывается, значит одно из двух:
1. это главное окно и у него в WM_DESTROY стоит PostQuitMessage,
который завершает цикл обработки сообщений,
т.е. в таком случае надо пересмотреть логику программы,
либо перенести PostQuitMessage в то окно, закрытие которого действительно должно завершить приложение

2. при создании окна, после CreateWindow/Ex стоит проверка на валидность возвращенного дескриптора,
т.е. в таком случае эту проверку надо убрать
Цитата(mekhanikus @  12.4.2011,  13:40 Найти цитируемый пост)
А как надо?Интересует именно самоуничтожение.

например "отложенная" посылка (PostMessage) самому себе сообщения закрытия, типа WM_CLOSE


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


Вольноопределяющийся
*


Профиль
Группа: Участник
Сообщений: 186
Регистрация: 16.6.2008
Где: Спасск-Дальний

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



Цитата(GremlinProg @  12.4.2011,  12:02 Найти цитируемый пост)
1. это главное окно и у него в WM_DESTROY стоит PostQuitMessage,
который завершает цикл обработки сообщений,

Нет, это окно инициализации диалога MonthDlg.
Дочернее от диалога YearWnd - главного окна.
Все сообщения, кроме WM_CREATE и WM_ERASEBKGND, передаются в DefWindowProc.

Цитата(GremlinProg @  12.4.2011,  12:02 Найти цитируемый пост)
2. при создании окна, после CreateWindow/Ex стоит проверка на валидность возвращенного дескриптора,
т.е. в таком случае эту проверку надо убрать

Наверно такая проверка спрятана в процедуре CreateDialogParam.
Типа если один контрол не получился, значит - все ф топку.

Цитата(GremlinProg @  12.4.2011,  12:02 Найти цитируемый пост)
например "отложенная" посылка (PostMessage) самому себе сообщения закрытия, типа WM_CLOSE

Попробую. Когда её посылать?
PM MAIL   Вверх
GremlinProg
Дата 13.4.2011, 06:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(mekhanikus @  12.4.2011,  15:57 Найти цитируемый пост)
Попробую. Когда её посылать?

ну, опять же, если я правильно понял, то самоуничтожиться должен дочерний диалог

вот на счет дочерних окон, не уверен, удалит ли WM_CLOSE такой диалог (по документации на DefWindowProc - да, а вот на DefDlgProc - по моему, все таки нет),
хотя всегда можно перехватить в процедуре этого дочернего диалога WM_CLOSE и вызвать из него DestroyWindow,
тогда точно удалит

либо придумать какое-нить другое сообщение для удаления

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


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


Вольноопределяющийся
*


Профиль
Группа: Участник
Сообщений: 186
Регистрация: 16.6.2008
Где: Спасск-Дальний

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



Поставил PostMessage в конце обработки WM_CREATE в InitMonthProc.

Вроде бы все работает как надо: диалог создается, лишнее окно убирается.

Респект GremlinProg.

Вопрос можно считать решенным!
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "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.0563 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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