Почему включение двойной буферизации нарушает мой список управления и изменяет размер окна, а затем исправляет его? - PullRequest
0 голосов
/ 11 октября 2019

Я использую wxListCtrl в стиле отчета в программном проекте для Windows 10 с использованием Visual Studio 2017. Я заметил, что при первом запуске программы возникают некоторые странные артефакты: вертикальные линии между столбцами не перемещаются с помощьюзаголовки, когда я изменяю их размер с помощью мыши. Кроме того, полоса прокрутки не перемещается, когда я перетаскиваю ее, но список переходит на позицию, когда я отпускаю кнопку мыши. Как только я изменяю размер окна, все в порядке.

После сокращения программы до минимального примера я обнаружил, что отключение двойной буферизации для кадра, содержащего элемент управления списком, исправляет все. Но я не очень понимаю, почему. Кто-нибудь может мне это объяснить?

#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);

1 Ответ

1 голос
/ 11 октября 2019

Вообще говоря, вы не должны мешать рисованию собственных элементов управления, а wxListCtrl является родным для MSW. Более того, он уже имеет двойную буферизацию, используя для этого собственный специальный механизм (LVS_EX_DOUBLEBUFFER), и поэтому совсем не удивительно, что настройка WS_EX_COMPOSITED для него неожиданно (с точки зрения управления) нарушает его.

Т.е. ответ прост: просто не вызывайте SetDoubleBuffered() для него, ни какой-либо другой нативный контроль.

...