我有一个从 CDockablePane 派生的可停靠窗格(附加到带有视图的框架),其中包含两个间隔开的编辑控件。我希望这些控件之间的空间绘制在该窗格的默认背景颜色上。相反,当我的应用程序。启动背景是透明的。当我(自动)隐藏/显示窗格时,该背景是透明的 - 显示其后面视图中的任何内容。
我做了以下事情:
重写 OnSize() 并调用 DoPaint() (参见下面的代码)。 这样,当我调整窗格大小或停靠窗格时,背景就会重新绘制得很好。 启动时,在窗格和视图显示在屏幕上之前,OnSize() 会被调用六次,因此没有任何帮助。
谢谢你。
编辑:
下面是代码的一部分 - 它创建了两个由 cmdDelta.y 间隔开的编辑控件。我此时不绘制或擦除任何内容,只需重新定位 OnSize() 中的控件即可。
class CSerialPortEdit : public CRichEditCtrl
{ .... };
class COutputWnd : public CDockablePane
{
public:
COutputWnd() { };
public:
CSerialPortEdit m_wndPortEdit;
CMFCEditBrowseCtrl m_cmdLine;
CFont m_cmdFont;
public:
virtual ~COutputWnd();
void UpdateFonts();
protected:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnSetFocus(CWnd* pOldWnd);
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
DECLARE_MESSAGE_MAP()
};
int COutputWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDockablePane::OnCreate(lpCreateStruct) == -1)
return -1;
// Create port edit:
const DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_BORDER | ES_LEFT | ES_AUTOVSCROLL | ES_MULTILINE | ES_WANTRETURN;
if (!m_wndPortEdit.Create(dwStyle, CRect(0,0,0,0), this, IDC_SERIAL_EDIT))
{
TRACE0("Failed to create port window\n");
return -1; // fail to create
}
// Create command line:
const DWORD edStyle = WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT | WS_TABSTOP | ES_AUTOHSCROLL | ES_MULTILINE | ES_WANTRETURN;
if (!m_cmdLine.CreateEx(WS_EX_CLIENTEDGE, _T("EDIT"), NULL, edStyle, CRect(0,0,0,0), this, IDC_COMMAND_EDIT))
{
TRACE0("Failed to create command line\n");
return -1; // fail to create
}
m_cmdLine.SetMargins(4, 4);
m_cmdLine.EnableFileBrowseButton();
UpdateFonts();
return 0;
}
void COutputWnd::OnSize(UINT nType, int cx, int cy)
{
CDockablePane::OnSize(nType, cx, cy);
CDC* pdc = GetDC();
DoPaint(pdc); // redraw background
ReleaseDC(pdc);
m_wndPortEdit.SetWindowPos (NULL, 0, 0, cx, cy-cmdSize.y-cmdDelta.y-2, SWP_NOACTIVATE | SWP_NOZORDER);
m_cmdLine.SetWindowPos (NULL, 0, cy-cmdSize.y-2, cx, cmdSize.y, SWP_NOACTIVATE | SWP_NOZORDER);
}
void COutputWnd::OnSetFocus(CWnd* pOldWnd)
{
CDockablePane::OnSetFocus(pOldWnd);
m_wndPortEdit.SetFocus();
}
BOOL COutputWnd::OnEraseBkgnd(CDC* pDC)
{
CDC* pdc = GetDC();
DoPaint(pdc); // redraw background
ReleaseDC(pdc);
return CWnd::OnEraseBkgnd(pDC);
}
COutputWnd
窗口。删除了列表窗口和选项卡控件。问题立即变得明显(无需添加两个控件),即它是透明的,不会擦除其背景。使用
SpyXX实用程序检查窗口,发现其类的背景画笔设置为
COLOR_3DFACE
(对话框背景的标准颜色)。那么为什么它不起作用呢?检查了MFC头文件和源代码,找到了罪魁祸首:COutputWnd
源自
CDockablePane
CPane
<- CBasePane
。 <- CBasePane
有一个 OnEraseBkgnd()
覆盖,您可以在文件 afxbasepane.cpp: 中找到它
BOOL CBasePane::OnEraseBkgnd(CDC* /*pDC*/)
{
return TRUE;
}
即不做任何事情,返回
TRUE
,表示不需要进一步擦除。这可能是因为所有这些“窗格”窗口都应该让其客户区域完全被另一个控件(选项卡、树视图等)覆盖,因此“不需要”擦除背景。但在这里您已经删除了原始的选项卡控件,并且(禁用的)背景被揭开。因此,有多种解决方案,所有解决方案都涉及覆盖
OnEraseBkgnd()
,您的选择取决于偏好:A。使用 Visual Manager 背景颜色(首选)
BOOL COutputWnd::OnEraseBkgnd(CDC* pDC)
{
DoPaint(pDC); // Fill background with the standard theme color
return TRUE; // No further erasing is required
}
DoPaint()
是
CBasePane
的一个方法,它的实现也在afxbasepane.cpp中,就在OnEraseBkgnd()
下面;致电CMFCVisualManager::OnFillBarBackground()
。B.使用默认(WNDCLASS)背景颜色
BOOL COutputWnd::OnEraseBkgnd(CDC* pDC)
{
return CWnd::OnEraseBkgnd(pDC); // Erase background using the class background brush.
}
此实现“恢复”原始
OnEraseBkgnd()
行为,以规避
CBasePane
中的覆盖。原始实现(在CWnd
中)使用类背景画笔填充背景。它设置为 COLOR_3DFACE
,这是对话框背景的标准 Windows 颜色。C.使用自定义背景颜色
HBRUSH hBrYellow = CreateSolidBrush(RGB(255, 255, 0)); // Yellow Brush
BOOL COutputWnd::OnEraseBkgnd(CDC* pDC)
{
RECT rct;
GetClientRect(&rct);
FillRect(pDC->m_hDC, &rct, hBrYellow); // Fill the client area with the yellow brush
return TRUE; // No further erasing is required
}
您还应该删除所有其他
GetDC()
/
DoPaint()
/ReleaseDC()
调用(例如在 OnSize()
或其他地方)。在您的 Beep(1000,50);
实现中放置 OnEraseBkgnd()
调用,以获得有关调用时间和调用频率的声音指示。应该在窗口放大时调用它(因此必须擦除其新发现的背景),但在缩小窗口时不应调用它 - 但我不知道重新定位两个控件的效果。我宁愿在代码重新定位控件后将 CDockablePane::OnSize(nType, cx, cy);
调用移至 COutputWnd::OnSize()
中。