MSWDetachWindowMenu();
+#ifndef __WXUNIVERSAL__
// VS: make sure there's no wxFrame with last focus set to us:
- for (wxWindow *win = GetParent(); win; win = win->GetParent())
+ for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
{
wxFrame *frame = wxDynamicCast(win, wxFrame);
if ( frame )
{
if ( frame->GetLastFocus() == this )
+ {
frame->SetLastFocus((wxWindow*)NULL);
+ }
break;
}
}
+#endif // __WXUNIVERSAL__
// VS: destroy children first and _then_ detach *this from its parent.
// If we'd do it the other way around, children wouldn't be able
m_isShown = FALSE;
}
- return MSWCreate(m_windowId, parent, wxCanvasClassName,
- (wxWindow *)this, NULL,
- pos.x, pos.y,
- WidthDefault(size.x), HeightDefault(size.y),
- msflags, NULL, exStyle);
+ return MSWCreate(wxCanvasClassName, NULL, pos, size, msflags, exStyle);
}
// ---------------------------------------------------------------------------
POINT point;
::GetCursorPos(&point);
- RECT rect;
- ::GetWindowRect(hWnd, &rect);
+ RECT rect = wxGetWindowRect(hWnd);
if ( ::PtInRect(&rect, point) && !wxIsBusy() )
::SetCursor(GetHcursorOf(m_cursor));
wxAssociateWinWithHandle(hwnd, this);
- m_oldWndProc = (WXFARPROC) GetWindowLong(hwnd, GWL_WNDPROC);
-
- wxASSERT( (WXFARPROC) m_oldWndProc != (WXFARPROC) wxWndProc );
+ m_oldWndProc = (WXFARPROC)::GetWindowLong(hwnd, GWL_WNDPROC);
- SetWindowLong(hwnd, GWL_WNDPROC, (LONG) wxWndProc);
+ // we don't need to subclass the window of our own class (in the Windows
+ // sense of the word)
+ if ( (WXFARPROC) m_oldWndProc != (WXFARPROC) wxWndProc )
+ {
+ ::SetWindowLong(hwnd, GWL_WNDPROC, (LONG) wxWndProc);
+ }
+ else
+ {
+ // don't bother restoring it neither
+ m_oldWndProc = NULL;
+ }
}
void wxWindowMSW::UnsubclassWin()
wxCHECK_RET( ::IsWindow(hwnd), wxT("invalid HWND in UnsubclassWin") );
- FARPROC farProc = (FARPROC) GetWindowLong(hwnd, GWL_WNDPROC);
- if ( (m_oldWndProc != 0) && (farProc != (FARPROC) m_oldWndProc) )
+ if ( m_oldWndProc )
{
- SetWindowLong(hwnd, GWL_WNDPROC, (LONG) m_oldWndProc);
- m_oldWndProc = 0;
+ FARPROC wndProc = (FARPROC)::GetWindowLong(hwnd, GWL_WNDPROC);
+ if ( wndProc != (FARPROC) m_oldWndProc )
+ {
+ ::SetWindowLong(hwnd, GWL_WNDPROC, (LONG) m_oldWndProc);
+ }
+
+ m_oldWndProc = NULL;
}
}
}
exStyle |= WS_EX_STATICEDGE;
#endif
}
+
return exStyle;
}
// applying a default border style if required, and returning an extended
// style to pass to CreateWindowEx.
WXDWORD wxWindowMSW::Determine3DEffects(WXDWORD defaultBorderStyle,
- bool *want3D) const
+ bool *want3D) const
{
// If matches certain criteria, then assume no 3D effects
// unless specifically requested (dealt with in MakeExtendedStyle)
|| (m_windowStyle & wxNO_BORDER) )
{
*want3D = FALSE;
- return MakeExtendedStyle(m_windowStyle, FALSE);
+ return MakeExtendedStyle(m_windowStyle);
}
// Determine whether we should be using 3D effects or not.
// we need to have client coordinates here for symmetry with
// wxEVT_ENTER_WINDOW
- RECT rect;
- if ( !::GetWindowRect(GetHwnd(), &rect) )
- {
- wxLogLastError(_T("GetWindowRect"));
- }
+ RECT rect = wxGetWindowRect(GetHwnd());
pt.x -= rect.left;
pt.y -= rect.top;
// Get total size
void wxWindowMSW::DoGetSize(int *x, int *y) const
{
- HWND hWnd = GetHwnd();
- RECT rect;
-#ifdef __WIN16__
- ::GetWindowRect(hWnd, &rect);
-#else
- if ( !::GetWindowRect(hWnd, &rect) )
- {
- wxLogLastError(_T("GetWindowRect"));
- }
-#endif
+ RECT rect = wxGetWindowRect(GetHwnd());
+
if ( x )
*x = rect.right - rect.left;
if ( y )
*y = rect.bottom - rect.top;
}
-void wxWindowMSW::DoGetPosition(int *x, int *y) const
+// Get size *available for subwindows* i.e. excluding menu bar etc.
+void wxWindowMSW::DoGetClientSize(int *x, int *y) const
{
- HWND hWnd = GetHwnd();
+ RECT rect = wxGetClientRect(GetHwnd());
- RECT rect;
- GetWindowRect(hWnd, &rect);
+ if ( x )
+ *x = rect.right;
+ if ( y )
+ *y = rect.bottom;
+}
+
+void wxWindowMSW::DoGetPosition(int *x, int *y) const
+{
+ RECT rect = wxGetWindowRect(GetHwnd());
POINT point;
point.x = rect.left;
if ( y )
pt.y = *y;
- HWND hWnd = GetHwnd();
- ::ScreenToClient(hWnd, &pt);
+ ::ScreenToClient(GetHwnd(), &pt);
if ( x )
*x = pt.x;
if ( y )
pt.y = *y;
- HWND hWnd = GetHwnd();
- ::ClientToScreen(hWnd, &pt);
+ ::ClientToScreen(GetHwnd(), &pt);
if ( x )
*x = pt.x;
*y = pt.y;
}
-// Get size *available for subwindows* i.e. excluding menu bar etc.
-void wxWindowMSW::DoGetClientSize(int *x, int *y) const
-{
- HWND hWnd = GetHwnd();
- RECT rect;
- ::GetClientRect(hWnd, &rect);
- if ( x )
- *x = rect.right;
- if ( y )
- *y = rect.bottom;
-}
-
void wxWindowMSW::DoMoveWindow(int x, int y, int width, int height)
{
if ( !::MoveWindow(GetHwnd(), x, y, width, height, TRUE) )
return wxPoint(0, 0);
}
-// Makes an adjustment to the window position (for example, a frame that has
-// a toolbar that it manages itself).
-void wxWindowMSW::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags)
-{
- // don't do it for the dialogs/frames - they float independently of their
- // parent
- if ( !IsTopLevel() )
- {
- wxWindow *parent = GetParent();
- if ( !(sizeFlags & wxSIZE_NO_ADJUSTMENTS) && parent )
- {
- wxPoint pt(parent->GetClientAreaOrigin());
- x += pt.x;
- y += pt.y;
- }
- }
-}
-
// ---------------------------------------------------------------------------
// text metrics
// ---------------------------------------------------------------------------
// popup menu
// ---------------------------------------------------------------------------
+#if wxUSE_MENUS_NATIVE
+
// yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue
// immediately, without waiting for the next event loop iteration
//
}
}
-#if wxUSE_MENUS_NATIVE
-
bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y)
{
menu->SetInvokingWindow(this);
// Hook for new window just as it's being created, when the window isn't yet
// associated with the handle
-wxWindowMSW *wxWndHook = NULL;
+static wxWindowMSW *gs_winBeingCreated = NULL;
+
+// implementation of wxWindowCreationHook class: it just sets gs_winBeingCreated to the
+// window being created and insures that it's always unset back later
+wxWindowCreationHook::wxWindowCreationHook(wxWindowMSW *winBeingCreated)
+{
+ gs_winBeingCreated = winBeingCreated;
+}
+
+wxWindowCreationHook::~wxWindowCreationHook()
+{
+ gs_winBeingCreated = NULL;
+}
// Main window proc
LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
wxWindowMSW *wnd = wxFindWinFromHandle((WXHWND) hWnd);
// when we get the first message for the HWND we just created, we associate
- // it with wxWindow stored in wxWndHook
- if ( !wnd && wxWndHook )
+ // it with wxWindow stored in gs_winBeingCreated
+ if ( !wnd && gs_winBeingCreated )
{
-#if 0 // def __WXDEBUG__
- char buf[512];
- ::GetClassNameA((HWND) hWnd, buf, 512);
- wxString className(buf);
-#endif
-
- wxAssociateWinWithHandle(hWnd, wxWndHook);
- wnd = wxWndHook;
- wxWndHook = NULL;
+ wxAssociateWinWithHandle(hWnd, gs_winBeingCreated);
+ wnd = gs_winBeingCreated;
+ gs_winBeingCreated = NULL;
wnd->SetHWND((WXHWND)hWnd);
}
LRESULT rc;
- // Stop right here if we don't have a valid handle in our wxWindow object.
- if ( wnd && !wnd->GetHWND() )
- {
- // FIXME: why do we do this?
- wnd->SetHWND((WXHWND) hWnd);
- rc = wnd->MSWDefWindowProc(message, wParam, lParam );
- wnd->SetHWND(0);
- }
+ if ( wnd )
+ rc = wnd->MSWWindowProc(message, wParam, lParam);
else
- {
- if ( wnd )
- rc = wnd->MSWWindowProc(message, wParam, lParam);
- else
- rc = DefWindowProc( hWnd, message, wParam, lParam );
- }
+ rc = ::DefWindowProc(hWnd, message, wParam, lParam);
return rc;
}
break;
#endif // __WIN32__
-#ifdef __WXUNIVERSAL__
+ // unfortunately this doesn't really work as then window which
+ // doesn't accept focus doesn't get any mouse events neither which
+ // means it can't get any input at all
+#if 0 //def __WXUNIVERSAL__
case WM_NCHITTEST:
// we shouldn't allow the windows which don't want to get focus to
// get it
return rc.result;
}
-// Dialog window proc
-LONG APIENTRY _EXPORT
-wxDlgProc(HWND WXUNUSED(hWnd), UINT message, WPARAM WXUNUSED(wParam), LPARAM WXUNUSED(lParam))
-{
- if ( message == WM_INITDIALOG )
- {
- // for this message, returning TRUE tells system to set focus to the
- // first control in the dialog box
- return TRUE;
- }
- else
- {
- // for all the other ones, FALSE means that we didn't process the
- // message
- return 0;
- }
-}
+// ----------------------------------------------------------------------------
+// wxWindow <-> HWND map
+// ----------------------------------------------------------------------------
wxList *wxWinHandleList = NULL;
+
wxWindow *wxFindWinFromHandle(WXHWND hWnd)
{
wxNode *node = wxWinHandleList->Find((long)hWnd);
return (wxWindow *)node->Data();
}
-#if 0 // def __WXDEBUG__
-static int gs_AssociationCount = 0;
-#endif
-
void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win)
{
// adding NULL hWnd is (first) surely a result of an error and
wxCHECK_RET( hWnd != (HWND)NULL,
wxT("attempt to add a NULL hWnd to window list ignored") );
-
wxWindow *oldWin = wxFindWinFromHandle((WXHWND) hWnd);
+#ifdef __WXDEBUG__
if ( oldWin && (oldWin != win) )
{
- wxString str(win->GetClassInfo()->GetClassName());
- wxLogError(wxT("Bug! Found existing HWND %X for new window of class %s"), (int) hWnd, (const wxChar*) str);
+ wxLogDebug(wxT("HWND %X already associated with another window (%s)"),
+ hWnd, win->GetClassInfo()->GetClassName());
}
- else if (!oldWin)
+ else
+#endif // __WXDEBUG__
+ if (!oldWin)
{
-#if 0 // def __WXDEBUG__
- gs_AssociationCount ++;
- wxLogDebug("+ Association %d", gs_AssociationCount);
-#endif
-
wxWinHandleList->Append((long)hWnd, win);
}
}
void wxRemoveHandleAssociation(wxWindowMSW *win)
{
-#if 0 // def __WXDEBUG__
- if (wxWinHandleList->Member(win))
- {
- wxLogDebug("- Association %d", gs_AssociationCount);
- gs_AssociationCount --;
- }
-#endif
wxWinHandleList->DeleteObject(win);
}
+// ----------------------------------------------------------------------------
+// various MSW speciic class dependent functions
+// ----------------------------------------------------------------------------
+
// Default destroyer - override if you destroy it in some other way
// (e.g. with MDI child windows)
void wxWindowMSW::MSWDestroyWindow()
}
}
}
-#endif
+#endif // __WXUNIVERSAL__
}
-bool wxWindowMSW::MSWCreate(int id,
- wxWindow *parent,
- const wxChar *wclass,
- wxWindow * WXUNUSED(wx_win),
- const wxChar *title,
- int x,
- int y,
- int width,
- int height,
- WXDWORD style,
- const wxChar *dialog_template,
- WXDWORD extendedStyle)
+bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint& pos,
+ const wxSize& size,
+ int& x, int& y,
+ int& w, int& h) const
{
- int x1 = CW_USEDEFAULT;
- int y1 = 0;
- int width1 = CW_USEDEFAULT;
- int height1 = 100;
+ bool nonDefault = FALSE;
- // Find parent's size, if it exists, to set up a possible default
- // panel size the size of the parent window
- RECT rectParent;
- if ( parent )
+ if ( pos.x == -1 )
{
- ::GetClientRect(GetHwndOf(parent), &rectParent);
-
- width1 = rectParent.right - rectParent.left;
- height1 = rectParent.bottom - rectParent.top;
- }
-
- if ( x != -1 )
- x1 = x;
- if ( y != -1 )
- y1 = y;
- if ( width != -1 )
- width1 = width;
- if ( height != -1 )
- height1 = height;
-
- // unfortunately, setting WS_EX_CONTROLPARENT only for some windows in the
- // hierarchy with several embedded panels (and not all of them) causes the
- // program to hang during the next call to IsDialogMessage() due to the bug
- // in this function (at least in Windows NT 4.0, it seems to work ok in
- // Win2K)
-#if 0
- // if we have wxTAB_TRAVERSAL style, we want WS_EX_CONTROLPARENT or
- // IsDialogMessage() won't work for us
- if ( GetWindowStyleFlag() & wxTAB_TRAVERSAL )
+ // if set x to CW_USEDEFAULT, y parameter is ignored anyhow so we can
+ // just as well set it to CW_USEDEFAULT as well
+ x =
+ y = CW_USEDEFAULT;
+ }
+ else
{
- extendedStyle |= WS_EX_CONTROLPARENT;
+ x = pos.x;
+ y = pos.y == -1 ? CW_USEDEFAULT : 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
+ 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
+ from some base class ctor and so this WM_SIZE is not processed in the
+ real class' OnSize() (because it's not fully constructed yet and the
+ 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
+ this and ignore any attempts to change the window size to the size it
+ already has - so no WM_SIZE would be sent.
+ */
+ if ( size.x == -1 )
+ {
+ // as abobe, h is not used at all in this case anyhow
+ w =
+ h = CW_USEDEFAULT;
}
-#endif // 0
+ else
+ {
+ w = size.x;
+ h = size.y == -1 ? CW_USEDEFAULT : size.y;
+
+ nonDefault = TRUE;
+ }
+
+ return nonDefault;
+}
+
+bool wxWindowMSW::MSWCreate(const wxChar *wclass,
+ const wxChar *title,
+ const wxPoint& pos,
+ const wxSize& size,
+ WXDWORD style,
+ WXDWORD extendedStyle)
+{
+ // choose the position/size for the new window
+ 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 ( GetWindowStyleFlag() & wxPOPUP_WINDOW )
{
// be limited to the parents client area as child windows usually are
hParent = ::GetDesktopWindow();
}
- else if ( parent )
- {
- hParent = GetHwndOf(parent);
- }
- else
+ else // !popup
{
- // top level window
- hParent = NULL;
- }
-
- wxWndHook = this;
-
-#ifndef __WXMICROWIN__
- if ( dialog_template )
- {
- // for the dialogs without wxDIALOG_NO_PARENT style, use the top level
- // app window as parent - this avoids creating modal dialogs without
- // parent
- if ( !hParent && !(GetWindowStyleFlag() & wxDIALOG_NO_PARENT) )
- {
- wxWindow *winTop = wxTheApp->GetTopWindow();
- if ( winTop )
- hParent = GetHwndOf(winTop);
- }
-
- m_hWnd = (WXHWND)::CreateDialog(wxGetInstance(),
- dialog_template,
- hParent,
- (DLGPROC)wxDlgProc);
-
- if ( m_hWnd == 0 )
+ if ( (isChild || HasFlag(wxFRAME_TOOL_WINDOW)) && parent )
{
- wxLogError(_("Can't find dialog template '%s'!\nCheck resource include path for finding wx.rc."),
- dialog_template);
-
- return FALSE;
+ // this is either a normal child window or a top level window with
+ // wxFRAME_TOOL_WINDOW style (see below)
+ hParent = GetHwndOf(parent);
}
-
- if ( extendedStyle != 0 )
+ else
{
- ::SetWindowLong(GetHwnd(), GWL_EXSTYLE, extendedStyle);
- ::SetWindowPos(GetHwnd(), NULL, 0, 0, 0, 0,
- SWP_NOSIZE |
- SWP_NOMOVE |
- SWP_NOZORDER |
- SWP_NOACTIVATE);
+ // this is either a window for which no parent was specified (not
+ // much we can do then) or 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;
}
-#if defined(__WIN95__)
- // For some reason, the system menu is activated when we use the
- // WS_EX_CONTEXTHELP style, so let's set a reasonable icon
- if (extendedStyle & WS_EX_CONTEXTHELP)
- {
- wxFrame *winTop = wxDynamicCast(wxTheApp->GetTopWindow(), wxFrame);
- if ( winTop )
- {
- wxIcon icon = winTop->GetIcon();
- if ( icon.Ok() )
- {
- ::SendMessage(GetHwnd(), WM_SETICON,
- (WPARAM)TRUE,
- (LPARAM)GetHiconOf(icon));
- }
- }
- }
-#endif // __WIN95__
-
-
- // JACS: is the following still necessary? The above seems to work.
+ }
- // ::SetWindowLong(GWL_EXSTYLE) doesn't work for the dialogs, so try
- // to take care of (at least some) extended style flags ourselves
- if ( extendedStyle & WS_EX_TOPMOST )
- {
- if ( !::SetWindowPos(GetHwnd(), HWND_TOPMOST, 0, 0, 0, 0,
- SWP_NOSIZE | SWP_NOMOVE) )
- {
- wxLogLastError(wxT("SetWindowPos"));
- }
- }
+ // 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();
- // move the dialog to its initial position without forcing repainting
- if ( !::MoveWindow(GetHwnd(), x1, y1, width1, height1, FALSE) )
+ if ( GetWindowStyleFlag() & wxCLIP_SIBLINGS )
{
- wxLogLastError(wxT("MoveWindow"));
+ style |= WS_CLIPSIBLINGS;
}
-
}
- else // creating a normal window, not a dialog
-#endif // !__WXMICROWIN__
+ else // !child
{
- int controlId = 0;
- if ( style & WS_CHILD )
- {
- controlId = id;
-
- if ( GetWindowStyleFlag() & wxCLIP_SIBLINGS )
- {
- style |= WS_CLIPSIBLINGS;
- }
- }
-
- wxString className(wclass);
- if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE )
- {
- className += wxT("NR");
- }
-
- m_hWnd = (WXHWND)CreateWindowEx(extendedStyle,
- className,
- title ? title : wxT(""),
- style,
- x1, y1,
- width1, height1,
- hParent, (HMENU)controlId,
- wxGetInstance(),
- NULL);
-
- if ( !m_hWnd )
- {
- wxLogError(_("Can't create window of class %s!\nPossible Windows 3.x compatibility problem?"),
- wclass);
+ controlId = 0;
+ }
- return FALSE;
- }
+ // 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
+ // ensures that the window is not fully repainted on each resize
+ wxString className(wclass);
+ if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE )
+ {
+ className += wxT("NR");
}
- wxWndHook = NULL;
+ // do create the window
+ wxWindowCreationHook hook(this);
-#ifdef __WXDEBUG__
- wxNode* node = wxWinHandleList->Member(this);
- if (node)
+ m_hWnd = (WXHWND)::CreateWindowEx
+ (
+ extendedStyle,
+ className,
+ title ? title : wxT(""),
+ style,
+ x, y, w, h,
+ hParent,
+ (HMENU)controlId,
+ wxGetInstance(),
+ NULL // no extra data
+ );
+
+ if ( !m_hWnd )
{
- HWND hWnd = (HWND) node->GetKeyInteger();
- if (hWnd != (HWND) m_hWnd)
- {
- wxLogError(wxT("A second HWND association is being added for the same window!"));
- }
+ wxLogSysError(_("Can't create window of class %s"), wclass);
+
+ return FALSE;
}
-#endif // Debug
- wxAssociateWinWithHandle((HWND) m_hWnd, this);
+ SubclassWin(m_hWnd);
SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT));
// create the key event of the given type for the given key - used by
// HandleChar and HandleKeyDown/Up
wxKeyEvent wxWindowMSW::CreateKeyEvent(wxEventType evType,
- int id,
- WXLPARAM lParam) const
+ int id,
+ WXLPARAM lParam) const
{
wxKeyEvent event(evType);
event.SetId(GetId());