为什么打开双缓冲会破坏我的列表控制并调整 window 的大小然后修复它?
Why does turning on double buffering break my list control and resizing the window then fixes it?
我在 Windows 10 的编程项目中使用报告样式的 wxListCtrl,使用 Visual Studio 2017。我注意到当程序第一次启动时,有一些奇怪的工件:垂直当我用鼠标调整它们的大小时,列之间的线不会随着 headers 移动。此外,当我拖动滚动条时,滚动条不会移动,但当我释放鼠标按钮时,列表会跳转到该位置。但是,一旦我调整 window 的大小,一切都很好。
将程序缩减为最小示例后,我发现关闭包含列表控件的帧的双缓冲可以解决所有问题。但我真的不明白为什么。谁能给我解释一下?
#include <wx/wx.h>
#include <wx/listctrl.h>
class MainWindow : public wxFrame
{
public:
MainWindow();
void updateWidgets();
private:
wxListCtrl *listCtrl;
void initWidgets();
};
MainWindow::MainWindow()
{
// ****************************************************************
// Set window properties and init the widgets.
// ****************************************************************
wxFrame::Create(NULL, wxID_ANY, wxT("wxListCtrl Issue"), wxDefaultPosition,
wxDefaultSize, wxCLOSE_BOX | wxMINIMIZE_BOX | wxMAXIMIZE_BOX |
wxSYSTEM_MENU | wxCAPTION | wxRAISED_BORDER | wxRESIZE_BORDER);
// Comment the following line to fix the list control, but why?
this->SetDoubleBuffered(true);
initWidgets();
}
void MainWindow::initWidgets()
{
listCtrl = new wxListCtrl(this, wxID_ANY, wxDefaultPosition,
wxDefaultSize, wxLC_REPORT);
listCtrl->InsertColumn(0, wxT("Col 0"), wxLIST_FORMAT_LEFT, 50);
for (int i = 0; i < 60; i++)
{
long index = listCtrl->InsertItem(0, wxT("Item"));
}
}
class wxListCtrl_Issue : public wxApp
{
public:
virtual bool OnInit();
};
bool wxListCtrl_Issue::OnInit()
{
MainWindow *mainWindow = new MainWindow();
mainWindow->Show(true);
return true;
}
wxIMPLEMENT_APP(wxListCtrl_Issue);
一般来说,你不应该干涉原生控件的绘制,wxListCtrl
在MSW下是原生的。此外,它已经使用自己的特定机制进行双缓冲 (LVS_EX_DOUBLEBUFFER
),因此设置 WS_EX_COMPOSITED
意外地(从控件的角度来看)破坏它也就不足为奇了。
即答案很简单:只是不要为它调用 SetDoubleBuffered()
,也不要调用任何其他本机控件。
我在 Windows 10 的编程项目中使用报告样式的 wxListCtrl,使用 Visual Studio 2017。我注意到当程序第一次启动时,有一些奇怪的工件:垂直当我用鼠标调整它们的大小时,列之间的线不会随着 headers 移动。此外,当我拖动滚动条时,滚动条不会移动,但当我释放鼠标按钮时,列表会跳转到该位置。但是,一旦我调整 window 的大小,一切都很好。
将程序缩减为最小示例后,我发现关闭包含列表控件的帧的双缓冲可以解决所有问题。但我真的不明白为什么。谁能给我解释一下?
#include <wx/wx.h>
#include <wx/listctrl.h>
class MainWindow : public wxFrame
{
public:
MainWindow();
void updateWidgets();
private:
wxListCtrl *listCtrl;
void initWidgets();
};
MainWindow::MainWindow()
{
// ****************************************************************
// Set window properties and init the widgets.
// ****************************************************************
wxFrame::Create(NULL, wxID_ANY, wxT("wxListCtrl Issue"), wxDefaultPosition,
wxDefaultSize, wxCLOSE_BOX | wxMINIMIZE_BOX | wxMAXIMIZE_BOX |
wxSYSTEM_MENU | wxCAPTION | wxRAISED_BORDER | wxRESIZE_BORDER);
// Comment the following line to fix the list control, but why?
this->SetDoubleBuffered(true);
initWidgets();
}
void MainWindow::initWidgets()
{
listCtrl = new wxListCtrl(this, wxID_ANY, wxDefaultPosition,
wxDefaultSize, wxLC_REPORT);
listCtrl->InsertColumn(0, wxT("Col 0"), wxLIST_FORMAT_LEFT, 50);
for (int i = 0; i < 60; i++)
{
long index = listCtrl->InsertItem(0, wxT("Item"));
}
}
class wxListCtrl_Issue : public wxApp
{
public:
virtual bool OnInit();
};
bool wxListCtrl_Issue::OnInit()
{
MainWindow *mainWindow = new MainWindow();
mainWindow->Show(true);
return true;
}
wxIMPLEMENT_APP(wxListCtrl_Issue);
一般来说,你不应该干涉原生控件的绘制,wxListCtrl
在MSW下是原生的。此外,它已经使用自己的特定机制进行双缓冲 (LVS_EX_DOUBLEBUFFER
),因此设置 WS_EX_COMPOSITED
意外地(从控件的角度来看)破坏它也就不足为奇了。
即答案很简单:只是不要为它调用 SetDoubleBuffered()
,也不要调用任何其他本机控件。