why the listctrl has the back window as background

This forum can be used to talk about general design strategies, new ideas and questions in general related to wxWidgets. If you feel your questions doesn't fit anywhere, put it here.
Post Reply
oyster
In need of some credit
In need of some credit
Posts: 4
Joined: Wed Jan 30, 2019 4:48 am

why the listctrl has the back window as background

Post by oyster » Wed Jan 30, 2019 5:19 am

sorry, language https://nim-lang.org/ + binding https://github.com/PMunch/wxnim is used in MSYS2+Mingw64 on windows 64bits

question 1
the source code can be compiled and run, but you can find that, the GUI interface of the bottom application is shown on the listctrl? why and how to get rid of it?

question 2
another question, how to set listctrl to fit the width? In my above code, I mean the total 3 columns always take the horizontal space

sorry to ask here because there is no wxnim discussion and I hope it is because I don't know wxWidgets well, but not the bug in wxnim

Why not to use Cpp? No, I give up after studying several times
Why not to use wxPython? Yes, I use it but want to extend my language skill

Code: Select all

import "wx", "richtext", "stc"

{.experimental.}
{.emit: "#include <wx/spinctrl.h>" .}
{.emit: "#include <wx/listctrl.h>" .}

converter toClong(x: int): clong = x.clong


proc createFrame(): ptr WxFrame
let f = createFrame()

proc handleButtonClick(e: var WxCommandEvent) {.cdecl.} =
    echo $WxCommandEvent
    f.setStatusText("Quit called!")

proc createFrame(): ptr WxFrame =
    result = cnew constructWxFrame(nil, wxID_ANY, "Hello World",
                                 constructWxPoint(50, 50),
                                 constructWxSize(450, 340))
    result.createStatusBar()
    result.setStatusText("Welcome to wxWidgets!")

    let menuFile = cnew constructWxMenu()

    let helloID = newControlId()
    menuFile.append(helloID, "&Hello...\tCtrl-H",
                   "Help string shown in status bar for this menu item")
    menuFile.appendSeparator()
    menuFile.append(wxID_EXIT)
    let menuHelp = cnew constructWxMenu()
    menuHelp.append(wxID_ABOUT)
    let menuBar = cnew constructWxMenuBar()
    menuBar.append(menuFile, "&File")
    menuBar.append(menuHelp, "&Help")
    result.setMenuBar(menuBar)

    menuBar.`bind`(wxEVT_MENU, handleButtonClick, wxID_EXIT)

    let btn = cnew constructWxButton(result, wxID_ANY, "click")

    let lstctl = cnew constructwxListCtrl(result, wxID_ANY, style=wxLC_REPORT)

    # Add first column
    var info = WxListItem()
    info.mItemId = 0
    info.mText = "A"
    info.mWidth = 50
    info.mMask = wxLIST_MASK_TEXT
    discard insertColumn(lstctl, 0, info)

    # Add second column
    info = WxListItem(mText:"B", mItemId:1, mMask:wxLIST_MASK_TEXT)
    discard insertColumn(lstctl, 1, info)

    # Add third column
    info = WxListItem(mText:"C", mItemId:2, mMask:wxLIST_MASK_TEXT)
    discard insertColumn(lstctl, 2, info)

    var item_amount = 3
    for n in 0 ..< item_amount:
        var item = WxListItem()
        item.mItemId = n
        discard insertItem(lstctl, item)

        #  set value in first column
        setItem(lstctl, n, 0, $n & ":0")

        #  set value in second column
        setItem(lstctl, n, 1, $n & ":1")

        #  set value in third column
        setItem(lstctl, n, 2, $n & ":2")

        if (getItemCount(lstctl) mod 2) == 1 :
            setItemBackgroundColour(lstctl, n,  constructWxColour( 255, 0, 0 ))
            setItemTextColour(lstctl, n,  constructWxColour( 255, 255, 255 ))


    let text = cnew constructWxStyledTextCtrl(result, wxID_ANY)
    text.styleClearAll()
    text.setLexer(wxSTC_LEX_CPP)

    text.setMarginWidth(0, 50)
    text.styleSetForeground(wxSTC_STYLE_LINENUMBER, constructWxColour(75, 75, 75) )
    text.styleSetBackground(wxSTC_STYLE_LINENUMBER, constructWxColour(220, 220, 220))
    text.setMarginType(0, wxSTC_MARGIN_NUMBER)

    text.setKeyWords(0, "return for while break continue")
    text.setKeyWords(1, "const int float void char double")

    let sizer = cnew constructWxBoxSizer(wxVERTICAL)

    sizer.add(btn, 1, wxSTRETCH_NOT)
    sizer.add(lstctl, 2, wxEXPAND)
    sizer.add(text, 3, wxEXPAND)

    result.setSizer(sizer)


f.show(true)

runMainLoop()
1.png
1.png (41.51 KiB) Viewed 569 times

PB
Part Of The Furniture
Part Of The Furniture
Posts: 2057
Joined: Sun Jan 03, 2010 5:45 pm

Re: why the listctrl has the back window as background

Post by PB » Wed Jan 30, 2019 1:49 pm

I have no knowledge of the language in the OP but the code looks OK to me. I also translated it word for word to C++ (see below) and it runs fine (wxWidgets GIT master head, MSW 10).

However, in your screenshot it is clear that your application is not themed, i.e., it does not have common controls version 6 in the application manifest and therefore the controls have the old Windows 95 look (usually odd looking buttons are easy to spot).

When I removed the manifest from my test application with your code, I could observe a similar issue, the part of wxListCtrl not covered by items is not painted which leads to visual artefacts. I thought I remembered such issue being discussed but I could not find it mentioned anywhere.

While this may be a bug, I would suggest using a manifest; every application should have one since Windows XP...

I do not know if a wxListCtrl has some setting to fit the columns / last column to its full size. At worst, you may have to do it by hand in the size event handler. But perhaps someone knows a better way...

Code: Select all

#include <wx/wx.h>
#include <wx/listctrl.h>
#include <wx/stc/stc.h>

class MyFrame : public wxFrame
{
public:
    MyFrame() : wxFrame(nullptr, wxID_ANY, "Hello World", wxPoint(50, 50), wxSize(450, 340))
    {               
        // Construct status bar        
        CreateStatusBar();
        SetStatusText("Welcome to wxWidgets!");

        // Construct menu
        wxMenu* menuFile = new wxMenu;
        wxWindowID helloID = wxNewId();
    
        menuFile->Append(helloID, "&Hello...\tCtrl-H", "Help string shown in status bar for this menu item");
        menuFile->AppendSeparator();
        menuFile->Append(wxID_EXIT);
    
        wxMenu* menuHelp = new wxMenu;        
        menuHelp->Append(wxID_ABOUT);

        wxMenuBar* menuBar = new wxMenuBar();
    
        menuBar->Append(menuFile, "&File");
        menuBar->Append(menuHelp, "&Help");
        SetMenuBar(menuBar);               

        // Construct the button
        wxButton* btn = new wxButton(this, wxID_ANY, "click");

        // Construct the list control
        wxListCtrl* lstctl = new wxListCtrl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT);

        wxListItem info;

        // # Add first column
        info.m_itemId = 0;
        info.m_text = "A";
        info.m_width = 50;
        info.m_mask = wxLIST_MASK_TEXT;
        lstctl->InsertColumn(0, info);

        // # Add second column
        info.m_itemId = 1;
        info.m_text = "B";
        info.m_width = 50;
        info.m_mask = wxLIST_MASK_TEXT;
        lstctl->InsertColumn(1, info);

        // # Add third column
        info.m_itemId = 2;
        info.m_text = "C";
        info.m_width = 50;
        info.m_mask = wxLIST_MASK_TEXT;
        lstctl->InsertColumn(2, info);
        
        const size_t item_amount = 3;

        for ( size_t n = 0; n < item_amount; ++n )
        {
            wxListItem item;

            item.m_itemId = n;
            lstctl->InsertItem(item);

            lstctl->SetItem(n, 0, wxString::Format("%zu : 0", n));
            lstctl->SetItem(n, 1, wxString::Format("%zu : 1", n));
            lstctl->SetItem(n, 2, wxString::Format("%zu : 2", n));

            if (lstctl->GetItemCount() % 2 == 1 )
                lstctl->SetItemBackgroundColour(n, wxColour(255, 0, 0));
            else
                lstctl->SetItemBackgroundColour(n, wxColour(255, 255, 255));
        }  

        lstctl->SetColumnWidth(2, wxLIST_AUTOSIZE);

        // Construct the styled text control

        wxStyledTextCtrl* text = new wxStyledTextCtrl(this, wxID_ANY);
        text->StyleClearAll();
        text->SetLexer(wxSTC_LEX_CPP);

        text->SetMarginWidth(0, 50);
        text->StyleSetForeground(wxSTC_STYLE_LINENUMBER, wxColour(75, 75, 75));
        text->StyleSetBackground(wxSTC_STYLE_LINENUMBER, wxColour(220, 220, 220));
        text->SetMarginType(0, wxSTC_MARGIN_NUMBER);

        text->SetKeyWords(0, "return for while break continue");
        text->SetKeyWords(1, "const int float void char double");

        wxSizer* sizer = new wxBoxSizer(wxVERTICAL);

        sizer->Add(btn, 1, wxSTRETCH_NOT);
        sizer->Add(lstctl, 2, wxEXPAND);
        sizer->Add(text, 3, wxEXPAND);

        SetSizer(sizer);
    }	
};

class MyApp : public wxApp
{
public:	
    bool OnInit()
    {
        (new MyFrame)->Show();
        return true;
    }
}; wxIMPLEMENT_APP(MyApp);

oyster
In need of some credit
In need of some credit
Posts: 4
Joined: Wed Jan 30, 2019 4:48 am

Re: why the listctrl has the back window as background

Post by oyster » Thu Jan 31, 2019 3:22 am

so bad, the CPP version has the back application interface on its own GUI interface
I have tested Cpp/nim version with/without the following manifest file, nothing good happens

Code: Select all

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
    version="0.64.1.0"
    processorArchitecture="amd64"
    name="Controls"
    type="win32"
/>
<description>Controls: wxWidgets sample application</description>
<dependency>
    <dependentAssembly>
        <assemblyIdentity
            type="win32"
            name="Microsoft.Windows.Common-Controls"
            version="6.0.0.0"
            processorArchitecture="amd64"
            publicKeyToken="6595b64144ccf1df"
            language="*"
        />
    </dependentAssembly>
</dependency>
</assembly>

User avatar
doublemax
Moderator
Moderator
Posts: 14098
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: why the listctrl has the back window as background

Post by doublemax » Thu Jan 31, 2019 7:38 am

so bad, the CPP version has the back application interface on its own GUI interface
What actually happens is that there is an area that doesn't get repainted at all. So it will "display" what was underneath before. You should see that if you move a window from another application across that window.

Try to create a wxPanel as the only child of the main frame and construct all controls as children of that wxPanel.
Use the source, Luke!

PB
Part Of The Furniture
Part Of The Furniture
Posts: 2057
Joined: Sun Jan 03, 2010 5:45 pm

Re: why the listctrl has the back window as background

Post by PB » Thu Jan 31, 2019 9:38 am

doublemax wrote:Try to create a wxPanel as the only child of the main frame and construct all controls as children of that wxPanel.
Surprisingly, this did not help and there were artefacts even with a manifest. There may be some issue with creating a list or styled text control? I did not have time to look into this any further.

Code: Select all

#include <wx/wx.h>
#include <wx/listctrl.h>
#include <wx/stc/stc.h>

class MyFrame : public wxFrame
{
public:
    MyFrame() : wxFrame(nullptr, wxID_ANY, "Hello World", wxPoint(50, 50), wxSize(450, 340))
    {               
        wxPanel* mainPanel = new wxPanel(this);        
        
        // Construct status bar        
        CreateStatusBar();
        SetStatusText("Welcome to wxWidgets!");

        // Construct menu
        wxMenu* menuFile = new wxMenu;
        wxWindowID helloID = wxNewId();
    
        menuFile->Append(helloID, "&Hello...\tCtrl-H", "Help string shown in status bar for this menu item");
        menuFile->AppendSeparator();
        menuFile->Append(wxID_EXIT);
    
        wxMenu* menuHelp = new wxMenu;        
        menuHelp->Append(wxID_ABOUT);

        wxMenuBar* menuBar = new wxMenuBar();
    
        menuBar->Append(menuFile, "&File");
        menuBar->Append(menuHelp, "&Help");
        SetMenuBar(menuBar);               

        // Construct the button
        wxButton* btn = new wxButton(mainPanel, wxID_ANY, "click");

        // Construct the list control
        wxListCtrl* lstctl = new wxListCtrl(mainPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT);

        wxListItem info;

        // # Add first column
        info.m_itemId = 0;
        info.m_text = "A";
        info.m_width = 50;
        info.m_mask = wxLIST_MASK_TEXT;
        lstctl->InsertColumn(0, info);

        // # Add second column
        info.m_itemId = 1;
        info.m_text = "B";
        info.m_width = 50;
        info.m_mask = wxLIST_MASK_TEXT;
        lstctl->InsertColumn(1, info);

        // # Add third column
        info.m_itemId = 2;
        info.m_text = "C";
        info.m_width = 50;
        info.m_mask = wxLIST_MASK_TEXT;
        lstctl->InsertColumn(2, info);
        
        const size_t item_amount = 3;

        for ( size_t n = 0; n < item_amount; ++n )
        {
            wxListItem item;

            item.m_itemId = n;
            lstctl->InsertItem(item);

            lstctl->SetItem(n, 0, wxString::Format("%zu : 0", n));
            lstctl->SetItem(n, 1, wxString::Format("%zu : 1", n));
            lstctl->SetItem(n, 2, wxString::Format("%zu : 2", n));

            if (lstctl->GetItemCount() % 2 == 1 )
                lstctl->SetItemBackgroundColour(n, wxColour(255, 0, 0));
            else
                lstctl->SetItemBackgroundColour(n, wxColour(255, 255, 255));
        }          

        // Construct the styled text control
        wxStyledTextCtrl* text = new wxStyledTextCtrl(mainPanel, wxID_ANY);
        text->StyleClearAll();
        text->SetLexer(wxSTC_LEX_CPP);

        text->SetMarginWidth(0, 50);
        text->StyleSetForeground(wxSTC_STYLE_LINENUMBER, wxColour(75, 75, 75));
        text->StyleSetBackground(wxSTC_STYLE_LINENUMBER, wxColour(220, 220, 220));
        text->SetMarginType(0, wxSTC_MARGIN_NUMBER);

        text->SetKeyWords(0, "return for while break continue");
        text->SetKeyWords(1, "const int float void char double");

        wxSizer* sizer = new wxBoxSizer(wxVERTICAL);

        sizer->Add(btn, 1, wxSTRETCH_NOT);
        sizer->Add(lstctl, 2, wxEXPAND);
        sizer->Add(text, 3, wxEXPAND);

        mainPanel->SetSizer(sizer);
    }	
};

class MyApp : public wxApp
{
public:	
    bool OnInit()
    {
        (new MyFrame)->Show();
        return true;
    }
}; wxIMPLEMENT_APP(MyApp);

New Pagodi
Super wx Problem Solver
Super wx Problem Solver
Posts: 307
Joined: Tue Jun 20, 2006 6:47 pm
Contact:

Re: why the listctrl has the back window as background

Post by New Pagodi » Thu Jan 31, 2019 10:15 am

I think the last line of the constructor should be 'mainPanel->Layout();'

PB
Part Of The Furniture
Part Of The Furniture
Posts: 2057
Joined: Sun Jan 03, 2010 5:45 pm

Re: why the listctrl has the back window as background

Post by PB » Thu Jan 31, 2019 11:19 am

New Pagodi wrote:I think the last line of the constructor should be 'mainPanel->Layout();'
Ah yes, this helps for the executable with a CC6 manifest.

oyster
In need of some credit
In need of some credit
Posts: 4
Joined: Wed Jan 30, 2019 4:48 am

Re: why the listctrl has the back window as background

Post by oyster » Thu Jan 31, 2019 1:09 pm

I get totally lost. I am using the manifest file `a.exe.manifest` I post above

Do you mean this code I enclosed below? No matter I use `mainPanel->SetSizer(sizer); ` or `mainPanel->Layout();`, the underneath face are drawn too. What is even worse, you may find that the button, listctrl and the textctrol overlaps each other in this version, I understood the usage of sizer is "sizer->Add(ctrl, index)" before, but this code lets me hesitate

I am using the latest cloned wxWidgets compiled by

Code: Select all

$ g++ --version
g++.exe (Rev2, Built by MSYS2 project) 6.2.0
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions`.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
and the demos is compiled by

Code: Select all

$ g++  `(/opt/windows_64/bin/wx-config --cxxflags)` test_cpp.cpp `(/opt/windows_64/bin/wx-config --libs all)`

this is `test_cpp.cpp`

Code: Select all

#include <wx/wx.h>
#include <wx/listctrl.h>
#include <wx/stc/stc.h>

class MyFrame : public wxFrame
{
public:
    MyFrame() : wxFrame(nullptr, wxID_ANY, "Hello World", wxPoint(50, 50), wxSize(450, 340))
    {
        wxPanel* mainPanel = new wxPanel(this);

        // Construct status bar
        CreateStatusBar();
        SetStatusText("Welcome to wxWidgets!");

        // Construct menu
        wxMenu* menuFile = new wxMenu;
        wxWindowID helloID = wxNewId();

        menuFile->Append(helloID, "&Hello...\tCtrl-H", "Help string shown in status bar for this menu item");
        menuFile->AppendSeparator();
        menuFile->Append(wxID_EXIT);

        wxMenu* menuHelp = new wxMenu;
        menuHelp->Append(wxID_ABOUT);

        wxMenuBar* menuBar = new wxMenuBar();

        menuBar->Append(menuFile, "&File");
        menuBar->Append(menuHelp, "&Help");
        SetMenuBar(menuBar);

        // Construct the button
        wxButton* btn = new wxButton(mainPanel, wxID_ANY, "click");

        // Construct the list control
        wxListCtrl* lstctl = new wxListCtrl(mainPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT);

        wxListItem info;

        // # Add first column
        info.m_itemId = 0;
        info.m_text = "A";
        info.m_width = 50;
        info.m_mask = wxLIST_MASK_TEXT;
        lstctl->InsertColumn(0, info);

        // # Add second column
        info.m_itemId = 1;
        info.m_text = "B";
        info.m_width = 50;
        info.m_mask = wxLIST_MASK_TEXT;
        lstctl->InsertColumn(1, info);

        // # Add third column
        info.m_itemId = 2;
        info.m_text = "C";
        info.m_width = 50;
        info.m_mask = wxLIST_MASK_TEXT;
        lstctl->InsertColumn(2, info);

        const size_t item_amount = 3;

        for ( size_t n = 0; n < item_amount; ++n )
        {
            wxListItem item;

            item.m_itemId = n;
            lstctl->InsertItem(item);

            lstctl->SetItem(n, 0, wxString::Format("%zu : 0", n));
            lstctl->SetItem(n, 1, wxString::Format("%zu : 1", n));
            lstctl->SetItem(n, 2, wxString::Format("%zu : 2", n));

            if (lstctl->GetItemCount() % 2 == 1 )
                lstctl->SetItemBackgroundColour(n, wxColour(255, 0, 0));
            else
                lstctl->SetItemBackgroundColour(n, wxColour(255, 255, 255));
        }

        // Construct the styled text control
        wxStyledTextCtrl* text = new wxStyledTextCtrl(mainPanel, wxID_ANY);
        text->StyleClearAll();
        text->SetLexer(wxSTC_LEX_CPP);

        text->SetMarginWidth(0, 50);
        text->StyleSetForeground(wxSTC_STYLE_LINENUMBER, wxColour(75, 75, 75));
        text->StyleSetBackground(wxSTC_STYLE_LINENUMBER, wxColour(220, 220, 220));
        text->SetMarginType(0, wxSTC_MARGIN_NUMBER);

        text->SetKeyWords(0, "return for while break continue");
        text->SetKeyWords(1, "const int float void char double");

        wxSizer* sizer = new wxBoxSizer(wxVERTICAL);

        sizer->Add(btn, 1, wxSTRETCH_NOT);
        sizer->Add(lstctl, 2, wxEXPAND);
        sizer->Add(text, 3, wxEXPAND);

        //~ mainPanel->SetSizer(sizer);    // ***** no matter this line
        mainPanel->Layout();       // ***** or this line, nothing changed to better
    }
};

class MyApp : public wxApp
{
public:
    bool OnInit()
    {
        (new MyFrame)->Show();
        return true;
    }
}; wxIMPLEMENT_APP(MyApp);
2.png
2.png (35.28 KiB) Viewed 476 times

PB
Part Of The Furniture
Part Of The Furniture
Posts: 2057
Joined: Sun Jan 03, 2010 5:45 pm

Re: why the listctrl has the back window as background

Post by PB » Thu Jan 31, 2019 1:32 pm

I haven't used Windows 7 in a while so I am not sure but to me, judging from the button appearance, it seems the application is still not themed. Or does the button look like the buttons do in proper applications (e.g. buttons in File Open dialog in Notepad or WordPad)?

The controls overlap each other because the code is probably still missing

Code: Select all

mainPanel->Layout();
after

Code: Select all

mainPanel->SetSizer(sizer);
and this gets fixed after manually resizing the frame?

oyster
In need of some credit
In need of some credit
Posts: 4
Joined: Wed Jan 30, 2019 4:48 am

Re: why the listctrl has the back window as background

Post by oyster » Thu Jan 31, 2019 2:59 pm

I think this is this another try which lets me run away from CPP(and nimlang binding) :evil: . I think the only way to erase underneath interface is to write extra codes to make the listctrl zoom and take all the space.


In wxPython, we do not need to care about it

Post Reply