#include "wx/msw/private.h"
#if wxUSE_TOOLTIPS
-
-#ifndef __GNUWIN32__
- #include <commctrl.h>
-#endif
-
+// #ifndef __GNUWIN32__
+ #include <commctrl.h>
+// #endif
#include "wx/tooltip.h"
#endif // wxUSE_TOOLTIPS
IMPLEMENT_DYNAMIC_CLASS(wxRadioBox, wxControl)
-// VZ: the new behaviour is to create the radio buttons as children of the
-// radiobox instead of creating them as children of the radiobox' parent.
+// there are two possible ways to create the radio buttons: either as children
+// of the radiobox or as siblings of it - allow playing with both variants for
+// now, eventually we will choose the best one for our purposes
//
-// This seems more logical, more consistent with what other frameworks do
-// and allows tooltips to work with radioboxes, so there should be no
-// reason to revert to the backward compatible behaviour - but I still
-// leave this possibility just in case.
-
+// two main problems are the keyboard navigation inside the radiobox (arrows
+// should switch between buttons, not pass focus to the next control) and the
+// tooltips - a tooltip is associated with the radiobox itself, not the
+// children...
+//
+// the problems with setting this to 1:
+// a) Alt-<mnemonic of radiobox> isn't handled properly by IsDialogMessage()
+// because it sets focus to the next control accepting it which is not a
+// radio button but a radiobox sibling in this case - the only solution to
+// this would be to handle Alt-<mnemonic> ourselves
+// b) the problems with setting radiobox colours under Win98/2K were reported
+// but I couldn't reproduce it so I have no idea about what causes it
+//
+// the problems with setting this to 0:
+// a) the tooltips are not shown for the radiobox - possible solution: make
+// TTM_WINDOWFROMPOS handling code in msw/tooltip.cpp work (easier said than
+// done because I don't know why it doesn't work)
#define RADIOBTN_PARENT_IS_RADIOBOX 0
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// the pointer to standard radio button wnd proc
-static WXFARPROC s_wndprocRadioBtn = (WXFARPROC)NULL;
+static WNDPROC s_wndprocRadioBtn = (WNDPROC)NULL;
#endif // __WIN32__
ProcessCommand (event);
}
+// NB: if this code is changed, wxGetWindowForHWND() which relies on having the
+// radiobox pointer in GWL_USERDATA for radio buttons must be updated too!
void wxRadioBox::SubclassRadioButton(WXHWND hWndBtn)
{
+ // No GWL_USERDATA in Win16, so omit this subclassing.
#ifdef __WIN32__
HWND hwndBtn = (HWND)hWndBtn;
if ( !s_wndprocRadioBtn )
- s_wndprocRadioBtn = (WXFARPROC)::GetWindowLong(hwndBtn, GWL_WNDPROC);
+ s_wndprocRadioBtn = (WNDPROC)::GetWindowLong(hwndBtn, GWL_WNDPROC);
- // No GWL_USERDATA in Win16, so omit this subclassing.
::SetWindowLong(hwndBtn, GWL_WNDPROC, (long)wxRadioBtnWndProc);
::SetWindowLong(hwndBtn, GWL_USERDATA, (long)this);
#endif // __WIN32__
::SendMessage((HWND)m_radioButtons[n], WM_SETFONT, (WPARAM)hfont, 0L);
}
+ // this is needed because otherwise the buttons are not redrawn correctly
+ Refresh();
+
return TRUE;
}
+// ----------------------------------------------------------------------------
+// our window proc
+// ----------------------------------------------------------------------------
+
long wxRadioBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
{
switch ( nMsg )
{
-#ifndef __WIN16__
+#ifdef __WIN32__
case WM_CTLCOLORSTATIC:
// set the colour of the radio buttons to be the same as ours
{
return (WXHBRUSH)brush->GetResourceHandle();
}
-#endif
+#endif // Win32
// This is required for the radiobox to be sensitive to mouse input,
// e.g. for Dialog Editor.
if (yPos < 10)
return (long)HTCLIENT;
}
- // fall through
-
- default:
- return wxControl::MSWWindowProc(nMsg, wParam, lParam);
+ break;
}
+
+ return wxControl::MSWWindowProc(nMsg, wParam, lParam);
}
// ---------------------------------------------------------------------------
#ifdef __WIN32__
LRESULT APIENTRY _EXPORT wxRadioBtnWndProc(HWND hwnd,
- UINT msg,
+ UINT message,
WPARAM wParam,
LPARAM lParam)
{
- bool processed = FALSE;
- if ( msg == WM_KEYDOWN
-#if wxUSE_TOOLTIPS
- || msg == WM_NOTIFY
-#endif // wxUSE_TOOLTIPS
- )
+ switch ( message )
{
- wxRadioBox *radiobox = (wxRadioBox *)::GetWindowLong(hwnd, GWL_USERDATA);
+ case WM_GETDLGCODE:
+ // we must tell IsDialogMessage()/our kbd processing code that we
+ // want to process arrows ourselves because neither of them is
+ // smart enough to handle arrows properly for us
+ {
+ long lDlgCode = ::CallWindowProc(CASTWNDPROC s_wndprocRadioBtn, hwnd,
+ message, wParam, lParam);
- wxCHECK_MSG( radiobox, 0, wxT("radio button without radio box?") );
+ return lDlgCode | DLGC_WANTARROWS;
+ }
-#if wxUSE_TOOLTIPS && !defined(__GNUWIN32__)
- if ( msg == WM_NOTIFY )
- {
- NMHDR* hdr = (NMHDR *)lParam;
- if ( (int)hdr->code == TTN_NEEDTEXT )
+#if wxUSE_TOOLTIPS
+ case WM_NOTIFY:
{
- wxToolTip *tt = radiobox->GetToolTip();
- if ( tt )
+ NMHDR* hdr = (NMHDR *)lParam;
+ if ( (int)hdr->code == TTN_NEEDTEXT )
{
- TOOLTIPTEXT *ttt = (TOOLTIPTEXT *)lParam;
- ttt->lpszText = (wxChar *)tt->GetTip().c_str();
+ wxRadioBox *radiobox = (wxRadioBox *)
+ ::GetWindowLong(hwnd, GWL_USERDATA);
- processed = TRUE;
+ wxCHECK_MSG( radiobox, 0,
+ wxT("radio button without radio box?") );
+
+ wxToolTip *tooltip = radiobox->GetToolTip();
+ if ( tooltip )
+ {
+ TOOLTIPTEXT *ttt = (TOOLTIPTEXT *)lParam;
+ ttt->lpszText = (wxChar *)tooltip->GetTip().c_str();
+ }
+
+ // processed
+ return 0;
}
}
- }
- else // msg == WM_KEYDOWN
+ break;
#endif // wxUSE_TOOLTIPS
- {
- processed = TRUE;
- int sel = radiobox->GetSelection();
-
- switch ( wParam )
+ case WM_KEYDOWN:
{
- case VK_UP:
- sel--;
- break;
+ wxRadioBox *radiobox = (wxRadioBox *)
+ ::GetWindowLong(hwnd, GWL_USERDATA);
- case VK_LEFT:
- sel -= radiobox->GetNumVer();
- break;
+ wxCHECK_MSG( radiobox, 0, wxT("radio button without radio box?") );
- case VK_DOWN:
- sel++;
- break;
+ bool processed = TRUE;
- case VK_RIGHT:
- sel += radiobox->GetNumVer();
- break;
+ int selOld = radiobox->GetSelection();
+ int selNew = selOld;
- case VK_TAB:
- {
- wxNavigationKeyEvent event;
- event.SetDirection(!(::GetKeyState(VK_SHIFT) & 0x100));
- event.SetWindowChange(FALSE);
- event.SetEventObject(radiobox);
+ switch ( wParam )
+ {
+ case VK_UP:
+ selNew--;
+ break;
- if ( radiobox->GetEventHandler()->ProcessEvent(event) )
- return 0;
- }
- // fall through
+ case VK_LEFT:
+ selNew -= radiobox->GetNumVer();
+ break;
- default:
- processed = FALSE;
- }
+ case VK_DOWN:
+ selNew++;
+ break;
- if ( processed )
- {
- if ( sel >= 0 && sel < radiobox->Number() )
+ case VK_RIGHT:
+ selNew += radiobox->GetNumVer();
+ break;
+
+ default:
+ processed = FALSE;
+ }
+
+ if ( processed )
{
- radiobox->SetSelection(sel);
+ // ensure that selNew is in range [0..num)
+ int num = radiobox->Number();
+ selNew += num;
+ selNew %= num;
+
+ if ( selNew != selOld )
+ {
+ radiobox->SetSelection(selNew);
+
+ // emulate the button click
+ radiobox->SendNotificationEvent();
- // emulate the button click
- radiobox->SendNotificationEvent();
+ return 0;
+ }
}
}
- }
}
- if ( processed )
- return 0;
-
- return ::CallWindowProc(CASTWNDPROC s_wndprocRadioBtn, hwnd, msg, wParam, lParam);
+ return ::CallWindowProc(CASTWNDPROC s_wndprocRadioBtn, hwnd, message, wParam, lParam);
}
#endif // __WIN32__