int wxRadioBox::GetItemFromPoint(const wxPoint& pt) const { const unsigned int count = GetCount(); #if defined(__INTEL_COMPILER) && 1 /* VDM auto patch */ # pragma ivdep # pragma swp # pragma unroll # pragma prefetch # if 0 # pragma simd noassert # endif #endif /* VDM auto patch */ for ( unsigned int i = 0; i < count; i++ ) { RECT rect = wxGetWindowRect((*m_radioButtons)[i]); if ( rect.left <= pt.x && pt.x < rect.right && rect.top <= pt.y && pt.y < rect.bottom ) { return i; } } return wxNOT_FOUND; }
UINT_PTR APIENTRY wxFileDialogHookFunction(HWND hDlg, UINT iMsg, WPARAM WXUNUSED(wParam), LPARAM lParam) { switch ( iMsg ) { #ifndef __WXWINCE__ case WM_INITDIALOG: { OPENFILENAME* ofn = reinterpret_cast<OPENFILENAME *>(lParam); reinterpret_cast<wxFileDialog *>(ofn->lCustData) ->MSWOnInitDialogHook((WXHWND)hDlg); } break; #endif // __WXWINCE__ case WM_NOTIFY: { NMHDR* const pNM = reinterpret_cast<NMHDR*>(lParam); if ( pNM->code > CDN_LAST && pNM->code <= CDN_FIRST ) { OFNOTIFY* const pNotifyCode = reinterpret_cast<OFNOTIFY *>(lParam); wxFileDialog* const dialog = reinterpret_cast<wxFileDialog *>( pNotifyCode->lpOFN->lCustData ); switch ( pNotifyCode->hdr.code ) { case CDN_INITDONE: dialog->MSWOnInitDone((WXHWND)hDlg); break; case CDN_SELCHANGE: dialog->MSWOnSelChange((WXHWND)hDlg); break; } } } break; case WM_DESTROY: // reuse the position used for the dialog the next time by default // // NB: at least under Windows 2003 this is useless as after the // first time it's shown the dialog always remembers its size // and position itself and ignores any later SetWindowPos calls wxCopyRECTToRect(wxGetWindowRect(::GetParent(hDlg)), gs_rectDialog); break; } // do the default processing return 0; }
// generate an artificial resize event void wxFrame::SendSizeEvent() { if ( !m_iconized ) { RECT r = wxGetWindowRect(GetHwnd()); (void)::PostMessage(GetHwnd(), WM_SIZE, IsMaximized() ? SIZE_MAXIMIZED : SIZE_RESTORED, MAKELPARAM(r.right - r.left, r.bottom - r.top)); } }
void wxDialog::ResizeGripper() { wxASSERT_MSG( m_hGripper, wxT("shouldn't be called if we have no gripper") ); HWND hwndGripper = (HWND)m_hGripper; const wxRect rectGripper = wxRectFromRECT(wxGetWindowRect(hwndGripper)); const wxSize size = GetClientSize() - rectGripper.GetSize(); ::SetWindowPos(hwndGripper, HWND_BOTTOM, size.x, size.y, rectGripper.width, rectGripper.height, SWP_NOACTIVATE); }
int wxRadioBox::GetItemFromPoint(const wxPoint& pt) const { const unsigned int count = GetCount(); for ( unsigned int i = 0; i < count; i++ ) { RECT rect = wxGetWindowRect((*m_radioButtons)[i]); if ( rect.left <= pt.x && pt.x < rect.right && rect.top <= pt.y && pt.y < rect.bottom ) { return i; } } return wxNOT_FOUND; }
bool wxNativeWindow::Create(wxWindow* parent, wxWindowID winid, wxNativeWindowHandle hwnd) { wxCHECK_MSG( hwnd, false, wxS("Invalid null HWND") ); wxCHECK_MSG( parent, false, wxS("Must have a valid parent") ); wxASSERT_MSG( ::GetParent(hwnd) == GetHwndOf(parent), wxS("The native window has incorrect parent") ); const wxRect r = wxRectFromRECT(wxGetWindowRect(hwnd)); // Skip wxWindow::Create() which would try to create a new HWND, we don't // want this as we already have one. if ( !CreateBase(parent, winid, r.GetPosition(), r.GetSize(), 0, wxDefaultValidator, wxS("nativewindow")) ) return false; parent->AddChild(this); SubclassWin(hwnd); if ( winid == wxID_ANY ) { // We allocated a new ID to the control, use it at Windows level as // well because we assume that our and MSW IDs are the same in many // places and it seems prudent to avoid breaking this assumption. SetId(GetId()); } else // We used a fixed ID. { // For the same reason as above, check that it's the same as the one // used by the native HWND. wxASSERT_MSG( ::GetWindowLong(hwnd, GWL_ID) == winid, wxS("Mismatch between wx and native IDs") ); } InheritAttributes(); return true; }
// generate an artificial resize event void wxFrame::SendSizeEvent(int flags) { if ( !m_iconized ) { RECT r = wxGetWindowRect(GetHwnd()); if ( flags & wxSEND_EVENT_POST ) { ::PostMessage(GetHwnd(), WM_SIZE, IsMaximized() ? SIZE_MAXIMIZED : SIZE_RESTORED, MAKELPARAM(r.right - r.left, r.bottom - r.top)); } else // send it { ::SendMessage(GetHwnd(), WM_SIZE, IsMaximized() ? SIZE_MAXIMIZED : SIZE_RESTORED, MAKELPARAM(r.right - r.left, r.bottom - r.top)); } } }
bool wxSpinCtrl::Reparent(wxWindowBase *newParent) { // Reparenting both the updown control and its buddy does not seem to work: // they continue to be connected somehow, but visually there is no feedback // on the buddy edit control. To avoid this problem, we reparent the buddy // window normally, but we recreate the updown control and reassign its // buddy. if ( !wxWindowBase::Reparent(newParent) ) return false; newParent->GetChildren().DeleteObject(this); // preserve the old values const wxSize size = GetSize(); int value = GetValue(); const wxRect btnRect = wxRectFromRECT(wxGetWindowRect(GetHwnd())); // destroy the old spin button UnsubclassWin(); if ( !::DestroyWindow(GetHwnd()) ) { wxLogLastError(wxT("DestroyWindow")); } // create and initialize the new one if ( !wxSpinButton::Create(GetParent(), GetId(), btnRect.GetPosition(), btnRect.GetSize(), GetWindowStyle(), GetName()) ) return false; SetValue(value); SetRange(m_min, m_max); SetInitialSize(size); // associate it with the buddy control again ::SetParent(GetBuddyHwnd(), GetHwndOf(GetParent())); (void)::SendMessage(GetHwnd(), UDM_SETBUDDY, (WPARAM)GetBuddyHwnd(), 0); return true; }
UINT_PTR APIENTRY wxFileDialogHookFunction(HWND hDlg, UINT iMsg, WPARAM WXUNUSED(wParam), LPARAM lParam) { switch ( iMsg ) { case WM_NOTIFY: { OFNOTIFY *pNotifyCode = wx_reinterpret_cast(OFNOTIFY *, lParam); if ( pNotifyCode->hdr.code == CDN_INITDONE ) { // note that we need to move the parent window: hDlg is a // child of it when OFN_EXPLORER is used ::SetWindowPos ( ::GetParent(hDlg), HWND_TOP, gs_rectDialog.x, gs_rectDialog.y, 0, 0, SWP_NOZORDER | SWP_NOSIZE ); } } break; case WM_DESTROY: // reuse the position used for the dialog the next time by default // // NB: at least under Windows 2003 this is useless as after the // first time it's shown the dialog always remembers its size // and position itself and ignores any later SetWindowPos calls wxCopyRECTToRect(wxGetWindowRect(::GetParent(hDlg)), gs_rectDialog); break; } // do the default processing return 0; }
bool wxTopLevelWindowMSW::ShowFullScreen(bool show, long style) { if ( show == IsFullScreen() ) { // nothing to do return true; } m_fsIsShowing = show; if ( show ) { m_fsStyle = style; // zap the frame borders // save the 'normal' window style m_fsOldWindowStyle = GetWindowLong(GetHwnd(), GWL_STYLE); // save the old position, width & height, maximize state m_fsOldSize = GetRect(); m_fsIsMaximized = IsMaximized(); // decide which window style flags to turn off LONG newStyle = m_fsOldWindowStyle; LONG offFlags = 0; if (style & wxFULLSCREEN_NOBORDER) { offFlags |= WS_BORDER; #ifndef __WXWINCE__ offFlags |= WS_THICKFRAME; #endif } if (style & wxFULLSCREEN_NOCAPTION) offFlags |= WS_CAPTION | WS_SYSMENU; newStyle &= ~offFlags; // Full screen windows should logically be popups as they don't have // decorations (and are definitely not children) and while not using // this style doesn't seem to make any difference for most windows, it // breaks wxGLCanvas in some cases, see #15434, so just always use it. newStyle |= WS_POPUP; // change our window style to be compatible with full-screen mode ::SetWindowLong(GetHwnd(), GWL_STYLE, newStyle); wxRect rect; #if wxUSE_DISPLAY // resize to the size of the display containing us int dpy = wxDisplay::GetFromWindow(this); if ( dpy != wxNOT_FOUND ) { rect = wxDisplay(dpy).GetGeometry(); } else // fall back to the main desktop #endif // wxUSE_DISPLAY { // resize to the size of the desktop wxCopyRECTToRect(wxGetWindowRect(::GetDesktopWindow()), rect); #ifdef __WXWINCE__ // FIXME: size of the bottom menu (toolbar) // should be taken in account rect.height += rect.y; rect.y = 0; #endif } SetSize(rect); // now flush the window style cache and actually go full-screen long flags = SWP_FRAMECHANGED; // showing the frame full screen should also show it if it's still // hidden if ( !IsShown() ) { // don't call wxWindow version to avoid flicker from calling // ::ShowWindow() -- we're going to show the window at the correct // location directly below -- but do call the wxWindowBase version // to sync the internal m_isShown flag wxWindowBase::Show(); flags |= SWP_SHOWWINDOW; } SetWindowPos(GetHwnd(), HWND_TOP, rect.x, rect.y, rect.width, rect.height, flags); #if !defined(__HANDHELDPC__) && (defined(__WXWINCE__) && (_WIN32_WCE < 400)) ::SHFullScreen(GetHwnd(), SHFS_HIDETASKBAR | SHFS_HIDESIPBUTTON); #endif // finally send an event allowing the window to relayout itself &c wxSizeEvent event(rect.GetSize(), GetId()); event.SetEventObject(this); HandleWindowEvent(event); } else // stop showing full screen { #if !defined(__HANDHELDPC__) && (defined(__WXWINCE__) && (_WIN32_WCE < 400)) ::SHFullScreen(GetHwnd(), SHFS_SHOWTASKBAR | SHFS_SHOWSIPBUTTON); #endif Maximize(m_fsIsMaximized); SetWindowLong(GetHwnd(),GWL_STYLE, m_fsOldWindowStyle); SetWindowPos(GetHwnd(),HWND_TOP,m_fsOldSize.x, m_fsOldSize.y, m_fsOldSize.width, m_fsOldSize.height, SWP_FRAMECHANGED); } return true; }
void wxMessageDialog::AdjustButtonLabels() { // changing the button labels is the easy part but we also need to ensure // that the buttons are big enough for the label strings and increase their // size (and maybe the size of the message box itself) if they are not // TODO-RTL: check whether this works correctly in RTL // we want to use this font in GetTextExtent() calls below but we don't // want to send WM_SETFONT to the message box, who knows how is it going to // react to it (right now it doesn't seem to do anything but what if this // changes) wxWindowBase::SetFont(GetMessageFont()); // first iteration: find the widest button and update the buttons labels int wBtnOld = 0, // current buttons width wBtnNew = 0; // required new buttons width RECT rcBtn; // stores the button height and y positions unsigned numButtons = 0; // total number of buttons in the message box unsigned n; for ( n = 0; n < WXSIZEOF(ms_buttons); n++ ) { const HWND hwndBtn = ::GetDlgItem(GetHwnd(), ms_buttons[n].id); if ( !hwndBtn ) continue; // it's ok, not all buttons are always present numButtons++; const wxString label = (this->*ms_buttons[n].getter)(); const wxSize sizeLabel = wxWindowBase::GetTextExtent(label); // check if the button is big enough for this label const RECT rc = wxGetWindowRect(hwndBtn); if ( !wBtnOld ) { // initialize wBtnOld using the first button width, all the other // ones should have the same one wBtnOld = rc.right - rc.left; rcBtn = rc; // remember for use below when we reposition the buttons } else { wxASSERT_MSG( wBtnOld == rc.right - rc.left, "all buttons are supposed to be of same width" ); } const int widthNeeded = wxMSWButton::GetFittingSize(this, sizeLabel).x; if ( widthNeeded > wBtnNew ) wBtnNew = widthNeeded; ::SetWindowText(hwndBtn, label.wx_str()); } if ( wBtnNew <= wBtnOld ) { // all buttons fit, nothing else to do return; } // resize the message box to be wider if needed const int wBoxOld = wxGetClientRect(GetHwnd()).right; const int CHAR_WIDTH = GetCharWidth(); const int MARGIN_OUTER = 2*CHAR_WIDTH; // margin between box and buttons const int MARGIN_INNER = CHAR_WIDTH; // margin between buttons RECT rcBox = wxGetWindowRect(GetHwnd()); const int wAllButtons = numButtons*(wBtnNew + MARGIN_INNER) - MARGIN_INNER; int wBoxNew = 2*MARGIN_OUTER + wAllButtons; if ( wBoxNew > wBoxOld ) { const int dw = wBoxNew - wBoxOld; rcBox.left -= dw/2; rcBox.right += dw - dw/2; SetWindowRect(GetHwnd(), rcBox); // surprisingly, we don't need to resize the static text control, it // seems to adjust itself to the new size, at least under Windows 2003 // (TODO: test if this happens on older Windows versions) } else // the current width is big enough { wBoxNew = wBoxOld; } // finally position all buttons // notice that we have to take into account the difference between window // and client width rcBtn.left = (rcBox.left + rcBox.right - wxGetClientRect(GetHwnd()).right + wBoxNew - wAllButtons) / 2; rcBtn.right = rcBtn.left + wBtnNew; for ( n = 0; n < WXSIZEOF(ms_buttons); n++ ) { const HWND hwndBtn = ::GetDlgItem(GetHwnd(), ms_buttons[n].id); if ( !hwndBtn ) continue; MoveWindowToScreenRect(hwndBtn, rcBtn); rcBtn.left += wBtnNew + MARGIN_INNER; rcBtn.right += wBtnNew + MARGIN_INNER; } }
void wxMessageDialog::ReplaceStaticWithEdit() { // check if the message box fits the display int nDisplay = wxDisplay::GetFromWindow(this); if ( nDisplay == wxNOT_FOUND ) nDisplay = 0; const wxRect rectDisplay = wxDisplay(nDisplay).GetClientArea(); if ( rectDisplay.Contains(GetRect()) ) { // nothing to do return; } // find the static control to replace: normally there are two of them, the // icon and the text itself so search for all of them and ignore the icon // ones HWND hwndStatic = ::FindWindowEx(GetHwnd(), NULL, wxT("STATIC"), NULL); if ( ::GetWindowLong(hwndStatic, GWL_STYLE) & SS_ICON ) hwndStatic = ::FindWindowEx(GetHwnd(), hwndStatic, wxT("STATIC"), NULL); if ( !hwndStatic ) { wxLogDebug("Failed to find the static text control in message box."); return; } // set the right font for GetCharHeight() call below wxWindowBase::SetFont(GetMessageFont()); // put the new edit control at the same place RECT rc = wxGetWindowRect(hwndStatic); ScreenRectToClient(GetHwnd(), rc); // but make it less tall so that the message box fits on the screen: we try // to make the message box take no more than 7/8 of the screen to leave // some space above and below it const int hText = (7*rectDisplay.height)/8 - ( 2*::GetSystemMetrics(SM_CYFIXEDFRAME) + ::GetSystemMetrics(SM_CYCAPTION) + 5*GetCharHeight() // buttons + margins ); const int dh = (rc.bottom - rc.top) - hText; // vertical space we save rc.bottom -= dh; // and it also must be wider as it needs a vertical scrollbar (in order // to preserve the word wrap, otherwise the number of lines would change // and we want the control to look as similar as possible to the original) // // NB: you would have thought that 2*SM_CXEDGE would be enough but it // isn't, somehow, and the text control breaks lines differently from // the static one so fudge by adding some extra space const int dw = ::GetSystemMetrics(SM_CXVSCROLL) + 4*::GetSystemMetrics(SM_CXEDGE); rc.right += dw; // chop of the trailing new line(s) from the message box text, they are // ignored by the static control but result in extra lines and hence extra // scrollbar position in the edit one wxString text(wxGetWindowText(hwndStatic)); for ( wxString::reverse_iterator i = text.rbegin(); i != text.rend(); ++i ) { if ( *i != '\n' ) { // found last non-newline char, remove everything after it and stop text.erase(i.base() + 1, text.end()); break; } } // do create the new control HWND hwndEdit = ::CreateWindow ( wxT("EDIT"), wxTextBuffer::Translate(text).wx_str(), WS_CHILD | WS_VSCROLL | WS_VISIBLE | ES_MULTILINE | ES_READONLY | ES_AUTOVSCROLL, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, GetHwnd(), NULL, wxGetInstance(), NULL ); if ( !hwndEdit ) { wxLogDebug("Creation of replacement edit control failed in message box"); return; } // copy the font from the original control LRESULT hfont = ::SendMessage(hwndStatic, WM_GETFONT, 0, 0); ::SendMessage(hwndEdit, WM_SETFONT, hfont, 0); // and get rid of it ::DestroyWindow(hwndStatic); // shrink and centre the message box vertically and widen it box to account // for the extra scrollbar RECT rcBox = wxGetWindowRect(GetHwnd()); const int hMsgBox = rcBox.bottom - rcBox.top - dh; rcBox.top = (rectDisplay.height - hMsgBox)/2; rcBox.bottom = rcBox.top + hMsgBox + (rectDisplay.height - hMsgBox)%2; rcBox.left -= dw/2; rcBox.right += dw - dw/2; SetWindowRect(GetHwnd(), rcBox); // and adjust all the buttons positions for ( unsigned n = 0; n < WXSIZEOF(ms_buttons); n++ ) { const HWND hwndBtn = ::GetDlgItem(GetHwnd(), ms_buttons[n].id); if ( !hwndBtn ) continue; // it's ok, not all buttons are always present RECT rc = wxGetWindowRect(hwndBtn); rc.top -= dh; rc.bottom -= dh; rc.left += dw/2; rc.right += dw/2; MoveWindowToScreenRect(hwndBtn, rc); } }