На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела Visual C++ / MFC / WTL (далее Раздела)
1) На Раздел распространяются все Правила Форума.
2) Перед тем, как создать новый топик, убедитесь, что Вы читали Правила создания тем в Разделе.
3) Вопросы, не связанные с программированием (настройки MS Visual Studio, книги, библиотеки и т.д.),
обсуждаются в разделе C/C++: Прочее
4) Вопросы разработки .NET (Windows Form, C++/CLI и т.п.) приложений на Visual C++/C# обсуждаются в разделе .NET.
5) Нарушение Правил может повлечь наказание со стороны модераторов.

Полезные ссылки:
user posted image FAQ Раздела user posted image Обновления для FAQ Раздела user posted image Поиск по Разделу user posted image MSDN Library Online
Модераторы: ElcnU
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> динамическое создание контролов , Detach
    Здорово коллеги! :D

    пытаюсь понять детали MFC, я знаю что есть такая функция CWnd::Detach(), но не могу понять почему след код не пашет:
    ExpandedWrap disabled
      BOOL CInsideMFCDlg::OnInitDialog()
      {
          CDialog::OnInitDialog();
       
       
          CEdit edit;
          edit.Create(WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL, CRect(100, 50, 160, 73), this, 1001);
          edit.SetWindowText(_T("run-time created"));
          HWND hEdit = edit.Detach(); //<-- ASSERT
          TRACE("edit.m_hWnd = 0x%X, hEdit = 0x%X\n", edit.m_hWnd, hEdit);
          
          
          return TRUE;  // return TRUE  unless you set the focus to a control
      }


    Выхлоп :D:
    ExpandedWrap disabled
      edit.m_hWnd = 0x0, hEdit = 0x250608
      Program: C:\WINDOWS\SYSTEM32\mfc120ud.dll
      File: f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\wincore.cpp
      Line: 430


    там я обнаружил след:
    ExpandedWrap disabled
      LRESULT CALLBACK
      AfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
      {
          // special message which identifies the window as using AfxWndProc
          if (nMsg == WM_QUERYAFXWNDPROC)
              return 1;
       
          // all other messages route through message map
          CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);    
          ASSERT(pWnd != NULL);   //<------------------------ это строка 430
          ASSERT(pWnd==NULL || pWnd->m_hWnd == hWnd);
          if (pWnd == NULL || pWnd->m_hWnd != hWnd)
              return ::DefWindowProc(hWnd, nMsg, wParam, lParam);
          return AfxCallWndProc(pWnd, hWnd, nMsg, wParam, lParam);
      }

    ясно что вызов FromHandlePermanent() возвращает 0, т.о. нельзя юзать Detach для контролов?

    пс. я знаю что можно сделать так:
    ExpandedWrap disabled
      BOOL CInsideMFCDlg::OnInitDialog()
      {
          CDialog::OnInitDialog();
       
       
          CEdit* edit = new CEdit;
          edit->Create(....);

    или так:
    ExpandedWrap disabled
      BOOL CInsideMFCDlg::OnInitDialog()
      {
          CDialog::OnInitDialog();
       
      // сделать mEdit членом класса
          mEdit.Create(....);

    но мне не понятно почему нельзя юзать Detach в первом примере.
    Сообщение отредактировано: Cfon -
      Там для этих классов, по-моему, нужно делать что-то типа UnsubclassWindow
        Цитата Олег М @
        Там для этих классов, по-моему, нужно делать что-то типа UnsubclassWindow

        надо по гуглить :D позже отпишусь.

        Добавлено
        спс! работает :yes:
        Detach заменил на UnsubclassWindow :victory:
        ExpandedWrap disabled
          BOOL CInsideMFCDlg::OnInitDialog()
          {
              CDialogEx::OnInitDialog();
              
              static HWND hEdit;
              if (hEdit != NULL)
              {
                  TRACE("DestroyWindow\n");
                  ::DestroyWindow(hEdit); //<--- надо ли его удалять?
              }
           
              CEdit edit;
              edit.Create(WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL, CRect(100, 50, 160, 73), this, 1001);
              edit.SetWindowText(_T("run-time created"));
              //hEdit = edit.Detach();
              hEdit = edit.UnsubclassWindow(); //<--- все пучком
              TRACE("edit.m_hWnd = 0x%08X, hEdit = 0x%08X\n", edit.m_hWnd, hEdit);
           
           
              
              return TRUE;  // return TRUE unless you set the focus to a control
                            // EXCEPTION: OCX Property Pages should return FALSE
          }

        Выхлоп :D
        ExpandedWrap disabled
          edit.m_hWnd = 0x00000000, hEdit = 0x001507C4
          DestroyWindow
          edit.m_hWnd = 0x00000000, hEdit = 0x001A0100
          DestroyWindow
          edit.m_hWnd = 0x00000000, hEdit = 0x0022073A

        Кстати в приведенном выше примере надо ли удалять окно созданого конторла? оно вообще еще существует? :unsure:
        возможно при закрытии диалога также удаляются все окна контролов? что там с сохраненным дескриптором hEdit он валиден?
        возможно это лишнее телодвижение? :D
        я не силен в WinAPI имеет ли вызов DestroyWindow в моем случае профит? или все уже сделано при закрытии родительского окна диалога? :unsure:

        сама функция DestroyWindow не падает, чтобы я туда не передал, передаю разный мусор ей похер :D
        ::DestroyWindow((HWND)0x100000);
        думаю она проверяет валидность дескриптора и уже потом делает зачистку, так что я не уверен в необходимости вызова в моем случае DestroyWindow.
        Сообщение отредактировано: Cfon -
          А что ты вообще пытаешься сделать?
            Ничего :D
            Так что DestroyWindow тут нужен или лишнее это? :unsure:
              Ну, удалять ресурсы всегда нужно. Как правильно удалять окно не скажу, не помню. Вполне возможно, что DestroyWindow достаточно.
              Просто я посмотрел свой древний код и нигде не нашел, чтоб использовался UnsubclassWindow. Наоборот, SubclassWindow и SubclassDlgItem - довольно много. Чтоб привязать свои классы к контролам.
              Поэтому и спросил.

              Добавлено
              Цитата Cfon @
                static HWND hEdit;
                  if (hEdit != NULL)
                  {

              Кстати, ты бы здесь хотя бы вот так сделал static HWND hEdit = NULL;
                Цитата Олег М @
                Ну, удалять ресурсы всегда нужно. Как правильно удалять окно не скажу, не помню. Вполне возможно, что DestroyWindow достаточно.
                Просто я посмотрел свой древний код и нигде не нашел, чтоб использовался UnsubclassWindow. Наоборот, SubclassWindow и SubclassDlgItem - довольно много. Чтоб привязать свои классы к контролам.
                Поэтому и спросил.

                Добавлено
                Цитата Cfon @
                  static HWND hEdit;
                    if (hEdit != NULL)
                    {

                Кстати, ты бы здесь хотя бы вот так сделал static HWND hEdit = NULL;

                ну да в данном случае вообще лучше сделать Эдит членом класса и не париться. я просто изучаю MFC и UnsubclassWindow здесь чисто для понимания взаимодействия компонентов MFC ;)
                да и я сомневаюсь что здесь надо явно удалять окно эдит, вроде как при создании здесь указывается родитель а когда он удаляеься то удаляются все дочерние окна так?
                и разве статик переменная не иниц нулевым значением не явно? :)

                Добавлено
                кажется понял почему нельзя юзать Detach в случае окон :D
                ответ нашёл в этой статье:
                https://www.codeproject.com/Articles/535/Attaching-and-Detaching-Objects
                см раздел "When Detach is not good enough: CDialog and modeless dialogs".
                Сообщение отредактировано: Cfon -
                  Цитата Cfon @
                  да и я сомневаюсь что здесь надо явно удалять окно эдит, вроде как при создании здесь указывается родитель а когда он удаляеься то удаляются все дочерние окна так?

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

                  Добавлено
                  Цитата Cfon @
                  и разве статик переменная не иниц нулевым значением не явно?

                  То же самое. Может и явно, не знаю, но читабельности твоему коду не добавляет.
                    Цитата Олег М @
                    Цитата Cfon @
                    да и я сомневаюсь что здесь надо явно удалять окно эдит, вроде как при создании здесь указывается родитель а когда он удаляеься то удаляются все дочерние окна так?

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

                    Добавлено
                    Цитата Cfon @
                    и разве статик переменная не иниц нулевым значением не явно?

                    То же самое. Может и явно, не знаю, но читабельности твоему коду не добавляет.

                    да это понятно, но хотелось бы ясно представлять всю картину происходящего :D
                      Цитата Cfon @
                      да это понятно, но хотелось бы ясно представлять всю картину происходящего

                      Картина, я так понимаю, это когда ты вызываешь функцию, например DestroyWindow, со случайном параметром? Попробуй проделать подобные действия в линуксе. Там твоя программа просто свалится нахрен. Винды они очень дружественны как для пользователя, так и для разработчика. Но, привыкать не советую.
                        Цитата Олег М @
                        Цитата Cfon @
                        да это понятно, но хотелось бы ясно представлять всю картину происходящего

                        Картина, я так понимаю, это когда ты вызываешь функцию, например DestroyWindow, со случайном параметром? Попробуй проделать подобные действия в линуксе. Там твоя программа просто свалится нахрен. Винды они очень дружественны как для пользователя, так и для разработчика. Но, привыкать не советую.

                        я и не думал, это тестовый пример :D
                          ну как я и предполагал DestroyWindow здесь не требуется, сделал проверку возврата:
                          ExpandedWrap disabled
                                static HWND hEdit;
                                if (hEdit != NULL)
                                {
                                    TRACE("DestroyWindow\n");
                                    BOOL ret = ::DestroyWindow(hEdit);
                                    TRACE("ret = %d\n", ret);
                                }

                          Выхлоп :D
                          ExpandedWrap disabled
                            edit.m_hWnd = 0x00000000, hEdit = 0x00190728
                            DestroyWindow
                            ret = 0
                            edit.m_hWnd = 0x00000000, hEdit = 0x003507C2
                            DestroyWindow
                            ret = 0
                            edit.m_hWnd = 0x00000000, hEdit = 0x001B0728

                          согласно описанию функции DestroyWindow https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms632682(v=vs.85).aspx
                          Цитата
                          If the function succeeds, the return value is nonzero.
                          If the function fails, the return value is zero. To get extended error information, call GetLastError.

                          т.е. я делаю вывод что что эдит, а именно его окно, при повторном входе в OnInitDialog был уже удален :)
                          Вопросы? :D

                          в догонку код возврата GetLastError - 1400: "Invalid window handle" :)
                          Сообщение отредактировано: Cfon -
                            Цитата Cfon @
                            т.е. я делаю вывод что что эдит, а именно его окно, при повторном входе в OnInitDialog был уже удален

                            Так и есть
                            Цитата

                            If the specified window is a parent or owner window, DestroyWindow automatically destroys the associated child or owned windows when it destroys the parent or owner window. The function first destroys child or owned windows, and then it destroys the parent or owner window.


                            Только эти вещи лучше выяснять не таким, несколько диковатым, способом. Я обычно смотрел какие сообщения приходят окну, при помощи Spy++
                              Цитата Олег М @
                              Только эти вещи лучше выяснять не таким, несколько диковатым, способом. Я обычно смотрел какие сообщения приходят окну, при помощи Spy++

                              а я люблю дикий TRACE :D

                              интересно как ты узнаешь Спаем что окно эдит было удалено в моем случае? :unsure:

                              а все понял :D
                              Сообщение отредактировано: Cfon -
                                Цитата Cfon @
                                да это понятно, но хотелось бы ясно представлять всю картину происходящего :D

                                Цитата Cfon @
                                вроде как при создании здесь указывается родитель а когда он удаляеься то удаляются все дочерние окна так?

                                Всегда читай документацию по функциям, которые ты изучаешь, и вопросы все отпадут сами собой:
                                https://msdn.microsoft.com/ru-ru/library/wi...2(v=vs.85).aspx
                                Цитата
                                If the specified window is a parent or owner window, DestroyWindow automatically destroys the associated child or owned windows when it destroys the parent or owner window. The function first destroys child or owned windows, and then it destroys the parent or owner window.
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0540 ]   [ 17 queries used ]   [ Generated: 24.04.24, 09:25 GMT ]