如何改变CFormView大小

pango99 2001-08-26 11:40:49
VC中生成的CFormView窗口,我想让他在主窗口大小改变时也跟着改变大小,于是我重载CMainFrame::OnSize()函数,代码为:
if(GetActiveView())
GetActiveView()->MoveWindow(0,h1,cx,cy-h1-h2);
h1为工具条窗口高度,h2为状态条窗口高度,可执行后,主窗口老是会出现水平和垂直滚动条,好象CFormView没有缩小到规定大小,我的代码什么地方错了?关键是怎么把滚动条去掉.
...全文
336 5 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
羊叔不乖 2001-09-05
  • 打赏
  • 举报
回复
羊叔不乖 2001-09-05
  • 打赏
  • 举报
回复
羊叔不乖 2001-09-05
  • 打赏
  • 举报
回复
lily311 2001-09-04
  • 打赏
  • 举报
回复
其实这个问题的解决很简单.
如下所示,重载OnInitialUpdate后,加上SetScrollSizes(MM_TEXT,CSize(20,20)),让滚动条以为CFormView尺寸很小(CSize(20,20)),即可消失.
void CMyFormView::OnInitialUpdate()
{
CFormView::OnInitialUpdate();
GetParentFrame()->RecalcLayout();
ResizeParentToFit();

SetScrollSizes(MM_TEXT,CSize(20,20));
}
蒋晟 2001-08-27
  • 打赏
  • 举报
回复
你的程序是MDI的还是SDI的?要是MDI,CMainFrame::GetActiveView()返回NULL。应该在子框架的OnGetMinMaxInfo里面固定窗口大小。

Q I have a form-based app written in MFC. When the app starts up, the window is larger than the form. Because most of the form is blank, this doesn't look very good. I want to make the window just big enough to hold the form, but I don't know how big the form is until it's loaded. If I change the window size after the app comes up, then you can see the old size briefly, which looks even worse. Currently, I'm using trial and error to hardwire the size, but now every time someone changes the form, I have to manually edit the window size to fit. Isn't there some way I can make the window size fit the form automatically?

Ben Mundy

A This is a typical Windows chicken-and-egg problem, one of those things that seems like it should be easy but isn't. One way to find the size of a dialog is to load the dialog resource into memory—that is, into a DLGTEMPLATE structure—and look at the cx/cy parameters. Unfortunately, these values are in dialog base units, not pixels. So you have to call GetDialogBaseUnits and do some coordinate conversions, which depend on whether your dialog uses the system font or its own font.
Fortunately, there's an easy and surefire way to find out the size of a dialog, even if it is a bit kludgy: just create the dialog, and see how big it is! Of course, you have to create it invisibly if you don't want the user to see what you're doing. But the dialog used for a form-based app is invisible by default, so in this case making the dialog invisible doesn't require extra effort.
To see how it works, I added the automatic sizing feature to the FormSwap program mentioned in the answer to the previous question. The core of the autosize feature is a static function, GetDialogSize, which gets the size of the form. Yes, even in the days of C++, I still write static functions from time to time. But GetDialogSize is implemented using a C++ class, CTempDlg:

class CTempDlg : public CDialog {
public:
CRect m_rcDlg;
protected:
virtual BOOL OnInitDialog();
};

BOOL CTempDlg::OnInitDialog()
{
GetWindowRect(&m_rcDlg);
m_rcDlg -= m_rcDlg.TopLeft();
EndDialog(0);
return TRUE;
}


CTempDlg has just one function override: OnInitDialog. OnInitDialog saves the position of the dialog in a data member, then quits. (MFC does a bit of trickery to allow this; in straight C you can't call EndDialog from within WM_INITDIALOG.) GetDialogSize uses CTempDlg to get the dialog's size, which it returns as a CSize.

CSize GetDialogSize(LPCTSTR pszTemplName,
CWnd* pParent)
{
CTempDlg dlg;
dlg.Create(pszTemplName, pParent);
return dlg.m_rcDlg.Size();
}


Pretty simple. If you try this at home, just remember that the dialog should have no borders and should be invisible (dialogs used in form views always are).
If you want to get the size of a normal dialog, you'll have to do a bit more coding. To first load the dialog template into memory, turn off the WS_VISIBLE and WS_BORDER styles in the DLGTEMPLATE structure and call CDialog:: CreateIndirect instead of Create. If you're already loading the dialog into memory, you may as well just convert the cx and cy values using GetDialogBaseUnits. In passing, I should also mention another function, MapDialogRect, that converts dialog box units to screen pixels. However, this function requires an HDLG, which is an already created dialog.
Once you have the size of the dialog, you've solved the main problem of sizing your frame—but you aren't out of the woods yet. Now the problem is: given that you know how big the dialog is (that is, how big the client view area should be), how big must you create your main window to get a client area exactly that size? This sounds simple but it turns out to be a real pain in the keyboard. There's a virtual function, CWnd::CalcWindowRect, that's supposed to accomplish this feat. Given a certain-sized client rectangle, it calculates the corresponding frame rectangle. Unfortunately, no one in Redmond bothered to implement this function for CFrameWnd. So that leaves it to you.
Implementing CalcWindowRect is an exercise in nit-picking, or should I say pixel-picking. Given a certain-sized client rectangle, you have to add the heights and widths of all the toolbars, splitter borders, menus, window frames, and what-have-you. In the case of FormSwap, there are toolbars, the splitter window, and the left-pane view that must be taken into account. To calculate the height of the toolbars, you can use the MFC function CWnd::RepositionBars. You feed it a rectangle and a magic code, reposQuery—which says you only want to calculate the toolbars, not actually move them—and presto, you have the numbers you need. If you want to understand RepositionBars better, read the documentation. Good luck.
After calculating the heights of the toolbars, the next troublesome task is calculating the height and width of all the splitter window components: the border with which it surrounds each pane and the splitter bar itself. All these magic numbers are contained within data members in CSplitterWnd, but naturally the data is protected, which means you can't access it! Sigh. So what do you do? Simple: just derive a new class with public functions to export the protected data, and use it instead of CSplitterWnd in your main frame.

class CMySplitterWnd : public CSplitterWnd {
public:
CSize GetBorderSize()
{ return CSize(m_cxBorder,m_cyBorder); }
CSize GetSplitterSize()
{ return CSize(m_cxSplitter,m_cySplitter); }
};


If you're lazy (the best programmers are), you might be tempted to just hardwire the border size and other measurements instead of going to all this trouble. But be warned: the values m_cyBorder and its sisters are different under Windows 3.1, Windows 95, and Windows NT®. So if you want the exact values, you must get them from an instantiated CSplitterWnd object.
By now you've probably fallen asleep just thinking of all this tedious work, but once you've calculated how big your main frame should be, the next step is to actually modify the frame's size. Where do you do it? There are oh, so many places. You could override PreCreateWindow and set the size in CREATESTRUCT, implement a WM_GETMINMAXINFO handler, or alter the size in CFrameWnd::OnCreate. In this particular case, however, there's only one option because the magic RepositionBars function works only after the toolbars have been created. This means the winner is door number three: OnCreate.

int CMainFrame::OnCreate(...)
{
// normal stuff



// Make frame fit dialog
static CSize sz = GetDialogSize(MAKE
INTRESOURCE(IDD_DIALOG1), this);
CRect rc(CPoint(0,0), sz);
CalcWindowRect(&rc);
SetWindowPos(NULL, 0, 0,rc.Width(), rc.Height(),
SWP_NOMOVE|SWP_NOZORDER);
return 0;
}


With this and all the other code in place, the window now appears as in Figure 1, just large enough to enclose the form, and not one pixel larger. Whew!
Before signing off, let me spend a few words on WM_GETMINMAXINFO. Windows sends this message just before creating a window, and again whenever the user attempts to move or size it. WM_GETMINMAXINFO is your opportunity to specify the minimum and maximum sizes allowed for your window. If, after going to all that trouble to calculate the window size, you want to prevent the user from decreasing the size of the window, you should handle WM_GETMINMAXINFO. Just follow the directions in your Win32® Owner's Manual. Don't forget that Windows sends the first WM_GETMINMAXINFO before it creates your window, so RepositionBars won't work. You either have to implement CalcWindowRect another way, without using RepositionBars, or ignore the first WM_GETMINMAXINFO message. One way to do this would be to make the dialog size a data member, m_szDlg, which you initialize to zero and then set in OnCreate. Then your WM_GETMINMAXINFO handler would do nothing if m_szDlg is zero.

16,548

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • AIGC Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧