#endif
#include "wx/msw/private.h"
+#include "wx/msw/dcclient.h"
#if wxUSE_TOOLTIPS
#include "wx/tooltip.h"
// ---------------------------------------------------------------------------
#if wxUSE_MENUS_NATIVE
-wxMenu *wxCurrentPopupMenu = NULL;
-#endif // wxUSE_MENUS_NATIVE
+extern wxMenu *wxCurrentPopupMenu;
+#endif
#ifdef __WXWINCE__
extern wxChar *wxCanvasClassName;
static MSWMessageHandlers gs_messageHandlers;
+// hash containing all our windows, it uses HWND keys and wxWindow* values
+WX_DECLARE_HASH_MAP(HWND, wxWindow *,
+ wxPointerHash, wxPointerEqual,
+ WindowHandles);
+
+static WindowHandles gs_windowHandles;
+
// ---------------------------------------------------------------------------
// private functions
// ---------------------------------------------------------------------------
void wxRemoveHandleAssociation(wxWindowMSW *win);
extern void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win);
-wxWindow *wxFindWinFromHandle(WXHWND hWnd);
// get the text metrics for the current font
static TEXTMETRIC wxGetTextMetrics(const wxWindowMSW *win);
m_mouseInWindow = false;
m_lastKeydownProcessed = false;
- m_frozenness = 0;
-
m_hWnd = 0;
m_hDWP = 0;
static bool s_initDone = false;
if ( !s_initDone )
{
- wxLogNull noLog;
-
- wxDynamicLibrary dllUser32(_T("user32.dll"), wxDL_VERBATIM);
+ wxDynamicLibrary dllUser32(_T("user32.dll"), wxDL_VERBATIM | wxDL_QUIET);
wxDL_INIT_FUNC(s_pfn, AnimateWindow, dllUser32);
s_initDone = true;
/* static */ wxWindow *wxWindowBase::GetCapture()
{
HWND hwnd = ::GetCapture();
- return hwnd ? wxFindWinFromHandle((WXHWND)hwnd) : (wxWindow *)NULL;
+ return hwnd ? wxFindWinFromHandle(hwnd) : NULL;
}
bool wxWindowMSW::SetFont(const wxFont& font)
}
#endif // !HAVE_TRACKMOUSEEVENT
- if (wxUpdateUIEvent::CanUpdate(this) && IsShown())
+ if (wxUpdateUIEvent::CanUpdate(this) && IsShownOnScreen())
UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
}
#endif
}
-void wxWindowMSW::Freeze()
+void wxWindowMSW::DoFreeze()
{
- if ( !m_frozenness++ )
- {
- if ( IsShown() )
- SendSetRedraw(GetHwnd(), false);
- }
+ if ( IsShown() )
+ SendSetRedraw(GetHwnd(), false);
}
-void wxWindowMSW::Thaw()
+void wxWindowMSW::DoThaw()
{
- wxASSERT_MSG( m_frozenness > 0, _T("Thaw() without matching Freeze()") );
-
- if ( --m_frozenness == 0 )
+ if ( IsShown() )
{
- if ( IsShown() )
- {
- SendSetRedraw(GetHwnd(), true);
+ SendSetRedraw(GetHwnd(), true);
- // we need to refresh everything or otherwise the invalidated area
- // is not going to be repainted
- Refresh();
- }
+ // we need to refresh everything or otherwise the invalidated area
+ // is not going to be repainted
+ Refresh();
}
}
void wxWindowMSW::GetTextExtent(const wxString& string,
int *x, int *y,
int *descent, int *externalLeading,
- const wxFont *theFont) const
+ const wxFont *fontToUse) const
{
- wxASSERT_MSG( !theFont || theFont->Ok(),
+ wxASSERT_MSG( !fontToUse || fontToUse->Ok(),
_T("invalid font in GetTextExtent()") );
- wxFont fontToUse;
- if (theFont)
- fontToUse = *theFont;
+ HFONT hfontToUse;
+ if ( fontToUse )
+ hfontToUse = GetHfontOf(*fontToUse);
else
- fontToUse = GetFont();
+ hfontToUse = GetHfontOf(GetFont());
WindowHDC hdc(GetHwnd());
- SelectInHDC selectFont(hdc, GetHfontOf(fontToUse));
+ SelectInHDC selectFont(hdc, hfontToUse);
SIZE sizeRect;
TEXTMETRIC tm;
point.x = x;
point.y = y;
::ClientToScreen(hWnd, &point);
- wxCurrentPopupMenu = menu;
#if defined(__WXWINCE__)
static const UINT flags = 0;
#else // !__WXWINCE__
// for example) and so we do need to process the event immediately
wxYieldForCommandsOnly();
- wxCurrentPopupMenu = NULL;
-
menu->SetInvokingWindow(NULL);
return true;
if ( (style & BS_OWNERDRAW) == BS_OWNERDRAW )
{
// emulate the button click
- btn = wxFindWinFromHandle((WXHWND)msg->hwnd);
+ btn = wxFindWinFromHandle(msg->hwnd);
}
bProcess = false;
// trace all messages - useful for the debugging
#ifdef __WXDEBUG__
wxLogTrace(wxTraceMessages,
- wxT("Processing %s(hWnd=%08lx, wParam=%8lx, lParam=%8lx)"),
- wxGetMessageName(message), (long)hWnd, (long)wParam, lParam);
+ wxT("Processing %s(hWnd=%p, wParam=%08lx, lParam=%08lx)"),
+ wxGetMessageName(message), hWnd, (long)wParam, lParam);
#endif // __WXDEBUG__
- wxWindowMSW *wnd = wxFindWinFromHandle((WXHWND) hWnd);
+ wxWindowMSW *wnd = wxFindWinFromHandle(hWnd);
// when we get the first message for the HWND we just created, we associate
// it with wxWindow stored in gs_winBeingCreated
break;
case WM_SETFOCUS:
- processed = HandleSetFocus((WXHWND)(HWND)wParam);
+ processed = HandleSetFocus((WXHWND)wParam);
break;
case WM_KILLFOCUS:
- processed = HandleKillFocus((WXHWND)(HWND)wParam);
+ processed = HandleKillFocus((WXHWND)wParam);
break;
case WM_PRINTCLIENT:
// for these messages we must return true if process the message
#ifdef WM_DRAWITEM
case WM_DRAWITEM:
- case WM_MEASUREITEM:
- {
- int idCtrl = (UINT)wParam;
- if ( message == WM_DRAWITEM )
- {
- processed = MSWOnDrawItem(idCtrl,
- (WXDRAWITEMSTRUCT *)lParam);
- }
- else
- {
- processed = MSWOnMeasureItem(idCtrl,
- (WXMEASUREITEMSTRUCT *)lParam);
- }
+ processed = MSWOnDrawItem(wParam, (WXDRAWITEMSTRUCT *)lParam);
+ if ( processed )
+ rc.result = TRUE;
+ break;
- if ( processed )
- rc.result = TRUE;
- }
+ case WM_MEASUREITEM:
+ processed = MSWOnMeasureItem(wParam, (WXMEASUREITEMSTRUCT *)lParam);
+ if ( processed )
+ rc.result = TRUE;
break;
#endif // defined(WM_DRAWITEM)
break;
#endif // wxUSE_HOTKEY
+ case WM_CUT:
+ case WM_COPY:
+ case WM_PASTE:
+ processed = HandleClipboardEvent(message);
+ break;
+
case WM_HSCROLL:
case WM_VSCROLL:
{
#endif
case WM_PALETTECHANGED:
- processed = HandlePaletteChanged((WXHWND) (HWND) wParam);
+ processed = HandlePaletteChanged((WXHWND)wParam);
break;
case WM_CAPTURECHANGED:
- processed = HandleCaptureChanged((WXHWND) (HWND) lParam);
+ processed = HandleCaptureChanged((WXHWND)lParam);
break;
case WM_SETTINGCHANGE:
break;
case WM_ERASEBKGND:
- processed = HandleEraseBkgnd((WXHDC)(HDC)wParam);
+ processed = HandleEraseBkgnd((WXHDC)wParam);
if ( processed )
{
// we processed the message, i.e. erased the background
#endif
case WM_INITDIALOG:
- processed = HandleInitDialog((WXHWND)(HWND)wParam);
+ processed = HandleInitDialog((WXHWND)wParam);
if ( processed )
{
#endif
case WM_SETCURSOR:
- processed = HandleSetCursor((WXHWND)(HWND)wParam,
+ processed = HandleSetCursor((WXHWND)wParam,
LOWORD(lParam), // hit test
HIWORD(lParam)); // mouse msg
// we could have got an event from our child, reflect it back
// to it if this is the case
wxWindowMSW *win = NULL;
- if ( (WXHWND)wParam != m_hWnd )
+ WXHWND hWnd = (WXHWND)wParam;
+ if ( hWnd != m_hWnd )
{
- win = FindItemByHWND((WXHWND)wParam);
+ win = FindItemByHWND(hWnd);
}
if ( !win )
// now alter the client size making room for drawing a themed border
NCCALCSIZE_PARAMS *csparam = NULL;
- RECT rect;
- if (wParam)
+ RECT *rect;
+ if ( wParam )
{
- csparam = (NCCALCSIZE_PARAMS*)lParam;
- rect = csparam->rgrc[0];
+ csparam = (NCCALCSIZE_PARAMS *)lParam;
+ rect = &csparam->rgrc[0];
}
else
{
- rect = *((RECT*)lParam);
+ rect = (RECT *)lParam;
}
+
wxUxThemeHandle hTheme((wxWindow *)this, L"EDIT");
RECT rcClient = { 0, 0, 0, 0 };
wxClientDC dc((wxWindow *)this);
+ wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl();
- if (theme->GetThemeBackgroundContentRect(
- hTheme, GetHdcOf(dc), EP_EDITTEXT, ETS_NORMAL,
- &rect, &rcClient) == S_OK)
+ if ( theme->GetThemeBackgroundContentRect
+ (
+ hTheme,
+ GetHdcOf(*impl),
+ EP_EDITTEXT,
+ ETS_NORMAL,
+ rect,
+ &rcClient) == S_OK )
{
InflateRect(&rcClient, -1, -1);
- if (wParam)
- csparam->rgrc[0] = rcClient;
- else
- *((RECT*)lParam) = rcClient;
+ *rect = rcClient;
rc.result = WVR_REDRAW;
}
}
wxUxThemeHandle hTheme((wxWindow *)this, L"EDIT");
wxWindowDC dc((wxWindow *)this);
+ wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl();
// Clip the DC so that you only draw on the non-client area
RECT rcBorder;
RECT rcClient;
theme->GetThemeBackgroundContentRect(
- hTheme, GetHdcOf(dc), EP_EDITTEXT, ETS_NORMAL, &rcBorder, &rcClient);
+ hTheme, GetHdcOf(*impl), EP_EDITTEXT, ETS_NORMAL, &rcBorder, &rcClient);
InflateRect(&rcClient, -1, -1);
- ::ExcludeClipRect(GetHdcOf(dc), rcClient.left, rcClient.top,
+ ::ExcludeClipRect(GetHdcOf(*impl), rcClient.left, rcClient.top,
rcClient.right, rcClient.bottom);
// Make sure the background is in a proper state
if (theme->IsThemeBackgroundPartiallyTransparent(hTheme, EP_EDITTEXT, ETS_NORMAL))
{
- theme->DrawThemeParentBackground(GetHwnd(), GetHdcOf(dc), &rcBorder);
+ theme->DrawThemeParentBackground(GetHwnd(), GetHdcOf(*impl), &rcBorder);
}
// Draw the border
// nState = ETS_READONLY;
else
nState = ETS_NORMAL;
- theme->DrawThemeBackground(hTheme, GetHdcOf(dc), EP_EDITTEXT, nState, &rcBorder, NULL);
+ theme->DrawThemeBackground(hTheme, GetHdcOf(*impl), EP_EDITTEXT, nState, &rcBorder, NULL);
}
}
break;
// wxWindow <-> HWND map
// ----------------------------------------------------------------------------
-wxWinHashTable *wxWinHandleHash = NULL;
-
-wxWindow *wxFindWinFromHandle(WXHWND hWnd)
+wxWindow *wxFindWinFromHandle(HWND hwnd)
{
- return (wxWindow*)wxWinHandleHash->Get((long)hWnd);
+ WindowHandles::const_iterator i = gs_windowHandles.find(hwnd);
+ return i == gs_windowHandles.end() ? NULL : i->second;
}
-void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win)
+void wxAssociateWinWithHandle(HWND hwnd, wxWindowMSW *win)
{
- // adding NULL hWnd is (first) surely a result of an error and
+ // adding NULL hwnd is (first) surely a result of an error and
// (secondly) breaks menu command processing
- wxCHECK_RET( hWnd != (HWND)NULL,
- wxT("attempt to add a NULL hWnd to window list ignored") );
+ 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) )
+ WindowHandles::const_iterator i = gs_windowHandles.find(hwnd);
+ if ( i != gs_windowHandles.end() )
{
- wxLogDebug(wxT("HWND %X already associated with another window (%s)"),
- (int) hWnd, win->GetClassInfo()->GetClassName());
+ if ( i->second != win )
+ {
+ wxLogDebug(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
}
- else
#endif // __WXDEBUG__
- if (!oldWin)
- {
- wxWinHandleHash->Put((long)hWnd, (wxWindow *)win);
- }
+
+ gs_windowHandles[hwnd] = win;
}
void wxRemoveHandleAssociation(wxWindowMSW *win)
{
- wxWinHandleHash->Delete((long)win->GetHWND());
+ gs_windowHandles.erase(GetHwndOf(win));
}
// ----------------------------------------------------------------------------
style,
x, y, w, h,
(HWND)MSWGetParent(),
- (HMENU)controlId,
+ (HMENU)wxUIntToPtr(controlId),
wxGetInstance(),
NULL // no extra data
);
#ifndef __WXMICROWIN__
LPNMHDR hdr = (LPNMHDR)lParam;
HWND hWnd = hdr->hwndFrom;
- wxWindow *win = wxFindWinFromHandle((WXHWND)hWnd);
+ wxWindow *win = wxFindWinFromHandle(hWnd);
// if the control is one of our windows, let it handle the message itself
if ( win )
}
#endif // wxUSE_CARET
-#if wxUSE_TEXTCTRL
- // If it's a wxTextCtrl don't send the event as it will be done
- // after the control gets to process it from EN_FOCUS handler
- if ( wxDynamicCastThis(wxTextCtrl) )
- {
- return false;
- }
-#endif // wxUSE_TEXTCTRL
-
wxFocusEvent event(wxEVT_SET_FOCUS, m_windowId);
event.SetEventObject(this);
}
#endif // wxUSE_CARET
-#if wxUSE_TEXTCTRL
- // If it's a wxTextCtrl don't send the event as it will be done
- // after the control gets to process it.
- wxTextCtrl *ctrl = wxDynamicCastThis(wxTextCtrl);
- if ( ctrl )
- {
- return false;
- }
-#endif
-
// Don't send the event when in the process of being deleted. This can
// only cause problems if the event handler tries to access the object.
if ( m_isBeingDeleted )
#ifdef __WXUNIVERSAL__
event.Skip();
#else
- HDC hDC = (HDC) wxPaintDC::FindDCInCache((wxWindow*) event.GetEventObject());
+ HDC hDC = (HDC) wxPaintDCImpl::FindDCInCache((wxWindow*) event.GetEventObject());
if (hDC != 0)
{
MSWDefWindowProc(WM_PAINT, (WPARAM) hDC, 0);
bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc)
{
wxDCTemp dc(hdc, GetClientSize());
+ wxDCTempImpl *impl = (wxDCTempImpl*) dc.GetImpl();
- dc.SetHDC(hdc);
- dc.SetWindow((wxWindow *)this);
+ impl->SetHDC(hdc);
+ impl->SetWindow((wxWindow *)this);
wxEraseEvent event(m_windowId, &dc);
event.SetEventObject(this);
bool rc = HandleWindowEvent(event);
// must be called manually as ~wxDC doesn't do anything for wxDCTemp
- dc.SelectOldObjects(hdc);
+ impl->SelectOldObjects(hdc);
return rc;
}
return;
}
+ wxDC *dc = event.GetDC();
+ if (!dc) return;
+ wxMSWDCImpl *impl = (wxMSWDCImpl*) dc->GetImpl();
// do default background painting
- if ( !DoEraseBackground(GetHdcOf(*event.GetDC())) )
+ if ( !DoEraseBackground(GetHdcOf(*impl)) )
{
// let the system paint the background
event.Skip();
::IsWindowVisible(hwndUnderMouse) &&
::IsWindowEnabled(hwndUnderMouse) )
{
- wxWindow *winUnderMouse = wxFindWinFromHandle((WXHWND)hwndUnderMouse);
+ wxWindow *winUnderMouse = wxFindWinFromHandle(hwndUnderMouse);
if ( winUnderMouse )
{
// translate the mouse coords to the other window coords
break;
default:
- if ( isVirtual )
- *isVirtual = false;
- vk = (WXWORD)wxk;
- break;
+ // no VkKeyScan() under CE unfortunately, we need to test how does
+ // it handle OEM keys
+#ifndef __WXWINCE__
+ // check to see if its one of the OEM key codes.
+ BYTE vks = LOBYTE(VkKeyScan(wxk));
+ if ( vks != 0xff )
+ {
+ vk = vks;
+ }
+ else
+#endif // !__WXWINCE__
+ {
+ if ( isVirtual )
+ *isVirtual = false;
+ vk = (WXWORD)wxk;
+ }
}
return vk;
}
-#ifndef SM_SWAPBUTTON
- #define SM_SWAPBUTTON 23
-#endif
-
// small helper for wxGetKeyState() and wxGetMouseState()
static inline bool wxIsKeyDown(WXWORD vk)
{
- switch (vk)
+ // SM_SWAPBUTTON is not available under CE, so don't swap buttons there
+#ifdef SM_SWAPBUTTON
+ if ( vk == VK_LBUTTON || vk == VK_RBUTTON )
{
- case VK_LBUTTON:
- if (GetSystemMetrics(SM_SWAPBUTTON)) vk = VK_RBUTTON;
- break;
- case VK_RBUTTON:
- if (GetSystemMetrics(SM_SWAPBUTTON)) vk = VK_LBUTTON;
- break;
+ if ( ::GetSystemMetrics(SM_SWAPBUTTON) )
+ {
+ if ( vk == VK_LBUTTON )
+ vk = VK_RBUTTON;
+ else // vk == VK_RBUTTON
+ vk = VK_LBUTTON;
+ }
}
+#endif // SM_SWAPBUTTON
+
// the low order bit indicates whether the key was pressed since the last
// call and the high order one indicates whether it is down right now and
// we only want that one
HWND hWnd = GetActiveWindow();
if ( hWnd != 0 )
{
- return wxFindWinFromHandle((WXHWND) hWnd);
+ return wxFindWinFromHandle(hWnd);
}
return NULL;
}
wxWindow *win = (wxWindow *)NULL;
if ( hwnd )
{
- win = wxFindWinFromHandle((WXHWND)hwnd);
+ win = wxFindWinFromHandle(hwnd);
if ( !win )
{
#if wxUSE_RADIOBOX
#endif
hwnd = ::GetParent(hwnd);
- win = wxFindWinFromHandle((WXHWND)hwnd);
+ win = wxFindWinFromHandle(hwnd);
}
return win;