X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/c50f1fb9226d9260454ccb9c8a67d0be23c2827f..3995f8eb97f3fa807fb7d805bb8b86425f490b06:/src/msw/window.cpp diff --git a/src/msw/window.cpp b/src/msw/window.cpp index dd54ee8e9b..411e011c1a 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -31,6 +31,7 @@ #ifndef WX_PRECOMP #include #include "wx/msw/winundef.h" + #include "wx/window.h" #include "wx/accel.h" #include "wx/setup.h" #include "wx/menu.h" @@ -79,7 +80,7 @@ #include -#ifndef __GNUWIN32__ +#if !defined(__GNUWIN32__)|| defined(wxUSE_NORLANDER_HEADERS) #include #include #endif @@ -88,13 +89,15 @@ #include #endif -#if ( defined(__WIN95__) && !defined(__GNUWIN32__)) || defined(__TWIN32__ ) +#if ( defined(__WIN95__) && !defined(__GNUWIN32__)) || defined(__TWIN32__ ) || defined(wxUSE_NORLANDER_HEADERS) #include #endif #ifndef __TWIN32__ #ifdef __GNUWIN32__ - #include + #ifndef wxUSE_NORLANDER_HEADERS + #include + #endif #endif #endif @@ -159,7 +162,7 @@ END_EVENT_TABLE() // --------------------------------------------------------------------------- // Find an item given the MS Windows id -wxWindow *wxWindow::FindItem(int id) const +wxWindow *wxWindow::FindItem(long id) const { wxWindowList::Node *current = GetChildren().GetFirst(); while (current) @@ -294,9 +297,10 @@ bool wxWindow::Create(wxWindow *parent, wxWindowID id, long style, const wxString& name) { - wxCHECK_MSG( parent, FALSE, _T("can't create wxWindow without parent") ); + wxCHECK_MSG( parent, FALSE, wxT("can't create wxWindow without parent") ); - CreateBase(parent, id, pos, size, style, name); + if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) ) + return FALSE; parent->AddChild(this); @@ -444,7 +448,7 @@ bool wxWindow::SetFont(const wxFont& font) { WXHANDLE hFont = m_font.GetResourceHandle(); - wxASSERT_MSG( hFont, _T("should have valid font") ); + wxASSERT_MSG( hFont, wxT("should have valid font") ); ::SendMessage(hWnd, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0)); } @@ -460,7 +464,7 @@ bool wxWindow::SetCursor(const wxCursor& cursor) } wxASSERT_MSG( m_cursor.Ok(), - _T("cursor must be valid after call to the base version")); + wxT("cursor must be valid after call to the base version")); HWND hWnd = GetHwnd(); @@ -797,10 +801,10 @@ void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect) void wxWindow::SubclassWin(WXHWND hWnd) { - wxASSERT_MSG( !m_oldWndProc, _T("subclassing window twice?") ); + wxASSERT_MSG( !m_oldWndProc, wxT("subclassing window twice?") ); HWND hwnd = (HWND)hWnd; - wxCHECK_RET( ::IsWindow(hwnd), _T("invalid HWND in SubclassWin") ); + wxCHECK_RET( ::IsWindow(hwnd), wxT("invalid HWND in SubclassWin") ); wxAssociateWinWithHandle(hwnd, this); @@ -818,7 +822,7 @@ void wxWindow::UnsubclassWin() { m_hWnd = 0; - wxCHECK_RET( ::IsWindow(hwnd), _T("invalid HWND in SubclassWin") ); + wxCHECK_RET( ::IsWindow(hwnd), wxT("invalid HWND in UnsubclassWin") ); FARPROC farProc = (FARPROC) GetWindowLong(hwnd, GWL_WNDPROC); if ( (m_oldWndProc != 0) && (farProc != (FARPROC) m_oldWndProc) ) @@ -855,7 +859,8 @@ WXDWORD wxWindow::MakeExtendedStyle(long style, bool eliminateBorders) // Determines whether native 3D effects or CTL3D should be used, // applying a default border style if required, and returning an extended // style to pass to CreateWindowEx. -WXDWORD wxWindow::Determine3DEffects(WXDWORD defaultBorderStyle, bool *want3D) +WXDWORD wxWindow::Determine3DEffects(WXDWORD defaultBorderStyle, + bool *want3D) const { // If matches certain criteria, then assume no 3D effects // unless specifically requested (dealt with in MakeExtendedStyle) @@ -1112,12 +1117,9 @@ void wxWindow::DoGetPosition(int *x, int *y) const // We may be faking the client origin. So a window that's really at (0, // 30) may appear (to wxWin apps) to be at (0, 0). - if ( parent ) - { - wxPoint pt(parent->GetClientAreaOrigin()); - point.x -= pt.x; - point.y -= pt.y; - } + wxPoint pt(parent->GetClientAreaOrigin()); + point.x -= pt.x; + point.y -= pt.y; } if ( x ) @@ -1172,35 +1174,85 @@ void wxWindow::DoGetClientSize(int *x, int *y) const *y = rect.bottom; } +void wxWindow::DoMoveWindow(int x, int y, int width, int height) +{ + if ( !::MoveWindow(GetHwnd(), x, y, width, height, TRUE) ) + { + wxLogLastError("MoveWindow"); + } +} + +// set the size of the window: if the dimensions are positive, just use them, +// but if any of them is equal to -1, it means that we must find the value for +// it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in +// which case -1 is a valid value for x and y) +// +// If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate +// the width/height to best suit our contents, otherwise we reuse the current +// width/height void wxWindow::DoSetSize(int x, int y, int width, int height, int sizeFlags) { + // get the current size and position... int currentX, currentY; GetPosition(¤tX, ¤tY); int currentW,currentH; GetSize(¤tW, ¤tH); - if ( x == currentX && y == currentY && width == currentW && height == currentH ) + // ... and don't do anything (avoiding flicker) if it's already ok + if ( x == currentX && y == currentY && + width == currentW && height == currentH ) + { return; + } - int actualWidth = width; - int actualHeight = height; - int actualX = x; - int actualY = y; if ( x == -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE) ) - actualX = currentX; + x = currentX; if ( y == -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE) ) - actualY = currentY; + y = currentY; - AdjustForParentClientOrigin(actualX, actualY, sizeFlags); + AdjustForParentClientOrigin(x, y, sizeFlags); + wxSize size(-1, -1); if ( width == -1 ) - actualWidth = currentW; + { + if ( sizeFlags && wxSIZE_AUTO_WIDTH ) + { + size = DoGetBestSize(); + width = size.x; + } + else + { + // just take the current one + width = currentW; + } + } + if ( height == -1 ) - actualHeight = currentH; + { + if ( sizeFlags && wxSIZE_AUTO_HEIGHT ) + { + if ( size.x == -1 ) + { + size = DoGetBestSize(); + } + //else: already called DoGetBestSize() above - HWND hWnd = GetHwnd(); - if ( hWnd ) - MoveWindow(hWnd, actualX, actualY, actualWidth, actualHeight, (BOOL)TRUE); + height = size.y; + } + else + { + // just take the current one + height = currentH; + } + } + + DoMoveWindow(x, y, width, height); +} + +// for a generic window there is no natural best size - just use the current one +wxSize wxWindow::DoGetBestSize() +{ + return GetSize(); } void wxWindow::DoSetClientSize(int width, int height) @@ -1234,7 +1286,7 @@ void wxWindow::DoSetClientSize(int width, int height) ::ScreenToClient(hParentWnd, &point); } - MoveWindow(hWnd, point.x, point.y, actual_width, actual_height, (BOOL)TRUE); + DoMoveWindow(point.x, point.y, actual_width, actual_height); wxSizeEvent event(wxSize(width, height), m_windowId); event.SetEventObject(this); @@ -1316,7 +1368,7 @@ void wxWindow::GetTextExtent(const wxString& string, SIZE sizeRect; TEXTMETRIC tm; - GetTextExtentPoint(dc, (const wxChar *)string, (int)string.Length(), &sizeRect); + GetTextExtentPoint(dc, string, (int)string.Length(), &sizeRect); GetTextMetrics(dc, &tm); if ( fontToUse && fnt && hfontOld ) @@ -1324,10 +1376,14 @@ void wxWindow::GetTextExtent(const wxString& string, ReleaseDC(hWnd, dc); - if ( x ) *x = sizeRect.cx; - if ( y ) *y = sizeRect.cy; - if ( descent ) *descent = tm.tmDescent; - if ( externalLeading ) *externalLeading = tm.tmExternalLeading; + if ( x ) + *x = sizeRect.cx; + if ( y ) + *y = sizeRect.cy; + if ( descent ) + *descent = tm.tmDescent; + if ( externalLeading ) + *externalLeading = tm.tmExternalLeading; } #if wxUSE_CARET && WXWIN_COMPATIBILITY @@ -1376,7 +1432,7 @@ void wxWindow::GetCaretPos(int *x, int *y) const // popup menu // --------------------------------------------------------------------------- -bool wxWindow::PopupMenu(wxMenu *menu, int x, int y) +bool wxWindow::DoPopupMenu(wxMenu *menu, int x, int y) { menu->SetInvokingWindow(this); menu->UpdateUI(); @@ -1494,7 +1550,7 @@ bool wxWindow::MSWProcessMessage(WXMSG* pMsg) btn = panel->GetDefaultItem(); } - if ( btn ) + if ( btn && btn->IsEnabled() ) { // if we do have a default button, do press it btn->MSWCommand(BN_CLICKED, 0 /* unused */); @@ -1658,7 +1714,7 @@ LRESULT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARA { // trace all messages - useful for the debugging #ifdef __WXDEBUG__ - wxLogTrace(wxTraceMessages, _T("Processing %s(wParam=%8lx, lParam=%8lx)"), + wxLogTrace(wxTraceMessages, wxT("Processing %s(wParam=%8lx, lParam=%8lx)"), wxGetMessageName(message), wParam, lParam); #endif // __WXDEBUG__ @@ -1668,6 +1724,12 @@ LRESULT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARA // it with wxWindow stored in wxWndHook if ( !wnd && wxWndHook ) { +#if 0 // def __WXDEBUG__ + char buf[512]; + ::GetClassNameA((HWND) hWnd, buf, 512); + wxString className(buf); +#endif + wxAssociateWinWithHandle(hWnd, wxWndHook); wnd = wxWndHook; wxWndHook = NULL; @@ -1782,8 +1844,8 @@ long wxWindow::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam) case WM_MBUTTONUP: case WM_MBUTTONDBLCLK: { - int x = LOWORD(lParam); - int y = HIWORD(lParam); + short x = LOWORD(lParam); + short y = HIWORD(lParam); processed = HandleMouseEvent(message, x, y, wParam); } @@ -2037,7 +2099,7 @@ long wxWindow::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam) if ( !processed ) { #ifdef __WXDEBUG__ - wxLogTrace(wxTraceMessages, _T("Forwarding %s to DefWindowProc."), + wxLogTrace(wxTraceMessages, wxT("Forwarding %s to DefWindowProc."), wxGetMessageName(message)); #endif // __WXDEBUG__ rc.result = MSWDefWindowProc(message, wParam, lParam); @@ -2073,19 +2135,44 @@ wxWindow *wxFindWinFromHandle(WXHWND hWnd) return (wxWindow *)node->Data(); } +#if 0 // def __WXDEBUG__ +static int gs_AssociationCount = 0; +#endif + void wxAssociateWinWithHandle(HWND hWnd, wxWindow *win) { // adding NULL hWnd is (first) surely a result of an error and // (secondly) breaks menu command processing wxCHECK_RET( hWnd != (HWND)NULL, - _T("attempt to add a NULL hWnd to window list ignored") ); + wxT("attempt to add a NULL hWnd to window list ignored") ); + + + wxWindow *oldWin = wxFindWinFromHandle((WXHWND) hWnd); + if ( oldWin && (oldWin != win) ) + { + wxString str(win->GetClassInfo()->GetClassName()); + wxLogError("Bug! Found existing HWND %X for new window of class %s", (int) hWnd, (const char*) str); + } + else if (!oldWin) + { +#if 0 // def __WXDEBUG__ + gs_AssociationCount ++; + wxLogDebug("+ Association %d", gs_AssociationCount); +#endif - if ( !wxWinHandleList->Find((long)hWnd) ) wxWinHandleList->Append((long)hWnd, win); + } } void wxRemoveHandleAssociation(wxWindow *win) { +#if 0 // def __WXDEBUG__ + if (wxWinHandleList->Member(win)) + { + wxLogDebug("- Association %d", gs_AssociationCount); + gs_AssociationCount --; + } +#endif wxWinHandleList->DeleteObject(win); } @@ -2109,12 +2196,12 @@ void wxWindow::MSWDetachWindowMenu() int chars = GetMenuString(hMenu, i, buf, 100, MF_BYPOSITION); if ( !chars ) { - wxLogLastError(_T("GetMenuString")); + wxLogLastError(wxT("GetMenuString")); continue; } - if ( wxStrcmp(buf, _T("&Window")) == 0 ) + if ( wxStrcmp(buf, wxT("&Window")) == 0 ) { RemoveMenu(hMenu, i, MF_BYPOSITION); @@ -2158,11 +2245,7 @@ bool wxWindow::MSWCreate(int id, if ( width > -1 ) width1 = width; if ( height > -1 ) height1 = height; -#ifdef __WXWINE__ HWND hParent = (HWND)NULL; -#else - HWND hParent = NULL; -#endif if ( parent ) hParent = (HWND) parent->GetHWND(); @@ -2190,14 +2273,14 @@ bool wxWindow::MSWCreate(int id, if ( !::SetWindowPos(GetHwnd(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE) ) { - wxLogLastError(_T("SetWindowPos")); + wxLogLastError(wxT("SetWindowPos")); } } // move the dialog to its initial position without forcing repainting if ( !::MoveWindow(GetHwnd(), x1, y1, width1, height1, FALSE) ) { - wxLogLastError(_T("MoveWindow")); + wxLogLastError(wxT("MoveWindow")); } } else @@ -2206,9 +2289,15 @@ bool wxWindow::MSWCreate(int id, if ( style & WS_CHILD ) controlId = id; + wxString className(wclass); + if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE ) + { + className += wxT("NR"); + } + m_hWnd = (WXHWND)CreateWindowEx(extendedStyle, - wclass, - title ? title : _T(""), + className, + title ? title : wxT(""), style, x1, y1, width1, height1, @@ -2227,7 +2316,18 @@ bool wxWindow::MSWCreate(int id, } wxWndHook = NULL; - wxWinHandleList->Append((long)m_hWnd, this); +#ifdef __WXDEBUG__ + wxNode* node = wxWinHandleList->Member(this); + if (node) + { + HWND hWnd = (HWND) node->GetKeyInteger(); + if (hWnd != (HWND) m_hWnd) + { + wxLogError("A second HWND association is being added for the same window!"); + } + } +#endif + wxAssociateWinWithHandle((HWND) m_hWnd, this); return TRUE; } @@ -3172,7 +3272,7 @@ bool wxWindow::HandleJoystickEvent(WXUINT msg, int x, int y, WXUINT flags) break; default: - wxFAIL_MSG(_T("no such joystick event")); + wxFAIL_MSG(wxT("no such joystick event")); return FALSE; } @@ -3265,8 +3365,11 @@ void wxGetCharSize(WXHWND wnd, int *x, int *y,wxFont *the_font) SelectObject(dc,was); } ReleaseDC((HWND)wnd, dc); - *x = tm.tmAveCharWidth; - *y = tm.tmHeight + tm.tmExternalLeading; + + if ( x ) + *x = tm.tmAveCharWidth; + if ( y ) + *y = tm.tmHeight + tm.tmExternalLeading; // if ( the_font ) // the_font->ReleaseResource(); @@ -3453,11 +3556,12 @@ void wxSetKeyboardHook(bool doIt) { wxTheKeyboardHookProc = MakeProcInstance((FARPROC) wxKeyboardHook, wxGetInstance()); wxTheKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC) wxTheKeyboardHookProc, wxGetInstance(), + #if defined(__WIN32__) && !defined(__TWIN32__) GetCurrentThreadId()); // (DWORD)GetCurrentProcess()); // This is another possibility. Which is right? #else - GetCurrentTask()); + GetCurrentTask()); #endif } else