Привет!
Хочу обратить внимание на то, что изменение формы окон при помощи 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;
}