window.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 2,123 行 · 第 1/5 页
CPP
2,123 行
}
return style;
}
// Setup background and foreground colours correctly
void wxWindowMSW::SetupColours()
{
if ( GetParent() )
SetBackgroundColour(GetParent()->GetBackgroundColour());
}
bool wxWindowMSW::IsMouseInWindow() const
{
// get the mouse position
POINT pt;
#ifdef __WXWINCE__
::GetCursorPosWinCE(&pt);
#else
::GetCursorPos(&pt);
#endif
// find the window which currently has the cursor and go up the window
// chain until we find this window - or exhaust it
HWND hwnd = ::WindowFromPoint(pt);
while ( hwnd && (hwnd != GetHwnd()) )
hwnd = ::GetParent(hwnd);
return hwnd != NULL;
}
void wxWindowMSW::OnInternalIdle()
{
#ifndef HAVE_TRACKMOUSEEVENT
// Check if we need to send a LEAVE event
if ( m_mouseInWindow )
{
// note that we should generate the leave event whether the window has
// or doesn't have mouse capture
if ( !IsMouseInWindow() )
{
GenerateMouseLeave();
}
}
#endif // !HAVE_TRACKMOUSEEVENT
if (wxUpdateUIEvent::CanUpdate(this))
UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
}
// Set this window to be the child of 'parent'.
bool wxWindowMSW::Reparent(wxWindowBase *parent)
{
if ( !wxWindowBase::Reparent(parent) )
return false;
HWND hWndChild = GetHwnd();
HWND hWndParent = GetParent() ? GetWinHwnd(GetParent()) : (HWND)0;
::SetParent(hWndChild, hWndParent);
#ifndef __WXWINCE__
if ( ::GetWindowLong(hWndChild, GWL_EXSTYLE) & WS_EX_CONTROLPARENT )
{
EnsureParentHasControlParentStyle(GetParent());
}
#endif // !__WXWINCE__
return true;
}
static inline void SendSetRedraw(HWND hwnd, bool on)
{
#ifndef __WXMICROWIN__
::SendMessage(hwnd, WM_SETREDRAW, (WPARAM)on, 0);
#endif
}
void wxWindowMSW::Freeze()
{
if ( !m_frozenness++ )
{
if ( IsShown() )
SendSetRedraw(GetHwnd(), false);
}
}
void wxWindowMSW::Thaw()
{
wxASSERT_MSG( m_frozenness > 0, _T("Thaw() without matching Freeze()") );
if ( !--m_frozenness )
{
if ( IsShown() )
{
SendSetRedraw(GetHwnd(), true);
// we need to refresh everything or otherwise the invalidated area
// is not going to be repainted
Refresh();
}
}
}
void wxWindowMSW::Refresh(bool eraseBack, const wxRect *rect)
{
HWND hWnd = GetHwnd();
if ( hWnd )
{
RECT mswRect;
const RECT *pRect;
if ( rect )
{
mswRect.left = rect->x;
mswRect.top = rect->y;
mswRect.right = rect->x + rect->width;
mswRect.bottom = rect->y + rect->height;
pRect = &mswRect;
}
else
{
pRect = NULL;
}
// RedrawWindow not available on SmartPhone or eVC++ 3
#if !defined(__SMARTPHONE__) && !(defined(_WIN32_WCE) && _WIN32_WCE < 400)
UINT flags = RDW_INVALIDATE | RDW_ALLCHILDREN;
if ( eraseBack )
flags |= RDW_ERASE;
::RedrawWindow(hWnd, pRect, NULL, flags);
#else
::InvalidateRect(hWnd, pRect, eraseBack);
#endif
}
}
void wxWindowMSW::Update()
{
if ( !::UpdateWindow(GetHwnd()) )
{
wxLogLastError(_T("UpdateWindow"));
}
#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
// just calling UpdateWindow() is not enough, what we did in our WM_PAINT
// handler needs to be really drawn right now
(void)::GdiFlush();
#endif // __WIN32__
}
// ---------------------------------------------------------------------------
// drag and drop
// ---------------------------------------------------------------------------
#if wxUSE_DRAG_AND_DROP
void wxWindowMSW::SetDropTarget(wxDropTarget *pDropTarget)
{
if ( m_dropTarget != 0 ) {
m_dropTarget->Revoke(m_hWnd);
delete m_dropTarget;
}
m_dropTarget = pDropTarget;
if ( m_dropTarget != 0 )
m_dropTarget->Register(m_hWnd);
}
#endif // wxUSE_DRAG_AND_DROP
// old style file-manager drag&drop support: we retain the old-style
// DragAcceptFiles in parallel with SetDropTarget.
void wxWindowMSW::DragAcceptFiles(bool WXUNUSED_IN_WINCE(accept))
{
#ifndef __WXWINCE__
HWND hWnd = GetHwnd();
if ( hWnd )
::DragAcceptFiles(hWnd, (BOOL)accept);
#endif
}
// ----------------------------------------------------------------------------
// tooltips
// ----------------------------------------------------------------------------
#if wxUSE_TOOLTIPS
void wxWindowMSW::DoSetToolTip(wxToolTip *tooltip)
{
wxWindowBase::DoSetToolTip(tooltip);
if ( m_tooltip )
m_tooltip->SetWindow((wxWindow *)this);
}
#endif // wxUSE_TOOLTIPS
// ---------------------------------------------------------------------------
// moving and resizing
// ---------------------------------------------------------------------------
bool wxWindowMSW::IsSizeDeferred() const
{
#if USE_DEFERRED_SIZING
if ( m_pendingPosition != wxDefaultPosition ||
m_pendingSize != wxDefaultSize )
return true;
#endif // USE_DEFERRED_SIZING
return false;
}
// Get total size
void wxWindowMSW::DoGetSize(int *x, int *y) const
{
// if SetSize() had been called at wx level but not realized at Windows
// level yet (i.e. EndDeferWindowPos() not called), we still should return
// the new and not the old position to the other wx code
if ( m_pendingSize != wxDefaultSize )
{
if ( x )
*x = m_pendingSize.x;
if ( y )
*y = m_pendingSize.y;
}
else // use current size
{
RECT rect = wxGetWindowRect(GetHwnd());
if ( x )
*x = rect.right - rect.left;
if ( y )
*y = rect.bottom - rect.top;
}
}
// Get size *available for subwindows* i.e. excluding menu bar etc.
void wxWindowMSW::DoGetClientSize(int *x, int *y) const
{
#if USE_DEFERRED_SIZING
if ( IsTopLevel() || m_pendingSize == wxDefaultSize )
#endif
{
// top level windows resizing is never deferred, so we can safely use
// the current size here
RECT rect = wxGetClientRect(GetHwnd());
if ( x )
*x = rect.right;
if ( y )
*y = rect.bottom;
}
#if USE_DEFERRED_SIZING
else // non top level and using deferred sizing
{
// we need to calculate the *pending* client size here
RECT rect;
rect.left = m_pendingPosition.x;
rect.top = m_pendingPosition.y;
rect.right = rect.left + m_pendingSize.x;
rect.bottom = rect.top + m_pendingSize.y;
::SendMessage(GetHwnd(), WM_NCCALCSIZE, FALSE, (LPARAM)&rect);
if ( x )
*x = rect.right - rect.left;
if ( y )
*y = rect.bottom - rect.top;
}
#endif
}
void wxWindowMSW::DoGetPosition(int *x, int *y) const
{
wxWindow * const parent = GetParent();
wxPoint pos;
if ( m_pendingPosition != wxDefaultPosition )
{
pos = m_pendingPosition;
}
else // use current position
{
RECT rect = wxGetWindowRect(GetHwnd());
POINT point;
point.x = rect.left;
point.y = rect.top;
// we do the adjustments with respect to the parent only for the "real"
// children, not for the dialogs/frames
if ( !IsTopLevel() )
{
// Since we now have the absolute screen coords, if there's a
// parent we must subtract its top left corner
if ( parent )
{
::ScreenToClient(GetHwndOf(parent), &point);
}
}
pos.x = point.x;
pos.y = point.y;
}
// we also must adjust by the client area offset: a control which is just
// under a toolbar could be at (0, 30) in Windows but at (0, 0) in wx
if ( parent && !IsTopLevel() )
{
const wxPoint pt(parent->GetClientAreaOrigin());
pos.x -= pt.x;
pos.y -= pt.y;
}
if ( x )
*x = pos.x;
if ( y )
*y = pos.y;
}
void wxWindowMSW::DoScreenToClient(int *x, int *y) const
{
POINT pt;
if ( x )
pt.x = *x;
if ( y )
pt.y = *y;
::ScreenToClient(GetHwnd(), &pt);
if ( x )
*x = pt.x;
if ( y )
*y = pt.y;
}
void wxWindowMSW::DoClientToScreen(int *x, int *y) const
{
POINT pt;
if ( x )
pt.x = *x;
if ( y )
pt.y = *y;
::ClientToScreen(GetHwnd(), &pt);
if ( x )
*x = pt.x;
if ( y )
*y = pt.y;
}
bool
wxWindowMSW::DoMoveSibling(WXHWND hwnd, int x, int y, int width, int height)
{
#if USE_DEFERRED_SIZING
// if our parent had prepared a defer window handle for us, use it (unless
// we are a top level window)
wxWindowMSW * const parent = IsTopLevel() ? NULL : GetParent();
HDWP hdwp = parent ? (HDWP)parent->m_hDWP : NULL;
if ( hdwp )
{
hdwp = ::DeferWindowPos(hdwp, (HWND)hwnd, NULL, x, y, width, height,
SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE);
if ( !hdwp )
{
wxLogLastError(_T("DeferWindowPos"));
}
}
if ( parent )
{
// hdwp must be updated as it may have been changed
parent->m_hDWP = (WXHANDLE)hdwp;
}
if ( hdwp )
{
// did deferred move, remember new coordinates of the window as they're
// different from what Windows would return for it
return true;
}
// otherwise (or if deferring failed) move the window in place immediately
#endif // USE_DEFERRED_SIZING
if ( !::MoveWindow((HWND)hwnd, x, y, width, height, IsShown()) )
{
wxLogLastError(wxT("MoveWindow"));
}
// if USE_DEFERRED_SIZING, indicates that we didn't use deferred move,
// ignored otherwise
return false;
}
void wxWindowMSW::DoMoveWindow(int x, int y, int width, int height)
{
// TODO: is this consistent with other platforms?
// Still, negative width or height shouldn't be allowed
if (width < 0)
width = 0;
if (height < 0)
height = 0;
if ( DoMoveSibling(m_hWnd, x, y, width, height) )
{
#if USE_DEFERRED_SIZING
m_pendingPosition = wxPoint(x, y);
m_pendingSize = wxSize(width, height);
#endif // USE_DEFERRED_SIZING
}
}
// set the size of the window: if the dimensions are positive, just use them,
// but if any of them is equal to -1, it means that we must find the value for
// it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
// which case -1 is a valid value for x and y)
//
// If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
// the width/height to best suit our contents, otherwise we reuse the current
// width/height
void wxWindowMSW::DoSetSize(int x, int y, int width, int height, int sizeFlags)
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?