15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


Toolbar out of visible area.

Poul A. Costinsky -- wizsofti@datasrv.co.il
Tuesday, January 16, 1996

Hi MFC-ers!

My app (MFC 3.2, NT 3.51 & Win95) has 3 toolbars. When an user 
drags one of them and drops it over another, the second toolbar 
moves right, and if it's too much right, it becomes out of mainframe
window - so user cannot see it. Next time user runs a program
(after SaveBarState/LoadBarState) it remains out.

Can I prevent toolbar from being moved out of client area of 
mainframe window?


Here is a code:

//***********************************************************************
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	if (!m_wndToolBar.Create(this) ||
		!m_wndToolBar.LoadBitmap(IDR_MAINFRAME) ||
		!m_wndToolBar.SetButtons(buttons,
		  sizeof(buttons)/sizeof(buttons [0])))
	{
		TRACE0("Failed to create toolbar\n");
		return -1;      // fail to create
	}

	if (!m_wndStatusBar.Create(this) ||
		!m_wndStatusBar.SetIndicators(indicators,
		  sizeof(indicators)/sizeof(indicators [0])))
	{
		TRACE0("Failed to create status bar\n");
		return -1;      // fail to create
	}
	{
	UINT nID, nStyle; 
	int cx;
	m_wndStatusBar.GetPaneInfo (0, nID, nStyle, cx);
	m_wndStatusBar.SetPaneInfo (0, nID, SBPS_STRETCH | SBPS_NORMAL, cx);
	}
	if (!m_wndNavigationBar.Create (this))
	{
		TRACE0("Failed to create navig. bar\n");
		return -1;      // fail to create
	}

	if (!m_wndInputDialogBar.Create (this, IDD_INPUT_DIALOG_BAR,
		CBRS_TOP | CBRS_TOOLTIPS | CBRS_FLYBY, IDD_INPUT_DIALOG_BAR))
	{
		TRACE0("Failed to create Dialog bar\n");
		return -1;      // fail to create
	}
	m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
	EnableDocking(CBRS_ALIGN_ANY);

	DockControlBar(&m_wndToolBar);
	DockControlBar(&m_wndNavigationBar);
	m_wndInputDialogBar.EnableDocking(CBRS_ALIGN_ANY);
	DockControlBar(&m_wndInputDialogBar);
	m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |
		CBRS_TOOLTIPS | CBRS_FLYBY);
	m_wndInputDialogBar.SetBarStyle(m_wndInputDialogBar.GetBarStyle() |
		CBRS_TOOLTIPS | CBRS_FLYBY);

	LoadBarState (TOOLBAR_STR);
	return 0;
}

void CMainFrame::OnDestroy() 
{
	SaveBarState (TOOLBAR_STR);
	CMDIFrameWnd::OnDestroy();
}

Regards,
Poul A. Costinsky(PoulACost@msn.com).

  ("`-''-/").___..--''"`-._
    (`6_ 6  )   `-.  (     ).`-.__.`)
     (_Y_.)'  ._   )  `._ `. ``-..-'
   _..`--'_..-_/  /--'_.' ,'
  (il).-''  (li).'  ((!.-




Ghislain Lachapelle -- Ghislain.Lachapelle@Matrox.COM
Monday, January 22, 1996

At 11:27 96-01-16 +-200, you wrote:
>Hi MFC-ers!
>
>My app (MFC 3.2, NT 3.51 & Win95) has 3 toolbars. When an user 
>drags one of them and drops it over another, the second toolbar 
>moves right, and if it's too much right, it becomes out of mainframe
>window - so user cannot see it. Next time user runs a program
>(after SaveBarState/LoadBarState) it remains out.
>
>Can I prevent toolbar from being moved out of client area of 
>mainframe window?
>
>
>Here is a code:
>
>//***********************************************************************
>int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
>{
>	if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1)
>		return -1;
>	
>	if (!m_wndToolBar.Create(this) ||
>		!m_wndToolBar.LoadBitmap(IDR_MAINFRAME) ||
>		!m_wndToolBar.SetButtons(buttons,
>		  sizeof(buttons)/sizeof(buttons [0])))
>	{
>		TRACE0("Failed to create toolbar\n");
>		return -1;      // fail to create
>	}
>
>	if (!m_wndStatusBar.Create(this) ||
>		!m_wndStatusBar.SetIndicators(indicators,
>		  sizeof(indicators)/sizeof(indicators [0])))
>	{
>		TRACE0("Failed to create status bar\n");
>		return -1;      // fail to create
>	}
>	{
>	UINT nID, nStyle; 
>	int cx;
>	m_wndStatusBar.GetPaneInfo (0, nID, nStyle, cx);
>	m_wndStatusBar.SetPaneInfo (0, nID, SBPS_STRETCH | SBPS_NORMAL, cx);
>	}
>	if (!m_wndNavigationBar.Create (this))
>	{
>		TRACE0("Failed to create navig. bar\n");
>		return -1;      // fail to create
>	}
>
>	if (!m_wndInputDialogBar.Create (this, IDD_INPUT_DIALOG_BAR,
>		CBRS_TOP | CBRS_TOOLTIPS | CBRS_FLYBY, IDD_INPUT_DIALOG_BAR))
>	{
>		TRACE0("Failed to create Dialog bar\n");
>		return -1;      // fail to create
>	}
>	m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
>	EnableDocking(CBRS_ALIGN_ANY);
>
>	DockControlBar(&m_wndToolBar);
>	DockControlBar(&m_wndNavigationBar);
>	m_wndInputDialogBar.EnableDocking(CBRS_ALIGN_ANY);
>	DockControlBar(&m_wndInputDialogBar);
>	m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |
>		CBRS_TOOLTIPS | CBRS_FLYBY);
>	m_wndInputDialogBar.SetBarStyle(m_wndInputDialogBar.GetBarStyle() |
>		CBRS_TOOLTIPS | CBRS_FLYBY);
>
>	LoadBarState (TOOLBAR_STR);
>	return 0;
>}

Hi is the code is right. Unfortunately, it seems our dear friends at
Microsoft didn't test so much their stuff with real world control bars
(except DOCKTOOL sample!!). I got a very similar problem last fall and
partially solved it. In addition to what you said, the same problem appears
if the user changes its resolution for a lower one. 

Each time I load the application (in CMainframe::OnCreate) and each time I
make my control bar visible (in View menu), I call the following utility
function (for all controls in OnCreate and only one in View menu):

// GLachape, November 10th, 1995, BUG FIX: The MFC LoadBarState and
SaveBarState functions
// do not check the screen resolution. If a CControlBar is undocked and
positionned to the 
// right of the screen, changing the video resolution for a lower one will
make this control
// appear outside the monitor screen and it is impossible to recover it
without destroying
// the registry database.
// This simple function is intended to prevent this problem to appear. It
simply checks if
// the window is visible and undocked. If yes, it verifies that the control
origin is not 
// outside the screen resolution right and bottom sides.
void CMainFrame::CheckControlToFitInScreen(CControlBar* pControlBar)
{
	int ScreenResX= GetSystemMetrics(SM_CXSCREEN);
	int ScreenResY= GetSystemMetrics(SM_CYSCREEN);
	int nOffsetFactor= 15;

	BOOL bVisibilityCheck= ( (pControlBar->GetStyle() & WS_VISIBLE) != 0);

	if (!bVisibilityCheck)
		return;				// toolbar not visible

	if (!pControlBar->IsFloating())
		{
		// GLachape, November 14th, 1995, Second bug fix.
		// a toolbar is moved when we dock another toolbar over it.
		// this moved toolbar can be outside the screen.
		CRect ControlBarRect;
		pControlBar->GetWindowRect(&ControlBarRect);   

		BOOL bControlBarMoved= FALSE;
		DWORD dwStyle= 0;
		
		if (ControlBarRect.left >= (ScreenResX - nOffsetFactor) )
			{
			bControlBarMoved= TRUE;
			dwStyle= CBRS_ALIGN_TOP;
			ControlBarRect.left= ScreenResX- ControlBarRect.Width();
			}
		if ( ControlBarRect.top >= (ScreenResY - nOffsetFactor))
			{
			bControlBarMoved= TRUE;
			dwStyle= CBRS_ALIGN_LEFT;
			ControlBarRect.top= ScreenResY- ControlBarRect.Height();
			} 
		if (bControlBarMoved)
			{
			CPoint ControlBarOrigin(ControlBarRect.TopLeft());
			FloatControlBar( pControlBar, ControlBarOrigin, dwStyle);
			}
		return;				// toolbar is docked
		}

	// Not sure it is neccessary
	RecalcLayout();
	
	// ok, criterias meet: visible and undocked
	CFrameWnd* pControlFrame= pControlBar->GetDockingFrame();
	if (pControlFrame== NULL)
		return;

	CRect ControlRect;
	pControlFrame->GetWindowRect(ControlRect);
	
	BOOL bControlMoved= FALSE;

	if (ControlRect.left >= (ScreenResX - nOffsetFactor) )
		{
		bControlMoved= TRUE;
		ControlRect.left= ScreenResX- ControlRect.Width();
		}

	if (ControlRect.top >= (ScreenResY - nOffsetFactor) )
		{
		bControlMoved= TRUE;
		ControlRect.top= ScreenResY- ControlRect.Height();
		}

	// move the control bar if needed
	if (bControlMoved)
		{
		pControlFrame->SetWindowPos(&wndTop, ControlRect.left, ControlRect.top,	
				    					0, 0, SWP_NOSIZE | SWP_NOZORDER ); //| SWP_NOACTIVATE);
		}
}


Be aware that this function doesn't solve completely the problem because a
control bar still can be moved outside the screen area. But it will come
back if the user swicth the View-->my_bar option in the menu or the next
time he reloads the application.

To solve completely the problem, we should perhaps derive the CToolbar or
overwrite the CMainFrame::RecalcLayout function. I didn't have the time to
try it for now, if you do or have other suggestions, please reply me.

Hope this will help


///////////////////////////////////////////////////////////////////////
Ghislain Lachapelle(Ghislain.Lachapelle@matrox.com)

Ghislain Lachapelle, ext. 2495
Matrox Electronic Systems Ltd.
Imaging Group
1055 St-Regis Blvd.
Dorval, Quebec, Canada
H9P 2T4


(514) 685-7230, ext. 2495
////////////////////////////////////////////////////////////////////////




Poul A. Costinsky -- wizsofti@datasrv.co.il
Thursday, January 25, 1996

Thank you, it worked. Actually, I did the same thing.
I just wondered maybe there is an easier way. 
Anybody?

Regards,
Poul A. Costinsky(PoulACost@msn.com).

  ("`-''-/").___..--''"`-._
    (`6_ 6  )   `-.  (     ).`-.__.`)
     (_Y_.)'  ._   )  `._ `. ``-..-'
   _..`--'_..-_/  /--'_.' ,'
  (il).-''  (li).'  ((!.-

----------
From: 	owner-mfc-l@netcom.com on behalf of Ghislain Lachapelle
Sent: 	Monday, January 22, 1996 3:34 PM
To: 	mfc-l@netcom.com
Subject: 	Re: Toolbar out of visible area.

Hi is the code is right. Unfortunately, it seems our dear friends at
Microsoft didn't test so much their stuff with real world control bars
(except DOCKTOOL sample!!). I got a very similar problem last fall and
partially solved it. In addition to what you said, the same problem appears
if the user changes its resolution for a lower one. 

Each time I load the application (in CMainframe::OnCreate) and each time I
make my control bar visible (in View menu), I call the following utility
function (for all controls in OnCreate and only one in View menu):

// GLachape, November 10th, 1995, BUG FIX: The MFC LoadBarState and
SaveBarState functions
// do not check the screen resolution. If a CControlBar is undocked and
positionned to the 
// right of the screen, changing the video resolution for a lower one will
make this control
// appear outside the monitor screen and it is impossible to recover it
without destroying
// the registry database.
// This simple function is intended to prevent this problem to appear. It
simply checks if
// the window is visible and undocked. If yes, it verifies that the control
origin is not 
// outside the screen resolution right and bottom sides.
void CMainFrame::CheckControlToFitInScreen(CControlBar* pControlBar)
{
	int ScreenResX= GetSystemMetrics(SM_CXSCREEN);
	int ScreenResY= GetSystemMetrics(SM_CYSCREEN);
	int nOffsetFactor= 15;

	BOOL bVisibilityCheck= ( (pControlBar->GetStyle() & WS_VISIBLE) != 0);

	if (!bVisibilityCheck)
		return;				// toolbar not visible

	if (!pControlBar->IsFloating())
		{
		// GLachape, November 14th, 1995, Second bug fix.
		// a toolbar is moved when we dock another toolbar over it.
		// this moved toolbar can be outside the screen.
		CRect ControlBarRect;
		pControlBar->GetWindowRect(&ControlBarRect);   

		BOOL bControlBarMoved= FALSE;
		DWORD dwStyle= 0;
		
		if (ControlBarRect.left >= (ScreenResX - nOffsetFactor) )
			{
			bControlBarMoved= TRUE;
			dwStyle= CBRS_ALIGN_TOP;
			ControlBarRect.left= ScreenResX- ControlBarRect.Width();
			}
		if ( ControlBarRect.top >= (ScreenResY - nOffsetFactor))
			{
			bControlBarMoved= TRUE;
			dwStyle= CBRS_ALIGN_LEFT;
			ControlBarRect.top= ScreenResY- ControlBarRect.Height();
			} 
		if (bControlBarMoved)
			{
			CPoint ControlBarOrigin(ControlBarRect.TopLeft());
			FloatControlBar( pControlBar, ControlBarOrigin, dwStyle);
			}
		return;				// toolbar is docked
		}

	// Not sure it is neccessary
	RecalcLayout();
	
	// ok, criterias meet: visible and undocked
	CFrameWnd* pControlFrame= pControlBar->GetDockingFrame();
	if (pControlFrame== NULL)
		return;

	CRect ControlRect;
	pControlFrame->GetWindowRect(ControlRect);
	
	BOOL bControlMoved= FALSE;

	if (ControlRect.left >= (ScreenResX - nOffsetFactor) )
		{
		bControlMoved= TRUE;
		ControlRect.left= ScreenResX- ControlRect.Width();
		}

	if (ControlRect.top >= (ScreenResY - nOffsetFactor) )
		{
		bControlMoved= TRUE;
		ControlRect.top= ScreenResY- ControlRect.Height();
		}

	// move the control bar if needed
	if (bControlMoved)
		{
		pControlFrame->SetWindowPos(&wndTop, ControlRect.left, ControlRect.top,	
				    					0, 0, SWP_NOSIZE | SWP_NOZORDER ); //| SWP_NOACTIVATE);
		}
}


Be aware that this function doesn't solve completely the problem because a
control bar still can be moved outside the screen area. But it will come
back if the user swicth the View-->my_bar option in the menu or the next
time he reloads the application.

To solve completely the problem, we should perhaps derive the CToolbar or
overwrite the CMainFrame::RecalcLayout function. I didn't have the time to
try it for now, if you do or have other suggestions, please reply me.

Hope this will help


///////////////////////////////////////////////////////////////////////
Ghislain Lachapelle(Ghislain.Lachapelle@matrox.com)

Ghislain Lachapelle, ext. 2495
Matrox Electronic Systems Ltd.
Imaging Group
1055 St-Regis Blvd.
Dorval, Quebec, Canada
H9P 2T4


(514) 685-7230, ext. 2495
////////////////////////////////////////////////////////////////////////







| Вернуться в корень Архива |