maxswjeon
maxswjeon

Reputation: 120

wxWidgets wxBORDER_NONE and wxRESIZE_BORDER makes white area

White Border

How can I remove this white area? it Ruins my GUI design.
I want to make a shadow and a blue line which generated by windows. so I found a option that makes the blue line(wxRESIZE_BORDER) but it makes a white area like the image.

//MainFrame.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS

#include <wx/frame.h>


class MainFrame : public wxFrame
{
public:

    MainFrame(wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize(310, 390), long style = wxSUNKEN_BORDER|wxRESIZE_BORDER);

};  


//MainFrame.cpp
#include "MainFrame.h"

MainFrame::MainFrame(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style) : wxFrame(parent, id, title, pos, size, style)
{
    this->Centre(wxBOTH);
}


//Main.h
#pragma once
#include <wx/wx.h>

class App : public wxApp
{
public:
    virtual bool OnInit();
};


//Main.cpp
#include "Main.h"
#include "MainFrame.h"

IMPLEMENT_APP(App)

bool App::OnInit()
{
    MainFrame *frame = new MainFrame(NULL);
    frame->Show(true);

    return true;
}

Upvotes: 1

Views: 1428

Answers (3)

user10091872
user10091872

Reputation:

As Reza said, the best approach is to override MSWWindowProc. As for my recommendation:

  1. Set main frame flags/style this way in constructor body of your main frame class:
this->SetWindowStyle(wxSYSTEM_MENU | wxRESIZE_BORDER| wxCLIP_CHILDREN);
  1. In main frame class, create a declaration for MSWWindowProc to override:
    WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) wxOVERRIDE;
  1. Create a body for MSWWindowProc:
WXLRESULT _YOUR_MAIN_FRAME_CLASS::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
{
    switch (nMsg)
    {
    case WM_NCACTIVATE:
    {
        lParam = -1;
        break;
    }
    case WM_NCCALCSIZE:
        if (wParam)
        {
            HWND hWnd = (HWND)this->GetHandle();
            WINDOWPLACEMENT wPos;
            wPos.length = sizeof(wPos);
            GetWindowPlacement(hWnd, &wPos);
            if (wPos.showCmd != SW_SHOWMAXIMIZED)
            {
                RECT borderThickness;
                SetRectEmpty(&borderThickness);
                AdjustWindowRectEx(&borderThickness,
                    GetWindowLongPtr(hWnd, GWL_STYLE) & ~WS_CAPTION, FALSE, NULL);
                borderThickness.left *= -1;
                borderThickness.top *= -1;
                NCCALCSIZE_PARAMS* sz = reinterpret_cast<NCCALCSIZE_PARAMS*>(lParam);
                sz->rgrc[0].top += 1;
                sz->rgrc[0].left += borderThickness.left;
                sz->rgrc[0].right -= borderThickness.right;
                sz->rgrc[0].bottom -= borderThickness.bottom;
                return 0;
            }
        }
        break;
    }
    return wxFrame::MSWWindowProc(nMsg, wParam, lParam);
}

Upvotes: 0

Reza
Reza

Reputation: 3919

This white top border is the resize border and it belongs to the non client area of a window. So for removing it you should handle window messages related to the resizing and activating of non-client area of a window like below:

  WXLRESULT MSWWindowProc( WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam )
  {
    /* When we have a custom titlebar in the window, we don't need the non-client area of a normal window
      * to be painted. In order to achieve this, we handle the "WM_NCCALCSIZE" which is responsible for the
      * size of non-client area of a window and set the return value to 0. Also we have to tell the
      * application to not paint this area on activate and deactivation events so we also handle
      * "WM_NCACTIVATE" message. */
      switch( nMsg )
      {
      case WM_NCACTIVATE:
      {
        /* Returning 0 from this message disable the window from receiving activate events which is not
        desirable. However When a visual style is not active (?) for this window, "lParam" is a handle to an
        optional update region for the nonclient area of the window. If this parameter is set to -1,
        DefWindowProc does not repaint the nonclient area to reflect the state change. */
        lParam = -1;
        break;
      }
      /* To remove the standard window frame, you must handle the WM_NCCALCSIZE message, specifically when
      its wParam value is TRUE and the return value is 0 */
      case WM_NCCALCSIZE:
        if( wParam )
        {
          /* Detect whether window is maximized or not. We don't need to change the resize border when win is
          *  maximized because all resize borders are gone automatically */
          HWND hWnd = ( HWND ) this->GetHandle();
          WINDOWPLACEMENT wPos;
          // GetWindowPlacement fail if this member is not set correctly.
          wPos.length = sizeof( wPos );
          GetWindowPlacement( hWnd, &wPos );
          if( wPos.showCmd != SW_SHOWMAXIMIZED )
          {
            RECT borderThickness;
            SetRectEmpty( &borderThickness );
            AdjustWindowRectEx( &borderThickness,
              GetWindowLongPtr( hWnd, GWL_STYLE ) & ~WS_CAPTION, FALSE, NULL );
            borderThickness.left *= -1;
            borderThickness.top *= -1;
            NCCALCSIZE_PARAMS* sz = reinterpret_cast< NCCALCSIZE_PARAMS* >( lParam );
            // Add 1 pixel to the top border to make the window resizable from the top border
            sz->rgrc[ 0 ].top += 1;
            sz->rgrc[ 0 ].left += borderThickness.left;
            sz->rgrc[ 0 ].right -= borderThickness.right;
            sz->rgrc[ 0 ].bottom -= borderThickness.bottom;
            return 0;
          }
        }
        break;
      }
    return wxFrame::MSWWindowProc( nMsg, wParam, lParam );
  }

Upvotes: 1

Lehue
Lehue

Reputation: 435

With wxSUNKEN_BORDER you get something like this:Window without border

Then it does not need the wxRESIZE_BORDER part. But note that this makes the cross disappear.

Upvotes: 0

Related Questions