Hi again,
Another question from me. Now regarding the dialog styles.
Is it possible to draw black thin (2px) border around the dialog but without drawing border around the caption (header with close button)?
I didn't find anything similar in dialog styles and border styles.
Only variant I see is to draw needed border by myself on dialog's DC, but here I've got some unclear moments:
1) When should I draw this (constructor, show method, etc.)?
2) How should I draw this correctly (just as 3 lines on each side of the dialog)?
3) How should I process repaint event (for example, if dialog changes the position)?
Thanks.
Border around wxDialog
-
- Earned some good credits
- Posts: 107
- Joined: Tue Aug 28, 2018 1:02 pm
- Location: Belarus
Re: Border around wxDialog
Forget about all the custom drawing, it won't work.
Can't you just use a wxPanel as child that fills the whole client area and set a double border for that?
Can't you just use a wxPanel as child that fills the whole client area and set a double border for that?
Use the source, Luke!
Re: Border around wxDialog
Hi,
wxWidgets is using native controls whenever possible.
It means that what you want to do (this type of styling), is not available under any of the native controls.
You can try to implement something like this, but it is stronglyt discouiraged to interfere with the painting of the native controls.
You can probably workaround this by subclassing a wxPanel and create an internal panel on top.
Thank you.
wxWidgets is using native controls whenever possible.
It means that what you want to do (this type of styling), is not available under any of the native controls.
You can try to implement something like this, but it is stronglyt discouiraged to interfere with the painting of the native controls.
You can probably workaround this by subclassing a wxPanel and create an internal panel on top.
Thank you.
-
- Earned some good credits
- Posts: 107
- Joined: Tue Aug 28, 2018 1:02 pm
- Location: Belarus
Re: Border around wxDialog
Turning back to this topic.
The problems start after I changed wxWidgets version in the project from 3.1.2 to 3.1.3. By the problem I mean that border isn't drawn anymore. I can't find the reason why.
I did it in the way you described here:
m_dialogContent - is the object of wxCustomPanel class (class wxCustomPanel : public wxPanel)
So the question is why this approach doesn't work with 3.1.3 widgets and how to make it work again?
Thanks.
The problems start after I changed wxWidgets version in the project from 3.1.2 to 3.1.3. By the problem I mean that border isn't drawn anymore. I can't find the reason why.
I did it in the way you described here:
Here is needed code (wxCustomDialog)You can probably workaround this by subclassing a wxPanel and create an internal panel on top
Code: Select all
wxCustomDialog::wxCustomDialog(wxWindow* parent, const wxString& title, const IdType& id, long dialogStyle, long buttonsStyle):
m_identifier(id)
, m_dialogContent(nullptr)
, m_buttonsStyle(buttonsStyle)
, m_processor(nullptr)
{
SetBackgroundColour(StylesFactory::BackgroundColor);
SetForegroundColour(StylesFactory::ForegroundColor);
if (parent
&& (parent->GetWindowStyle() & wxSTAY_ON_TOP) != 0)
{
dialogStyle |= wxSTAY_ON_TOP;
}
Create(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, DialogStyle | dialogStyle);
#if defined(BUILD_WINDOWS)
HWND hWnd = reinterpret_cast<HWND>(GetHandle());
auto style = GetWindowLongPtr(hWnd, GWL_EXSTYLE);
SetWindowLong(hWnd, GWL_EXSTYLE, style | WS_EX_LAYERED);
SetLayeredWindowAttributes(hWnd, 0, 255, LWA_ALPHA);
#endif
Bind(wxEVT_SIZE, &wxCustomDialog::OnSize, this);
Bind(wxEVT_CLOSE_WINDOW, &wxCustomDialog::OnCloseWindow, this);
Bind(wxEVT_BUTTON, &wxCustomDialog::OnOk, this, wxID_OK);
Bind(wxEVT_BUTTON, &wxCustomDialog::OnCancel, this, wxID_CANCEL);
Bind(wxEVT_BUTTON, &wxCustomDialog::OnCancel, this, wxID_CLOSE);
Bind(wxEVT_BUTTON, &wxCustomDialog::OnYes, this, wxID_YES);
Bind(wxEVT_BUTTON, &wxCustomDialog::OnNo, this, wxID_NO);
}
void wxCustomDialog::Init()
{
DefaultReturnCode();
m_dialogContent = new wxCustomPanel(this);
auto mainSizer = new wxBoxSizer(wxVERTICAL);
m_caption = CreateCaption();
m_caption->Init();
mainSizer->Add(m_caption, wxSizerFlags(0).Expand());
mainSizer->Add(CreateContent(), wxSizerFlags(1).Border(wxUP | wxLEFT | wxRIGHT, FromDIP(DefaultBorder)).Expand());
mainSizer->Add(CreateButtons(), wxSizerFlags(0).Border(wxALL, FromDIP(DefaultBorder)).Expand());
mainSizer->Fit(this);
m_dialogContent->SetSizerAndFit(mainSizer);
m_dialogContent->SetPosition(FromDIP(wxPoint(1, 1))); // move content panel to 1, 1 position
SetBackgroundColour(*wxBLACK);
UpdateLayout();
CenterOnScreen();
}
std::int32_t wxCustomDialog::ShowModal()
{
Show();
Raise();
Refresh();
return wxDialog::ShowModal();
}
void wxCustomDialog::Fit()
{
m_dialogContent->Fit();
m_dialogContent->Layout();
wxDialog::Fit();
wxSize sz = this->GetSize();
sz.IncBy(FromDIP(wxSize(1, 1)));
this->SetSize(sz); // increase dialog's size
}
void wxCustomDialog::OnSize(wxSizeEvent& event)
{
#ifdef BUILD_LINUX
DecorSize size = {};
if (memcmp(&size, &m_decorSize, sizeof(m_decorSize)) != 0)
{
m_deferShow = true;
}
#endif
Layout();
}
void wxCustomDialog::UpdateLayout()
{
m_dialogContent->GetSizer()->SetSizeHints(m_dialogContent);
Fit();
Layout();
Refresh();
}
Code: Select all
wxCustomPanel::wxCustomPanel(wxWindow* parent)
{
Create(parent);
}
bool wxCustomPanel::Create(wxWindow *parent, wxWindowID winid, const wxPoint& pos, const wxSize& size, long style, const wxString& name)
{
SetBackgroundColour(parent->GetBackgroundColour());
SetBackgroundStyle(wxBG_STYLE_PAINT);
SetForegroundColour(parent->GetForegroundColour());
Bind(wxEVT_PAINT, &wxCustomPanel::OnPaint, this);
Bind(wxEVT_SIZE, &wxCustomPanel::OnSize, this);
Bind(wxEVT_ERASE_BACKGROUND, &wxCustomPanel::OnErase, this);
Bind(wxEVT_CLOSE_WINDOW, &wxCustomPanel::OnClose, this);
Bind(wxEVT_ICONIZE, &wxCustomPanel::OnIconize, this);
return wxPanel::Create(parent, winid, pos, size, style, name);
}
void wxCustomPanel::OnPaint(wxPaintEvent&)
{
wxPaintDC dc(this);
wxGCDC gcdc(dc);
dc.Clear();
auto parent = dynamic_cast<wxCustomControlInterface*>(GetParent());
if (parent)
{
parent->DrawBackground(gcdc, wxRect(GetPosition(), GetSize()));
}
DrawInternal(gcdc, this);
}
void wxCustomPanel::OnErase(wxEraseEvent&)
{}
void wxCustomPanel::OnIconize(wxIconizeEvent& WXUNUSED(event))
{
auto parent = GetParent();
auto iconizeEvt = new wxIconizeEvent(parent->GetId(), true);
wxQueueEvent(parent, iconizeEvt);
}
wxSize wxCustomPanel::CalculateBestSize() const
{
return wxSize(wxDefaultCoord, wxDefaultCoord);
}
wxSize wxCustomPanel::GetBestSize() const
{
auto bestSize = CalculateBestSize();
if (bestSize.x == wxDefaultCoord || bestSize.y == wxDefaultCoord)
{
auto defaultBestSize = wxPanel::GetBestSize();
if (bestSize.x == wxDefaultCoord) bestSize.x = defaultBestSize.x;
if (bestSize.y == wxDefaultCoord) bestSize.y = defaultBestSize.y;
}
return bestSize;
}
wxSize wxCustomPanel::GetEffectiveMinSize() const
{
// merge the best size with the min size, giving priority to the min size
wxSize min = GetMinSize();
if (min.x == wxDefaultCoord || min.y == wxDefaultCoord)
{
wxSize best = GetBestSize();
if (min.x == wxDefaultCoord) min.x = best.x;
if (min.y == wxDefaultCoord) min.y = best.y;
}
return min;
}
void wxCustomPanel::OnSize(wxSizeEvent& evt)
{
Layout();
evt.Skip();
}
void wxCustomPanel::DrawBackground(wxDC& dc, const wxRect& rect)
{
auto parent = dynamic_cast<wxCustomControlInterface*>(GetParent());
if (parent)
{
wxRect drawRect(GetSize());
drawRect.SetBottom(wxMin(drawRect.GetBottom(), rect.GetBottom()));
drawRect.SetRight(wxMin(drawRect.GetRight(), rect.GetRight()));
drawRect.SetPosition(GetPosition() + rect.GetPosition());
parent->DrawBackground(dc, drawRect);
}
}
Thanks.