InitBase();
// MSW specific
- m_doubleClickAllowed = 0;
-
m_isBeingDeleted = FALSE;
- m_oldWndProc = 0;
+ m_oldWndProc = NULL;
m_useCtl3D = FALSE;
m_mouseInWindow = FALSE;
m_lastKeydownProcessed = FALSE;
// VS: make sure there's no wxFrame with last focus set to us:
for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
{
- wxFrame *frame = wxDynamicCast(win, wxFrame);
+ wxTopLevelWindow *frame = wxDynamicCast(win, wxTopLevelWindow);
if ( frame )
{
if ( frame->GetLastFocus() == this )
{
- frame->SetLastFocus((wxWindow*)NULL);
+ frame->SetLastFocus(NULL);
}
break;
}
}
else
{
- // don't bother restoring it neither
+ // 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
+ // simply check m_oldWndProc
m_oldWndProc = NULL;
}
}
*exstyle |= WS_EX_DLGMODALFRAME;
break;
}
+
+ // wxUniv doesn't use Windows dialog navigation functions at all
+#ifndef __WXUNIVERSAL__
+ // 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__
}
return style;
// here we try to do all the job which ::IsDialogMessage() usually does
// internally
#if 1
- bool bProcess = TRUE;
- if ( msg->message != WM_KEYDOWN )
- bProcess = FALSE;
-
- if ( bProcess && (HIWORD(msg->lParam) & KF_ALTDOWN) == KF_ALTDOWN )
- bProcess = FALSE;
-
- if ( bProcess )
+ if ( msg->message == WM_KEYDOWN )
{
bool bCtrlDown = wxIsCtrlDown();
bool bShiftDown = wxIsShiftDown();
bool bForward = TRUE,
bWindowChange = FALSE;
+ // should we process this message specially?
+ bool bProcess = TRUE;
switch ( msg->wParam )
{
case VK_TAB:
// place edit control from being closed with Escape in a dialog
if ( msg->message != WM_KEYDOWN || msg->wParam != VK_ESCAPE )
{
- if ( ::IsDialogMessage(GetHwnd(), msg) )
+ // ::IsDialogMessage() can enter in an infinite loop when the
+ // currently focused window is disabled or hidden and its parent
+ // has WS_EX_CONTROLPARENT style, so don't call it in this case
+ bool canSafelyCallIsDlgMsg = TRUE;
+
+ HWND hwndFocus = ::GetFocus();
+ while ( hwndFocus )
+ {
+ if ( !::IsWindowEnabled(hwndFocus) ||
+ !::IsWindowVisible(hwndFocus) )
+ {
+ // it would enter an infinite loop if we do this!
+ canSafelyCallIsDlgMsg = FALSE;
+
+ break;
+ }
+
+ if ( !(::GetWindowLong(hwndFocus, GWL_STYLE) & WS_CHILD) )
+ {
+ // it's a top level window, don't go further -- e.g. even
+ // if the parent of a dialog is disabled, this doesn't
+ // break navigation inside the dialog
+ break;
+ }
+
+ hwndFocus = ::GetParent(hwndFocus);
+ }
+
+ if ( canSafelyCallIsDlgMsg && ::IsDialogMessage(GetHwnd(), msg) )
{
// IsDialogMessage() did something...
return TRUE;
break;
}
- if (!processed)
+ if ( processed )
+ break;
+
#endif // __WXMICROWIN__
- {
- // VZ: why do we need it here? DefWindowProc() is supposed
- // to do this for us anyhow
- if ( message == WM_LBUTTONDOWN && AcceptsFocus() )
- SetFocus();
+ // VZ: if you find a situation when this is needed, tell
+ // me about it, do *not* uncomment this code as it
+ // causes other strange problems
+#if 0
+ if ( message == WM_LBUTTONDOWN && AcceptsFocus() )
+ SetFocus();
+#endif // 0
- int x = GET_X_LPARAM(lParam),
- y = GET_Y_LPARAM(lParam);
+ int x = GET_X_LPARAM(lParam),
+ y = GET_Y_LPARAM(lParam);
- // redirect the event to a static control if necessary
- if (this == GetCapture())
- {
- processed = HandleMouseEvent(message, x, y, wParam);
- }
- else
- {
- wxWindowMSW *win = FindWindowForMouseEvent(this, &x, &y); //TW:REQ:Univ
- processed = win->HandleMouseEvent(message, x, y, wParam);
- }
+ // redirect the event to a static control if necessary by
+ // finding one under mouse
+ wxWindowMSW *win;
+ if ( GetCapture() == this )
+ {
+ // but don't do it if the mouse is captured by this window
+ // because then it should really get this event itself
+ win = this;
}
+ else
+ {
+ win = FindWindowForMouseEvent(this, &x, &y);
+ }
+
+ processed = win->HandleMouseEvent(message, x, y, wParam);
}
break;
#endif // defined(WM_DRAWITEM)
case WM_GETDLGCODE:
- if ( GetWindowStyleFlag() & wxWANTS_CHARS )
+ if ( !IsOfStandardClass() )
{
- // want everything: i.e. all keys and WM_CHAR message
- rc.result = DLGC_WANTARROWS | DLGC_WANTCHARS |
- DLGC_WANTTAB | DLGC_WANTMESSAGE;
+ // we always want to get the char events
+ rc.result = DLGC_WANTCHARS;
+
+ if ( GetWindowStyleFlag() & wxWANTS_CHARS )
+ {
+ // in fact, we want everything
+ rc.result |= DLGC_WANTARROWS |
+ DLGC_WANTTAB |
+ DLGC_WANTALLKEYS;
+ }
+
processed = TRUE;
}
//else: get the dlg code from the DefWindowProc()
return nonDefault;
}
+WXHWND wxWindowMSW::MSWGetParent() const
+{
+ return m_parent ? m_parent->GetHWND() : NULL;
+}
+
bool wxWindowMSW::MSWCreate(const wxChar *wclass,
const wxChar *title,
const wxPoint& pos,
int x, y, w, h;
(void)MSWGetCreateWindowCoords(pos, size, x, y, w, h);
- // find the correct parent HWND
- wxWindow *parent = GetParent();
- bool isChild = (style & WS_CHILD) != 0;
- HWND hParent;
- if ( (isChild || HasFlag(wxPOPUP_WINDOW) || HasFlag(wxFRAME_TOOL_WINDOW)) )
- {
- // this is either a normal child window, a popup window or a top level
- // window with wxFRAME_TOOL_WINDOW style (see below)
- hParent = parent ? GetHwndOf(parent) : NULL;
- }
- else
- {
- // this is a frame without wxFRAME_TOOL_WINDOW style: we should use
- // NULL parent HWND for it or it would be always on top of its parent
- // which is not what we usually want (in fact, we only want it for
- // frames with the special wxFRAME_TOOL_WINDOW as above)
- hParent = NULL;
- }
-
// controlId is menu handle for the top level windows, so set it to 0
// unless we're creating a child window
- int controlId;
- if ( isChild )
- {
- controlId = GetId();
-
- if ( GetWindowStyleFlag() & wxCLIP_SIBLINGS )
- {
- style |= WS_CLIPSIBLINGS;
- }
- }
- else // !child
- {
- controlId = 0;
- }
+ int controlId = style & WS_CHILD ? GetId() : 0;
// for each class "Foo" we have we also have "FooNR" ("no repaint") class
// which is the same but without CS_[HV]REDRAW class styles so using it
wxWindowCreationHook hook(this);
m_hWnd = (WXHWND)::CreateWindowEx
- (
- extendedStyle,
- className,
- title ? title : wxT(""),
- style,
- x, y, w, h,
- hParent,
- (HMENU)controlId,
- wxGetInstance(),
- NULL // no extra data
- );
+ (
+ extendedStyle,
+ className,
+ title ? title : wxT(""),
+ style,
+ x, y, w, h,
+ (HWND)MSWGetParent(),
+ (HMENU)controlId,
+ wxGetInstance(),
+ NULL // no extra data
+ );
if ( !m_hWnd )
{
// window creation/destruction
// ---------------------------------------------------------------------------
-bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT WXUNUSED(cs), bool *mayCreate)
+bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT cs, bool *mayCreate)
{
+ // if we have WS_EX_CONTROLPARENT flag we absolutely *must* set it for our
+ // parent as well as otherwise several Win32 functions using
+ // GetNextDlgTabItem() to iterate over all controls such as
+ // IsDialogMessage() or DefDlgProc() would enter an infinite loop: indeed,
+ // all of them iterate over all the controls starting from the focus and
+ // stop iterating when they get back to the focus but unless all parents
+ // have WS_EX_CONTROLPARENT bit set, they would never get back to focus
+ if ( ((CREATESTRUCT *)cs)->dwExStyle & WS_EX_CONTROLPARENT )
+ {
+ // there is no need to do anything for the top level windows
+ const wxWindow *parent = GetParent();
+ if ( parent && !parent->IsTopLevel() )
+ {
+ LONG exStyle = ::GetWindowLong(GetHwndOf(parent), GWL_EXSTYLE);
+ if ( !(exStyle & WS_EX_CONTROLPARENT) )
+ {
+ // force the parent to have this style
+ ::SetWindowLong(GetHwndOf(parent), GWL_EXSTYLE,
+ exStyle | WS_EX_CONTROLPARENT);
+ }
+ }
+ }
+
// TODO: should generate this event from WM_NCCREATE
wxWindowCreateEvent event((wxWindow *)this);
(void)GetEventHandler()->ProcessEvent(event);
event.SetTimestamp(s_currentMsg.time);
event.m_eventObject = this;
+ event.SetId(GetId());
#if wxUSE_MOUSEEVENT_HACK
m_lastMouseX = x;