wxWidgets wxBORDER_NONE 和 wxRESIZE_BORDER 使白色区域
wxWidgets wxBORDER_NONE and wxRESIZE_BORDER makes white area
White Border
如何去除这个白色区域?它毁了我的 GUI 设计。
我想制作由 windows 生成的阴影和蓝线。
所以我找到了一个使蓝线(wxRESIZE_BORDER)但像图像一样的白色区域的选项。
//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;
}
使用 wxSUNKEN_BORDER
你会得到这样的结果:
那么就不需要wxRESIZE_BORDER
部分了。但请注意,这会使十字架消失。
这个白色的上边框是resize border,属于window的非客户区。因此,要删除它,您应该处理 window 与 window 的非客户区的大小调整和激活相关的消息,如下所示:
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 );
}
正如 Reza 所说,最好的方法是覆盖 MSWWindowProc
。
至于我的推荐:
- 在主框架的构造函数体中以这种方式设置主框架flags/style class:
this->SetWindowStyle(wxSYSTEM_MENU | wxRESIZE_BORDER| wxCLIP_CHILDREN);
- 在主框架 class 中,为
MSWWindowProc
创建声明以覆盖:
WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) wxOVERRIDE;
- 为
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);
}
White Border
如何去除这个白色区域?它毁了我的 GUI 设计。
我想制作由 windows 生成的阴影和蓝线。
所以我找到了一个使蓝线(wxRESIZE_BORDER)但像图像一样的白色区域的选项。
//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;
}
使用 wxSUNKEN_BORDER
你会得到这样的结果:
那么就不需要wxRESIZE_BORDER
部分了。但请注意,这会使十字架消失。
这个白色的上边框是resize border,属于window的非客户区。因此,要删除它,您应该处理 window 与 window 的非客户区的大小调整和激活相关的消息,如下所示:
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 );
}
正如 Reza 所说,最好的方法是覆盖 MSWWindowProc
。
至于我的推荐:
- 在主框架的构造函数体中以这种方式设置主框架flags/style class:
this->SetWindowStyle(wxSYSTEM_MENU | wxRESIZE_BORDER| wxCLIP_CHILDREN);
- 在主框架 class 中,为
MSWWindowProc
创建声明以覆盖:
WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) wxOVERRIDE;
- 为
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);
}