/////////////////////////////////////////////////////////////////////////////
-// Name: src/msw/windows.cpp
-// Purpose: wxWindow
+// Name: src/msw/window.cpp
+// Purpose: wxWindowMSW
// Author: Julian Smart
// Modified by: VZ on 13.05.99: no more Default(), MSWOnXXX() reorganisation
// Created: 04/01/98
#include "wx/msw/wrapwin.h"
#include "wx/window.h"
#include "wx/accel.h"
- #include "wx/setup.h"
#include "wx/menu.h"
#include "wx/dc.h"
#include "wx/dcclient.h"
// resizing complicated window hierarchies, but this can in theory result in
// different behaviour than the old code so we keep the possibility to use it
// by setting this to 0 (in the future this should be removed completely)
+#ifdef __WXWINCE__
+#define USE_DEFERRED_SIZING 0
+#else
#define USE_DEFERRED_SIZING 1
+#endif
// set this to 1 to filter out duplicate mouse events, e.g. mouse move events
// when mouse position didnd't change
// last mouse event information we need to filter out the duplicates
#if wxUSE_MOUSEEVENT_HACK
-static struct
+static struct MouseEventInfoDummy
{
// mouse position (in screen coordinates)
wxPoint pos;
get back to the initial (focused) window: as we do have this style,
GetNextDlgTabItem() will leave this window and continue in its parent,
but if the parent doesn't have it, it wouldn't recurse inside it later
- on and so wouldn't have a chance of getting back to this window neither.
+ on and so wouldn't have a chance of getting back to this window either.
*/
while ( parent && !parent->IsTopLevel() )
{
wxControl *item = wxDynamicCastThis(wxControl);
if ( item )
{
- // is it we or one of our "internal" children?
+ // is it us or one of our "internal" children?
if ( item->GetId() == id
#ifndef __WXUNIVERSAL__
|| (item->GetSubcontrols().Index(id) != wxNOT_FOUND)
#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
+ // If we did it the other way around, children wouldn't be able
// find their parent frame (see above).
DestroyChildren();
if ( enable )
{
- // enable the child back unless it had been disabled before us
+ // re-enable the child unless it had been disabled before us
if ( !m_childrenDisabled || !m_childrenDisabled->Find(child) )
child->Enable();
}
return false;
HWND hWnd = GetHwnd();
- int cshow = show ? SW_SHOW : SW_HIDE;
- ::ShowWindow(hWnd, cshow);
- if ( show && IsTopLevel() )
+ // we could be called before the underlying window is created (this is
+ // actually useful to prevent it from being initially shown), e.g.
+ //
+ // wxFoo *foo = new wxFoo;
+ // foo->Hide();
+ // foo->Create(parent, ...);
+ //
+ // should work without errors
+ if ( hWnd )
{
- wxBringWindowToTop(hWnd);
+ ::ShowWindow(hWnd, show ? SW_SHOW : SW_HIDE);
}
return true;
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
-void wxWindowMSW::SetTitle( const wxString& title)
-{
- SetWindowText(GetHwnd(), title.c_str());
-}
-
-wxString wxWindowMSW::GetTitle() const
-{
- return wxGetWindowText(GetHWND());
-}
-
void wxWindowMSW::DoCaptureMouse()
{
HWND hWnd = GetHwnd();
}
}
-void wxWindowMSW::MSWUpdateUIState(int action)
+void wxWindowMSW::MSWUpdateUIState(int action, int state)
{
- // WM_UPDATEUISTATE only appeared in Windows 2000 so it can do us no good
+ // WM_CHANGEUISTATE only appeared in Windows 2000 so it can do us no good
// to use it on older systems -- and could possibly do some harm
static int s_needToUpdate = -1;
if ( s_needToUpdate == -1 )
if ( s_needToUpdate )
{
- // NB: it doesn't seem to matter what we put in wParam, whether we
- // include just one UISF_XXX or both, both are affected, no idea
- // why
- ::SendMessage(GetHwnd(), WM_UPDATEUISTATE,
- MAKEWPARAM(action, UISF_HIDEFOCUS | UISF_HIDEACCEL), 0);
+ // we send WM_CHANGEUISTATE so if nothing needs changing then the system
+ // won't send WM_UPDATEUISTATE
+ ::SendMessage(GetHwnd(), WM_CHANGEUISTATE, MAKEWPARAM(action, state), 0);
}
}
WinStruct<SCROLLINFO> scrollInfo;
scrollInfo.cbSize = sizeof(SCROLLINFO);
scrollInfo.fMask = SIF_POS;
- if ( !::GetScrollInfo(hWnd,
- wOrient,
- &scrollInfo) )
- {
- // Not necessarily an error, if there are no scrollbars yet.
- // wxLogLastError(_T("GetScrollInfo"));
- }
+ ::GetScrollInfo(hWnd, wOrient, &scrollInfo );
+
return scrollInfo.nPos;
-// return ::GetScrollPos(hWnd, wOrient);
+
#endif
}
HWND hWnd = GetHwnd();
if ( hWnd )
{
+ // We have to set the variables here to make them valid in events
+ // triggered by ::SetScrollInfo()
+ *(orient == wxHORIZONTAL ? &m_xThumbSize : &m_yThumbSize) = pageSize;
+
::SetScrollInfo(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT,
&info, refresh);
}
-
- *(orient == wxHORIZONTAL ? &m_xThumbSize : &m_yThumbSize) = pageSize;
}
void wxWindowMSW::ScrollWindow(int dx, int dy, const wxRect *prect)
}
else
{
- // don't bother restoring it neither: this also makes it easy to
+ // don't bother restoring it either: this also makes it easy to
// implement IsOfStandardClass() method which returns true for the
// standard controls and false for the wxWidgets own windows as it can
// simply check m_oldWndProc
bool wxCheckWindowWndProc(WXHWND hWnd,
- WXFARPROC WXUNUSED_IN_WINCE(wndProc))
+ WXFARPROC WXUNUSED(wndProc))
{
- // Unicows note: the code below works, but only because WNDCLASS contains
- // original window handler rather that the unicows fake one. This may not
- // be on purpose, though; if it stops working with future versions of
- // unicows.dll, we can override unicows hooks by setting
- // Unicows_{Set,Get}WindowLong and Unicows_RegisterClass to our own
- // versions that keep track of fake<->real wnd proc mapping.
+// TODO: This list of window class names should be factored out so they can be
+// managed in one place and then accessed from here and other places, such as
+// wxApp::RegisterWindowClasses() and wxApp::UnregisterWindowClasses()
- // On WinCE (at least), the wndproc comparison doesn't work,
- // so have to use something like this.
#ifdef __WXWINCE__
extern wxChar *wxCanvasClassName;
extern wxChar *wxCanvasClassNameNR;
+#else
+ extern const wxChar *wxCanvasClassName;
+ extern const wxChar *wxCanvasClassNameNR;
+#endif
extern const wxChar *wxMDIFrameClassName;
extern const wxChar *wxMDIFrameClassNameNoRedraw;
extern const wxChar *wxMDIChildFrameClassName;
wxString str(wxGetWindowClass(hWnd));
if (str == wxCanvasClassName ||
str == wxCanvasClassNameNR ||
+#if wxUSE_GLCANVAS
+ str == _T("wxGLCanvasClass") ||
+ str == _T("wxGLCanvasClassNR") ||
+#endif // wxUSE_GLCANVAS
str == wxMDIFrameClassName ||
str == wxMDIFrameClassNameNoRedraw ||
str == wxMDIChildFrameClassName ||
return true; // Effectively means don't subclass
else
return false;
-#else
- WNDCLASS cls;
- if ( !::GetClassInfo(wxGetInstance(), wxGetWindowClass(hWnd), &cls) )
- {
- wxLogLastError(_T("GetClassInfo"));
-
- return false;
- }
-
- return wndProc == (WXFARPROC)cls.lpfnWndProc;
-#endif
}
// ----------------------------------------------------------------------------
// 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).but sometimes results in redraw problems, so
+ // box is not redrawn twice), but sometimes results in redraw problems, so
// optionally allow the old code to continue to use it provided a special
// system option is turned on
if ( !wxSystemOptions::GetOptionInt(wxT("msw.window.no-clip-children"))
}
#endif // wxUSE_DRAG_AND_DROP
-// old style file-manager drag&drop support: we retain the old-style
+// old-style file manager drag&drop support: we retain the old-style
// DragAcceptFiles in parallel with SetDropTarget.
void wxWindowMSW::DragAcceptFiles(bool WXUNUSED_IN_WINCE(accept))
{
// Get size *available for subwindows* i.e. excluding menu bar etc.
void wxWindowMSW::DoGetClientSize(int *x, int *y) const
{
- // this is only for top level windows whose resizing is never deferred, so
- // we can safely use the current size here
- RECT rect = wxGetClientRect(GetHwnd());
+#if USE_DEFERRED_SIZING
+ if ( IsTopLevel() || m_pendingSize == wxDefaultSize )
+#endif
+ { // top level windows resizing is never deferred, so we can safely use
+ // the current size here
+ RECT rect = wxGetClientRect(GetHwnd());
- if ( x )
- *x = rect.right;
- if ( y )
- *y = rect.bottom;
+ if ( x )
+ *x = rect.right;
+ if ( y )
+ *y = rect.bottom;
+ }
+#if USE_DEFERRED_SIZING
+ else // non top level and using deferred sizing
+ {
+ // we need to calculate the *pending* client size here
+ RECT rect;
+ rect.left = m_pendingPosition.x;
+ rect.top = m_pendingPosition.y;
+ rect.right = rect.left + m_pendingSize.x;
+ rect.bottom = rect.top + m_pendingSize.y;
+
+ ::SendMessage(GetHwnd(), WM_NCCALCSIZE, FALSE, (LPARAM)&rect);
+
+ if ( x )
+ *x = rect.right - rect.left;
+ if ( y )
+ *y = rect.bottom - rect.top;
+ }
+#endif
}
void wxWindowMSW::DoGetPosition(int *x, int *y) const
if ( hdwp )
{
hdwp = ::DeferWindowPos(hdwp, (HWND)hwnd, NULL, x, y, width, height,
- SWP_NOZORDER);
+ SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE);
if ( !hdwp )
{
wxLogLastError(_T("DeferWindowPos"));
void wxWindowMSW::DoSetClientSize(int width, int height)
{
- // setting the client size is less obvious than it it could have been
+ // setting the client size is less obvious than it could have been
// because in the result of changing the total size the window scrollbar
- // may [dis]appear and/or its menubar may [un]wrap and so the client size
- // will not be correct as the difference between the total and client size
- // changes - so we keep changing it until we get it right
+ // may [dis]appear and/or its menubar may [un]wrap (and AdjustWindowRect()
+ // doesn't take neither into account) and so the client size will not be
+ // correct as the difference between the total and client size changes --
+ // so we keep changing it until we get it right
//
// normally this loop shouldn't take more than 3 iterations (usually 1 but
// if scrollbars [dis]appear as the result of the first call, then 2 and it
}
// don't call DoMoveWindow() because we want to move window immediately
- // and not defer it here
+ // and not defer it here as otherwise the value returned by
+ // GetClient/WindowRect() wouldn't change as the window wouldn't be
+ // really resized
if ( !::MoveWindow(GetHwnd(),
rectWin.left,
rectWin.top,
#endif
::TrackPopupMenu(hMenu, flags, point.x, point.y, 0, hWnd, NULL);
- // we need to do it righ now as otherwise the events are never going to be
+ // we need to do it right now as otherwise the events are never going to be
// sent to wxCurrentPopupMenu from HandleCommand()
//
// note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't
else // no default button
#endif // wxUSE_BUTTON
{
+#ifdef __WXWINCE__
+ wxJoystickEvent event(wxEVT_JOY_BUTTON_DOWN);
+ event.SetEventObject(this);
+ if(GetEventHandler()->ProcessEvent(event))
+ return true;
+#endif
// this is a quick and dirty test for a text
// control
if ( !(lDlgCode & DLGC_HASSETSEL) )
{
// as we don't call IsDialogMessage(), which would take of
// this by default, we need to manually send this message
- // so that controls could change their appearance
- // appropriately
- MSWUpdateUIState(UIS_CLEAR);
+ // so that controls can change their UI state if needed
+ MSWUpdateUIState(UIS_CLEAR, UISF_HIDEFOCUS);
return true;
}
{
// ::IsDialogMessage() is broken and may sometimes hang the
// application by going into an infinite loop, so we try to detect
- // [some of] the situatations when this may happen and not call it
+ // [some of] the situations when this may happen and not call it
// then
// assume we can call it by default
#if !defined(__WXWINCE__)
if ( ::GetWindowLong(hwndFocus, GWL_EXSTYLE) & WS_EX_CONTROLPARENT )
{
- // passimistic by default
+ // pessimistic by default
canSafelyCallIsDlgMsg = false;
for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
node;
break;
#endif // !__WXWINCE__
-#if !(defined(_WIN32_WCE) && _WIN32_WCE < 400)
- case WM_WINDOWPOSCHANGED:
- {
- WINDOWPOS *lpPos = (WINDOWPOS *)lParam;
-
- if ( !(lpPos->flags & SWP_NOSIZE) )
- {
- RECT rc;
- ::GetClientRect(GetHwnd(), &rc);
-
- AutoHRGN hrgnClient(::CreateRectRgnIndirect(&rc));
- AutoHRGN hrgnNew(::CreateRectRgn(lpPos->x, lpPos->y,
- lpPos->cx, lpPos->cy));
-
- // we need to invalidate any new exposed areas here
- // to force them to repaint
- if ( ::CombineRgn(hrgnNew, hrgnNew, hrgnClient, RGN_DIFF) != NULLREGION )
- ::InvalidateRgn(GetHwnd(), hrgnNew, TRUE);
- }
- }
- break;
-#endif
#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
case WM_ACTIVATEAPP:
// This implicitly sends a wxEVT_ACTIVATE_APP event
{
switch ( wParam )
{
- // we consider these message "not interesting" to OnChar, so
+ // we consider these messages "not interesting" to OnChar, so
// just don't do anything more with them
case VK_SHIFT:
case VK_CONTROL:
// WM_NOTIFY
// ---------------------------------------------------------------------------
-#ifdef __WIN95__
-
bool wxWindowMSW::HandleNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
{
#ifndef __WXMICROWIN__
return false;
}
-#endif // __WIN95__
-
// ---------------------------------------------------------------------------
// end session messages
// ---------------------------------------------------------------------------
return GetEventHandler()->ProcessEvent(event);
}
+// ---------------------------------------------------------------------------
+// labels
+// ---------------------------------------------------------------------------
+
+void wxWindowMSW::SetLabel( const wxString& label)
+{
+ SetWindowText(GetHwnd(), label.c_str());
+}
+
+wxString wxWindowMSW::GetLabel() const
+{
+ return wxGetWindowText(GetHWND());
+}
+
// ---------------------------------------------------------------------------
// miscellaneous
// ---------------------------------------------------------------------------
dc.SetHDC(hdc);
dc.SetWindow((wxWindow *)this);
- dc.BeginDrawing();
wxEraseEvent event(m_windowId, &dc);
event.SetEventObject(this);
bool rc = GetEventHandler()->ProcessEvent(event);
- dc.EndDrawing();
-
// must be called manually as ~wxDC doesn't do anything for wxDCTemp
dc.SelectOldObjects(hdc);
GenerateMouseLeave();
}
}
-#endif // HAVE_TRACKMOUSEEVENT
+#endif // HAVE_TRACKMOUSEEVENT
#if wxUSE_MOUSEEVENT_HACK
// Windows often generates mouse events even if mouse position hasn't
MENUITEMINFO mii;
wxZeroMemory(mii);
mii.cbSize = sizeof(MENUITEMINFO);
+
+ // we could use MIIM_FTYPE here as we only need to know if the item is
+ // ownerdrawn or not and not dwTypeData which MIIM_TYPE also returns, but
+ // MIIM_FTYPE is not supported under Win95
mii.fMask = MIIM_TYPE | MIIM_DATA;
// find if we have this letter in any owner drawn item
const int count = ::GetMenuItemCount(hmenu);
for ( int i = 0; i < count; i++ )
{
+ // previous loop iteration could modify it, reset it back before
+ // calling GetMenuItemInfo() to prevent it from overflowing dwTypeData
+ mii.cch = 0;
+
if ( ::GetMenuItemInfo(hmenu, i, TRUE, &mii) )
{
if ( mii.fType == MFT_OWNERDRAW )
}
else // failed to get the menu text?
{
- // it's not fatal, so don't show error, but still log
- // it
+ // it's not fatal, so don't show error, but still log it
wxLogLastError(_T("GetMenuItemInfo"));
}
}
// the_font.ReleaseResource();
}
+// use the "extended" bit (24) of lParam to distinguish extended keys
+// from normal keys as the same key is sent
+static inline int ChooseNormalOrExtended(int lParam, int keyNormal, int keyExtended)
+{
+ return lParam & (1 << 24) ? keyExtended : keyNormal;
+}
+
// Returns 0 if was a normal ASCII value, not a special key. This indicates that
// the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead.
int wxCharCodeMSWToWX(int keySym, WXLPARAM lParam)
case VK_CAPITAL: id = WXK_CAPITAL; break;
case VK_SPACE: id = WXK_SPACE; break;
case VK_ESCAPE: id = WXK_ESCAPE; break;
- case VK_PRIOR: id = WXK_PRIOR; break;
- case VK_NEXT : id = WXK_NEXT; break;
- case VK_END: id = WXK_END; break;
- case VK_HOME : id = WXK_HOME; break;
- case VK_LEFT : id = WXK_LEFT; break;
- case VK_UP: id = WXK_UP; break;
- case VK_RIGHT: id = WXK_RIGHT; break;
- case VK_DOWN : id = WXK_DOWN; break;
case VK_SELECT: id = WXK_SELECT; break;
case VK_PRINT: id = WXK_PRINT; break;
case VK_EXECUTE: id = WXK_EXECUTE; break;
- case VK_INSERT: id = WXK_INSERT; break;
- case VK_DELETE: id = WXK_DELETE; break;
case VK_HELP : id = WXK_HELP; break;
case VK_NUMPAD0: id = WXK_NUMPAD0; break;
case VK_NUMPAD1: id = WXK_NUMPAD1; break;
case VK_APPS: id = WXK_WINDOWS_MENU; break;
#endif // VK_APPS defined
+ // handle extended keys
+ case VK_PRIOR:
+ id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_PRIOR, WXK_PRIOR);
+ break;
+ case VK_NEXT:
+ id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_NEXT, WXK_NEXT);
+ break;
+ case VK_END:
+ id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_END, WXK_END);
+ break;
+ case VK_HOME:
+ id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_HOME, WXK_HOME);
+ break;
+ case VK_LEFT:
+ id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_LEFT, WXK_LEFT);
+ break;
+ case VK_UP:
+ id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_UP, WXK_UP);
+ break;
+ case VK_RIGHT:
+ id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_RIGHT, WXK_RIGHT);
+ break;
+ case VK_DOWN:
+ id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_DOWN, WXK_DOWN);
+ break;
+ case VK_INSERT:
+ id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_INSERT, WXK_INSERT);
+ break;
+ case VK_DELETE:
+ id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_DELETE, WXK_DELETE);
+ break;
+ // this order is correct as the numpad enter is the extended key
case VK_RETURN:
- // the same key is sent for both the "return" key on the main
- // keyboard and the numeric keypad but we want to distinguish
- // between them: we do this using the "extended" bit (24) of lParam
- id = lParam & (1 << 24) ? WXK_NUMPAD_ENTER : WXK_RETURN;
+ id = ChooseNormalOrExtended(lParam, WXK_RETURN, WXK_NUMPAD_ENTER);
break;
default:
#endif
}
+
+wxMouseState wxGetMouseState()
+{
+ wxMouseState ms;
+ POINT pt;
+ GetCursorPos( &pt );
+
+ ms.SetX(pt.x);
+ ms.SetY(pt.y);
+ ms.SetLeftDown( (GetAsyncKeyState(VK_LBUTTON) & (1<<15)) != 0 );
+ ms.SetMiddleDown( (GetAsyncKeyState(VK_MBUTTON) & (1<<15)) != 0 );
+ ms.SetRightDown( (GetAsyncKeyState(VK_RBUTTON) & (1<<15)) != 0 );
+
+ ms.SetControlDown( (GetAsyncKeyState(VK_CONTROL) & (1<<15)) != 0 );
+ ms.SetShiftDown( (GetAsyncKeyState(VK_SHIFT) & (1<<15)) != 0 );
+ ms.SetAltDown( (GetAsyncKeyState(VK_MENU) & (1<<15)) != 0 );
+// ms.SetMetaDown();
+
+ return ms;
+}
+
+
wxWindow *wxGetActiveWindow()
{
HWND hWnd = GetActiveWindow();
event.Skip();
}
#endif
-