#endif
#include "wx/module.h"
+#include "wx/sysopt.h"
#if wxUSE_DRAG_AND_DROP
#include "wx/dnd.h"
#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
// ---------------------------------------------------------------------------
wxMenu *wxCurrentPopupMenu = NULL;
#endif // wxUSE_MENUS_NATIVE
+#ifdef __WXWINCE__
+extern wxChar *wxCanvasClassName;
+#else
extern const wxChar *wxCanvasClassName;
+#endif
// true if we had already created the std colour map, used by
// wxGetStdColourMap() and wxWindow::OnSysColourChanged() (FIXME-MT)
extern void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win);
wxWindow *wxFindWinFromHandle(WXHWND hWnd);
-// this magical function is used to translate VK_APPS key presses to right
-// mouse clicks
-static void TranslateKbdEventToMouse(wxWindowMSW *win,
- int *x, int *y, WPARAM *flags);
-
// get the text metrics for the current font
static TEXTMETRIC wxGetTextMetrics(const wxWindowMSW *win);
wxFLAGS_MEMBER(wxBORDER_RAISED)
wxFLAGS_MEMBER(wxBORDER_STATIC)
wxFLAGS_MEMBER(wxBORDER_NONE)
-
+
// old style border flags
wxFLAGS_MEMBER(wxSIMPLE_BORDER)
wxFLAGS_MEMBER(wxSUNKEN_BORDER)
wxEND_FLAGS( wxWindowStyle )
wxBEGIN_PROPERTIES_TABLE(wxWindow)
- wxEVENT_PROPERTY( Close , wxEVT_CLOSE_WINDOW , wxCloseEvent)
- wxEVENT_PROPERTY( Create , wxEVT_CREATE , wxWindowCreateEvent )
- wxEVENT_PROPERTY( Destroy , wxEVT_DESTROY , wxWindowDestroyEvent )
+ wxEVENT_PROPERTY( Close , wxEVT_CLOSE_WINDOW , wxCloseEvent)
+ wxEVENT_PROPERTY( Create , wxEVT_CREATE , wxWindowCreateEvent )
+ wxEVENT_PROPERTY( Destroy , wxEVT_DESTROY , wxWindowDestroyEvent )
// Always constructor Properties first
wxREADONLY_PROPERTY( Parent,wxWindow*, GetParent, EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
- wxPROPERTY( Id,wxWindowID, SetId, GetId, -1, 0 /*flags*/ , wxT("Helpstring") , wxT("group") )
- wxPROPERTY( Position,wxPoint, SetPosition , GetPosition, wxPoint(-1,-1) , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // pos
- wxPROPERTY( Size,wxSize, SetSize, GetSize, wxSize(-1,-1) , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // size
+ 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
// Then all relations of the object graph
// and finally all other properties
- wxPROPERTY( ExtraStyle , long , SetExtraStyle , GetExtraStyle , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // extstyle
- wxPROPERTY( BackgroundColour , wxColour , SetBackgroundColour , GetBackgroundColour , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // bg
- wxPROPERTY( ForegroundColour , wxColour , SetForegroundColour , GetForegroundColour , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // fg
- wxPROPERTY( Enabled , bool , Enable , IsEnabled , wxxVariant((bool)true) , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
- wxPROPERTY( Shown , bool , Show , IsShown , wxxVariant((bool)true) , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
+ wxPROPERTY( ExtraStyle , long , SetExtraStyle , GetExtraStyle , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // extstyle
+ wxPROPERTY( BackgroundColour , wxColour , SetBackgroundColour , GetBackgroundColour , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // bg
+ wxPROPERTY( ForegroundColour , wxColour , SetForegroundColour , GetForegroundColour , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // fg
+ wxPROPERTY( Enabled , bool , Enable , IsEnabled , wxxVariant((bool)true) , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
+ 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( Font , wxFont , SetFont , GetWindowFont , )
- wxPROPERTY( Label,wxString, SetLabel, GetLabel, wxT("") )
- // MaxHeight, Width , MinHeight , Width
- // TODO switch label to control and title to toplevels
+ wxPROPERTY( Title,wxString, SetTitle, GetTitle, wxEmptyString )
+ wxPROPERTY( Font , wxFont , SetFont , GetWindowFont , )
+ wxPROPERTY( Label,wxString, SetLabel, GetLabel, wxEmptyString )
+ // MaxHeight, Width , MinHeight , Width
+ // TODO switch label to control and title to toplevels
- wxPROPERTY( ThemeEnabled , bool , SetThemeEnabled , GetThemeEnabled , )
- //wxPROPERTY( Cursor , wxCursor , SetCursor , GetCursor , )
- // wxPROPERTY( ToolTip , wxString , SetToolTip , GetToolTipText , )
- wxPROPERTY( AutoLayout , bool , SetAutoLayout , GetAutoLayout , )
+ wxPROPERTY( ThemeEnabled , bool , SetThemeEnabled , GetThemeEnabled , )
+ //wxPROPERTY( Cursor , wxCursor , SetCursor , GetCursor , )
+ // wxPROPERTY( ToolTip , wxString , SetToolTip , GetToolTipText , )
+ wxPROPERTY( AutoLayout , bool , SetAutoLayout , GetAutoLayout , )
#endif // __WXUNIVERSAL__/__WXMSW__
BEGIN_EVENT_TABLE(wxWindowMSW, wxWindowBase)
- EVT_ERASE_BACKGROUND(wxWindowMSW::OnEraseBackground)
EVT_SYS_COLOUR_CHANGED(wxWindowMSW::OnSysColourChanged)
+ EVT_ERASE_BACKGROUND(wxWindowMSW::OnEraseBackground)
+#ifdef __WXWINCE__
EVT_INIT_DIALOG(wxWindowMSW::OnInitDialog)
+#endif
END_EVENT_TABLE()
// ===========================================================================
m_childrenDisabled = NULL;
m_frozenness = 0;
- // wxWnd
- m_hMenu = 0;
-
m_hWnd = 0;
+ m_hDWP = 0;
m_xThumbSize = 0;
m_yThumbSize = 0;
msflags |= WS_VISIBLE;
}
- return MSWCreate(wxCanvasClassName, NULL, pos, size, msflags, exstyle);
+ if ( !MSWCreate(wxCanvasClassName, NULL, pos, size, msflags, exstyle) )
+ return false;
+
+ InheritAttributes();
+
+ return true;
}
// ---------------------------------------------------------------------------
}
// Get the window with the focus
-wxWindow *wxWindowBase::FindFocus()
+wxWindow *wxWindowBase::DoFindFocus()
{
HWND hWnd = ::GetFocus();
if ( 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) )
+ if ( !wxCheckWindowWndProc(hWnd, (WXFARPROC)wxWndProc) )
{
wxSetWindowProc(hwnd, wxWndProc);
}
{
// 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 wxWindows own windows as it can
+ // standard controls and false for the wxWidgets own windows as it can
// simply check m_oldWndProc
m_oldWndProc = NULL;
}
HWND hwnd = GetHwnd();
if ( hwnd )
{
- m_hWnd = 0;
+ SetHWND(0);
wxCHECK_RET( ::IsWindow(hwnd), wxT("invalid HWND in UnsubclassWin") );
}
}
+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 wndProc)
{
// Unicows note: the code below works, but only because WNDCLASS contains
// Unicows_{Set,Get}WindowLong and Unicows_RegisterClass to our own
// versions that keep track of fake<->real wnd proc mapping.
- // On WinCE (at least), the wndproc comparison doesn't work,
- // so have to use something like this.
+ // On WinCE (at least), the wndproc comparison doesn't work,
+ // so have to use something like this.
#ifdef __WXWINCE__
- extern const wxChar *wxCanvasClassName;
- extern const wxChar *wxCanvasClassNameNR;
- 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 ||
- str == wxMDIFrameClassName ||
- str == wxMDIFrameClassNameNoRedraw ||
- str == wxMDIChildFrameClassName ||
- str == wxMDIChildFrameClassNameNoRedraw ||
- str == _T("wxTLWHiddenParent"))
- return true; // Effectively means don't subclass
- else
- return false;
+ extern wxChar *wxCanvasClassName;
+ extern wxChar *wxCanvasClassNameNR;
+ 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 ||
+ str == wxMDIFrameClassName ||
+ str == wxMDIFrameClassNameNoRedraw ||
+ str == wxMDIChildFrameClassName ||
+ str == wxMDIChildFrameClassNameNoRedraw ||
+ str == _T("wxTLWHiddenParent"))
+ return true; // Effectively means don't subclass
+ else
+ return false;
#else
WNDCLASS cls;
if ( !::GetClassInfo(wxGetInstance(), wxGetWindowClass(hWnd), &cls) )
WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const
{
- // translate the style
- WXDWORD style = WS_CHILD | WS_VISIBLE;
+ // translate common wxWidgets styles to Windows ones
- if ( flags & wxCLIP_CHILDREN )
+ // 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).
+ // wxCLIP_CHILDREN support is for compatibility with old applications only.
+ if ((!wxSystemOptions::GetOptionInt(wxT("msw.window.no-clip-children")) == 1) || (flags & wxCLIP_CHILDREN))
style |= WS_CLIPCHILDREN;
- if ( flags & wxCLIP_SIBLINGS )
- style |= WS_CLIPSIBLINGS;
+ // 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;
void wxWindowMSW::OnInternalIdle()
{
+#ifndef HAVE_TRACKMOUSEEVENT
// Check if we need to send a LEAVE event
if ( m_mouseInWindow )
{
// or doesn't have mouse capture
if ( !IsMouseInWindow() )
{
- // Generate a LEAVE event
- m_mouseInWindow = false;
-
- // Unfortunately the mouse button and keyboard state may have
- // changed by the time the OnInternalIdle function is called, so 'state'
- // may be meaningless.
- int state = 0;
- if ( wxIsShiftDown() )
- state |= MK_SHIFT;
- if ( wxIsCtrlDown() )
- state |= MK_CONTROL;
- if ( GetKeyState( VK_LBUTTON ) )
- state |= MK_LBUTTON;
- if ( GetKeyState( VK_MBUTTON ) )
- state |= MK_MBUTTON;
- if ( GetKeyState( VK_RBUTTON ) )
- state |= MK_RBUTTON;
-
- POINT pt;
- if ( !::GetCursorPos(&pt) )
- {
- wxLogLastError(_T("GetCursorPos"));
- }
-
- // we need to have client coordinates here for symmetry with
- // wxEVT_ENTER_WINDOW
- RECT rect = wxGetWindowRect(GetHwnd());
- pt.x -= rect.left;
- pt.y -= rect.top;
-
- wxMouseEvent event2(wxEVT_LEAVE_WINDOW);
- InitMouseEvent(event2, pt.x, pt.y, state);
-
- (void)GetEventHandler()->ProcessEvent(event2);
+ GenerateMouseLeave();
}
}
+#endif // !HAVE_TRACKMOUSEEVENT
if (wxUpdateUIEvent::CanUpdate(this))
UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
HWND hWnd = GetHwnd();
if ( hWnd )
::DragAcceptFiles(hWnd, (BOOL)accept);
+#else
+ wxUnusedVar(accept);
#endif
}
width = 0;
if (height < 0)
height = 0;
- if ( !::MoveWindow(GetHwnd(), x, y, width, height, TRUE) )
+
+ // 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;
+ if ( hdwp )
{
- wxLogLastError(wxT("MoveWindow"));
+ hdwp = ::DeferWindowPos(hdwp, GetHwnd(), NULL,
+ x, y, width, height,
+ SWP_NOZORDER);
+ if ( !hdwp )
+ {
+ wxLogLastError(_T("DeferWindowPos"));
+ }
+
+ // hdwp must be updated as it may have been changed
+ parent->m_hDWP = (WXHANDLE)hdwp;
+ }
+
+ // otherwise (or if deferring failed) move the window in place immediately
+ if ( !hdwp )
+ {
+ if ( !::MoveWindow(GetHwnd(), x, y, width, height, IsShown()) )
+ {
+ wxLogLastError(wxT("MoveWindow"));
+ }
}
}
return;
}
- if ( x == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
+ if ( x == wxDefaultCoord && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
x = currentX;
- if ( y == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
+ if ( y == wxDefaultCoord && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
y = currentY;
AdjustForParentClientOrigin(x, y, sizeFlags);
- wxSize size(-1, -1);
- if ( width == -1 )
+ wxSize size = wxDefaultSize;
+ if ( width == wxDefaultCoord )
{
if ( sizeFlags & wxSIZE_AUTO_WIDTH )
{
}
}
- if ( height == -1 )
+ if ( height == wxDefaultCoord )
{
if ( sizeFlags & wxSIZE_AUTO_HEIGHT )
{
- if ( size.x == -1 )
+ if ( size.x == wxDefaultCoord )
{
size = DoGetBestSize();
}
::GetClientRect(GetHwnd(), &rectClient);
// if the size is already ok, stop here (rectClient.left = top = 0)
- if ( (rectClient.right == width || width == -1) &&
- (rectClient.bottom == height || height == -1) )
+ if ( (rectClient.right == width || width == wxDefaultCoord) &&
+ (rectClient.bottom == height || height == wxDefaultCoord) )
{
break;
}
}
}
-// For implementation purposes - sometimes decorations make the client area
-// smaller
-wxPoint wxWindowMSW::GetClientAreaOrigin() const
-{
- return wxPoint(0, 0);
-}
-
// ---------------------------------------------------------------------------
// text metrics
// ---------------------------------------------------------------------------
int *descent, int *externalLeading,
const wxFont *theFont) const
{
- const wxFont *fontToUse = theFont;
- if ( !fontToUse )
- fontToUse = &m_font;
+ wxASSERT_MSG( !theFont || theFont->Ok(),
+ _T("invalid font in GetTextExtent()") );
- HWND hWnd = GetHwnd();
- HDC dc = ::GetDC(hWnd);
+ wxFont fontToUse;
+ if (theFont)
+ fontToUse = *theFont;
+ else
+ fontToUse = GetFont();
- HFONT fnt = 0;
- HFONT hfontOld = 0;
- if ( fontToUse && fontToUse->Ok() )
- {
- fnt = (HFONT)((wxFont *)fontToUse)->GetResourceHandle(); // const_cast
- if ( fnt )
- hfontOld = (HFONT)SelectObject(dc,fnt);
- }
+ WindowHDC hdc(GetHwnd());
+ SelectInHDC selectFont(hdc, GetHfontOf(fontToUse));
SIZE sizeRect;
TEXTMETRIC tm;
- GetTextExtentPoint(dc, string, (int)string.Length(), &sizeRect);
- GetTextMetrics(dc, &tm);
-
- if ( fontToUse && fnt && hfontOld )
- SelectObject(dc, hfontOld);
-
- ReleaseDC(hWnd, dc);
+ GetTextExtentPoint(hdc, string, string.length(), &sizeRect);
+ GetTextMetrics(hdc, &tm);
if ( x )
*x = sizeRect.cx;
menu->SetInvokingWindow(this);
menu->UpdateUI();
+ if ( x == wxDefaultCoord && y == wxDefaultCoord )
+ {
+ wxPoint mouse = ScreenToClient(wxGetMousePosition());
+ x = mouse.x; y = mouse.y;
+ }
+
HWND hWnd = GetHwnd();
HMENU hMenu = GetHmenuOf(menu);
POINT point;
point.y = y;
::ClientToScreen(hWnd, &point);
wxCurrentPopupMenu = menu;
+#if defined(__WXWINCE__)
UINT flags = 0;
-#if !defined(__WXWINCE__)
- flags = TPM_RIGHTBUTTON;
+#else
+ UINT flags = TPM_RIGHTBUTTON;
#endif
::TrackPopupMenu(hMenu, flags, point.x, point.y, 0, hWnd, NULL);
// here we try to do all the job which ::IsDialogMessage() usually does
// internally
-#if 1
if ( msg->message == WM_KEYDOWN )
{
bool bCtrlDown = wxIsCtrlDown();
}
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;
case VK_ESCAPE:
{
#if wxUSE_BUTTON
- wxButton *btn = wxDynamicCast(FindWindow(wxID_CANCEL),
- wxButton);
+ wxButton *btn = wxDynamicCast(FindWindow(wxID_CANCEL),wxButton);
+
+ // our own wxLogDialog should react to Esc
+ // without Cancel button but this is a private class
+ // so let's try recognize it by content
+ #if wxUSE_LOG_DIALOG
+ if ( !btn &&
+ wxDynamicCast(this,wxDialog) &&
+ FindWindow(wxID_MORE) &&
+ FindWindow(wxID_OK) &&
+ !FindWindow(wxID_CANCEL) &&
+ GetTitle().MakeLower().StartsWith(wxTheApp->GetAppName().c_str())
+ )
+ btn = wxDynamicCast(FindWindow(wxID_OK),wxButton);
+ #endif // wxUSE_LOG_DIALOG
if ( btn && btn->IsEnabled() )
{
// if we do have a cancel button, do press it
bProcess = false;
}
// FIXME: this should be handled by
- // wxNavigationKeyEvent handler and not here!!
+ // wxNavigationKeyEvent handler and not here!
else
{
#if wxUSE_BUTTON
return true;
}
else // no default button
- {
#endif // wxUSE_BUTTON
+ {
// this is a quick and dirty test for a text
// control
if ( !(lDlgCode & DLGC_HASSETSEL) )
wxNavigationKeyEvent event;
event.SetDirection(bForward);
event.SetWindowChange(bWindowChange);
+ event.SetFromTab(bFromTab);
event.SetEventObject(this);
if ( GetEventHandler()->ProcessEvent(event) )
}
}
}
-#else // 0
- // let ::IsDialogMessage() do almost everything and handle just the
- // things it doesn't here: Ctrl-TAB for switching notebook pages
- if ( msg->message == WM_KEYDOWN )
- {
- // don't process system keys here
- if ( !(HIWORD(msg->lParam) & KF_ALTDOWN) )
- {
- if ( (msg->wParam == VK_TAB) && wxIsCtrlDown() )
- {
- // find the first notebook parent and change its page
- wxWindow *win = this;
- wxNotebook *nbook = NULL;
- while ( win && !nbook )
- {
- nbook = wxDynamicCast(win, wxNotebook);
- win = win->GetParent();
- }
-
- if ( nbook )
- {
- bool forward = !wxIsShiftDown();
-
- nbook->AdvanceSelection(forward);
- }
- }
- }
- }
-#endif // 1/0
// don't let IsDialogMessage() get VK_ESCAPE as it _always_ eats the
// message even when there is no cancel button and when the message is
}
void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam, WXLPARAM lParam,
- WXWORD *nCtlColor, WXHDC *hdc, WXHWND *hwnd)
+ WXHDC *hdc, WXHWND *hwnd)
{
-#ifndef __WXMICROWIN__
- *nCtlColor = CTLCOLOR_BTN;
*hwnd = (WXHWND)lParam;
*hdc = (WXHDC)wParam;
-#endif
}
void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam, WXLPARAM lParam,
}
// ---------------------------------------------------------------------------
-// Main wxWindows window proc and the window proc for wxWindow
+// Main wxWidgets window proc and the window proc for wxWindow
// ---------------------------------------------------------------------------
// Hook for new window just as it's being created, when the window isn't yet
(void)HandleDestroy();
break;
+ case WM_SIZE:
+ processed = HandleSize(LOWORD(lParam), HIWORD(lParam), wParam);
+ break;
+
case WM_MOVE:
processed = HandleMove(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
break;
}
}
break;
-#endif
-
- case WM_SIZE:
- switch ( wParam )
- {
- case SIZE_MAXHIDE:
- case SIZE_MAXSHOW:
- // we're not interested in these messages at all
- break;
-
- case SIZE_MINIMIZED:
- // we shouldn't send sizev events for these messages as the
- // client size may be negative which breaks existing code
- //
- // OTOH we might send another (wxMinimizedEvent?) one or
- // add an additional parameter to wxSizeEvent if this is
- // useful to anybody
- break;
-
- default:
- wxFAIL_MSG( _T("unexpected WM_SIZE parameter") );
- // fall through nevertheless
- case SIZE_MAXIMIZED:
- case SIZE_RESTORED:
- processed = HandleSize(LOWORD(lParam), HIWORD(lParam),
- wParam);
- }
- break;
-
-#if !defined(__WXWINCE__)
case WM_SIZING:
{
LPRECT pRect = (LPRECT)lParam;
}
}
break;
-#endif
+#endif // !__WXWINCE__
#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
case WM_ACTIVATEAPP:
break;
}
-#ifndef __WXWINCE__
- case WM_PRINT:
+#ifdef WM_PRINT
+ case WM_PRINTCLIENT:
+ if ( GetParent() &&
+ GetParent()->MSWPrintChild((wxWindow *)this, wParam, lParam) )
{
- // Don't call the wx handlers in this case
- if ( wxIsKindOf(this, wxListCtrl) )
- break;
+ processed = true;
+ }
+ break;
+ case WM_PRINT:
+ {
if ( lParam & PRF_ERASEBKGND )
HandleEraseBkgnd((WXHDC)(HDC)wParam);
wxPaintDCEx dc((wxWindow *)this, (WXHDC)wParam);
+
processed = HandlePaint();
}
break;
-#endif
+#endif // WM_PRINT
case WM_CLOSE:
#ifdef __WXUNIVERSAL__
wParam);
break;
- // Seems to be broken currently
-#if 0 // ndef __WXWINCE__
+#ifdef HAVE_TRACKMOUSEEVENT
case WM_MOUSELEAVE:
- {
- wxASSERT_MSG( !m_mouseInWindow, wxT("the mouse should be in a window to generate this event!") );
-
- // only process this message if the mouse is not in the window,
- // This can also check for children in composite windows.
- // however, this may mean the the wxEVT_LEAVE_WINDOW is never sent
- // if the mouse does not enter the window from it's child before
- // leaving the scope of the window. ( perhaps this can be picked
- // up in the OnIdle code as before, for this special case )
- if ( /*IsComposite() && */ !IsMouseInWindow() )
+ // filter out excess WM_MOUSELEAVE events sent after PopupMenu() (on XP at least)
+ if ( m_mouseInWindow )
{
- m_mouseInWindow = false;
-
- // Unfortunately no mouse state is passed with a WM_MOUSE_LEAVE
- int state = 0;
- if ( wxIsShiftDown() )
- state |= MK_SHIFT;
- if ( wxIsCtrlDown() )
- state |= MK_CONTROL;
- if ( GetKeyState( VK_LBUTTON ) )
- state |= MK_LBUTTON;
- if ( GetKeyState( VK_MBUTTON ) )
- state |= MK_MBUTTON;
- if ( GetKeyState( VK_RBUTTON ) )
- state |= MK_RBUTTON;
-
- POINT pt;
- if ( !::GetCursorPos(&pt) )
- {
- wxLogLastError(_T("GetCursorPos"));
- }
-
- // we need to have client coordinates here for symmetry with
- // wxEVT_ENTER_WINDOW
- RECT rect = wxGetWindowRect(GetHwnd());
- pt.x -= rect.left;
- pt.y -= rect.top;
-
- wxMouseEvent event2(wxEVT_LEAVE_WINDOW);
- InitMouseEvent(event2, pt.x, pt.y, state);
-
- (void)GetEventHandler()->ProcessEvent(event2);
+ 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;
- }
- break;
-#endif
- // __WXWINCE__
-
+ // 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 // HAVE_TRACKMOUSEEVENT
+
#if wxUSE_MOUSEWHEEL
case WM_MOUSEWHEEL:
processed = HandleMouseWheel(wParam, lParam);
// this should never happen
wxCHECK_MSG( win, 0,
_T("FindWindowForMouseEvent() returned NULL") );
+ }
+ processed = win->HandleMouseEvent(message, x, y, wParam);
+
+ // if the app didn't eat the event, handle it in the default
+ // way, that is by giving this window the focus
+ if ( !processed )
+ {
// for the standard classes their WndProc sets the focus to
// them anyhow and doing it from here results in some weird
- // problems, but for our windows we want them to acquire
- // focus when clicked
+ // problems, so don't do it for them (unnecessary anyhow)
if ( !win->IsOfStandardClass() )
{
if ( message == WM_LBUTTONDOWN && win->AcceptsFocus() )
win->SetFocus();
}
}
-
- processed = win->HandleMouseEvent(message, x, y, wParam);
}
break;
break;
#endif // __WXMICROWIN__
- case WM_SYSCOMMAND:
- processed = HandleSysCommand(wParam, lParam);
- break;
-
case WM_COMMAND:
{
WORD id, cmd;
// special case of VK_APPS: treat it the same as right mouse
// click because both usually pop up a context menu
case VK_APPS:
- {
- WPARAM flags;
- int x, y;
-
- TranslateKbdEventToMouse(this, &x, &y, &flags);
- processed = HandleMouseEvent(WM_RBUTTONDOWN, x, y, flags);
- }
+ processed = HandleMouseEvent(WM_RBUTTONDOWN, -1, -1, 0);
break;
#endif // VK_APPS
// special case of VK_APPS: treat it the same as right mouse button
if ( wParam == VK_APPS )
{
- WPARAM flags;
- int x, y;
-
- TranslateKbdEventToMouse(this, &x, &y, &flags);
- processed = HandleMouseEvent(WM_RBUTTONUP, x, y, flags);
+ processed = HandleMouseEvent(WM_RBUTTONUP, -1, -1, 0);
}
else
#endif // VK_APPS
break;
// CTLCOLOR messages are sent by children to query the parent for their
- // colors#ifndef __WXMICROWIN__
+ // colors
#ifndef __WXMICROWIN__
case WM_CTLCOLORMSGBOX:
case WM_CTLCOLOREDIT:
case WM_CTLCOLORSCROLLBAR:
case WM_CTLCOLORSTATIC:
{
- WXWORD nCtlColor;
WXHDC hdc;
WXHWND hwnd;
- UnpackCtlColor(wParam, lParam, &nCtlColor, &hdc, &hwnd);
-
- processed = HandleCtlColor(&rc.hBrush,
- (WXHDC)hdc,
- (WXHWND)hwnd,
- nCtlColor,
- message,
- wParam,
- lParam);
+ UnpackCtlColor(wParam, lParam, &hdc, &hwnd);
+
+ processed = HandleCtlColor(&rc.hBrush, (WXHDC)hdc, (WXHWND)hwnd);
}
break;
#endif // !__WXMICROWIN__
wxHelpEvent helpEvent(wxEVT_HELP,
subjectOfHelp->GetId(),
#ifdef __WXWINCE__
- wxPoint(0, 0)
+ wxPoint(0,0)
#else
wxPoint(info->MousePos.x, info->MousePos.y)
#endif
wxWindow *wxFindWinFromHandle(WXHWND hWnd)
{
- return wxWinHandleHash->Get((long)hWnd);
+ return (wxWindow*)wxWinHandleHash->Get((long)hWnd);
}
void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win)
bool nonDefault = false;
- if ( pos.x == -1 )
+ if ( pos.x == wxDefaultCoord )
{
// if x is set to CW_USEDEFAULT, y parameter is ignored anyhow so we
// can just as well set it to CW_USEDEFAULT as well
// neither because it is not handled as a special value by Windows then
// and so we have to choose some default value for it
x = pos.x;
- y = pos.y == -1 ? DEFAULT_Y : pos.y;
+ y = pos.y == wxDefaultCoord ? DEFAULT_Y : pos.y;
nonDefault = true;
}
/*
NB: there used to be some code here which set the initial size of the
window to the client size of the parent if no explicit size was
- specified. This was wrong because wxWindows programs often assume
+ specified. This was wrong because wxWidgets programs often assume
that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke
it. To see why, you should understand that Windows sends WM_SIZE from
inside ::CreateWindow() anyhow. However, ::CreateWindow() is called
event goes to some base class OnSize() instead). So the WM_SIZE we
rely on is the one sent when the parent frame resizes its children
but here is the problem: if the child already has just the right
- size, nothing will happen as both wxWindows and Windows check for
+ size, nothing will happen as both wxWidgets and Windows check for
this and ignore any attempts to change the window size to the size it
already has - so no WM_SIZE would be sent.
*/
-
+
// we don't use CW_USEDEFAULT here for several reasons:
//
// 1. it results in huge frames on modern screens (1000*800 is not
// uncommon on my 1280*1024 screen) which is way too big for a half
- // empty frame of most of wxWindows samples for example)
+ // empty frame of most of wxWidgets samples for example)
//
// 2. it is buggy for frames with wxFRAME_TOOL_WINDOW style for which
// the default is for whatever reason 8*8 which breaks client <->
// level window in some smart way which we can't do, but we can
// guess a reasonably good size for a new window just as well
// ourselves
- if ( size.x == -1 || size.y == -1)
+
+ // However, on PocketPC devices, we must use the default
+ // size if possible.
+#ifdef _WIN32_WCE
+ if (size.x == wxDefaultCoord)
+ w = CW_USEDEFAULT;
+ else
+ w = size.x;
+ if (size.y == wxDefaultCoord)
+ h = CW_USEDEFAULT;
+ else
+ h = size.y;
+#else
+ if ( size.x == wxDefaultCoord || size.y == wxDefaultCoord)
{
nonDefault = true;
}
w = WidthDefault(size.x);
h = HeightDefault(size.y);
+#endif
AdjustForParentClientOrigin(x, y);
// do create the window
wxWindowCreationHook hook(this);
- // VZ: anyonce cares to explain why is this done for CE?
-#ifdef __WXWINCE__
- if (extendedStyle == 0)
- {
- m_hWnd = (WXHWND)::CreateWindow
- (
- className,
- title ? title : wxEmptyString,
- style,
- x, y, w, h,
- (HWND)MSWGetParent(),
- (HMENU)controlId,
- wxGetInstance(),
- NULL // no extra data
- );
- }
- else
-#endif // __WXWINCE__
- {
- m_hWnd = (WXHWND)::CreateWindowEx
- (
- extendedStyle,
- className,
- title ? title : wxEmptyString,
- style,
- x, y, w, h,
- (HWND)MSWGetParent(),
- (HMENU)controlId,
- wxGetInstance(),
- NULL // no extra data
- );
- }
+ m_hWnd = (WXHWND)::CreateWindowEx
+ (
+ extendedStyle,
+ className,
+ title ? title : m_windowName.c_str(),
+ style,
+ x, y, w, h,
+ (HWND)MSWGetParent(),
+ (HMENU)controlId,
+ wxGetInstance(),
+ NULL // no extra data
+ );
if ( !m_hWnd )
{
- wxLogSysError(_("Can't create window of class %s"), wclass);
+ wxLogSysError(_("Can't create window of class %s"), className.c_str());
return false;
}
return true;
}
}
+#else
+ wxUnusedVar(lParam);
#endif // wxUSE_TOOLTIPS
return false;
bool wxWindowMSW::HandleQueryEndSession(long logOff, bool *mayEnd)
{
#ifndef __WXWINCE__
- wxCloseEvent event(wxEVT_QUERY_END_SESSION, -1);
+ wxCloseEvent event(wxEVT_QUERY_END_SESSION, wxID_ANY);
event.SetEventObject(wxTheApp);
event.SetCanVeto(true);
event.SetLoggingOff(logOff == (long)ENDSESSION_LOGOFF);
if ( (this != wxTheApp->GetTopWindow()) )
return false;
- wxCloseEvent event(wxEVT_END_SESSION, -1);
+ wxCloseEvent event(wxEVT_END_SESSION, wxID_ANY);
event.SetEventObject(wxTheApp);
event.SetCanVeto(false);
event.SetLoggingOff( (logOff == (long)ENDSESSION_LOGOFF) );
#ifndef __WXWINCE__
if ( ((CREATESTRUCT *)cs)->dwExStyle & WS_EX_CONTROLPARENT )
EnsureParentHasControlParentStyle(GetParent());
+#else
+ wxUnusedVar(cs);
#endif // !__WXWINCE__
// TODO: should generate this event from WM_NCCREATE
bool wxWindowMSW::HandleSetFocus(WXHWND hwnd)
{
+ // Strangly enough, some controls get set focus events when they are being
+ // deleted, even if they already had focus before.
+ if ( m_isBeingDeleted )
+ {
+ return false;
+ }
+
// notify the parent keeping track of focus for the kbd navigation
// purposes that we got it
wxChildFocusEvent eventFocus((wxWindow *)this);
bool wxWindowMSW::HandleShow(bool show, int WXUNUSED(status))
{
wxShowEvent event(GetId(), show);
- event.m_eventObject = this;
+ event.SetEventObject(this);
return GetEventHandler()->ProcessEvent(event);
}
bool wxWindowMSW::HandleInitDialog(WXHWND WXUNUSED(hWndFocus))
{
wxInitDialogEvent event(GetId());
- event.m_eventObject = this;
+ event.SetEventObject(this);
return GetEventHandler()->ProcessEvent(event);
}
bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam)
{
#if defined (__WXMICROWIN__) || defined(__WXWINCE__)
+ wxUnusedVar(wParam);
return false;
#else // __WXMICROWIN__
HDROP hFilesInfo = (HDROP) wParam;
DragFinish (hFilesInfo);
wxDropFilesEvent event(wxEVT_DROP_FILES, gwFilesDropped, files);
- event.m_eventObject = this;
+ event.SetEventObject(this);
POINT dropPoint;
DragQueryPoint(hFilesInfo, (LPPOINT) &dropPoint);
{
wxMenuItem *pMenuItem = (wxMenuItem *)(pDrawStruct->itemData);
- wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), false );
+ wxCHECK_MSG( pMenuItem && pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)),
+ false, _T("MSWOnDrawItem: bad wxMenuItem pointer") );
// prepare to call OnDrawItem(): notice using of wxDCTemp to prevent
// the DC from being released
#else // !wxUSE_OWNER_DRAWN
// we may still have owner-drawn buttons internally because we have to make
// them owner-drawn to support colour change
- wxControl *item = wxDynamicCast(FindItem(id), wxButton);
+ wxControl *item =
+# if wxUSE_BUTTON
+ wxDynamicCast(FindItem(id), wxButton)
+# else
+ NULL
+# endif
+ ;
#endif // USE_OWNER_DRAWN
if ( item )
}
bool
-wxWindowMSW::MSWOnMeasureItem(int WXUNUSED_UNLESS_ODRAWN(id),
- WXMEASUREITEMSTRUCT *
- WXUNUSED_UNLESS_ODRAWN(itemStruct))
+wxWindowMSW::MSWOnMeasureItem(int id, WXMEASUREITEMSTRUCT *itemStruct)
{
#if wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE
// is it a menu item?
{
wxMenuItem *pMenuItem = (wxMenuItem *)(pMeasureStruct->itemData);
- wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), false );
+ wxCHECK_MSG( pMenuItem && pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)),
+ false, _T("MSWOnMeasureItem: bad wxMenuItem pointer") );
size_t w, h;
bool rc = pMenuItem->OnMeasureItem(&w, &h);
{
return item->MSWOnMeasure(itemStruct);
}
-#endif // wxUSE_OWNER_DRAWN
+#else
+ wxUnusedVar(id);
+ wxUnusedVar(itemStruct);
+#endif // wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE
return false;
}
return GetEventHandler()->ProcessEvent(event);
}
-bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush,
- WXHDC pDC,
- WXHWND pWnd,
- WXUINT nCtlColor,
- WXUINT message,
- WXWPARAM wParam,
- WXLPARAM lParam)
-{
#ifndef __WXMICROWIN__
- WXHBRUSH hBrush = 0;
-#ifdef __WXWINCE__
- if (false)
-#else
- if ( nCtlColor == CTLCOLOR_DLG )
-#endif
- {
- hBrush = OnCtlColor(pDC, pWnd, nCtlColor, message, wParam, lParam);
- }
+bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush, WXHDC pDC, WXHWND pWnd)
+{
#if wxUSE_CONTROLS
+ wxWindow *item = FindItemByHWND(pWnd, true);
+ if ( item )
+ *brush = item->MSWControlColor(pDC);
else
- {
- wxControl *item = (wxControl *)FindItemByHWND(pWnd, true);
- if ( item )
- hBrush = item->OnCtlColor(pDC, pWnd, nCtlColor, message, wParam, lParam);
- }
#endif // wxUSE_CONTROLS
+ *brush = NULL;
- if ( hBrush )
- *brush = hBrush;
-
- return hBrush != 0;
-#else // __WXMICROWIN__
- return false;
-#endif
+ return *brush != NULL;
}
-// Define for each class of dialog and control
-WXHBRUSH wxWindowMSW::OnCtlColor(WXHDC WXUNUSED(hDC),
- WXHWND WXUNUSED(hWnd),
- WXUINT WXUNUSED(nCtlColor),
- WXUINT WXUNUSED(message),
- WXWPARAM WXUNUSED(wParam),
- WXLPARAM WXUNUSED(lParam))
+#endif // __WXMICROWIN__
+
+WXHBRUSH wxWindowMSW::MSWControlColor(WXHDC WXUNUSED(hDC))
{
return (WXHBRUSH)0;
}
while (!win->HasCustomPalette() && win->GetParent()) win = win->GetParent();
if (win->HasCustomPalette()) {
/* realize the palette to see whether redrawing is needed */
- HDC hdc = GetDC((HWND) GetHWND());
+ HDC hdc = ::GetDC((HWND) GetHWND());
win->m_palette.SetHPALETTE( (WXHPALETTE)
::SelectPalette(hdc, (HPALETTE) win->m_palette.GetHPALETTE(), FALSE) );
node = node->GetNext();
}
-
- // update the colours we use if they were not set explicitly by the user:
- // this must be done or OnCtlColor() would continue to use the old colours
- if ( !m_hasFgCol || !m_hasBgCol )
- {
- wxVisualAttributes attrs = GetDefaultAttributes();
- if ( !m_hasFgCol )
- m_foregroundColour = attrs.colFg;
-
- if ( !m_hasBgCol )
- m_backgroundColour = attrs.colBg;
- }
}
extern wxCOLORMAP *wxGetStdColourMap()
bool wxWindowMSW::HandlePaint()
{
-// if (GetExtraStyle() & wxWS_EX_THEMED_BACKGROUND)
-// return FALSE;
-
HRGN hRegion = ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle
if ( !hRegion )
wxLogLastError(wxT("CreateRectRgn"));
bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc)
{
- // Prevents flicker when dragging
- if ( ::IsIconic(GetHwnd()) )
- return true;
-
-#if 0
- if (GetParent() && GetParent()->GetExtraStyle() & wxWS_EX_THEMED_BACKGROUND)
- {
- return false;
- }
-
- if (GetExtraStyle() & wxWS_EX_THEMED_BACKGROUND)
- {
- if (wxUxThemeEngine::Get())
- {
- WXHTHEME hTheme = wxUxThemeEngine::Get()->m_pfnOpenThemeData(GetHWND(), L"TAB");
- if (hTheme)
- {
- WXURECT rect;
- ::GetClientRect((HWND) GetHWND(), (RECT*) & rect);
- wxUxThemeEngine::Get()->m_pfnDrawThemeBackground(hTheme, hdc, 10 /* TABP_BODY */, 0, &rect, &rect);
- wxUxThemeEngine::Get()->m_pfnCloseThemeData(hTheme);
- return true;
- }
- }
- }
-#endif
-
wxDCTemp dc(hdc);
dc.SetHDC(hdc);
void wxWindowMSW::OnEraseBackground(wxEraseEvent& event)
{
- RECT rect;
- ::GetClientRect(GetHwnd(), &rect);
+ // standard non top level controls (i.e. except the dialogs) always erase
+ // their background themselves in HandleCtlColor() or have some control-
+ // specific ways to set the colours (common controls)
+ if ( IsOfStandardClass() && !IsTopLevel() )
+ {
+ event.Skip();
+ return;
+ }
+
+ if ( GetBackgroundStyle() == wxBG_STYLE_CUSTOM )
+ {
+ // don't skip the event here, custom background means that the app
+ // is drawing it itself in its OnPaint(), so don't draw it at all
+ // now to avoid flicker
+ return;
+ }
+
+
+ // do default background painting
+ if ( !DoEraseBackground(*event.GetDC()) )
+ {
+ // let the system paint the background
+ event.Skip();
+ }
+}
- COLORREF ref = PALETTERGB(m_backgroundColour.Red(),
- m_backgroundColour.Green(),
- m_backgroundColour.Blue());
- HBRUSH hBrush = ::CreateSolidBrush(ref);
+bool wxWindowMSW::DoEraseBackground(wxDC& dc)
+{
+ HBRUSH hBrush = (HBRUSH)MSWGetBgBrush(dc.GetHDC());
if ( !hBrush )
- wxLogLastError(wxT("CreateSolidBrush"));
+ return false;
- HDC hdc = (HDC)event.GetDC()->GetHDC();
+ RECT rc;
+ ::GetClientRect(GetHwnd(), &rc);
+ ::FillRect(GetHdcOf(dc), &rc, hBrush);
-#ifndef __WXWINCE__
- int mode = ::SetMapMode(hdc, MM_TEXT);
-#endif
+ return true;
+}
- ::FillRect(hdc, &rect, hBrush);
- ::DeleteObject(hBrush);
+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);
-#ifndef __WXWINCE__
- ::SetMapMode(hdc, mode);
-#endif
+ return (WXHBRUSH)brush->GetResourceHandle();
+ }
+
+ return 0;
+}
+
+wxColour wxWindowMSW::MSWGetBgColourForChild(wxWindow *child)
+{
+ 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) )
+ {
+ return GetBackgroundColour();
+ }
+ }
+
+ return wxNullColour;
+}
+
+WXHBRUSH wxWindowMSW::MSWGetBgBrushForSelf(wxWindow *parent, WXHDC hDC)
+{
+ return parent->MSWGetBgBrushForChild(hDC, (wxWindow *)this);
+}
+
+WXHBRUSH wxWindowMSW::MSWGetBgBrush(WXHDC hDC)
+{
+ for ( wxWindow *win = (wxWindow *)this; win; win = win->GetParent() )
+ {
+ WXHBRUSH hBrush = MSWGetBgBrushForSelf(win, hDC);
+ 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) )
+ break;
+ }
+
+ return 0;
+}
+
+bool
+wxWindowMSW::MSWPrintChild(wxWindow * WXUNUSED(win),
+ WXWPARAM WXUNUSED(wParam),
+ WXLPARAM WXUNUSED(lParam))
+{
+ return false;
}
// ---------------------------------------------------------------------------
bool wxWindowMSW::HandleMove(int x, int y)
{
- wxMoveEvent event(wxPoint(x, y), m_windowId);
+ wxPoint point(x,y);
+ wxMoveEvent event(point, m_windowId);
event.SetEventObject(this);
return GetEventHandler()->ProcessEvent(event);
return rc;
}
-bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h),
- WXUINT WXUNUSED(flag))
+bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT wParam)
{
- // don't use w and h parameters as they specify the client size while
- // according to the docs EVT_SIZE handler is supposed to receive the total
- // size
- wxSizeEvent event(GetSize(), m_windowId);
- event.SetEventObject(this);
+ // when we resize this window, its children are probably going to be
+ // repositioned as well, prepare to use DeferWindowPos() for them
+ const int numChildren = GetChildren().GetCount();
+ if ( numChildren > 1 )
+ {
+ m_hDWP = (WXHANDLE)::BeginDeferWindowPos(numChildren);
+ if ( !m_hDWP )
+ {
+ wxLogLastError(_T("BeginDeferWindowPos"));
+ }
+ }
- return GetEventHandler()->ProcessEvent(event);
+ // update this window size
+ bool processed = false;
+ switch ( wParam )
+ {
+ default:
+ wxFAIL_MSG( _T("unexpected WM_SIZE parameter") );
+ // fall through nevertheless
+
+ case SIZE_MAXHIDE:
+ case SIZE_MAXSHOW:
+ // we're not interested in these messages at all
+ break;
+
+ case SIZE_MINIMIZED:
+ processed = HandleMinimize();
+ break;
+
+ case SIZE_MAXIMIZED:
+ /* processed = */ HandleMaximize();
+ // fall through to send a normal size event as well
+
+ case SIZE_RESTORED:
+ // don't use w and h parameters as they specify the client size
+ // while according to the docs EVT_SIZE handler is supposed to
+ // receive the total size
+ wxSizeEvent event(GetSize(), m_windowId);
+ event.SetEventObject(this);
+
+ processed = GetEventHandler()->ProcessEvent(event);
+ }
+
+ // and finally change the positions of all child windows at once
+ if ( m_hDWP )
+ {
+ // reset m_hDWP to NULL so that child windows don't try to use our
+ // m_hDWP after we call EndDeferWindowPos() on it (this shouldn't
+ // happen anyhow normally but who knows what weird flow of control we
+ // may have depending on what the users EVT_SIZE handler does...)
+ HDWP hDWP = (HDWP)m_hDWP;
+ m_hDWP = NULL;
+
+ // do put all child controls in place at once
+ if ( !::EndDeferWindowPos(hDWP) )
+ {
+ wxLogLastError(_T("EndDeferWindowPos"));
+ }
+ }
+
+ return processed;
}
bool wxWindowMSW::HandleSizing(wxRect& rect)
bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo)
{
#ifdef __WXWINCE__
+ wxUnusedVar(mmInfo);
return false;
#else
MINMAXINFO *info = (MINMAXINFO *)mmInfo;
maxWidth = GetMaxWidth(),
maxHeight = GetMaxHeight();
- if ( minWidth != -1 )
+ if ( minWidth != wxDefaultCoord )
{
info->ptMinTrackSize.x = minWidth;
rc = true;
}
- if ( minHeight != -1 )
+ if ( minHeight != wxDefaultCoord )
{
info->ptMinTrackSize.y = minHeight;
rc = true;
}
- if ( maxWidth != -1 )
+ if ( maxWidth != wxDefaultCoord )
{
info->ptMaxTrackSize.x = maxWidth;
rc = true;
}
- if ( maxHeight != -1 )
+ if ( maxHeight != wxDefaultCoord )
{
info->ptMaxTrackSize.y = maxHeight;
rc = true;
return false;
}
-bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam, WXLPARAM WXUNUSED(lParam))
-{
-#ifndef __WXWINCE__
- // 4 bits are reserved
- switch ( wParam & 0xFFFFFFF0 )
- {
- case SC_MAXIMIZE:
- return HandleMaximize();
-
- case SC_MINIMIZE:
- return HandleMinimize();
- }
-#endif
-
- return false;
-}
-
// ---------------------------------------------------------------------------
// mouse events
// ---------------------------------------------------------------------------
event.m_leftDown = (flags & MK_LBUTTON) != 0;
event.m_middleDown = (flags & MK_MBUTTON) != 0;
event.m_rightDown = (flags & MK_RBUTTON) != 0;
- // event.m_altDown = (::GetKeyState(VK_MENU) & 0x80000000) != 0;
- // Returns different negative values on WinME and WinNT,
- // so simply test for negative value.
event.m_altDown = ::GetKeyState(VK_MENU) < 0;
#ifndef __WXWINCE__
event.SetTimestamp(::GetMessageTime());
#endif
- event.m_eventObject = this;
+ event.SetEventObject(this);
event.SetId(GetId());
#if wxUSE_MOUSEEVENT_HACK
bool wxWindowMSW::HandleMouseEvent(WXUINT msg, int x, int y, WXUINT flags)
{
// the mouse events take consecutive IDs from WM_MOUSEFIRST to
- // WM_MOUSELAST, so it's enough to substract WM_MOUSEMOVE == WM_MOUSEFIRST
+ // WM_MOUSELAST, so it's enough to subtract WM_MOUSEMOVE == WM_MOUSEFIRST
// from the message id and take the value in the table to get wxWin event
// id
static const wxEventType eventsMouse[] =
{
// Generate an ENTER event
m_mouseInWindow = true;
-#if _WIN32_WINNT >= 0x0400
-#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
-#endif
+#endif // HAVE_TRACKMOUSEEVENT
+
wxMouseEvent event(wxEVT_ENTER_WINDOW);
InitMouseEvent(event, x, y, flags);
event.m_linesPerAction = s_linesPerRotation;
return GetEventHandler()->ProcessEvent(event);
-#else
- (void) wParam;
- (void) lParam;
+#else // !wxUSE_MOUSEWHEEL
+ wxUnusedVar(wParam);
+ wxUnusedVar(lParam);
return false;
-#endif
+#endif // wxUSE_MOUSEWHEEL/!wxUSE_MOUSEWHEEL
}
+void wxWindowMSW::GenerateMouseLeave()
+{
+ m_mouseInWindow = false;
+
+ int state = 0;
+ if ( wxIsShiftDown() )
+ state |= MK_SHIFT;
+ if ( wxIsCtrlDown() )
+ state |= MK_CONTROL;
+
+ // Only the high-order bit should be tested
+ if ( GetKeyState( VK_LBUTTON ) & (1<<15) )
+ state |= MK_LBUTTON;
+ if ( GetKeyState( VK_MBUTTON ) & (1<<15) )
+ state |= MK_MBUTTON;
+ if ( GetKeyState( VK_RBUTTON ) & (1<<15) )
+ state |= MK_RBUTTON;
+
+ POINT pt;
+ if ( !::GetCursorPos(&pt) )
+ {
+ wxLogLastError(_T("GetCursorPos"));
+ }
+
+ // we need to have client coordinates here for symmetry with
+ // wxEVT_ENTER_WINDOW
+ RECT rect = wxGetWindowRect(GetHwnd());
+ pt.x -= rect.left;
+ pt.y -= rect.top;
+
+ wxMouseEvent event(wxEVT_LEAVE_WINDOW);
+ InitMouseEvent(event, pt.x, pt.y, state);
+
+ (void)GetEventHandler()->ProcessEvent(event);
+}
// ---------------------------------------------------------------------------
// keyboard handling
event.m_controlDown = wxIsCtrlDown();
event.m_altDown = (HIWORD(lParam) & KF_ALTDOWN) == KF_ALTDOWN;
- event.m_eventObject = (wxWindow *)this; // const_cast
+ event.SetEventObject((wxWindow *)this); // const_cast
event.m_keyCode = id;
+#if wxUSE_UNICODE
+ event.m_uniChar = (wxChar) wParam;
+#endif
event.m_rawCode = (wxUint32) wParam;
event.m_rawFlags = (wxUint32) lParam;
#ifndef __WXWINCE__
// FIXME-UNICODE: this comparison doesn't risk to work
// for non ASCII accelerator characters I'm afraid, but
// what can we do?
- if ( wxToupper(*p) == chAccel )
+ if ( (wchar_t)wxToupper(*p) == (wchar_t)chAccel )
{
return i;
}
wxLogLastError(_T("GetMenuItemInfo"));
}
}
+#else
+ wxUnusedVar(chAccel);
+ wxUnusedVar(lParam);
#endif
return wxNOT_FOUND;
}
return GetEventHandler()->ProcessEvent(event);
#else
+ wxUnusedVar(msg);
+ wxUnusedVar(x);
+ wxUnusedVar(y);
+ wxUnusedVar(flags);
return false;
#endif
}
bool wxWindowMSW::MSWOnScroll(int orientation, WXWORD wParam,
WXWORD pos, WXHWND control)
-{
+{
if ( control && control != m_hWnd ) // Prevent infinite recursion
{
wxWindow *child = wxFindWinFromHandle(control);
wxScrollWinEvent event;
event.SetPosition(pos);
event.SetOrientation(orientation);
- event.m_eventObject = this;
+ event.SetEventObject(this);
switch ( wParam )
{
case SB_TOP:
- event.m_eventType = wxEVT_SCROLLWIN_TOP;
+ event.SetEventType(wxEVT_SCROLLWIN_TOP);
break;
case SB_BOTTOM:
- event.m_eventType = wxEVT_SCROLLWIN_BOTTOM;
+ event.SetEventType(wxEVT_SCROLLWIN_BOTTOM);
break;
case SB_LINEUP:
- event.m_eventType = wxEVT_SCROLLWIN_LINEUP;
+ event.SetEventType(wxEVT_SCROLLWIN_LINEUP);
break;
case SB_LINEDOWN:
- event.m_eventType = wxEVT_SCROLLWIN_LINEDOWN;
+ event.SetEventType(wxEVT_SCROLLWIN_LINEDOWN);
break;
case SB_PAGEUP:
- event.m_eventType = wxEVT_SCROLLWIN_PAGEUP;
+ event.SetEventType(wxEVT_SCROLLWIN_PAGEUP);
break;
case SB_PAGEDOWN:
- event.m_eventType = wxEVT_SCROLLWIN_PAGEDOWN;
+ event.SetEventType(wxEVT_SCROLLWIN_PAGEDOWN);
break;
case SB_THUMBPOSITION:
event.SetPosition(scrollInfo.nTrackPos);
}
- event.m_eventType = wParam == SB_THUMBPOSITION
+ event.SetEventType( wParam == SB_THUMBPOSITION
? wxEVT_SCROLLWIN_THUMBRELEASE
- : wxEVT_SCROLLWIN_THUMBTRACK;
+ : wxEVT_SCROLLWIN_THUMBTRACK );
break;
default:
// global functions
// ===========================================================================
-void wxGetCharSize(WXHWND wnd, int *x, int *y, const wxFont *the_font)
+void wxGetCharSize(WXHWND wnd, int *x, int *y, const wxFont& the_font)
{
TEXTMETRIC tm;
HDC dc = ::GetDC((HWND) wnd);
- HFONT fnt =0;
HFONT was = 0;
- if ( the_font )
- {
- // the_font->UseResource();
- // the_font->RealizeResource();
- fnt = (HFONT)((wxFont *)the_font)->GetResourceHandle(); // const_cast
- if ( fnt )
- was = (HFONT) SelectObject(dc,fnt);
- }
+
+ // the_font.UseResource();
+ // the_font.RealizeResource();
+ HFONT fnt = (HFONT)the_font.GetResourceHandle(); // const_cast
+ if ( fnt )
+ was = (HFONT) SelectObject(dc,fnt);
+
GetTextMetrics(dc, &tm);
- if ( the_font && fnt && was )
+ if ( fnt && was )
{
SelectObject(dc,was);
}
if ( y )
*y = tm.tmHeight + tm.tmExternalLeading;
- // if ( the_font )
- // the_font->ReleaseResource();
+ // the_font.ReleaseResource();
}
// Returns 0 if was a normal ASCII value, not a special key. This indicates that
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 VK_NUMLOCK: id = WXK_NUMLOCK; break;
case VK_SCROLL: id = WXK_SCROLL; break;
+ // the mapping for these keys may be incorrect on non-US keyboards so
+ // maybe we shouldn't map them to ASCII values at all
case VK_OEM_1: id = ';'; break;
case VK_OEM_PLUS: id = '+'; break;
case VK_OEM_COMMA: id = ','; break;
return id;
}
-int wxCharCodeWXToMSW(int id, bool *isVirtual)
+WXWORD wxCharCodeWXToMSW(int id, bool *isVirtual)
{
*isVirtual = true;
- int keySym;
+ WXWORD keySym;
switch (id)
{
case WXK_CANCEL: keySym = VK_CANCEL; break;
case WXK_CLEAR: keySym = VK_CLEAR; break;
case WXK_SHIFT: keySym = VK_SHIFT; break;
case WXK_CONTROL: keySym = VK_CONTROL; break;
- case WXK_MENU : keySym = VK_MENU; break;
+ case WXK_ALT: 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;
case WXK_NEXT : keySym = VK_NEXT; break;
case WXK_END: keySym = VK_END; break;
default:
{
*isVirtual = false;
- keySym = id;
+ keySym = (WORD)id;
break;
}
}
bool wxGetKeyState(wxKeyCode key)
{
bool bVirtual;
- int vkey = wxCharCodeWXToMSW(key, &bVirtual);
-
- //there aren't WXK_ macros for non-virtual key codes
- if (bVirtual == false)
- return false;
- return GetKeyState(vkey) < 0;
+//High order with GetAsyncKeyState only available on WIN32
+#ifdef __WIN32__
+ //If the requested key is a LED key, return
+ //true if the led is pressed
+ if (key == WXK_NUMLOCK ||
+ key == WXK_CAPITAL ||
+ key == WXK_SCROLL)
+ {
+#endif
+ //low order bit means LED is highlighted,
+ //high order means key is down
+ //Here, for compat with other ports we want both
+ return GetKeyState( wxCharCodeWXToMSW(key, &bVirtual) ) != 0;
+
+#ifdef __WIN32__
+ }
+ else
+ {
+ //normal key
+ //low order bit means key pressed since last call
+ //high order means key is down
+ //We want only the high order bit - the key may not be down if only low order
+ return ( GetAsyncKeyState( wxCharCodeWXToMSW(key, &bVirtual) ) & (1<<15) ) != 0;
+ }
+#endif
}
wxWindow *wxGetActiveWindow()
if ( (HIWORD(lParam) & KF_ALTDOWN) == KF_ALTDOWN )
event.m_altDown = true;
- event.m_eventObject = NULL;
+ event.SetEventObject(NULL);
event.m_keyCode = id;
event.m_shiftDown = wxIsShiftDown();
event.m_controlDown = wxIsCtrlDown();
else
{
handler = wxTheApp;
- event.SetId(-1);
+ event.SetId(wxID_ANY);
}
if ( handler && handler->ProcessEvent(event) )
}
#endif //__WXDEBUG__
-static void TranslateKbdEventToMouse(wxWindowMSW *win,
- int *x, int *y, WPARAM *flags)
-{
- // construct the key mask
- WPARAM& fwKeys = *flags;
-
- fwKeys = MK_RBUTTON;
- if ( wxIsCtrlDown() )
- fwKeys |= MK_CONTROL;
- if ( wxIsShiftDown() )
- fwKeys |= MK_SHIFT;
-
- // simulate right mouse button click
- DWORD dwPos = ::GetMessagePos();
- *x = GET_X_LPARAM(dwPos);
- *y = GET_Y_LPARAM(dwPos);
-
- win->ScreenToClient(x, y);
-}
-
static TEXTMETRIC wxGetTextMetrics(const wxWindowMSW *win)
{
// prepare the DC
return true;
}
+#if wxUSE_ACCEL
+
bool wxWindowMSW::HandleHotKey(WXWPARAM wParam, WXLPARAM lParam)
{
int hotkeyId = wParam;
return GetEventHandler()->ProcessEvent(event);
}
+#endif // wxUSE_ACCEL
+
#endif // wxUSE_HOTKEY
// Not tested under WinCE
class wxIdleWakeUpModule : public wxModule
{
public:
- virtual bool OnInit()
+ virtual bool OnInit()
{
- ms_hMsgHookProc = ::SetWindowsHookEx
+ ms_hMsgHookProc = ::SetWindowsHookEx
(
WH_GETMESSAGE,
&wxIdleWakeUpModule::MsgHookProc,
}
return true;
- }
+ }
- virtual void OnExit()
+ virtual void OnExit()
{
- ::UnhookWindowsHookEx(wxIdleWakeUpModule::ms_hMsgHookProc);
- }
+ ::UnhookWindowsHookEx(wxIdleWakeUpModule::ms_hMsgHookProc);
+ }
- static LRESULT CALLBACK MsgHookProc(int nCode, WPARAM wParam, LPARAM lParam)
+ static LRESULT CALLBACK MsgHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
- MSG *msg = (MSG*)lParam;
- if ( msg->message == WM_NULL )
- {
+ MSG *msg = (MSG*)lParam;
+
+ // only process the message if it is actually going to be removed from
+ // the message queue, this prevents that the same event from being
+ // processed multiple times if now someone just called PeekMessage()
+ if ( msg->message == WM_NULL && wParam == PM_REMOVE )
+ {
wxTheApp->ProcessPendingEvents();
- }
+ }
- return CallNextHookEx(ms_hMsgHookProc, nCode, wParam, lParam);
- };
+ return CallNextHookEx(ms_hMsgHookProc, nCode, wParam, lParam);
+ };
private:
- static HHOOK ms_hMsgHookProc;
+ static HHOOK ms_hMsgHookProc;
DECLARE_DYNAMIC_CLASS(wxIdleWakeUpModule)
};
IMPLEMENT_DYNAMIC_CLASS(wxIdleWakeUpModule, wxModule)
#endif // __WXWINCE__
-
+
+#ifdef __WXWINCE__
+
+#if wxUSE_STATBOX
+static void wxAdjustZOrder(wxWindow* parent)
+{
+ if (parent->IsKindOf(CLASSINFO(wxStaticBox)))
+ {
+ // Set the z-order correctly
+ SetWindowPos((HWND) parent->GetHWND(), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
+ }
+
+ wxWindowList::compatibility_iterator current = parent->GetChildren().GetFirst();
+ while (current)
+ {
+ wxWindow *childWin = current->GetData();
+ wxAdjustZOrder(childWin);
+ current = current->GetNext();
+ }
+}
+#endif
+
+// We need to adjust the z-order of static boxes in WinCE, to
+// make 'contained' controls visible
+void wxWindowMSW::OnInitDialog( wxInitDialogEvent& event )
+{
+#if wxUSE_STATBOX
+ wxAdjustZOrder(this);
+#endif
+
+ event.Skip();
+}
+#endif
+