131.用CSplitterWnd产生的视图不能显示。
分析代码:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
// create a view to occupy the client area of the frame
//原先的代码为:
//if (!m_wndView.Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
// CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST, NULL))
if (!m_wndView.Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
CRect(0, 0, 0, 0), this, 0, NULL))
{
TRACE0("Failed to create view window/n");
return -1;
}
......
}
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
CRect cr;
GetClientRect(&cr); //获得窗口客户区的位置坐标
//m_splitter.CreateStatic(this,3,1);
//函数原型为:
//BOOL CreateStatic( CWnd* pParentWnd, int nRows, int nCols,
// DWORD dwStyle = WS_CHILD | WS_VISIBLE, UINT nID = AFX_IDW_PANE_FIRST );
m_splitter.CreateStatic(this,3,1,AFX_WS_DEFAULT_VIEW,AFX_IDW_PANE_FIRST ); //创建静态切分窗口
m_splitter.CreateView(0,0,RUNTIME_CLASS(CStaticView),CSize(cr.Width(),200),pContext);
m_splitter.CreateView(1,0,RUNTIME_CLASS(CSelectForm),CSize(cr.Width(),200),pContext);
m_splitter.CreateView(2,0,RUNTIME_CLASS(CManager),CSize(cr.Width(),cr.Height()-400),pContext);
return TRUE;
}
对比原先的代码和改正后的代码就会发现问题所在了。
132.参考资料:
《Visual c++程序开发 范例宝典》 实例018 Out look 导航界面。
实例032 不可移动的窗体。
实例037 拖动没有标题栏的窗体。
133.为什么在分割窗口中不能直接得到CMainFrame的指针。
在此程序中分割窗口是通过CSplitterWnd来实现的。其每个子窗口中调用GetParent函数得到的是CSplitterWnd的
指针(当然这还需要强制转换).而如果要想得到CMainFrame的指针还需要再次调用GetParent函数。
134.显示无模式对话框出现异常。
代码如下:
// m_memberman.Create(IDD_MEMBERMAN);
// m_memberman.ShowWindow(true);
m_memberman为类中定义的变量。
经过验证,错误的代码为:m_memberman.Create(IDD_MEMBERMAN);
解决:这个错误并不是这些代码的问题,而是定义对话框时,把对话框的样式改成“下层”了。只需要把样式属性改成“弹出”即可。
135.获取CSplitterWnd的子窗口出现异常。
代码如下:则个代码是在CSelectForm::Create函数中的代码
CSplitterWnd * wnd=(CSplitterWnd *)GetParent();
m_baseView=(CBaseView *)(wnd->GetPane(2,0));
在创建客户窗口中的代码为:
m_splitter.CreateStatic(this,3,1,AFX_WS_DEFAULT_VIEW,AFX_IDW_PANE_FIRST ); //创建静态切分窗口
m_splitter.CreateView(0,0,RUNTIME_CLASS(CStaticView),CSize(cr.Width(),80),pContext);
m_splitter.CreateView(1,0,RUNTIME_CLASS(CSelectForm),CSize(cr.Width(),60),pContext);
m_splitter.CreateView(2,0,RUNTIME_CLASS(CBaseView),CSize(cr.Width(),cr.Height()-173),pContext);
解决:这个问题的出现不是代码的语法的问题。如果把出现异常的代码放在其他函数体中就好着。这说明了CSplitterWnd创建窗口
是一个一个创建的,在创建第二个窗口时第三个窗口还没有创建,而代码却要第三个窗口的指针。这样做当然就出错了。
136.如何去掉CSplitterWnd的分割线?
问题描述:
用CSplitterWnd划分窗口,各个窗口之间有一条分界线。
分割窗口我在OnCreateClient函数中是这样写的:
CRect cr;
GetClientRect(&cr); //获得窗口客户区的位置坐标
m_splitter.CreateStatic(this,3,1,AFX_WS_DEFAULT_VIEW,AFX_IDW_PANE_FIRST ); //创建静态切分窗口
m_splitter.CreateView(0,0,RUNTIME_CLASS(CStaticView),CSize(cr.Width(),80),pContext);
m_splitter.CreateView(1,0,RUNTIME_CLASS(CSelectForm),CSize(cr.Width(),60),pContext);
m_splitter.CreateView(2,0,RUNTIME_CLASS(CManager),CSize(cr.Width(),cr.Height()-400),pContext);
问题的初步解决:
参考网址:
CSplitterWnd没有提供设置分割条尺寸的public函数,通过分析CSplitterWnd的源码得知:
它里面有几个没有公开的受保护的成员变量:
m_cxSplitter,
m_cySplitter,
m_cxBorderShare,
m_cyBorderShare,
m_cxSplitterGap,
m_cySplitterGap,
m_cxBorlder,
m_cyBorlder
通过重新构造m_cxSplitterGap,m_cySplitterGap变量的值,就可以实现改变分割条尺寸的功能。
————————————解决方案———————————————————
1.从CSplitterWnd派生一个新类CMySplitterWnd;
2.在.h文件中添加成员变量和函数如下:
int m_cx;
int m_cy;
void HideSplitter();
void ShowSplitter();
3.在.cpp文件中添加实现代码如下:
void CMySplitterWnd::HideSplitter()
{
m_cx=m_cxSplitterGap;//save previous cx
m_cy=m_cxSplitterGap;//save previous cy
m_cxSplitterGap=0;
m_cySplitterGap=0;
}
void CMySplitterWnd::ShowSplitter()
{
m_cxSplitterGap=m_cx;
m_cySplitterGap=m_cy;
}
4.使用新类CMySplitterWnd生成分割器窗口,在需要的时候调用HideSplitter、ShowSplitter函数即可。
//备注:如果直接运行会出错,需将想隐藏边框的视图隐藏。————–By Lonkil
原文地址:http://blog.csdn.net/cx0928/archive/2004/10/11/131833.aspx
这个解答尚有一点问题。m_cxSplitterGap=0;m_cySplitterGap=0;如果不隐藏视图会出现异常。所以在解决我的问题时我把
m_cxSplitterGap=1;m_cySplitterGap=1;
137.如何设定视图窗口大大小。
设定视图窗口的大小不能在OnCreate、OnCreateClient等函数中简单的用CREATESTRUCT的对象来设定,而应该在
CMainFrame::PreCreateWindow调用::AdjustWindowRectEx函数来设定。然后把宽度传递给CREATESTRUCT的引用变量。
如下代码:
CRect rect(0,0,800,515);
::AdjustWindowRectEx(&rect,cs.style,TRUE,cs.dwExStyle);
cs.cx=rect.Width();
cs.cy=rect.Height();
138.MFC中消息映射的怪现象。
我自定义了一个CEditListCtrl类,其相应的消息有ON_WM_LBUTTONDOWN()、ON_WM_CREATE()、
ON_EN_KILLFOCUS(1001, DisposeEdit)三个。当我们多次按下鼠标键,跟踪其执行顺序时会发现一个比较奇怪的现象。
先看为关联的三个函数:
1.左键按下
void CEditListCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
(1) LVHITTESTINFO info;
info.pt=point;
if(SubItemHitTest(&info)!=-1){
m_row=info.iItem;
m_col=info.iSubItem;
ShowEdit();
}
(2) CListCtrl::OnLButtonDown(nFlags, point);
}
2.显示edit控件
void CEditListCtrl::ShowEdit()
{
(3) MessageBox("1");
CRect rect;
GetSubItemRect(m_row,m_col,LVIR_LABEL,rect);
CString str;
str=GetItemText(m_row,m_col);
m_edit.MoveWindow(rect);
m_edit.SetWindowText(str);
m_edit.ShowWindow(SW_SHOW);
m_edit.SetSel(0,-1);
// m_edit.SetFocus();
(4) UpdateWindow();
}
3.控件失去焦点
BOOL CEditListCtrl::DisposeEdit()
{
(5) MessageBox("2");
CString str;
m_edit.GetWindowText(str);
(6) this->SetItemText(m_row,m_col,str);
m_edit.ShowWindow(SW_HIDE);
::SendMessage(this->m_hWnd,NULL,NULL,NULL);
(7) return TRUE;
}
当我第一次按下左键后,出现编辑框,然后在编辑框中输入文字,然后在别的地方按下左键奇怪的现象就出现了。
MFC先响应ON_WM_LBUTTONDOWN(),但还没当ON_WM_LBUTTONDOWN()响应的函数执行完ON_EN_KILLFOCUS(1001, DisposeEdit)
消息响应了。这样就造成了函数执行的错误。可能函数执行的顺序为(1)--(3)--(5)--(4)--(2)--(6)--(7).这也从一方面说明了
消息映射函数执行的独立性。其实这很像是多线程的执行。
139.CString和int连接出错.
我定义一个CString str=“E2006”;
然后把它与一个整形数int m_count/*=10*/;相连接。
但老是不成功。为用的方法是:
str.Format("%s%d",str,m_count);
为什么产生的结果不是我所想要的,产生错误的原因是什么,应该如何操作。
解答:
str.Format没有连接的能力,CString的Format函数,不能用自身作为参数;sprintf等函数也一样。
MSDN中这样说:
The call will fail if the string object itself is offered as a parameter to Format. For example, the following code:
CString str = "Some Data";
str.Format("%s%d", str, 123); // Attention: str is also used in the parameter list.
will cause unpredictable results.
140.类中的静态属性应该怎么初始化?