#define HAVE_TRACKMOUSEEVENT
#endif // everything needed for TrackMouseEvent()
-// if this is set to 1, we use deferred window sizing to reduce flicker when
-// 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
#ifdef __WXWINCE__
extern wxMenu *wxCurrentPopupMenu;
#endif
-#ifdef __WXWINCE__
-extern wxChar *wxCanvasClassName;
-#else
-extern const wxChar *wxCanvasClassName;
-#endif
-
// true if we had already created the std colour map, used by
// wxGetStdColourMap() and wxWindow::OnSysColourChanged() (FIXME-MT)
static bool gs_hasStdCmap = false;
WPARAM wParam, LPARAM lParam);
-#ifdef __WXDEBUG__
+#if wxDEBUG_LEVEL >= 2
const wxChar *wxGetMessageName(int message);
-#endif //__WXDEBUG__
+#endif // wxDEBUG_LEVEL >= 2
void wxRemoveHandleAssociation(wxWindowMSW *win);
extern void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win);
void wxWindowMSW::Init()
{
// MSW specific
- m_isBeingDeleted = false;
m_oldWndProc = NULL;
m_mouseInWindow = false;
m_lastKeydownProcessed = false;
m_hWnd = 0;
- m_hDWP = 0;
m_xThumbSize = 0;
m_yThumbSize = 0;
+#if wxUSE_DEFERRED_SIZING
+ m_hDWP = 0;
m_pendingPosition = wxDefaultPosition;
m_pendingSize = wxDefaultSize;
+#endif // wxUSE_DEFERRED_SIZING
#ifdef __POCKETPC__
m_contextMenuEnabled = false;
// Destructor
wxWindowMSW::~wxWindowMSW()
{
- m_isBeingDeleted = true;
+ SendDestroyEvent();
#ifndef __WXUNIVERSAL__
// VS: make sure there's no wxFrame with last focus set to us:
}
+/* static */
+const wxChar *wxWindowMSW::MSWGetRegisteredClassName()
+{
+ return wxApp::GetRegisteredClassName(_T("wxWindow"), COLOR_BTNFACE);
+}
+
// real construction (Init() must have been called before!)
bool wxWindowMSW::Create(wxWindow *parent,
wxWindowID id,
msflags |= WS_VISIBLE;
}
- if ( !MSWCreate(wxCanvasClassName, NULL, pos, size, msflags, exstyle) )
+ if ( !MSWCreate(MSWGetRegisteredClassName(),
+ NULL, pos, size, msflags, exstyle) )
return false;
InheritAttributes();
HWND hWnd = GetHwnd();
wxCHECK_RET( hWnd, _T("can't set focus to invalid window") );
-#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
+#if !defined(__WXWINCE__)
::SetLastError(0);
#endif
if ( !::SetFocus(hWnd) )
{
-#if defined(__WXDEBUG__) && !defined(__WXMICROWIN__)
// was there really an error?
DWORD dwRes = ::GetLastError();
if ( dwRes )
wxLogApiError(_T("SetFocus"), dwRes);
}
}
-#endif // Debug
}
}
// scrolling stuff
// ---------------------------------------------------------------------------
+namespace
+{
+
inline int GetScrollPosition(HWND hWnd, int wOrient)
{
#ifdef __WXMICROWIN__
#endif
}
+inline UINT WXOrientToSB(int orient)
+{
+ return orient == wxHORIZONTAL ? SB_HORZ : SB_VERT;
+}
+
+} // anonymous namespace
+
int wxWindowMSW::GetScrollPos(int orient) const
{
HWND hWnd = GetHwnd();
wxCHECK_MSG( hWnd, 0, _T("no HWND in GetScrollPos") );
- return GetScrollPosition(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT);
+ return GetScrollPosition(hWnd, WXOrientToSB(orient));
}
// This now returns the whole range, not just the number
HWND hWnd = GetHwnd();
if ( !hWnd )
return 0;
-#if 0
- ::GetScrollRange(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT,
- &minPos, &maxPos);
-#endif
WinStruct<SCROLLINFO> scrollInfo;
scrollInfo.fMask = SIF_RANGE;
- if ( !::GetScrollInfo(hWnd,
- orient == wxHORIZONTAL ? SB_HORZ : SB_VERT,
- &scrollInfo) )
+ if ( !::GetScrollInfo(hWnd, WXOrientToSB(orient), &scrollInfo) )
{
// Most of the time this is not really an error, since the return
// value can also be zero when there is no scrollbar yet.
info.fMask |= SIF_DISABLENOSCROLL;
}
- ::SetScrollInfo(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT,
- &info, refresh);
+ ::SetScrollInfo(hWnd, WXOrientToSB(orient), &info, refresh);
}
// New function that will replace some of the above.
int range,
bool refresh)
{
+ // We have to set the variables here to make them valid in events
+ // triggered by ::SetScrollInfo()
+ *(orient == wxHORIZONTAL ? &m_xThumbSize : &m_yThumbSize) = pageSize;
+
+ HWND hwnd = GetHwnd();
+ if ( !hwnd )
+ return;
+
WinStruct<SCROLLINFO> info;
- info.nPage = pageSize;
- info.nMin = 0; // range is nMax - nMin + 1
- info.nMax = range - 1; // as both nMax and nMax are inclusive
- info.nPos = pos;
+ if ( range != -1 )
+ {
+ info.nPage = pageSize;
+ info.nMin = 0; // range is nMax - nMin + 1
+ info.nMax = range - 1; // as both nMax and nMax are inclusive
+ info.nPos = pos;
+
+ // enable the scrollbar if it had been disabled before by specifying
+ // SIF_DISABLENOSCROLL below: as we can't know whether this had been
+ // done or not just do it always
+ ::EnableScrollBar(hwnd, WXOrientToSB(orient), ESB_ENABLE_BOTH);
+ }
+ //else: leave all the fields to be 0
+
info.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
- if ( HasFlag(wxALWAYS_SHOW_SB) )
+ if ( HasFlag(wxALWAYS_SHOW_SB) || range == -1 )
{
// disable scrollbar instead of removing it then
info.fMask |= SIF_DISABLENOSCROLL;
}
- 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);
- }
+ ::SetScrollInfo(hwnd, WXOrientToSB(orient), &info, refresh);
}
void wxWindowMSW::ScrollWindow(int dx, int dy, const wxRect *prect)
bool wxCheckWindowWndProc(WXHWND hWnd,
WXFARPROC WXUNUSED(wndProc))
{
-// 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()
+ const wxString str(wxGetWindowClass(hWnd));
-#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;
- extern const wxChar *wxMDIChildFrameClassNameNoRedraw;
- 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 ||
- str == wxMDIChildFrameClassNameNoRedraw ||
- str == _T("wxTLWHiddenParent"))
- return true; // Effectively means don't subclass
- else
- return false;
+ // TODO: get rid of wxTLWHiddenParent special case (currently it's not
+ // registered by wxApp but using ad hoc code in msw/toplevel.cpp);
+ // there is also a hidden window class used by sockets &c
+ return wxApp::IsRegisteredClassName(str) || str == _T("wxTLWHiddenParent");
}
// ----------------------------------------------------------------------------
bool wxWindowMSW::IsSizeDeferred() const
{
-#if USE_DEFERRED_SIZING
+#if wxUSE_DEFERRED_SIZING
if ( m_pendingPosition != wxDefaultPosition ||
m_pendingSize != wxDefaultSize )
return true;
-#endif // USE_DEFERRED_SIZING
+#endif // wxUSE_DEFERRED_SIZING
return false;
}
// Get total size
void wxWindowMSW::DoGetSize(int *x, int *y) const
{
-#if USE_DEFERRED_SIZING
+#if wxUSE_DEFERRED_SIZING
// if SetSize() had been called at wx level but not realized at Windows
// level yet (i.e. EndDeferWindowPos() not called), we still should return
// the new and not the old position to the other wx code
*y = m_pendingSize.y;
}
else // use current size
-#endif // USE_DEFERRED_SIZING
+#endif // wxUSE_DEFERRED_SIZING
{
RECT rect = wxGetWindowRect(GetHwnd());
// Get size *available for subwindows* i.e. excluding menu bar etc.
void wxWindowMSW::DoGetClientSize(int *x, int *y) const
{
-#if USE_DEFERRED_SIZING
+#if wxUSE_DEFERRED_SIZING
if ( m_pendingSize != wxDefaultSize )
{
// we need to calculate the client size corresponding to pending size
*y = rect.bottom - rect.top;
}
else
-#endif // USE_DEFERRED_SIZING
+#endif // wxUSE_DEFERRED_SIZING
{
RECT rect = wxGetClientRect(GetHwnd());
bool
wxWindowMSW::DoMoveSibling(WXHWND hwnd, int x, int y, int width, int height)
{
-#if USE_DEFERRED_SIZING
+#if wxUSE_DEFERRED_SIZING
// if our parent had prepared a defer window handle for us, use it (unless
// we are a top level window)
wxWindowMSW * const parent = IsTopLevel() ? NULL : GetParent();
}
// otherwise (or if deferring failed) move the window in place immediately
-#endif // USE_DEFERRED_SIZING
+#endif // wxUSE_DEFERRED_SIZING
if ( !::MoveWindow((HWND)hwnd, x, y, width, height, IsShown()) )
{
wxLogLastError(wxT("MoveWindow"));
}
- // if USE_DEFERRED_SIZING, indicates that we didn't use deferred move,
+ // if wxUSE_DEFERRED_SIZING, indicates that we didn't use deferred move,
// ignored otherwise
return false;
}
if ( DoMoveSibling(m_hWnd, x, y, width, height) )
{
-#if USE_DEFERRED_SIZING
+#if wxUSE_DEFERRED_SIZING
m_pendingPosition = wxPoint(x, y);
m_pendingSize = wxSize(width, height);
-#endif // USE_DEFERRED_SIZING
+ }
+ else // window was moved immediately, without deferring it
+ {
+ m_pendingPosition = wxDefaultPosition;
+ m_pendingSize = wxDefaultSize;
+#endif // wxUSE_DEFERRED_SIZING
}
}
width == currentW && height == currentH &&
!(sizeFlags & wxSIZE_FORCE) )
{
+ if (sizeFlags & wxSIZE_FORCE_EVENT)
+ {
+ wxSizeEvent event( wxSize(width,height), GetId() );
+ event.SetEventObject( this );
+ HandleWindowEvent( event );
+ }
return;
}
// Main window proc
LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
- // trace all messages - useful for the debugging
-#ifdef __WXDEBUG__
+ // trace all messages: useful for the debugging but noticeably slows down
+ // the code so don't do it by default
+#if wxDEBUG_LEVEL >= 2
wxLogTrace(wxTraceMessages,
wxT("Processing %s(hWnd=%p, wParam=%08lx, lParam=%08lx)"),
wxGetMessageName(message), hWnd, (long)wParam, lParam);
-#endif // __WXDEBUG__
+#endif // wxDEBUG_LEVEL >= 2
wxWindowMSW *wnd = wxFindWinFromHandle(hWnd);
rc.result = MSWDefWindowProc(message, wParam, lParam);
processed = true;
- // now alter the client size making room for drawing a themed border
- NCCALCSIZE_PARAMS *csparam = NULL;
+ // now alter the client size making room for drawing a
+ // themed border
RECT *rect;
if ( wParam )
{
- csparam = (NCCALCSIZE_PARAMS *)lParam;
+ NCCALCSIZE_PARAMS *csparam = (NCCALCSIZE_PARAMS *)lParam;
rect = &csparam->rgrc[0];
}
else
if ( !processed )
{
-#ifdef __WXDEBUG__
+#if wxDEBUG_LEVEL >= 2
wxLogTrace(wxTraceMessages, wxT("Forwarding %s to DefWindowProc."),
wxGetMessageName(message));
-#endif // __WXDEBUG__
+#endif // wxDEBUG_LEVEL >= 2
rc.result = MSWDefWindowProc(message, wParam, lParam);
}
wxCHECK_RET( hwnd != (HWND)NULL,
wxT("attempt to add a NULL hwnd to window list ignored") );
-#ifdef __WXDEBUG__
+#if wxDEBUG_LEVEL
WindowHandles::const_iterator i = gs_windowHandles.find(hwnd);
if ( i != gs_windowHandles.end() )
{
if ( i->second != win )
{
- wxLogDebug(wxT("HWND %p already associated with another window (%s)"),
- hwnd, win->GetClassInfo()->GetClassName());
+ wxFAIL_MSG(
+ wxString::Format(
+ wxT("HWND %p already associated with another window (%s)"),
+ hwnd, win->GetClassInfo()->GetClassName()
+ )
+ );
}
//else: this actually happens currently because we associate the window
// with its HWND during creation (if we create it) and also when
// SubclassWin() is called later, this is ok
}
-#endif // __WXDEBUG__
+#endif // wxDEBUG_LEVEL
gs_windowHandles[hwnd] = (wxWindow *)win;
}
// especially for wxTLWs
wxCHECK_MSG( !m_hWnd, true, "window can't be recreated" );
+ // this can happen if this function is called using the return value of
+ // wxApp::GetRegisteredClassName() which failed
+ wxCHECK_MSG( wclass, false, "failed to register window class?" );
+
+
// choose the position/size for the new window
int x, y, w, h;
(void)MSWGetCreateWindowCoords(pos, size, x, y, w, h);
wxString className(wclass);
if ( !HasFlag(wxFULL_REPAINT_ON_RESIZE) )
{
- className += wxT("NR");
+ className += wxApp::GetNoRedrawClassSuffix();
}
// do create the window
// if we got TTN_NEEDTEXTW in Unicode build: in this case we just have
// to copy the string we have into the buffer
static wxChar buf[513];
- wxStrncpy(buf, ttip.c_str(), WXSIZEOF(buf) - 1);
- buf[WXSIZEOF(buf) - 1] = _T('\0');
+ wxStrlcpy(buf, ttip.c_str(), WXSIZEOF(buf));
ttText->lpszText = buf;
}
bool wxWindowMSW::HandleDestroy()
{
- SendDestroyEvent();
-
// delete our drop target if we've got one
#if wxUSE_DRAG_AND_DROP
if ( m_dropTarget != NULL )
::DragQueryFile(hFilesInfo, wIndex,
wxStringBuffer(files[wIndex], len), len);
}
- DragFinish (hFilesInfo);
wxDropFilesEvent event(wxEVT_DROP_FILES, gwFilesDropped, files);
event.SetEventObject(this);
event.m_pos.x = dropPoint.x;
event.m_pos.y = dropPoint.y;
+ DragFinish(hFilesInfo);
+
return HandleWindowEvent(event);
#endif
}
bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT wParam)
{
-#if USE_DEFERRED_SIZING
+#if wxUSE_DEFERRED_SIZING
// when we resize this window, its children are probably going to be
// repositioned as well, prepare to use DeferWindowPos() for them
int numChildren = 0;
useDefer = true;
}
}
-#endif // USE_DEFERRED_SIZING
+#endif // wxUSE_DEFERRED_SIZING
// update this window size
bool processed = false;
processed = HandleWindowEvent(event);
}
-#if USE_DEFERRED_SIZING
+#if wxUSE_DEFERRED_SIZING
// and finally change the positions of all child windows at once
if ( useDefer && m_hDWP )
{
node;
node = node->GetNext() )
{
- wxWindowMSW *child = node->GetData();
- child->m_pendingPosition = wxDefaultPosition;
- child->m_pendingSize = wxDefaultSize;
+ wxWindowMSW * const child = node->GetData();
+ child->MSWEndDeferWindowPos();
}
}
-#endif // USE_DEFERRED_SIZING
+#endif // wxUSE_DEFERRED_SIZING
return processed;
}
static bool s_initDone = false;
if ( !s_initDone )
{
- wxLogNull noLog;
-
- wxDynamicLibrary dllComCtl32(_T("comctl32.dll"), wxDL_VERBATIM);
+ // see comment in wxApp::GetComCtl32Version() explaining the
+ // use of wxLoadedDLL
+ wxLoadedDLL dllComCtl32(_T("comctl32.dll"));
if ( dllComCtl32.IsLoaded() )
{
s_pfn_TrackMouseEvent = (_TrackMouseEvent_t)
- dllComCtl32.GetSymbol(_T("_TrackMouseEvent"));
+ dllComCtl32.RawGetSymbol(_T("_TrackMouseEvent"));
}
s_initDone = true;
-
- // notice that it's ok to unload comctl32.dll here as it won't
- // be really unloaded, being still in use because we link to it
- // statically too
}
if ( s_pfn_TrackMouseEvent )
scrollInfo.fMask = SIF_TRACKPOS;
if ( !::GetScrollInfo(GetHwnd(),
- orientation == wxHORIZONTAL ? SB_HORZ
- : SB_VERT,
+ WXOrientToSB(orientation),
&scrollInfo) )
{
// Not necessarily an error, if there are no scrollbars yet.
// For a radiobutton, we get the radiobox from GWL_USERDATA (which is set
// by code in msw/radiobox.cpp), for all the others we just search up the
// window hierarchy
- wxWindow *win = (wxWindow *)NULL;
+ wxWindow *win = NULL;
if ( hwnd )
{
win = wxFindWinFromHandle(hwnd);
// Windows keyboard hook. Allows interception of e.g. F1, ESCAPE
// in active frames and dialogs, regardless of where the focus is.
static HHOOK wxTheKeyboardHook = 0;
-static FARPROC wxTheKeyboardHookProc = 0;
-int APIENTRY _EXPORT
-wxKeyboardHook(int nCode, WORD wParam, DWORD lParam);
-
-void wxSetKeyboardHook(bool doIt)
-{
- if ( doIt )
- {
- wxTheKeyboardHookProc = MakeProcInstance((FARPROC) wxKeyboardHook, wxGetInstance());
- wxTheKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC) wxTheKeyboardHookProc, wxGetInstance(),
-
- GetCurrentThreadId()
- // (DWORD)GetCurrentProcess()); // This is another possibility. Which is right?
- );
- }
- else
- {
- UnhookWindowsHookEx(wxTheKeyboardHook);
- }
-}
-int APIENTRY _EXPORT
+int APIENTRY
wxKeyboardHook(int nCode, WORD wParam, DWORD lParam)
{
DWORD hiWord = HIWORD(lParam);
return (int)CallNextHookEx(wxTheKeyboardHook, nCode, wParam, lParam);
}
+void wxSetKeyboardHook(bool doIt)
+{
+ if ( doIt )
+ {
+ wxTheKeyboardHook = ::SetWindowsHookEx
+ (
+ WH_KEYBOARD,
+ (HOOKPROC)wxKeyboardHook,
+ NULL, // must be NULL for process hook
+ ::GetCurrentThreadId()
+ );
+ if ( !wxTheKeyboardHook )
+ {
+ wxLogLastError(_T("SetWindowsHookEx(wxKeyboardHook)"));
+ }
+ }
+ else // uninstall
+ {
+ if ( wxTheKeyboardHook )
+ ::UnhookWindowsHookEx(wxTheKeyboardHook);
+ }
+}
+
#endif // !__WXMICROWIN__
-#ifdef __WXDEBUG__
+#if wxDEBUG_LEVEL >= 2
const wxChar *wxGetMessageName(int message)
{
switch ( message )
case 0x0120: return wxT("WM_MENUCHAR");
case 0x0121: return wxT("WM_ENTERIDLE");
+ case 0x0127: return wxT("WM_CHANGEUISTATE");
+ case 0x0128: return wxT("WM_UPDATEUISTATE");
+ case 0x0129: return wxT("WM_QUERYUISTATE");
+
case 0x0132: return wxT("WM_CTLCOLORMSGBOX");
case 0x0133: return wxT("WM_CTLCOLOREDIT");
case 0x0134: return wxT("WM_CTLCOLORLISTBOX");
return s_szBuf.c_str();
}
}
-#endif //__WXDEBUG__
+#endif // wxDEBUG_LEVEL >= 2
static TEXTMETRIC wxGetTextMetrics(const wxWindowMSW *win)
{