[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 2558
  • Last Modified:

How to set main SDI window to fix size and no scrollbar

I created an SDI formview application, and I want the main window to always open to a fixed size, which is large enough to display the form.
And for it not to have scroll bars.

Currently when I run the application it always opens with horizontal and vertical scroll bars on the form.

I added the below line of code, to stop user from being able to resize the window, but I need logic to make the window open to required size.
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
	cs.style &= ~WS_THICKFRAME;

Open in new window

0
Axter
Asked:
Axter
  • 13
  • 12
  • 12
  • +4
3 Solutions
 
Janusz CzopowikCommented:
You should have this code already in if you used app wizard.
If not insert following code in OnInitialUpdate:

	CFormView::OnInitialUpdate();
	
	CFrameWnd* pWnd = GetParentFrame();
	ASSERT(pWnd != NULL);
	pWnd->RecalcLayout();
	ResizeParentToFit();

Open in new window

If you are using VS 2008 with SP1 or feature pack and docking panels, you may have to disable code that restores windows sizes to previously saved.
0
 
AxterAuthor Commented:
A version of that is already in the code, but the scroll bars still appear.
void CGameMenuFreeView::OnInitialUpdate()
{
      CFormView::OnInitialUpdate();
      GetParentFrame()->RecalcLayout();
      ResizeParentToFit();

}
0
 
Janusz CzopowikCommented:
What Windows version, VS version, SDK version?
If you create new application with CFormView, and run it without additional code, does it behave the same way?
Would it be possible for you to post app in question or test application that duplicates problem?
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
jkrCommented:
I'd try to handle WM_GETMINMAXINFO (http://msdn.microsoft.com/en-us/library/ms632626%28VS.85%29.aspx) by overriding 'CWnd::OnGetMinMaxInfo()'  (http://msdn.microsoft.com/en-us/library/d214c9dk%28VS.80%29.aspx). E.g.
void CMySDIWnd::OnGetMinMaxInfo(MINMAXINFO* lpmmi)
{
     lpmmi->ptMaxSize.x = 640;
     lpmmi->ptMaxSize.y = 480;
     lpmmi->ptMaxTrackSize.x = 640;
     lpmmi->ptMaxTrackSize.y = 480;
     lpmmi->ptMinTrackSize.x = 320;
     lpmmi->ptMinTrackSize.y = 240;
}

Open in new window

0
 
ZoppoCommented:
Hi Axter,

>>> A version of that is already in the code, but the scroll bars still appear.

calling 'ResizeParentToFit' with 'bShrinkOnly = TRUE' (which is the default) doesn't enlarge the frame if it's too small ... IMO you simply have to pass 'FALSE' to ResizeParentToFit to allow the frame can be enlarged too:

void CGameMenuFreeView::OnInitialUpdate()
{
      CFormView::OnInitialUpdate();
      GetParentFrame()->RecalcLayout();
      ( FALSE );
}

Open in new window


Hope that helps,

ZOPPO
0
 
ZoppoCommented:
Sorry, made a cut and paste error - here the corrected code:

void CGameMenuFreeView::OnInitialUpdate()
{
      CFormView::OnInitialUpdate();
      GetParentFrame()->RecalcLayout();
      ResizeParentToFit( FALSE );
}

Open in new window

0
 
SaKuRaGiCommented:
Hi Axter,

You should pass in FALSE to ResizeParentToFit. This tells it that it can either grow the frame or shrink it. Otherwise, when you go from the small view to the larger view, it will not resize.

ResizeParentToFit( FALSE );

or also visit
http://msdn.microsoft.com/en-us/library/2c6ye477(v=vs.80).aspx
0
 
ZoppoCommented:
@SaKuRaGi: Did you read the previous comments? Using 'ResizeParentToFit( FALSE )' was already suggested ...
0
 
AndyAinscowCommented:
To be really precise - also in the link I posted even earlier.  It is the very first point being adressed in the article along with an explanation of why.
0
 
ZoppoCommented:
@AndyAinscow: yes, sorry, that's right - to be honest I didn't read that article. Mea culpa ...
0
 
AndyAinscowCommented:
No probs - I know you know MFC in such detail you wouldn't need to look at it to have made that suggestion.
0
 
ZoppoCommented:
:o) Thanks ...
0
 
SaKuRaGiCommented:
@zoppo
    Forgive me I did'nt. just got excited I posted a similar solution with yours. Sorry again.
0
 
ZoppoCommented:
No problem ...
0
 
sarabandeCommented:
axter, is the dialog resource greater than screen size or only greater than initial view size?  

if the first you would need to shrink the dialog resource.

if the second you could set the sizes in CMainFrame::PreCreateWindow so that the dialog would fit into view.

the ResizeParentToFit also should work but i found code in working projects where i had two calls

      ResizeParentToFit(FALSE);  
      ResizeParentToFit(TRUE);  

and though i didn't remember what the reason was, i am sure something didn't work as expected without that.
 
Sara
0
 
AxterAuthor Commented:
Sorry for late reply.


>>ResizeParentToFit( FALSE );

Changing this value was one of the first things I tried, and this make no difference.

What I do see different is when I make content in the explorer style toolbar small enough so both the regular toolbar and explorer style toolbar fit side by side, then the scroll bars disappear.
So it seems that the Explore style scrollbar is triggering the issue.



Here's how to repro it.
Using VC++ 2008, create new project MFC project (Visual C++->MFC->MFC Application).
On option window "MFC Application Wizard" select "Application Type" and set [Single Document] option and also select "Windows Explorer" for the Project style.
Then select "Generated Classes", and change Base class to "CFormView"
Then select "User Interface Features", and select "Browser style"
Click Finish


Modify CMainFrame::PreCreateWindow function by adding the following:
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
      cs.style &= ~WS_THICKFRAME;





Build and run the application, and you'll be able to reproduce this.
I've tested this on my machine at home (Windows 7 x64), and also on a Windows 2003 Win32 machine, and I get the same results.
0
 
AxterAuthor Commented:
Here's a screen shot:

Axter-415709.flv
0
 
Janusz CzopowikCommented:
This thread has been going for some time and grew kind of long.
Axter,
From a nice demo you posted, I can see you are using a dialog bas (CDialogBar). Therefore, I think you have missed some steps describing how your application is created.

In addition to what you described, you have chosen to "use a classic menu" and "use a browser style toolbar" on "User Interface Features" page. This caused wizard to create app with main frame class derived from CFrameWnd instead CFrameWndEx that does not suppport CDialogBar.

And this is your problem. You should have mentioned this at the beginning of this thread.

Had you have made different choice and selected "classic docking bar", you would not have this problem.

I do not have time right now to investigate why but I think this an error in reporting size of the rebar with one band and two toolbars. This is just a wild guess.

Do you really need a rebar? If you can, change a toolbar type to classic docking bar and you won’t have this problem and in addition your toolbars will have floating functionality.

In a free time (that is a rare commodity nowadays) I may try to determine why it is happening.
Meanwhile, happy programming.
0
 
AxterAuthor Commented:
>>Therefore, I think you have missed some steps describing how your application is created.
I was very careful not to miss any steps.  The following step in my instruction will cause the wizard to add a CDialogBar:
Then select "User Interface Features", and select "Browser style"

>>Do you really need a rebar?
At this point, I'm not absolutely certain if I need the rebar or if I can just use the classic docking bar by itself.
My plan is to add logic which will DYNAMICALLY add new toolbar items (buttons) at runtime.
I'm not sure if the rebar will have additional benefits over using classic toolbar for this goal.
0
 
AxterAuthor Commented:
>>Had you have made different choice and selected "classic docking bar", you would not have this problem.

I should mention that the app wizard created the project with both classic toolbar and with the CDialogBar.
Both are in the screen shot.  You'll notice the classic toolbar setting right on top of the CDialogBar.

I was thinking of programming it with having the static buttons on the classic toolbar, and having the dynamic buttons on the CDialogBar.
0
 
AndyAinscowCommented:
I have a choice of VS2005 or VS2010 installed, VS2005 doesn't support numbers of these options so I've tried it in VS2010.
Same behaviour.

ALSO, it is not just the vertical scroll bar, the horizontal one is visible as well.  So (IMHO) just changing from DialogBar to a classic toolbar shouldn't affect the width calculation.
0
 
AndyAinscowCommented:
Sorry, not correct - making wider by the width of the vertical scrollbar does result in the horizontal one disappearing.

/*	if (!m_wndDlgBar.Create(this, IDR_MAINFRAME, CBRS_ALIGN_TOP, AFX_IDW_DIALOGBAR))
	{
		TRACE0("Failed to create dialogbar\n");
		return -1;		// fail to create
	}

	if (!m_wndReBar.Create(this) || !m_wndReBar.AddBar(&m_wndToolBar) || !m_wndReBar.AddBar(&m_wndDlgBar))*/
	if (!m_wndReBar.Create(this) || !m_wndReBar.AddBar(&m_wndToolBar) )

Open in new window


Stopping the Dialogbar (but still having the toolbar on the rebar) and no scrollbars appear.  Looks like JohnCz has noticed what is causing the problem.
0
 
ZoppoCommented:
Hi Axter,

I'm not really sure what you mean with '... logic which will DYNAMICALLY add new toolbar items (buttons) at runtime', but IMO it might be a good idea if you check out the new GUI features/classes introduced with MFC FeaturePack (i.e. the CFrameWndEx class JohnCz mentioned before) - i.e. with the new class CMFCToolBar it's quite easy to add/remove buttons dynamically; further you get a nicer GUI look, easy toolbar customization, comboboxes as toolbar buttons, VisualStudio-like dockable panes, lot of new controls like color picker, font selection combo, explorer-like folder selection tree control and lots of more.

If you're interested you can download the feature pack containing some pretty samples here: http://www.microsoft.com/downloads/en/details.aspx?FamilyId=D466226B-8DAB-445F-A7B4-448B326C48E7&displaylang=en

But, one thing more: If you think using new MFC controls is a way to go for you I would suggest to upgrade to VS 2010 since 1.) the new MFC classes are completely integrated and 2.) the FeaturePack for VS 2008 contained some bugs which were resolved in VS 2010.

ZOPPO
0
 
Janusz CzopowikCommented:
Unless you are programming professional, there is no need for updating to VS2010.
Instead download and install VS 2008 SP1, you do not need Feature Pack. SP1 integrates new classes and works very well.
0
 
ZoppoCommented:
Well, I only partially agree - in VS 2008 new dialog controls are missing in resource editor, even no ribbon support exists. Further there are bugs within VS 2008's implementation (I just remember one: using '&' to mark a character as shortcut in top menu didn't work, the '_' wasn't shown in menues even if ALT was pressed. I know there were more problems but I just can't remember) ... anyhow VS 2008 is good enough to test if using new MFC features is a way to go.

Anyhow, this talking about MFC feature pack isn't really related to this question, I guess we should let Axter decide how to continue ...
0
 
Janusz CzopowikCommented:
Well, I agree the last word belongs to Axter, however we are here to help and possibly, Axter is not aware that MFC has been changes and new features were added.
Therefore any sound suggestion is in order.

I am not sure what missing control you are referring to; and I am not aware of any. New controlds were added in 2010 though.
VS 2010 has full support of the ribbon; ribbn editor has been added to VS 2010,
Ampersand works as expected and is added after ALT key is pressed.
<< I know there were more problems but I just can't remember>> statement is not really useful since if you cannot remember how can you state that you know? (Contradiction?)  ;).

I think you are referring to Feature Pack, not to SP1.

I have been working with VS since 4.2 and I noticed a lot of good stuff added over the years.

Of course, you can always stumble upon some oddities and it also includes VS 2010.
0
 
ZoppoCommented:
> I am not sure what missing control you are referring to; and I am not aware of any. New controlds were added in 2010 though.
Resource editor of VS 2008 doesn't support controls like 'MFC MaskedEdit' or 'MFC SheelTree' allthough the classes for them exist and can be used.

> Ampersand works as expected and is added after ALT key is pressed.
I just created a new SDI application without changing any settings from their default - running the app I see File insted of File when pressing ALT - in VS 2010 I see File

> ... statement is not really useful ...
Sorry, I really don't remember all problems I once found - it's about 2 and half years ago that I started to port a VS 6.0 app to use new VS 2008 GUI features and I found I needed to implement some workarounds to get it working as expected. Since about a half year ago we ported to VS 2010 and I found that some of the workarounds weren't needed anymore. For example here's one more I remember: If you close an undocked toolbar it is shown restored again after restarting the app in VS 2008, in VS 2010 it keeps hidden. If you want a complete list of bugs MS solved between VS 2008 and VS 2010 please don't ask me :o)

I reproduced both problems with VS 2008 SP1.

> I have been working with VS since 4.2 and I noticed a lot of good stuff added over the years.
I started with MSVC 1.5 and can only agree ...

Anyhow beside all of these I can give everyone the advice to upgrade to VS 2010 because IMO it has a lot of improvements, especially STL was improved, some (I don't know if all) features of TR1/C++0x exist like 'auto' or lambdas, nice GUI features were implemented like undockable document views ... a.s.o.

I think we should start a new thread if we want to continue this discussion as it has nothing to do with Axter's problem ...
0
 
AxterAuthor Commented:
>>Axter is not aware that MFC has been changes and new features were added.
Thanks for the info, but I'm aware of the new set of classes, which I did recently find out when I started this new project.
I'm using one of them already in this project (CMFCButton), because it allows me to easily add image and text on the button at the same time.

I'm using VC++ 2008, because that's what I have available at home, and at work.  If I find too many issues with 2008, I might upgrade in the future.

I just tried replacing CToolBar with CMFCToolBar and running the program.
This causes the classic toolbar to disappear, as if the users shrunk it down.  I can't slide the bar over to get it back.

See screenshot.
toolbar1.png
0
 
AxterAuthor Commented:
Here's a screen shot of what the application looks like using CToolBar instead of CMFCToolBar
toolbar0.png
0
 
ZoppoCommented:
Hm - with 'This causes the classic toolbar to disappear' do you mean you mix CToolBar and CMFCToolBar? Do you still use a CReBar?
0
 
Janusz CzopowikCommented:
In my previous post:
<<Unless you are programming professional, there is no need for updating to VS2010>>
Meaning: do not invest money if you are programming for fun.
Below is app built with 2008 running on Win7.

I am not trying to say VS 2010 is bad or VS2008 is better. I like 2010 with reservations. I like Class wizard, I do not like removed ability to customize buttons (only test is allowed, no bitmaps), there are also other bugs in 2010
I do not like toolbars you cannot float. But you are right there is no need to continue this discussion. We have difference of opinion that is it.

Alt.bmp
0
 
Janusz CzopowikCommented:
You have to use CFrameWndEx, since CFrameWnddoes not support CMFCToolbar. Using CFrameWndEx will prevent from using CDialog bar.
0
 
AndyAinscowCommented:
re my earlier comment #35024641

It seems like the problem is with 2 toolbars (rebars, whatever bars) taking too much vertical height.

Consider - do you need two or will just one be OK?  If you do need two then it should not be too difficult to perform the default action, then resize the frame by extending vertically to compensate for the extra toolbar.

The behaviour seems to be a bug which isn't cured in VS2010 so changing to that will not provide a solution to the problem.
0
 
AxterAuthor Commented:
>>Hm - with 'This causes the classic toolbar to disappear' do you mean you mix CToolBar and CMFCToolBar? Do you still use a CReBar?
If you look at the screen shots I posted, you'll see in the first screen shot there has only one toolbar being displayed.

On the second screen shot, there are two tool bars, with one being CToolBar type, and the other is CDialogBar type.

0
 
ZoppoCommented:
I thought in the first screenshot one can see the grips of two toolbars, just as if the left one is completeley (except that grip) covered by the second one ... but maybe I'm wrong.
0
 
AxterAuthor Commented:
>>Consider - do you need two or will just one be OK?
I'm designing it with 2, because I want the first one to be static items, and the second one to be items associated with user options, which are displayed only when user has certain configuration and options set.


>>If you do need two then it should not be too difficult to perform the default action, then resize the frame by extending vertically to compensate for the extra toolbar.

My MFC is really rusty.  I did try adding code to extend the length, but it didn't work.
Moreover, I'm not absolutely certain when the length should get extended.

Do you have any example code, and where should the code get  place?
I'm assuming it should be inserted somewhere around the following section:
void CGameMenuFreeView::OnInitialUpdate()
{
      CFormView::OnInitialUpdate();
      GetParentFrame()->RecalcLayout();
      ResizeParentToFit();

But I'm not certain where and exactly what the code should look like.
0
 
AxterAuthor Commented:
>>I thought in the first screenshot one can see the grips of two toolbars

Yes, the grip is there for the other hidden toolbar, but if you try moving the grip, it doesn't allow you.  I think this is another MFC bug.  It's probably all associated with the same bug causing the scroll bar.
0
 
Janusz CzopowikCommented:
Axter, this is not a bug. In my previous post:
You have to use CFrameWndEx, since CFrameWnd does not support CMFCToolbar. Using CFrameWndEx will prevent from using CDialog bar.
You are mot likely still using using CFrameWnd as a base class for CMainFrame
0
 
AxterAuthor Commented:
>>You have to use CFrameWndEx, since CFrameWnddoes not support CMFCToolbar. Using CFrameWndEx will prevent from using CDialog bar.

When I used CFrameWndEx, both toolbars disappeared.

toolbar2.png
0
 
AxterAuthor Commented:
>>You have to use CFrameWndEx, since CFrameWnd does not support CMFCToolbar. Using CFrameWndEx will prevent from using CDialog bar.

Just to clarify, in above snap shot, I'm using both CFrameWndEx and CMFCToolbar.
I still also have CDialogBar in the code, and considering your above comments, I would expect that the CDialogBar toolbar might disappear, but I would still expect the CMFCToolbar to be displayed.

Below is the header.
#include "afxtoolbar.h"
#include "afxframewndex.h"

//Use following define to change between CFrameWndEx and CFrameWnd
#define MY_CFRAMEWND CFrameWndEx

class CMainFrame : public MY_CFRAMEWND
{
	
protected: // create from serialization only
	CMainFrame();
	DECLARE_DYNCREATE(CMainFrame)

// Attributes
public:

// Operations
public:

// Overrides
public:
	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);

// Implementation
public:
	virtual ~CMainFrame();
#ifdef _DEBUG
	virtual void AssertValid() const;
	virtual void Dump(CDumpContext& dc) const;
#endif

protected:  // control bar embedded members
	CStatusBar  m_wndStatusBar;
	CMFCToolBar   m_wndToolBar;
	CReBar      m_wndReBar;
	CDialogBar      m_wndDlgBar;

// Generated message map functions
protected:
	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
	DECLARE_MESSAGE_MAP()
};

Open in new window

0
 
ZoppoCommented:
Well, maybe I found some kind of solution, but I think it's a bit of a hack - but, as I even think the problem you have comes from a MFC bug maybe you'll find it's ok for you.

Make the 'm_wndDlgBar' public, then override 'CalcWindowRect' for your view and implement it like this:

void CTestEEView::CalcWindowRect(LPRECT lpClientRect, UINT nAdjustType)
{
	CFormView::CalcWindowRect(lpClientRect, nAdjustType);

	if ( nAdjustType == CWnd::adjustOutside )
	{

		CRect rect;
		CMainFrame* pMainFrame = (CMainFrame*)GetParentFrame();

		if ( ::IsWindow( pMainFrame->m_wndDlgBar.m_hWnd ) )
		{
			pMainFrame->m_wndDlgBar.GetWindowRect( &rect );
			lpClientRect->bottom += rect.Height();
		}
	}
}

Open in new window


In my test app with this the scrollbars don't appear ...

ZOPPO
0
 
Janusz CzopowikCommented:
Axter:
<<CDialogBar toolbar might disappear, but I would still expect the CMFCToolbar to be displayed.>>

Even though you add toolbars to the rebar and nothing prevents that, you are calling base class implementation.
CFrameWndEx handle RecalcLayout differently and all bars added are not being resized, hence their height is 0.
0
 
jkrCommented:
<unsubscribing>
0
 
Janusz CzopowikCommented:
I think I know what is going on. ResizeParentToFit fails to calculate proper size of the frame.
Instead of asking main frame about size to accommodate client, it calculates size different way.
I really do not hace a time to get to the bottom of it and pinpoint where mistake is being made (dentinst appointment) but I present you with solution that is not a hack and it will work for allcases: bars in one or multiple lines, visible or not:

Solution:
In OnInitialUpdate insert this code.

	CFormView::OnInitialUpdate();
	CFrameWnd* pParent = GetParentFrame();
	pParent->RecalcLayout();

	CRect rectParent;
	CRect rectView;

	pParent->GetClientRect(rectParent);
	GetClientRect(rectView);

	int iBarsHeight = rectParent.Height() - rectView.Height();
	CRect rectNew(0, 0, m_totalDev.cx, m_totalDev.cy + iBarsHeight);
	
	// adjust for an outside, since view usually have client frame mosr frequently 2 px on each side
	CalcWindowRect(rectNew, adjustOutside);
	// offset to have 0,0 left /top
	rectNew.OffsetRect(-rectNew.left, -rectNew.top);

	// politely ask frame to calculate own size for you
	// using needed client rectangle
	pParent->CalcWindowRect(rectNew, adjustBorder);

	// finally rezise main frame but do not change z-order and do not move it from original position
	pParent->SetWindowPos(NULL, rectNew.left, rectNew.top, rectNew.Width(), rectNew.Height(), SWP_NOZORDER | SWP_NOMOVE);

Open in new window

0
 
Janusz CzopowikCommented:
I have made a little mistake. I was rushing to make an appointment in time and posted wrong snippet. I missed last minute change I have made to make it work.
Correct snippet follows:

	CRect rectParent;
	CRect rectView;

	CFormView::OnInitialUpdate();

	CFrameWnd* pParent = GetParentFrame();

	pParent->RecalcLayout();

	// this will establish initial position of the toolbars	in one line 
	// as a result, returned sizes do not include the height of the second bar
	// in this case dialog bar.
	ResizeParentToFit();

	// this will position a long toolbar in separate row.
	// CFormView required size calculations are wrong,
	// resulting in scroll bars (or scroll bar) being still displayed. 
	pParent->RecalcLayout();

	pParent->GetClientRect(rectParent);
	GetClientRect(rectView);

	int iBarsHeight = rectParent.Height() - rectView.Height();

	CRect rectNew(0, 0, m_totalDev.cx, m_totalDev.cy + iBarsHeight);
	
	// adjust for an outside, since view usually have client frame, most frequently 2 px on each side
	CalcWindowRect(rectNew, adjustOutside);
	//pParent->RecalcLayout();

	// offset to have 0,0 left /top
	rectNew.OffsetRect(-rectNew.left, -rectNew.top);

	// politely ask frame to calculate own size for you
	// using needed client rectangle
	pParent->CalcWindowRect(rectNew, adjustBorder);

	// finally rezise main frame but do not change z-order and do not move it from original position
	pParent->SetWindowPos(NULL, rectNew.left, rectNew.top, rectNew.Width(), rectNew.Height(), SWP_NOZORDER | SWP_NOMOVE);

Open in new window

Alternate approach would be to move entire code to a separate function (without ResizeParentToFit and preceeding RecalcLayout) and call this function twice from OnInitialUpdate.
0
 
AxterAuthor Commented:
Thanks JohnCz and Zoppo for the workaround.

And thank you to other experts for trying.
0
 
Janusz CzopowikCommented:
You are welcome.
Add 2 to iBarsHeight in CRect rectNew(0, 0, m_totalDev.cx, m_totalDev.cy + iBarsHeight);

I have tested it without a splitter.
I am not sure why but with a splitter height is 2 pixels short.
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 13
  • 12
  • 12
  • +4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now