window.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 2,123 行 · 第 1/5 页
CPP
2,123 行
inline int GetScrollPosition(HWND hWnd, int wOrient)
{
#ifdef __WXMICROWIN__
return ::GetScrollPosWX(hWnd, wOrient);
#else
WinStruct<SCROLLINFO> scrollInfo;
scrollInfo.cbSize = sizeof(SCROLLINFO);
scrollInfo.fMask = SIF_POS;
::GetScrollInfo(hWnd, wOrient, &scrollInfo);
return scrollInfo.nPos;
#endif
}
int wxWindowMSW::GetScrollPos(int orient) const
{
HWND hWnd = GetHwnd();
wxCHECK_MSG( hWnd, 0, _T("no HWND in GetScrollPos") );
return GetScrollPosition(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT);
}
// This now returns the whole range, not just the number
// of positions that we can scroll.
int wxWindowMSW::GetScrollRange(int orient) const
{
int maxPos;
HWND hWnd = GetHwnd();
if ( !hWnd )
return 0;
#if 0
::GetScrollRange(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT,
&minPos, &maxPos);
#endif
WinStruct<SCROLLINFO> scrollInfo;
scrollInfo.fMask = SIF_RANGE;
if ( !::GetScrollInfo(hWnd,
orient == wxHORIZONTAL ? SB_HORZ : SB_VERT,
&scrollInfo) )
{
// Most of the time this is not really an error, since the return
// value can also be zero when there is no scrollbar yet.
// wxLogLastError(_T("GetScrollInfo"));
}
maxPos = scrollInfo.nMax;
// undo "range - 1" done in SetScrollbar()
return maxPos + 1;
}
int wxWindowMSW::GetScrollThumb(int orient) const
{
return orient == wxHORIZONTAL ? m_xThumbSize : m_yThumbSize;
}
void wxWindowMSW::SetScrollPos(int orient, int pos, bool refresh)
{
HWND hWnd = GetHwnd();
wxCHECK_RET( hWnd, _T("SetScrollPos: no HWND") );
WinStruct<SCROLLINFO> info;
info.nPage = 0;
info.nMin = 0;
info.nPos = pos;
info.fMask = SIF_POS;
if ( HasFlag(wxALWAYS_SHOW_SB) )
{
// disable scrollbar instead of removing it then
info.fMask |= SIF_DISABLENOSCROLL;
}
::SetScrollInfo(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT,
&info, refresh);
}
// New function that will replace some of the above.
void wxWindowMSW::SetScrollbar(int orient,
int pos,
int pageSize,
int range,
bool refresh)
{
WinStruct<SCROLLINFO> info;
info.nPage = pageSize;
info.nMin = 0; // range is nMax - nMin + 1
info.nMax = range - 1; // as both nMax and nMax are inclusive
info.nPos = pos;
info.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
if ( HasFlag(wxALWAYS_SHOW_SB) )
{
// disable scrollbar instead of removing it then
info.fMask |= SIF_DISABLENOSCROLL;
}
HWND hWnd = GetHwnd();
if ( hWnd )
{
// We have to set the variables here to make them valid in events
// triggered by ::SetScrollInfo()
*(orient == wxHORIZONTAL ? &m_xThumbSize : &m_yThumbSize) = pageSize;
::SetScrollInfo(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT,
&info, refresh);
}
}
void wxWindowMSW::ScrollWindow(int dx, int dy, const wxRect *prect)
{
RECT rect;
RECT *pr;
if ( prect )
{
rect.left = prect->x;
rect.top = prect->y;
rect.right = prect->x + prect->width;
rect.bottom = prect->y + prect->height;
pr = ▭
}
else
{
pr = NULL;
}
#ifdef __WXWINCE__
// FIXME: is this the exact equivalent of the line below?
::ScrollWindowEx(GetHwnd(), dx, dy, pr, pr, 0, 0, SW_SCROLLCHILDREN|SW_ERASE|SW_INVALIDATE);
#else
::ScrollWindow(GetHwnd(), dx, dy, pr, pr);
#endif
}
static bool ScrollVertically(HWND hwnd, int kind, int count)
{
int posStart = GetScrollPosition(hwnd, SB_VERT);
int pos = posStart;
for ( int n = 0; n < count; n++ )
{
::SendMessage(hwnd, WM_VSCROLL, kind, 0);
int posNew = GetScrollPosition(hwnd, SB_VERT);
if ( posNew == pos )
{
// don't bother to continue, we're already at top/bottom
break;
}
pos = posNew;
}
return pos != posStart;
}
bool wxWindowMSW::ScrollLines(int lines)
{
bool down = lines > 0;
return ScrollVertically(GetHwnd(),
down ? SB_LINEDOWN : SB_LINEUP,
down ? lines : -lines);
}
bool wxWindowMSW::ScrollPages(int pages)
{
bool down = pages > 0;
return ScrollVertically(GetHwnd(),
down ? SB_PAGEDOWN : SB_PAGEUP,
down ? pages : -pages);
}
// ---------------------------------------------------------------------------
// subclassing
// ---------------------------------------------------------------------------
void wxWindowMSW::SubclassWin(WXHWND hWnd)
{
wxASSERT_MSG( !m_oldWndProc, wxT("subclassing window twice?") );
HWND hwnd = (HWND)hWnd;
wxCHECK_RET( ::IsWindow(hwnd), wxT("invalid HWND in SubclassWin") );
wxAssociateWinWithHandle(hwnd, this);
m_oldWndProc = (WXFARPROC)wxGetWindowProc((HWND)hWnd);
// we don't need to subclass the window of our own class (in the Windows
// sense of the word)
if ( !wxCheckWindowWndProc(hWnd, (WXFARPROC)wxWndProc) )
{
wxSetWindowProc(hwnd, wxWndProc);
}
else
{
// don't bother restoring it neither: this also makes it easy to
// implement IsOfStandardClass() method which returns true for the
// standard controls and false for the wxWidgets own windows as it can
// simply check m_oldWndProc
m_oldWndProc = NULL;
}
}
void wxWindowMSW::UnsubclassWin()
{
wxRemoveHandleAssociation(this);
// Restore old Window proc
HWND hwnd = GetHwnd();
if ( hwnd )
{
SetHWND(0);
wxCHECK_RET( ::IsWindow(hwnd), wxT("invalid HWND in UnsubclassWin") );
if ( m_oldWndProc )
{
if ( !wxCheckWindowWndProc((WXHWND)hwnd, m_oldWndProc) )
{
wxSetWindowProc(hwnd, (WNDPROC)m_oldWndProc);
}
m_oldWndProc = NULL;
}
}
}
void wxWindowMSW::AssociateHandle(WXWidget handle)
{
if ( m_hWnd )
{
if ( !::DestroyWindow(GetHwnd()) )
wxLogLastError(wxT("DestroyWindow"));
}
WXHWND wxhwnd = (WXHWND)handle;
SetHWND(wxhwnd);
SubclassWin(wxhwnd);
}
void wxWindowMSW::DissociateHandle()
{
// this also calls SetHWND(0) for us
UnsubclassWin();
}
bool wxCheckWindowWndProc(WXHWND hWnd,
WXFARPROC WXUNUSED(wndProc))
{
// TODO: This list of window class names should be factored out so they can be
// managed in one place and then accessed from here and other places, such as
// wxApp::RegisterWindowClasses() and wxApp::UnregisterWindowClasses()
#ifdef __WXWINCE__
extern wxChar *wxCanvasClassName;
extern wxChar *wxCanvasClassNameNR;
#else
extern const wxChar *wxCanvasClassName;
extern const wxChar *wxCanvasClassNameNR;
#endif
extern const wxChar *wxMDIFrameClassName;
extern const wxChar *wxMDIFrameClassNameNoRedraw;
extern const wxChar *wxMDIChildFrameClassName;
extern const wxChar *wxMDIChildFrameClassNameNoRedraw;
wxString str(wxGetWindowClass(hWnd));
if (str == wxCanvasClassName ||
str == wxCanvasClassNameNR ||
#if wxUSE_GLCANVAS
str == _T("wxGLCanvasClass") ||
str == _T("wxGLCanvasClassNR") ||
#endif // wxUSE_GLCANVAS
str == wxMDIFrameClassName ||
str == wxMDIFrameClassNameNoRedraw ||
str == wxMDIChildFrameClassName ||
str == wxMDIChildFrameClassNameNoRedraw ||
str == _T("wxTLWHiddenParent"))
return true; // Effectively means don't subclass
else
return false;
}
// ----------------------------------------------------------------------------
// Style handling
// ----------------------------------------------------------------------------
void wxWindowMSW::SetWindowStyleFlag(long flags)
{
long flagsOld = GetWindowStyleFlag();
if ( flags == flagsOld )
return;
// update the internal variable
wxWindowBase::SetWindowStyleFlag(flags);
// now update the Windows style as well if needed - and if the window had
// been already created
if ( !GetHwnd() )
return;
WXDWORD exstyle, exstyleOld;
long style = MSWGetStyle(flags, &exstyle),
styleOld = MSWGetStyle(flagsOld, &exstyleOld);
if ( style != styleOld )
{
// some flags (e.g. WS_VISIBLE or WS_DISABLED) should not be changed by
// this function so instead of simply setting the style to the new
// value we clear the bits which were set in styleOld but are set in
// the new one and set the ones which were not set before
long styleReal = ::GetWindowLong(GetHwnd(), GWL_STYLE);
styleReal &= ~styleOld;
styleReal |= style;
::SetWindowLong(GetHwnd(), GWL_STYLE, styleReal);
}
// and the extended style
if ( exstyle != exstyleOld )
{
long exstyleReal = ::GetWindowLong(GetHwnd(), GWL_EXSTYLE);
exstyleReal &= ~exstyleOld;
exstyleReal |= exstyle;
::SetWindowLong(GetHwnd(), GWL_EXSTYLE, exstyleReal);
// we must call SetWindowPos() to flush the cached extended style and
// also to make the change to wxSTAY_ON_TOP style take effect: just
// setting the style simply doesn't work
if ( !::SetWindowPos(GetHwnd(),
exstyleReal & WS_EX_TOPMOST ? HWND_TOPMOST
: HWND_NOTOPMOST,
0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE) )
{
wxLogLastError(_T("SetWindowPos"));
}
}
}
WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const
{
// translate common wxWidgets styles to Windows ones
// most of windows are child ones, those which are not (such as
// wxTopLevelWindow) should remove WS_CHILD in their MSWGetStyle()
WXDWORD style = WS_CHILD;
// using this flag results in very significant reduction in flicker,
// especially with controls inside the static boxes (as the interior of the
// box is not redrawn twice).but sometimes results in redraw problems, so
// optionally allow the old code to continue to use it provided a special
// system option is turned on
if ( !wxSystemOptions::GetOptionInt(wxT("msw.window.no-clip-children"))
|| (flags & wxCLIP_CHILDREN) )
style |= WS_CLIPCHILDREN;
// it doesn't seem useful to use WS_CLIPSIBLINGS here as we officially
// don't support overlapping windows and it only makes sense for them and,
// presumably, gives the system some extra work (to manage more clipping
// regions), so avoid it alltogether
if ( flags & wxVSCROLL )
style |= WS_VSCROLL;
if ( flags & wxHSCROLL )
style |= WS_HSCROLL;
const wxBorder border = GetBorder(flags);
// WS_BORDER is only required for wxBORDER_SIMPLE
if ( border == wxBORDER_SIMPLE )
style |= WS_BORDER;
// now deal with ext style if the caller wants it
if ( exstyle )
{
*exstyle = 0;
#ifndef __WXWINCE__
if ( flags & wxTRANSPARENT_WINDOW )
*exstyle |= WS_EX_TRANSPARENT;
#endif
switch ( border )
{
default:
case wxBORDER_DEFAULT:
wxFAIL_MSG( _T("unknown border style") );
// fall through
case wxBORDER_NONE:
case wxBORDER_SIMPLE:
break;
case wxBORDER_STATIC:
*exstyle |= WS_EX_STATICEDGE;
break;
case wxBORDER_RAISED:
*exstyle |= WS_EX_DLGMODALFRAME;
break;
case wxBORDER_SUNKEN:
*exstyle |= WS_EX_CLIENTEDGE;
style &= ~WS_BORDER;
break;
case wxBORDER_DOUBLE:
*exstyle |= WS_EX_DLGMODALFRAME;
break;
}
// wxUniv doesn't use Windows dialog navigation functions at all
#if !defined(__WXUNIVERSAL__) && !defined(__WXWINCE__)
// to make the dialog navigation work with the nested panels we must
// use this style (top level windows such as dialogs don't need it)
if ( (flags & wxTAB_TRAVERSAL) && !IsTopLevel() )
{
*exstyle |= WS_EX_CONTROLPARENT;
}
#endif // __WXUNIVERSAL__
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?