Вход/Регистрация
Программирование на Visual C++. Архив рассылки
вернуться

Jenter Алекс

Шрифт:

Привет!

Хочу обратить внимание на то, что изменение формы окон при помощи SetWindowRgn не всегда правильно работает в старых версиях Windows – в частности, такая ситуация наблюдалась под Windows 95 (PLUS) не OSR 2.

Зато совершенно точно это работает под '98, NT, 2000.

– ------

Хочу предложить полезную уловку, позволяющую при использовании MFC-шаблонов документов управлять MDI-окнами из приложения. Этот трюк можно использовать при отображении разных категорий данных в различных окнах. При этом можно, в частности, автоматически переключать активные MDI-окна при обновлении данных в них.

Представьте библиотеку (класс), следующего вида:

class TReg {

public: 

 static CMapStringToPtr map;

 static BOOL RegisterTemplate(CString strName, CDocTemplate * ptr);

 static BOOL HasOpenViews(CString strName);

 static BOOL PostForAllViews(CString strName, UINT msg, WPARAM w, LPARAM p);

 static BOOL SendForAllViews(CString strName, UINT msg, WPARAM w, LPARAM p);

 static CDocTemplate * GetTemplate(CString strName);

 ... 

};

Зачем все элементы статические – легко понять, ведь у нас только один MDI-фрейм.

Далее, в методе WinApp::InitInstance при порождении шаблонов документов вместо (или вместе с) AddDocTemplate( CDocTemplate * ) записываем TReg::RegisterTemplate( "MyName", CDocTemplate * );

Здесь мы просто добавляем указатели шаблонов в словарь map.

С помощью метода GetTemplate мы можем извлечь указатель на шаблон из словаря по имени. Используя этот указатель, мы можем: 

– открыть новое окно при помощи DocTemplate::OpenDocumentFile;

– закрыть все окна, относящиеся к данному шаблону;

– отправить сообщение всем окнам данного шаблона:

for (POSITION pos= pTempl->GetFirstDocPosition; pos != NULL; ) {

 CDocument * pDoc= pTempl->GetNextDoc(pos);

 if (msg == NULL) pDoc->UpdateAllViews(NULL);

 else

for (POSITION p1= pDoc->GetFirstViewPosition; p1 != NULL; ) {

CView * pView= pDoc->GetNextView (p1);

pView->PostMessage (msg, w, l);

}

}

– проверить, имеются ли открытые окна, относящиеся к данному шаблону:

for (POSITION pos = pTempl->GetFirstDocPosition; pos != NULL; ) {

 CDocument * pDoc= pTempl->GetNextDoc(pos);

 for (POSITION p1 = pDoc->GetFirstViewPosition; p1 != NULL; ) {

CView * pView = pDoc->GetNextView(p1);

if (pView != NULL) return TRUE;

 }

}

return FALSE;

и т.д.

Активизация (всплывание наверх) MDI-окна в программе проще всего реализуется добавлением примерно такого метода класса CView:

void CMyView::DoActivate {

 CMDIChildWnd * pFrm = (CMDIChildWnd *)(GetParent);

 if (pFrm != NULL && IsWindow(pFrm->m_hWnd)) pFrm->MDIActivate;

}

Victor Yakovlev

Да, это может быть полезно, особенно для тех, кто сталкивался (или кому еще только предстоит столкнуться) с разработкой сложных MDI-приложений – они знают, как трудно добиться правильной совместной работы всех дочерних окон. 

ВОПРОС-ОТВЕТ

Q. Нужно изменить шрифт у одного элемента типа CStatic. Делаю это функцией SetFont(CFont font). Фонт меняется у элемента … и у всего окна :(. Включая кнопки и другие элементы типа static. Мне его надо было толстым сделать, так у меня такие кнопки стали — загляденье:)) Кто-нибудь знает в чем дело и как решить ?

LiMar

A. Присланные ответы на этот вопрос сводились к двум следующим: 

1) сделать класс-наследник от CStatic и перекрыть функцию прорисовки – OnPaint;

2) вызывать метод SetFont именно объекта CStatic (или указателя на этот контрол), а не всего диалога.

Порекомендовавшие первый способ явно забыли правило "бритвы" Оккама: не множить сущностей без нужды. (Кстати, нам, программистам, это правило особенно полезно.) Если для того, чтобы поменять шрифт, нужно создавать новый класс, ну уж извините… Этим способом, конечно, можно пользоваться, но я думаю, только в тех случаях, когда без этого не обойтись.

Итак, второй ответ был больше всего похож на искомую истину. Но "похож" – это еще не значит "есть", так что я решил проверить. Сделал простое SDI-приложение, и попробовал в окне About у одной из надписей поменять шрифт. 

Как же я был рад, когда он в самом деле изменился!!!

…Правда, на совершенно не тот, который я хотел. Да и размерчик прежний остался… Это было весело – в любом случае он ставил шрифт System, хотя (у меня много шрифтов!) я прописывал разные. Никакого результата. Способ No.2 у меня не работал. Либо он был неправильный, либо, как впоследствии оказалось, правильный не до конца.

Через некоторое время мне это надоело, и я решил, что раз уж не оказалось пророков среди читателей, пророком придется стать самому (это метафора;)

Самое обидное то, что ответ даже не пришлось искать ! Он лежал на самом видном месте в MSDN. Я ввел "SetFont" в строке поиска и мгновенно обнаружил интереснейшую статью с говорящим само за себя названием – "Correct Use of the SetFont Function in MFC". 

Суть статьи сводилась к следующему:

Обычно в SetFont передают указатель на шрифт – объект CFont. Так вот, обязательно нужно проследить , чтобы этот объект не уничтожился раньше, чем тот контрол, для которого он создается!

Итак, как было у меня раньше (или "способ №2"):

BOOL CAboutDlg::OnInitDialog {

 CDialog::OnInitDialog;

 CFont times;

 times.CreatePointFont(100, "Times New Roman");

 m_Static.SetFont(&times);

 times.DeleteObject;

 return TRUE; 

}

m_Static — переменная, представляющая соответствующий Static-контрол. Вместо нее можно воспользоваться указателем, возвращаемым ф-цией GetDlgItem. Как вы видите, объект CFont уничтожается сразу же после вызова SetFont.

А вот как надо было сделать:

class CAboutDlg : public CDialog {

 …

private:

 CStatic m_Static;

 CFont m_fntTahoma; // добавляем шрифт в диалог

}

BOOL CAboutDlg::OnInitDialog {

 CDialog::OnInitDialog;

 m_fntTahoma.CreatePointFont(100, "Tahoma");

 m_Static.SetFont(&m_fntTahoma);

 return TRUE; 

}

BOOL CAboutDlg::DestroyWindow {

 m_fntTahoma.DeleteObject;

 return CDialog::DestroyWindow;

}

Здесь все работает как надо. Вскоре, когда надоела Tahoma, я уже наслаждался отлично выглядевшей готической надписью. (Кстати, тут возникает еще вопрос – получается, чтобы нужный шрифт был всегда доступен, нужно распространять его вместе с приложением? Конечно, это не относится к стандартным Windows-шрифтам, типа Arial, Times, Tahoma или Courier. Лучше все-таки обходиться ими, когда возможно).

  • Читать дальше
  • 1
  • ...
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: