Руководство/лучшие практики по MFC MDI

Я взялся за задачу написать собственный эмулятор терминала. Если проект когда-нибудь воплотится в жизнь, он станет точной копией VanDyke SecureCRT.

Он должен поддерживать протоколы Telnet и SSH, а если дела пойдут хорошо, возможно, и больше.

На данный момент я работаю над самым простым из них — Telnet.

Приложение представляет собой MFC MDI, и здесь мне нужен ваш совет. Как лучше его структурировать?

  • Создать один шаблон документа для каждого протокола? Это кажется ужасной тратой, поскольку большая часть кода останется прежней.

  • Должно ли все быть сделано в классе Document? И есть ли просмотр только для отображения?

  • Или пусть представление выполняет всю работу по подключению, чтению пользовательского ввода и отображению вывода сервера?

  • Должно ли быть два представления? По одному на каждый протокол? Насколько я понимаю, это не так-то просто сделать и лучший способ сделать это возвращает меня к сценарию с двумя шаблонами документов.

Я написал работающий клиент Telnet для командной строки и на данный момент я дошел до того момента, когда мне нужно решить, как поступить с Windows.

Архитектура представления документов основана на MVC. С этим связан паттерн Observer. В общем, представления должны выполнять часть графического интерфейса/презентации, а документ - часть «модели».

gast128 06.05.2024 22:59

Избегайте MDI, если можете. Это модель пользовательского интерфейса, которая еще не устарела. Вы столкнетесь с ошибками на системном уровне, которые обычно не имеют решения.

IInspectable 08.05.2024 08:53

Спасибо @IInspectable за комментарий. Я не знаю, как я придерживался MDI. Тем не менее, это хобби/учебный проект. По профессии я не программист, поэтому какие бы знания я ни получил от этого, это будет плюс. Вдобавок ко всему, большая часть кода, который я пишу, вполне может быть использована в следующем проекте, когда мне будет достаточно MDI :D

NiemandDenDuKennst 10.05.2024 21:53
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
55
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В MFC вы обычно мало работаете (я бы сказал вообще) с классом шаблона документа. Шаблон документа — это ассоциация идентификатора ресурса с документом, фреймом-окном и классом представления. Платформа выполняет все свои операции, и я не понимаю, почему может потребоваться изменить ее поведение. Вместо этого вы создаете экземпляры класса CSingleDocTemplate (SDI) или CMultiDocTemplate (MDI) — по одному для каждой желаемой комбинации — в члене InitInstance() класса вашего приложения.

Одним из решений может быть:

  • Определите два типа документов(1) (для Telnet и SSH) и два экземпляра шаблона документа в CWinApp::InitInstance(), и я бы сказал, сохраните два указателя экземпляра.
  • Как предложено в комментарии выше, такие операции, как подключение к серверу, отправка или получение данных и т. д., должны выполняться в классе документа.
  • Класс представления должен выполнять такие действия, как чтение вводимых пользователем данных и представление данных, полученных классом документа (2)(3).
  • Представление считается объектом графического интерфейса. Однако он может изменять данные в связанном с ним документе (GetDocument()) напрямую или, что предпочтительнее, через функции-члены документа.

(1) Если вы обнаружите, что данные и/или операции двух протоколов очень похожи или почти идентичны, поэтому такая реализация была бы «ужасной тратой», вы можете определить общего предка или «базовый» класс документа (с помощью некоторые виртуальные или чисто виртуальные члены) и измените два класса документов так, чтобы они наследовались от этого, а не от CDocument.
(2) Совет по реализации: проверьте функции UpdateData(), OnUpdate() и UpdateAllViews().
(3) Возможно, вы захотите использовать отдельные потоки для операций подключения/отправки/чтения, особенно если вы подключаетесь к нескольким серверам и/или ваш API является только синхронным/блокирующим. Эти операции могут «заморозить» ваше приложение до тех пор, пока сервер не ответит.

Чтобы написать «чистый» MFC, попытайтесь структурировать свою программу так, чтобы класс(ы) документа не имел своих классов представления, т. е. класс документа не должен «знать» или делать предположения о своих представлениях. Для выполнения специальных обновлений вы можете закодировать необходимую информацию в параметрах #include и lHint функции pHint; вызов UpdateAllViews() означает полное обновление для всех представлений документа.

Определить два или более классов представления не особенно сложно, по крайней мере, я не понимаю, почему. Вы даже можете найти примеры использования двух или трех классов представления для одного и того же документа, например «графического» и «форменного», в одном дочернем фрейме MDI или в отдельных дочерних фреймах (в этом случае фреймворк называет их , например Документ1[1], Документ1[2] и т. д.). И если операции представления по существу одинаковы, вы можете просто определить один тип представления и вызвать виртуальные функции-члены базового класса документа (фактически это вызовет переопределенные функции).

Большое спасибо. Я буду следовать этому подходу. Ваше здоровье

NiemandDenDuKennst 07.05.2024 20:50

Другие вопросы по теме