#include "wx/msw/missing.h"
#if defined(__WXWINCE__)
-#include "wx/msw/wince/missing.h"
+ #include "wx/msw/wince/missing.h"
#endif
+#if defined(TME_LEAVE) && defined(WM_MOUSELEAVE)
+ #define HAVE_TRACKMOUSEEVENT
+#endif // everything needed for TrackMouseEvent()
+
// ---------------------------------------------------------------------------
// global variables
// ---------------------------------------------------------------------------
// Always constructor Properties first
wxREADONLY_PROPERTY( Parent,wxWindow*, GetParent, EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
- wxPROPERTY( Id,wxWindowID, SetId, GetId, wxID_ANY, 0 /*flags*/ , wxT("Helpstring") , wxT("group") )
+ wxPROPERTY( Id,wxWindowID, SetId, GetId, -1 /*wxID_ANY*/ , 0 /*flags*/ , wxT("Helpstring") , wxT("group") )
wxPROPERTY( Position,wxPoint, SetPosition , GetPosition, wxDefaultPosition , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // pos
wxPROPERTY( Size,wxSize, SetSize, GetSize, wxDefaultSize , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // size
wxPROPERTY( WindowStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
wxPROPERTY( Shown , bool , Show , IsShown , wxxVariant((bool)true) , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
#if 0
// possible property candidates (not in xrc) or not valid in all subclasses
- wxPROPERTY( Title,wxString, SetTitle, GetTitle, wxT("") )
+ wxPROPERTY( Title,wxString, SetTitle, GetTitle, wxEmptyString )
wxPROPERTY( Font , wxFont , SetFont , GetWindowFont , )
- wxPROPERTY( Label,wxString, SetLabel, GetLabel, wxT("") )
+ wxPROPERTY( Label,wxString, SetLabel, GetLabel, wxEmptyString )
// MaxHeight, Width , MinHeight , Width
// TODO switch label to control and title to toplevels
// scrolling stuff
// ---------------------------------------------------------------------------
-// convert wxHORIZONTAL/wxVERTICAL to SB_HORZ/SB_VERT
-static inline int wxDirToWinStyle(int orient)
-{
- return orient == wxHORIZONTAL ? SB_HORZ : SB_VERT;
-}
-
inline int GetScrollPosition(HWND hWnd, int wOrient)
{
#ifdef __WXMICROWIN__
// On WinCE (at least), the wndproc comparison doesn't work,
// so have to use something like this.
#ifdef __WXWINCE__
+ wxUnusedVar(wndProc);
+
extern wxChar *wxCanvasClassName;
extern wxChar *wxCanvasClassNameNR;
extern const wxChar *wxMDIFrameClassName;
::SetWindowLong(GetHwnd(), GWL_EXSTYLE, exstyleReal);
- // we must call SetWindowPos() to flash the cached extended style and
+ // 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(),
// 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)
- if (!wxSystemOptions::GetOptionInt(wxT("msw.window.no-clip-children")) == 1)
+ // 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
void wxWindowMSW::OnInternalIdle()
{
-#ifdef __WXWINCE__
+#ifndef HAVE_TRACKMOUSEEVENT
// Check if we need to send a LEAVE event
if ( m_mouseInWindow )
{
GenerateMouseLeave();
}
}
-#endif // !__WXWINCE__
+#endif // !HAVE_TRACKMOUSEEVENT
if (wxUpdateUIEvent::CanUpdate(this))
UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
{
if ( !m_frozenness++ )
{
- SendSetRedraw(GetHwnd(), false);
+ if ( IsShown() )
+ SendSetRedraw(GetHwnd(), false);
}
}
if ( !--m_frozenness )
{
- SendSetRedraw(GetHwnd(), true);
+ if ( IsShown() )
+ {
+ SendSetRedraw(GetHwnd(), true);
- // we need to refresh everything or otherwise he invalidated area is not
- // repainted
- Refresh();
+ // we need to refresh everything or otherwise the invalidated area
+ // is not going to be repainted
+ Refresh();
+ }
}
}
HWND hWnd = GetHwnd();
if ( hWnd )
{
+ RECT mswRect;
+ const RECT *pRect;
if ( rect )
{
- RECT mswRect;
mswRect.left = rect->x;
mswRect.top = rect->y;
mswRect.right = rect->x + rect->width;
mswRect.bottom = rect->y + rect->height;
- ::InvalidateRect(hWnd, &mswRect, eraseBack);
+ pRect = &mswRect;
}
else
- ::InvalidateRect(hWnd, NULL, eraseBack);
+ {
+ pRect = NULL;
+ }
+
+#ifndef __SMARTPHONE__
+ UINT flags = RDW_INVALIDATE | RDW_ALLCHILDREN;
+ if ( eraseBack )
+ flags |= RDW_ERASE;
+
+ ::RedrawWindow(hWnd, pRect, NULL, flags);
+#else
+ ::InvalidateRect(hWnd, pRect, eraseBack);
+#endif
}
}
// if our parent had prepared a defer window handle for us, use it (unless
// we are a top level window)
wxWindowMSW *parent = GetParent();
- HDWP hdwp = (parent && !IsTopLevel()) ? (HDWP)parent->m_hDWP : NULL;
+ HDWP hdwp = parent && !IsTopLevel() ? (HDWP)parent->m_hDWP : NULL;
if ( hdwp )
{
hdwp = ::DeferWindowPos(hdwp, GetHwnd(), NULL,
- x, y, width, height,
- SWP_NOZORDER);
+ x, y, width, height,
+ SWP_NOZORDER);
if ( !hdwp )
{
wxLogLastError(_T("DeferWindowPos"));
// otherwise (or if deferring failed) move the window in place immediately
if ( !hdwp )
{
- if ( !::MoveWindow(GetHwnd(), x, y, width, height, TRUE) )
+ if ( !::MoveWindow(GetHwnd(), x, y, width, height, IsShown()) )
{
wxLogLastError(wxT("MoveWindow"));
}
}
}
-// For implementation purposes - sometimes decorations make the client area
-// smaller
-wxPoint wxWindowMSW::GetClientAreaOrigin() const
-{
- return wxPoint(0, 0);
-}
-
// ---------------------------------------------------------------------------
// text metrics
// ---------------------------------------------------------------------------
}
bool bForward = true,
- bWindowChange = false;
+ bWindowChange = false,
+ bFromTab = false;
// should we process this message specially?
bool bProcess = true;
// Ctrl-Tab cycles thru notebook pages
bWindowChange = bCtrlDown;
bForward = !bShiftDown;
+ bFromTab = true;
}
break;
wxNavigationKeyEvent event;
event.SetDirection(bForward);
event.SetWindowChange(bWindowChange);
+ event.SetFromTab(bFromTab);
event.SetEventObject(this);
if ( GetEventHandler()->ProcessEvent(event) )
{
bool allow;
WXLRESULT result;
- WXHICON hIcon;
WXHBRUSH hBrush;
} rc;
#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
case WM_ACTIVATEAPP:
+ // This implicitly sends a wxEVT_ACTIVATE_APP event
wxTheApp->SetActive(wParam != 0, FindFocus());
break;
#endif
processed = HandleKillFocus((WXHWND)(HWND)wParam);
break;
+ case WM_PRINTCLIENT:
+ processed = HandlePrintClient((WXHDC)wParam);
+ break;
+
case WM_PAINT:
+ if ( wParam )
{
- if ( wParam )
- {
- // cast to wxWindow is needed for wxUniv
- wxPaintDCEx dc((wxWindow *)this, (WXHDC)wParam);
- processed = HandlePaint();
- }
- else
- {
- processed = HandlePaint();
- }
- break;
- }
+ wxPaintDCEx dc((wxWindow *)this, (WXHDC)wParam);
-#ifndef __WXWINCE__
- case WM_PRINT:
+ processed = HandlePaint();
+ }
+ else // no DC given
{
-#if wxUSE_LISTCTRL
- // Don't call the wx handlers in this case
- if ( wxIsKindOf(this, wxListCtrl) )
- break;
-#endif
-
- if ( lParam & PRF_ERASEBKGND )
- HandleEraseBkgnd((WXHDC)(HDC)wParam);
-
- wxPaintDCEx dc((wxWindow *)this, (WXHDC)wParam);
processed = HandlePaint();
}
break;
-#endif
case WM_CLOSE:
#ifdef __WXUNIVERSAL__
// Universal uses its own wxFrame/wxDialog, so we don't receive
// close events unless we have this.
Close();
- processed = true;
- rc.result = TRUE;
-#else
+#endif // __WXUNIVERSAL__
+
// don't let the DefWindowProc() destroy our window - we'll do it
// ourselves in ~wxWindow
processed = true;
rc.result = TRUE;
-#endif
break;
case WM_SHOWWINDOW:
wParam);
break;
-#ifdef WM_MOUSELEAVE
+#ifdef HAVE_TRACKMOUSEEVENT
case WM_MOUSELEAVE:
+ // filter out excess WM_MOUSELEAVE events sent after PopupMenu() (on XP at least)
+ if ( m_mouseInWindow )
{
- // filter out excess WM_MOUSELEAVE events sent after PopupMenu() (on XP at least)
- if ( m_mouseInWindow )
- {
- GenerateMouseLeave();
- }
-
- // always pass processed back as false, this allows the window
- // manager to process the message too. This is needed to
- // ensure windows XP themes work properly as the mouse moves
- // over widgets like buttons.
- processed = false;
+ GenerateMouseLeave();
}
+
+ // always pass processed back as false, this allows the window
+ // manager to process the message too. This is needed to
+ // ensure windows XP themes work properly as the mouse moves
+ // over widgets like buttons. So don't set processed to true here.
break;
-#endif // WM_MOUSELEAVE
+#endif // HAVE_TRACKMOUSEEVENT
#if wxUSE_MOUSEWHEEL
case WM_MOUSEWHEEL:
wxHelpEvent helpEvent(wxEVT_HELP,
subjectOfHelp->GetId(),
#ifdef __WXWINCE__
- wxPoint(0, 0)
+ wxPoint(0,0)
#else
wxPoint(info->MousePos.x, info->MousePos.y)
#endif
bool wxWindowMSW::HandleQueryEndSession(long logOff, bool *mayEnd)
{
-#ifndef __WXWINCE__
+#ifdef ENDSESSION_LOGOFF
wxCloseEvent event(wxEVT_QUERY_END_SESSION, wxID_ANY);
event.SetEventObject(wxTheApp);
event.SetCanVeto(true);
return rc;
#else
+ wxUnusedVar(logOff);
+ wxUnusedVar(mayEnd);
return false;
#endif
}
bool wxWindowMSW::HandleEndSession(bool endSession, long logOff)
{
-#ifndef __WXWINCE__
+#ifdef ENDSESSION_LOGOFF
// do nothing if the session isn't ending
if ( !endSession )
return false;
return wxTheApp->ProcessEvent(event);
#else
+ wxUnusedVar(endSession);
+ wxUnusedVar(logOff);
return false;
#endif
}
{
wxMenuItem *pMenuItem = (wxMenuItem *)(pMeasureStruct->itemData);
- wxCHECK_MSG( pMenuItem && pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)),
+ // according to Carsten Fuchs the pointer may be NULL under XP if an
+ // MDI child frame is initially maximized, see this for more info:
+ // http://article.gmane.org/gmane.comp.lib.wxwidgets.general/27745
+ //
+ // so silently ignore it instead of asserting
+ if ( !pMenuItem )
+ return false;
+
+ wxCHECK_MSG( wxDynamicCast(pMenuItem, wxMenuItem),
false, _T("MSWOnMeasureItem: bad wxMenuItem pointer") );
size_t w, h;
#ifndef __WXMICROWIN__
-bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush, WXHDC pDC, WXHWND pWnd)
+bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush, WXHDC hDC, WXHWND hWnd)
{
-#if wxUSE_CONTROLS
- wxWindow *item = FindItemByHWND(pWnd, true);
+#if !wxUSE_CONTROLS || defined(__WXUNIVERSAL__)
+ wxUnusedVar(pDC);
+ wxUnusedVar(hWnd);
+#else
+ wxControl *item = wxDynamicCast(FindItemByHWND(hWnd, true), wxControl);
+
if ( item )
- *brush = item->MSWControlColor(pDC);
+ *brush = item->MSWControlColor(hDC, hWnd);
else
#endif // wxUSE_CONTROLS
*brush = NULL;
#endif // __WXMICROWIN__
-WXHBRUSH wxWindowMSW::MSWControlColor(WXHDC WXUNUSED(hDC))
-{
- return (WXHBRUSH)0;
-}
-
bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange)
{
#if wxUSE_PALETTE
// do default background painting
- if ( !DoEraseBackground(*event.GetDC()) )
+ if ( !DoEraseBackground(GetHdcOf(*event.GetDC())) )
{
// let the system paint the background
event.Skip();
}
}
-bool wxWindowMSW::DoEraseBackground(wxDC& dc)
+bool wxWindowMSW::DoEraseBackground(WXHDC hDC)
{
- HBRUSH hBrush = (HBRUSH)MSWGetBgBrush(dc.GetHDC());
- if ( !hBrush )
+ HBRUSH hbr = (HBRUSH)MSWGetBgBrush(hDC);
+ if ( !hbr )
return false;
- RECT rc;
- ::GetClientRect(GetHwnd(), &rc);
- ::FillRect(GetHdcOf(dc), &rc, hBrush);
+ wxFillRect(GetHwnd(), (HDC)hDC, hbr);
return true;
}
-WXHBRUSH wxWindowMSW::MSWGetSolidBgBrushForChild(wxWindow *child)
-{
- wxColour col = MSWGetBgColourForChild(child);
- if ( col.Ok() )
- {
- // draw children with the same colour as the parent
- wxBrush *brush = wxTheBrushList->FindOrCreateBrush(col, wxSOLID);
-
- return (WXHBRUSH)brush->GetResourceHandle();
- }
-
- return 0;
-}
-
-wxColour wxWindowMSW::MSWGetBgColourForChild(wxWindow *child)
+WXHBRUSH
+wxWindowMSW::MSWGetBgBrushForChild(WXHDC WXUNUSED(hDC), WXHWND hWnd)
{
if ( m_hasBgCol )
{
// our background colour applies to:
// 1. this window itself, always
// 2. all children unless the colour is "not inheritable"
- // 3. immediate transparent children which should show the same
- // background as we do, but not for transparent grandchildren
- // which use the background of their immediate parent instead
- if ( m_inheritBgCol ||
- child == this ||
- (child->HasTransparentBackground() &&
- child->GetParent() == this) )
+ // 3. even if it is not inheritable, our immediate transparent
+ // children should still inherit it -- but not any transparent
+ // children because it would look wrong if a child of non
+ // transparent child would show our bg colour when the child itself
+ // does not
+ wxWindow *win = wxFindWinFromHandle(hWnd);
+ if ( win == this ||
+ m_inheritBgCol ||
+ (win && win->HasTransparentBackground() &&
+ win->GetParent() == this) )
{
- return GetBackgroundColour();
+ // draw children with the same colour as the parent
+ wxBrush *
+ brush = wxTheBrushList->FindOrCreateBrush(GetBackgroundColour());
+
+ return (WXHBRUSH)GetHbrushOf(*brush);
}
}
- return wxNullColour;
+ return 0;
}
-WXHBRUSH wxWindowMSW::MSWGetBgBrushForSelf(wxWindow *parent, WXHDC hDC)
+WXHBRUSH wxWindowMSW::MSWGetBgBrush(WXHDC hDC, WXHWND hWndToPaint)
{
- return parent->MSWGetBgBrushForChild(hDC, (wxWindow *)this);
-}
+ if ( !hWndToPaint )
+ hWndToPaint = GetHWND();
-WXHBRUSH wxWindowMSW::MSWGetBgBrush(WXHDC hDC)
-{
- for ( wxWindow *win = (wxWindow *)this; win; win = win->GetParent() )
+ for ( wxWindowMSW *win = this; win; win = win->GetParent() )
{
- WXHBRUSH hBrush = MSWGetBgBrushForSelf(win, hDC);
+ WXHBRUSH hBrush = win->MSWGetBgBrushForChild(hDC, hWndToPaint);
if ( hBrush )
return hBrush;
- // background is not inherited beyond the windows which have their own
- // fixed background such as top level windows and notebooks and for
- // windows for which a custom colour had been explicitly set with
- // SetOwnBackgroundColour() and so shouldn't affect its children
- if ( win->ProvidesBackground() ||
- (win->m_hasBgCol && !win->m_inheritBgCol) )
+ // background is not inherited beyond top level windows
+ if ( win->IsTopLevel() )
break;
}
return 0;
}
+bool wxWindowMSW::HandlePrintClient(WXHDC hDC)
+{
+ // we receive this message when DrawThemeParentBackground() is
+ // called from def window proc of several controls under XP and we
+ // must draw properly themed background here
+ //
+ // note that naively I'd expect filling the client rect with the
+ // brush returned by MSWGetBgBrush() work -- but for some reason it
+ // doesn't and we have to call parents MSWPrintChild() which is
+ // supposed to call DrawThemeBackground() with appropriate params
+ //
+ // also note that in this case lParam == PRF_CLIENT but we're
+ // clearly expected to paint the background and nothing else!
+ for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
+ {
+ if ( win->MSWPrintChild(hDC, (wxWindow *)this) )
+ return true;
+
+ if ( win->IsTopLevel() || win->InheritsBackgroundColour() )
+ break;
+ }
+
+ return false;
+}
+
// ---------------------------------------------------------------------------
// moving and resizing
// ---------------------------------------------------------------------------
return GetEventHandler()->ProcessEvent(event);
}
-#if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
else
{
+#if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
// the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND
// notifications to its parent which we want to reflect back to
// wxSpinCtrl
wxSpinCtrl *spin = wxSpinCtrl::GetSpinForTextCtrl(control);
if ( spin && spin->ProcessTextCommand(cmd, id) )
return true;
- }
#endif // wxUSE_SPINCTRL
+#if wxUSE_CHOICE && defined(__SMARTPHONE__)
+ // the listbox ctrl which is logically part of wxChoice sends WM_COMMAND
+ // notifications to its parent which we want to reflect back to
+ // wxChoice
+ wxChoice *choice = wxChoice::GetChoiceForListBox(control);
+ if ( choice && choice->MSWCommand(cmd, id) )
+ return true;
+#endif
+ }
+
return false;
}
{
// Generate an ENTER event
m_mouseInWindow = true;
-#ifndef __WXWINCE__
- TRACKMOUSEEVENT trackinfo;
- trackinfo.cbSize = sizeof(trackinfo);
+#ifdef HAVE_TRACKMOUSEEVENT
+ WinStruct<TRACKMOUSEEVENT> trackinfo;
+
trackinfo.dwFlags = TME_LEAVE;
trackinfo.hwndTrack = GetHwnd();
- //Use the commctrl.h _TrackMouseEvent, which will call the
- // appropriate TrackMouseEvent or emulate it ( win95 )
- // else we need _WIN32_WINNT >= 0x0400
+
+ // Use the commctrl.h _TrackMouseEvent(), which will call the real
+ // TrackMouseEvent() if available or emulate it
_TrackMouseEvent(&trackinfo);
-#endif // __WXWINCE__
+#endif // HAVE_TRACKMOUSEEVENT
+
wxMouseEvent event(wxEVT_ENTER_WINDOW);
InitMouseEvent(event, x, y, flags);
case VK_CLEAR: id = WXK_CLEAR; break;
case VK_SHIFT: id = WXK_SHIFT; break;
case VK_CONTROL: id = WXK_CONTROL; break;
- case VK_MENU : id = WXK_MENU; break;
+ case VK_MENU : id = WXK_ALT; break;
case VK_PAUSE: id = WXK_PAUSE; break;
case VK_CAPITAL: id = WXK_CAPITAL; break;
case VK_SPACE: id = WXK_SPACE; break;
case WXK_SHIFT: keySym = VK_SHIFT; break;
case WXK_CONTROL: keySym = VK_CONTROL; break;
case WXK_ALT: keySym = VK_MENU; break;
- case WXK_MENU : keySym = VK_MENU; break;
case WXK_PAUSE: keySym = VK_PAUSE; break;
case WXK_CAPITAL: keySym = VK_CAPITAL; break;
case WXK_PRIOR: keySym = VK_PRIOR; break;
{
bool bVirtual;
+ wxASSERT_MSG(key != WXK_LBUTTON && key != WXK_RBUTTON && key !=
+ WXK_MBUTTON, wxT("can't use wxGetKeyState() for mouse buttons"));
+
//High order with GetAsyncKeyState only available on WIN32
#ifdef __WIN32__
//If the requested key is a LED key, return
#if wxUSE_HOTKEY
+#if defined(__SMARTPHONE__) || defined(__POCKETPC__)
+static void WinCEUnregisterHotKey(int modifiers, int id)
+{
+ // Register hotkeys for the hardware buttons
+ HINSTANCE hCoreDll;
+ typedef BOOL (WINAPI *UnregisterFunc1Proc)(UINT, UINT);
+
+ UnregisterFunc1Proc procUnregisterFunc;
+ hCoreDll = LoadLibrary(_T("coredll.dll"));
+ if (hCoreDll)
+ {
+ procUnregisterFunc = (UnregisterFunc1Proc)GetProcAddress(hCoreDll, _T("UnregisterFunc1"));
+ if (procUnregisterFunc)
+ procUnregisterFunc(modifiers, id);
+ FreeLibrary(hCoreDll);
+ }
+}
+#endif
+
bool wxWindowMSW::RegisterHotKey(int hotkeyId, int modifiers, int keycode)
{
UINT win_modifiers=0;
if ( modifiers & wxMOD_WIN )
win_modifiers |= MOD_WIN;
+#if defined(__SMARTPHONE__) || defined(__POCKETPC__)
+ // Required for PPC and Smartphone hardware buttons
+ if (keycode >= WXK_SPECIAL1 && keycode <= WXK_SPECIAL20)
+ WinCEUnregisterHotKey(win_modifiers, hotkeyId);
+#endif
+
if ( !::RegisterHotKey(GetHwnd(), hotkeyId, win_modifiers, keycode) )
{
wxLogLastError(_T("RegisterHotKey"));
bool wxWindowMSW::UnregisterHotKey(int hotkeyId)
{
+#if defined(__SMARTPHONE__) || defined(__POCKETPC__)
+ WinCEUnregisterHotKey(MOD_WIN, hotkeyId);
+#endif
+
if ( !::UnregisterHotKey(GetHwnd(), hotkeyId) )
{
wxLogLastError(_T("UnregisterHotKey"));