Member 13089825 Ответов: 2

Сохранение размера позиции и состояния windows в MFC


Если я вызываю графический интерфейс, а затем изменяю его размер и закрываю, то при повторном запуске он возвращается к исходному размеру.
он должен помнить старые ценности

Что я уже пробовал:

приведенный ниже метод получит intiate при закрытии GUI и запишет размер
void CMainFrame::OnDestroy()
{
m_bShuttingDown = истина;

WINDOWPLACEMENT wp;
GetWindowPlacement(&wp);
AfxGetApp()-&ГТ;WriteProfileBinary(то _t("универсальный"), то _t("РГ"), (LPBYTE)&ампер;РГ, оператор sizeof(РГ));
CFrameWndEx::OnDestroy();
}

приведенный ниже метод получит вызов при загрузке графического интерфейса пользователя

oid CMainFrame::OnShowWindow(BOOL bShow, UINT nStatus)
{
    CFrameWndEx::OnShowWindow(bShow, nStatus);

    if (bShow && !IsWindowVisible()) //The formal parameter bShow is true when the window is about to be shown, 
                                        //and false when it is about to be hidden
       
    {
       
        WINDOWPLACEMENT *lwp;
        UINT nl;
     
        if (AfxGetApp()->GetProfileBinary(_T("MainFrame"), _T("WP"), (LPBYTE*)&lwp, &nl))
        {
            SetWindowPlacement(lwp);           
           
            UpdateWindow();
            delete[] lwp;
        }
}the above method its returning old values but gui is positioning as per that values
could you please tell me if anything is wrong here

Richard MacCutchan

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

Member 13089825

я отладил ,значения восстанавливаются правильно, но графический интерфейс не обновляется с восстановлением значений

2 Ответов

Рейтинг:
2

Jochen Arndt

Похоже, вы использовали код из статьи CodeProject Сохранение размера позиции и состояния windows в MFC[^] но не прочитал его полностью.

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

[EDIT: другой подход, который я использовал в прошлом]
Сохранить помещение в CMainFrame::OnClose вместо OnDestroy.

Установите размещение в CMainFrame::OnCreate вместо OnShowWindow Однако при этом будет задана только позиция, а размер будет установлен позже при вызове ShowWindow от InitInstance требуя чтобы команда была передана сохранена:

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    // ... (call OnCreate of base class)
    
    WINDOWPLACEMENT *lwp;
    UINT nl;
    if (AfxGetApp()->GetProfileBinary(_T("MainFrame"), _T("WP"), (LPBYTE*)&lwp, &nl))
    {    
        // save show state
        m_nCmdShow = lwp->showCmd;
        // must set this to normal here
        lwp->showCmd = SW_SHOWNORMAL;
        SetWindowPlacement(lwp);
        delete[] lwp;
    }
    
    // ...
}

// To be called from InitInstance()
void CMainFrame::ShowWindowInitial()
{
    ShowWindow(m_nCmdShow);
    UpdateWindow();
}

BOOL CMyApp::InitInstance()
{
    // ...
    //CMainFrame pMainFrame = new CMainFrame;
    pMainFrame->ShowWindowInitial();
    // ...
}
[/РЕДАКТИРОВАТЬ]


Member 13089825

void CMainFrame::OnShowWindow(BOOL bShow, UINT nStatus)
{
CFrameWndEx::OnShowWindow(bShow, nStatus);

статические кумполу типа bool = истина;

если (bShow && !IsWindowVisible()
усилитель&;&амп; кумполу)
{
bOnce = ложь;

WINDOWPLACEMENT *lwp;
UINT nl;

если (AfxGetApp()-&ГТ;GetProfileBinary(то _t("универсальный"), то _t("РГ"), (LPBYTE*)&ампер;живые обои, усилителя;amp; НЛ))
{
SetWindowPlacement(lwp);
удалить[] lwp;
}
}
}
Все тот же вопрос

Jochen Arndt

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

Я прочитал это как:
- Возврат старых значений = данные, сохраненные при последнем выходе из программы, считываются: OK
- Но GUI позиционируется в соответствии с этими значениями = ?
"это" тогда будет относиться к считанным данным, которые являются правильными.

Member 13089825

Я прочитал это как:
- Возврат старых значений = данные, сохраненные при последнем выходе из программы, считываются: OK
- Но GUI позиционируется в соответствии с этими значениями = ? графический интерфейс не позиционируется в соответствии со значениями
"это" тогда будет относиться к считанным данным, которые являются правильными.

Jochen Arndt

Я обновил свое решение с помощью кода, используемого одним из моих приложений.
Если это тоже не работает, вам придется использовать отладчик, чтобы проверить, достигает ли ваш код вызова SetWindowPlacement и какие значения установлены.

Member 13089825

положение x и y обновляется правильно но ширина и высота не обновляются

Jochen Arndt

Смотрите мое обновленное решение.

Там x и y (позиция) применяются в OnCreate, а размер применяется при отображении окна.

Member 13089825

привет, Йохен,извини, что побеспокоил тебя
положение экрана, кажется, запоминается правильно, это размер экрана, который не запоминается

Jochen Arndt

Размер экрана неправильно хранится в реестре или он не применяется?
Обратите внимание также, что размер зависит от команды. Так что проверьте и это значение.

Однако мое обновленное решение должно работать.

Member 13089825

Размер экрана неправильно хранится в реестре или он не применяется?
его не применяют

// сохранить показать состояние
m_nCmdShow = wpl->showCmd;// выбрасывание ошибки типа неинициализированной переменной wpl используется

Jochen Arndt

Я еще не опубликовал код для чтения замены, которая обозначена

// Get placement here

Вы должны вставить код, который уже используется вами (читается из реестра). Не забудьте удалить wpl aftwerwards. И не вызывайте UpdateWindow (), когда делаете это из OnCreate().

Member 13089825

void CMainFrame::OnClose()
{

WINDOWPLACEMENT wp;
GetWindowPlacement(&wp);
AfxGetApp()-&ГТ;WriteProfileBinary(то _t("универсальный"), то _t("РГ"), (LPBYTE)&ампер;РГ, оператор sizeof(РГ));
CFrameWndEx::OnClose();
}



int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{



if (CFrameWndEx::OnCreate(lpCreateStruct) == -1)
возврат -1;
WINDOWPLACEMENT *lwp;
// Получить размещение здесь
UINT nl;
если (AfxGetApp()-&ГТ;GetProfileBinary(то _t("универсальный"), то _t("РГ"), (LPBYTE*)&ампер;живые обои, усилителя;amp; НЛ))
{
m_nCmdShow = lwp->showCmd;// m_nCmdShow я создал локально
// должен установить это в нормальное состояние здесь
lwp->showCmd = SW_SHOWNORMAL;
SetWindowPlacement(lwp);


удалить[] lwp;
}

все тот же вопрос

Jochen Arndt

m_nCmdShow должен быть членом вашего класса CMainFrame.

Вы реализовали CMainFrame::ShowWindowInitial() и вызвали его из InitInstance()?
Именно в этот момент применяется размер (при последующем вызове UpdateWindow (); вы можете поместить вызов также в ShowWindowInitial).

Как уже отмечалось: он здесь работает.
Если у вас все еще есть проблемы, вы должны отладить свое приложение; например, проверив фактические настройки размера на различных этапах.

Member 13089825

void CMainFrame::ShowWindowInitial()
{
OnShowWindow(m_nCmdShow);// мы не имеем какой-либо функции OnShowWindow()право (у нас есть только функции showwindow или OnShowWindow(типа bool bShow, uint с nStatus)
}

Jochen Arndt

Вы правы: там должен быть ShowWindow(int nCmdShow), а не обработчик OnShowWindow ().

Member 13089825

извините,я следовал тому же самому, но это не работает для меня(размер не обновляется в графическом интерфейсе, а позиция обновляется)
извините, что потратил ваше время впустую

Jochen Arndt

Как уже упоминалось: время для отладки.
Вы должны выяснить, где размер не применяется. Например, вы можете проверить размер до и после вызова ShowWindow() с помощью GetWindowRect() и GetWindowPlacement() и сравнить его с ожидаемыми значениями, считанными из реестра.

Рейтинг:
0

Michael Haephrati

Я обнаружил, что эти 2 функции работают на меня.

void MyDialog::LoadDialogPlacement()
{
	static WINDOWPLACEMENT last_wp = {};
	// Load last stored DB version
	WINDOWPLACEMENT *wp = new WINDOWPLACEMENT;
	GetStoredWindowPlacement(&wp);
	if (memcmp((void *)&last_wp, (const void *)wp, sizeof(WINDOWPLACEMENT)) == 0) return;
	memcpy((void *)&last_wp, (const void *)wp, sizeof(WINDOWPLACEMENT));
	SetWindowPlacement(wp);
	delete[] wp;

}
void MyDialog::SaveDialogPlacement()
{
	static WINDOWPLACEMENT last_wp = {};

	if (IsWindowVisible())
	{
		WINDOWPLACEMENT wp = {};
		wp.length = sizeof(WINDOWPLACEMENT);
		GetWindowPlacement(&wp);
		if (memcmp((void *)&last_wp, (const void *)&wp, wp.length) == 0) return;
		memcpy((void *)&last_wp, (const void *)&wp, wp.length);
		StoreWindowPlacement(&wp);
	}

}