Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Visual C++/MFC/WTL > Управление окном при создании


Автор: GGoga 1.7.2007, 17:40
Здравствуйте, уважаемые господа программисты. Помогите разобраться с проблемой начинающему программисту.

А проблема заключается в следующем:
С помощью мастера MFC создаю SDI приложение, представление которого наследую от CFormView. Я хочу, чтобы запускаемое окно имело свойства, которые требуются мне, а именно: положение окна центрировалось относительно экрана, имело высоту и ширину пропорциональную экрану, а также загружало иконку, которую создал я. Чтобы это реализовать, я прописываю следующий код в обработчике InitInstance() класса приложения:
Код

BOOL CEmbadedDBApp::InitInstance()
{
   ...
    // Parse command line for standard shell commands, DDE, file open
    CCommandLineInfo cmdInfo;
    ParseCommandLine(cmdInfo);


    // Dispatch commands specified on the command line.  Will return FALSE if
    // app was launched with /RegServer, /Register, /Unregserver or /Unregister.

// При троссировке первое стандартное окно появляется вот на этой строке!!!
    if (!ProcessShellCommand(cmdInfo))
        return FALSE;


//*******************Мой код***************************//
    // Устанавливаем иконку окна
    m_pMainWnd->SetIcon(LoadIcon(IDI_MY_ICON), TRUE);
    // Устанавливаем окно поверх остальных
    if(!m_pMainWnd->SetForegroundWindow())
        MessageBox(m_pMainWnd->GetSafeHwnd(),_T("Не возможно установить окно поверх остальных окон!"),
        _T("Внимание"), MB_OK | MB_ICONEXCLAMATION | MB_ICONWARNING);
    // Устанавливаем размер окна
    m_pMainWnd->MoveWindow(&m_WRect, TRUE);
    // Центрируем положение окна
    m_pMainWnd->CenterWindow();
//*****************************************************//


    m_pMainWnd->ShowWindow(SW_SHOW);
    m_pMainWnd->UpdateWindow();
    // call DragAcceptFiles only if there's a suffix
    //  In an SDI app, this should occur after ProcessShellCommand
    

    return TRUE;
}



Однако, при запуске программы сначала запускается стандартное окошко (созданное приложением), которое имеет собственные размеры, положение на экране и иконку, потом оно исчезает и запускается мое окно с прописанными свойствами (появление и исчезновение первого окна длится около 1 сек. - мелочь, но не приятно...). Я хочу этого в своем мелком проекте избежать, пусть он хоть и небольшой и пишется для получения навыков в программировании, но будет, по крайней мере, красивым smile

Так вот у меня вопрос, что мне нужно сделать, чтобы добиться требуемого результата? Может мой код прописать в другом обработчике, или что-то добавить для скрытия из виду стандартного окна, или убрать что-то в автоматически сгенерированном коде?

Подскажите, кто знает решение проблемы, заранее ОГРОМНОЕ СПАСИБО!!!

Автор: Прохожий 2.7.2007, 10:02
В CMainFrame есть такая функция где и задаётся нужный стиль и положение окна
Код

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
    if( !CFrameWnd::PreCreateWindow(cs) )
        return FALSE;
    // TODO: Modify the Window class or styles here by modifying
    //  the CREATESTRUCT cs
//  ....... ВОТ здесь и вставляешь что треба ............
//  ....... Например ....................................................
    cs.dwExStyle |= WS_EX_TOOLWINDOW;
// ......... Это .....
    return TRUE;
}


Автор: GGoga 2.7.2007, 11:18
Цитата(Прохожий @ 2.7.2007,  10:02)
В CMainFrame есть такая функция где и задаётся нужный стиль и положение окна
Код

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
    if( !CFrameWnd::PreCreateWindow(cs) )
        return FALSE;
    // TODO: Modify the Window class or styles here by modifying
    //  the CREATESTRUCT cs
//  ....... ВОТ здесь и вставляешь что треба ............
//  ....... Например ....................................................
    cs.dwExStyle |= WS_EX_TOOLWINDOW;
// ......... Это .....
    return TRUE;
}


А как тогда загрузить иконку, чтобы не появлялась иконка по умолчанию? Это можно сделать в PreCreateWindow? И еще такой вопрос: можно ли установить позицию окна в центре относительно экрана не производя расчетов? Просто переменная CREATESTRUCT& cs имеет для этого 2 свойства: x и y, и чтобы разместить собственное окно центрировано, необходимо произвести соответствующие расчеты координат левого верхнего угла прямоугольника... Можно ли это сделать не производя расчетов, в том смысле, есть ли уже какая-нибудь стандартная функция для этого?


Заранее спасибо!

Автор: Прохожий 2.7.2007, 12:17
Цитата

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

Проще всего заменить имеющуюся своей или использовать 
SetIcon(AfxGetApp()->LoadIcon(IDI_ICON1), FALSE);
Тамже в функции 
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
Цитата

Просто переменная CREATESTRUCT& cs имеет для этого 2 свойства: x и y, и чтобы разместить собственное окно центрировано, необходимо произвести соответствующие расчеты координат левого верхнего угла прямоугольника... Можно ли это сделать не производя расчетов, в том смысле, есть ли уже какая-нибудь стандартная функция для этого?


Есть что-то с ходу не могу сказать. Может как-то можно использовать вот это CenterWindow(CWnd*); навскидку?

Автор: GGoga 2.7.2007, 17:17
Цитата(Прохожий @ 2.7.2007,  12:17)
Проще всего заменить имеющуюся своей или использовать 
SetIcon(AfxGetApp()->LoadIcon(IDI_ICON1), FALSE);
Тамже в функции 
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)

Я почему-то в обработчиках данного класса вообще не могу получить указатель на главное окно??? Может я что-то не то делаю?


У меня еще вот такой вопрос: почему я из обработчика BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) не могу получить указатель на главное окно? И вообще, можно ли это сделать?
А делаю я это следующим образом:

Код

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
    if(!CFrameWnd::PreCreateWindow(cs))
        return FALSE;

    CWnd* pScreen,
    
Код

//Вот здесь я пытаюсь получить указатель на главное окно:
          *pWnd = AfxGetMainWnd();
    //Проверяю на получение корректного результата:
    if(pWnd != NULL)
        pWnd->CenterWindow();//В итоге окно не центрируется относительно экрана, потому что указатель равен 0!!! И я не знаю, в чем проблема...
            

    // Определение разрешения экрана
    CRect pWndRect;
    if(!(pScreen = GetDesktopWindow()))
    {
        MessageBoxW(_T("Не возможно получить дескриптор экрана. Будут использованы настройки по умолчанию!"),
            _T("Внимание"), MB_OK | MB_ICONEXCLAMATION | MB_ICONWARNING);
        pWndRect.top = 0;
        pWndRect.left = 0;
        pWndRect.bottom = 800;
        pWndRect.right = 600;
    }
    else
        pScreen->GetWindowRect(&pWndRect);

    // Установить ширину и высоту формы
    // Уменьшение размеров окна как 1:1,5 по отношению к экрану
    cs.cx = static_cast<int>(static_cast<double>(pWndRect.right) / 1.5) - 2;
    cs.cy = static_cast<int>(static_cast<double>(pWndRect.bottom) / 1.5)  - 2;
    
Код

    //Приходится центрировать его вручную...
    cs.x = (pWndRect.right - cs.cx) / 2;
    cs.y = (pWndRect.bottom - cs.cy) / 2;

    cs.style = WS_OVERLAPPED | WS_CAPTION | FWS_ADDTOTITLE 
             | WS_MINIMIZEBOX | WS_SYSMENU;
    
    return TRUE;
}




Вот так я пытаюсь (выделено жирным) управлять главным окном из вышеуказанного обработчика, только не могу получить на него (на главное окно) указатель... Подскажите, можно ли так делать, а если можно, то почему в результате возвращается 0-вой результат?

Заранее СПАСИБО!!!

Добавлено через 5 минут и 38 секунд
Иконку сделал как Вы и говорили - изменил ту, что по умолчанию, но все равно, хотелось бы знать, как это можно сделать программно.

Автор: GGoga 2.7.2007, 18:48
Проблему с предыдущим вопросом решил, оказывается, что главное окно еще не существует в момент вызова обработчика BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) класса CMainFrame (формы). И как всегда, решение одного вопроса порождает новый... :( 

А можно ли (если можно, то в каком обработчике) вообще в этом классе (классе формы) в момент, когда окно еще не является видимым для пользователя произвести его настройки (центрировать, установить размеры, загрузить иконку и т.д.)? Просто я еще не совсем разбираюсь с принципами того, как и что за чем вызывается, поэтому, пожалуйста, не удивляйтесь моим столь тупым вопросам... 

Просто мне кажется слишком примитивным, например, центрировать окно с помощью вычисления соответсвующих координат левого верхнего угла, если для этого уже есть готовая функция (зачем изобретать велосипед?..), поэтому я и интересуюсь тем, как и где это можно сделать (получить указатель на главное окно) в классе формы?

Заранее СПАСИБО!

Автор: Прохожий 3.7.2007, 06:53
Цитата

Иконку сделал как Вы и говорили - изменил ту, что по умолчанию, но все равно, хотелось бы знать, как это можно сделать программно. 


Ну я тама указал и програмный способ
вот в ф-и 
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)

SetIcon(AfxGetApp()->LoadIcon(IDI_ICON1), FALSE);

А насчёт центрирования окна относительно экрана и вааще определения размеров относительно рабочего стола, просто никогда не занимался. Но может через
 GetDesktopWindow()
Можно получить что.
?
И ещё вот здесь
 http://www.firststeps.ru/ 
почитай тама МНОГО ОТВЕТОВ на МНОГО ВОПРОСОВ  smile 

Автор: GGoga 3.7.2007, 21:37
Цитата(Прохожий @ 3.7.2007,  06:53)
Ну я тама указал и програмный способ вот в ф-и  int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) - SetIcon(AfxGetApp()->LoadIcon(IDI_ICON1), FALSE);

Пробовал так, ничего не получилось :( Так что пришлось менять саму иконку, чтобы не было мелькания.

Добавлено через 4 минуты и 51 секунду
Цитата(Прохожий @ 3.7.2007,  06:53)
А насчёт центрирования окна относительно экрана и вааще определения размеров относительно рабочего стола, просто никогда не занимался. Но может через GetDesktopWindow()

Да именно так я и делал, хотя можно еще так:

Код

CRect workAreaRect;
SystemParametersInfo(SPI_GETWORKAREA, 0, &workAreaRect, 0);
cs.cx = workAreaRect.Width() / 1.5;
cs.cy = workAreaRect.Height() / 1.5;


А вообще все реализовал следующим образом:
Код

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
    if(!CFrameWnd::PreCreateWindow(cs))
        return FALSE;

    CWnd* pScreen;
    
    // Определение разрешения экрана
    CRect pWndRect;
    if(!(pScreen = GetDesktopWindow()))
    {
        MessageBoxW(_T("Не возможно получить дескриптор экрана. Будут использованы настройки по умолчанию!"),
            _T("Внимание"), MB_OK | MB_ICONEXCLAMATION | MB_ICONWARNING);
        pWndRect.top = 0;
        pWndRect.left = 0;
        pWndRect.bottom = 800;
        pWndRect.right = 600;
    }
    else
        pScreen->GetWindowRect(&pWndRect);

    // Установить ширину и высоту формы
    // Уменьшение размеров окна как 1:1,5 по отношению к экрану
    cs.cx = static_cast<int>(static_cast<double>(pWndRect.right) / 1.5) - 2;
    cs.cy = static_cast<int>(static_cast<double>(pWndRect.bottom) / 1.5)  - 2;
    
    cs.x = (pWndRect.right - cs.cx) / 2;
    cs.y = (pWndRect.bottom - cs.cy) / 2;

    cs.style = WS_OVERLAPPED | WS_CAPTION | FWS_ADDTOTITLE 
            | WS_MINIMIZEBOX | WS_SYSMENU;
    
    return TRUE;
}


Автор: Прохожий 4.7.2007, 12:33
Ну незнаю чем не работает смена иконки вот как здесь
Код

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
        return -1;
    
    if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
        | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
        !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
    {
        TRACE0("Failed to create toolbar\n");
        return -1;      // fail to create
    }

    if (!m_wndStatusBar.Create(this) ||
        !m_wndStatusBar.SetIndicators(indicators,
          sizeof(indicators)/sizeof(UINT)))
    {
        TRACE0("Failed to create status bar\n");
        return -1;      // fail to create
    }

    // TODO: Delete these three lines if you don't want the toolbar to
    //  be dockable
//==== А ВОТ МЫ ИКОНКУ ПОМЕНЯЛИ ПРИЧЁМ БЕЗ ПРОБЛЕМ =========
    SetIcon(AfxGetApp()->LoadIcon(IDR_TESTSDTYPE), TRUE);
//====================================================

    m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
    EnableDocking(CBRS_ALIGN_ANY);
    DockControlBar(&m_wndToolBar);

    return 0;
}


Работает за всю мазуту  smile 

Автор: GGoga 4.7.2007, 19:07
Да, действительно, так иконка устанавливается без проблем. Спасибо за полезный совет!

Автор: Gerk 9.7.2007, 20:28
Ну как еще один способ центрирования окна  smile 


Код

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
   // Размер окна будет равен 1/3 и окно будет отцентрировано
   cs.cy = ::GetSystemMetrics(SM_CYSCREEN) / 3;
   cs.cx = ::GetSystemMetrics(SM_CXSCREEN) / 3;
   cs.y = ((cs.cy * 3) - cs.cy) / 2;
   cs.x = ((cs.cx * 3) - cs.cx) / 2;

    return CFrameWnd::PreCreateWindow(cs);
}

Автор: Earnest 10.7.2007, 09:39
Попробуй еще переопределить функцию CFrameWnd::ActivateFrame: вроде бы она приходит до появления кона на экране, и там можно его отцентровать и т.д. 

Автор: GGoga 11.7.2007, 12:23
Цитата(Gerk @ 9.7.2007,  20:28)
Ну как еще один способ центрирования окна...

Спасибо! Знать лишний способ никогда не помешает smile

Автор: GGoga 11.7.2007, 12:40
Цитата(Earnest @ 10.7.2007,  09:39)
Попробуй еще переопределить функцию CFrameWnd::ActivateFrame: вроде бы она приходит до появления кона на экране, и там можно его отцентровать и т.д.

Спасибо smile Этот способ тоже работает, только с его помощью центрирование происходит постоянно при активации формы, даже если пользователь переместит окно в другое место, что не очень удобно, хотя знать еще один способ центрирования окна никогда не помешает smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)