1. '\n's in tooltip messages are handled (replaced by spaces anyhow, tooltip
made multiline if comctl32 supports it) 2. added wxTAB_TRAVERSAL to default wxScrolledWindow style 3. improved arrows handling in radiobox (still problems for multirow ones) 4. [Alt]-<mnemonic> works in nested panels as well now because we use WS_EX_CONTROLPARENT for all windows with wxTAB_TRAVERSAL style 5. tooltips for radioboxes work again, even if I'm not really satisfied with solution :-( but I spent 2 hours trying to make TTM_WINDOWFROMPOINT handler work and I don't have more time to waste on this. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@5620 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
ae80f83724
commit
8614c46755
@ -56,6 +56,8 @@ wxMSW:
|
||||
- wxTreeCtrl::IsVisible() bug fixed (thanks to Gary Chessun)
|
||||
- loading/saving big (> 32K) files in wxTextCtrl works
|
||||
- tooltips work with wxRadioBox
|
||||
- wxBitmap/wxIcon may be constructed from XPM included into a program, as in
|
||||
Unix ports
|
||||
- returning FALSE from OnPrintPage() aborts printing
|
||||
|
||||
wxGTK:
|
||||
|
@ -1,52 +1,65 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: scrolwin.h
|
||||
// Name: wx/generic/scrolwin.h
|
||||
// Purpose: wxScrolledWindow class
|
||||
// Author: Julian Smart
|
||||
// Modified by:
|
||||
// Created: 01/02/97
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) Julian Smart and Markus Holzem
|
||||
// Licence: wxWindows license
|
||||
// Licence: wxWindows license
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __SCROLWINH_G__
|
||||
#define __SCROLWINH_G__
|
||||
#ifndef _WX_GENERIC_SCROLLWIN_H_
|
||||
#define _WX_GENERIC_SCROLLWIN_H_
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "scrolwin.h"
|
||||
#pragma interface "scrolwin.h"
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers and constants
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include "wx/window.h"
|
||||
#include "wx/panel.h"
|
||||
|
||||
WXDLLEXPORT_DATA(extern const wxChar*) wxPanelNameStr;
|
||||
|
||||
// default scrolled window style
|
||||
#define wxScrolledWindowStyle (wxHSCROLL | wxVSCROLL | wxTAB_TRAVERSAL)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxScrolledWindow
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class WXDLLEXPORT wxScrolledWindow : public wxPanel
|
||||
{
|
||||
public:
|
||||
wxScrolledWindow();
|
||||
inline wxScrolledWindow(wxWindow *parent, wxWindowID id = -1,
|
||||
const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize,
|
||||
long style = wxHSCROLL|wxVSCROLL,
|
||||
const wxString& name = wxPanelNameStr)
|
||||
wxScrolledWindow(wxWindow *parent,
|
||||
wxWindowID id = -1,
|
||||
const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize,
|
||||
long style = wxScrolledWindowStyle,
|
||||
const wxString& name = wxPanelNameStr)
|
||||
{
|
||||
Create(parent, id, pos, size, style, name);
|
||||
Create(parent, id, pos, size, style, name);
|
||||
}
|
||||
|
||||
~wxScrolledWindow();
|
||||
|
||||
bool Create(wxWindow *parent, wxWindowID id,
|
||||
const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize,
|
||||
long style = wxHSCROLL|wxVSCROLL,
|
||||
const wxString& name = wxPanelNameStr);
|
||||
bool Create(wxWindow *parent,
|
||||
wxWindowID id,
|
||||
const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize,
|
||||
long style = wxScrolledWindowStyle,
|
||||
const wxString& name = wxPanelNameStr);
|
||||
|
||||
// Normally the wxScrolledWindow will scroll itself, but in
|
||||
// some rare occasions you might want it to scroll another
|
||||
// window (e.g. a child of it in order to scroll only a portion
|
||||
// Normally the wxScrolledWindow will scroll itself, but in
|
||||
// some rare occasions you might want it to scroll another
|
||||
// window (e.g. a child of it in order to scroll only a portion
|
||||
// the area between the scrollbars (spreadsheet: only cell area
|
||||
// will move).
|
||||
// will move).
|
||||
virtual void SetTargetWindow( wxWindow *target );
|
||||
virtual wxWindow *GetTargetWindow();
|
||||
|
||||
@ -56,21 +69,21 @@ public:
|
||||
virtual void SetScrollbars(int pixelsPerUnitX, int pixelsPerUnitY,
|
||||
int noUnitsX, int noUnitsY,
|
||||
int xPos = 0, int yPos = 0,
|
||||
bool noRefresh = FALSE );
|
||||
bool noRefresh = FALSE );
|
||||
|
||||
// Physically scroll the window
|
||||
virtual void Scroll(int x_pos, int y_pos);
|
||||
|
||||
#if WXWIN_COMPATIBILITY
|
||||
virtual void GetScrollUnitsPerPage(int *x_page, int *y_page) const;
|
||||
virtual void CalcUnscrolledPosition(int x, int y, float *xx, float *yy) const ;
|
||||
virtual void CalcUnscrolledPosition(int x, int y, float *xx, float *yy) const;
|
||||
#endif
|
||||
|
||||
int GetScrollPageSize(int orient) const ;
|
||||
int GetScrollPageSize(int orient) const;
|
||||
void SetScrollPageSize(int orient, int pageSize);
|
||||
|
||||
virtual void GetScrollPixelsPerUnit(int *x_unit, int *y_unit) const;
|
||||
|
||||
|
||||
// Enable/disable Windows scrolling in either direction.
|
||||
// If TRUE, wxWindows scrolls the canvas and only a bit of
|
||||
// the canvas is invalidated; no Clear() is necessary.
|
||||
@ -93,8 +106,8 @@ public:
|
||||
double GetScaleX() const { return m_scaleX; }
|
||||
double GetScaleY() const { return m_scaleY; }
|
||||
|
||||
virtual void CalcScrolledPosition(int x, int y, int *xx, int *yy) const ;
|
||||
virtual void CalcUnscrolledPosition(int x, int y, int *xx, int *yy) const ;
|
||||
virtual void CalcScrolledPosition(int x, int y, int *xx, int *yy) const;
|
||||
virtual void CalcUnscrolledPosition(int x, int y, int *xx, int *yy) const;
|
||||
|
||||
// Adjust the scrollbars
|
||||
virtual void AdjustScrollbars(void);
|
||||
@ -135,4 +148,4 @@ private:
|
||||
};
|
||||
|
||||
#endif
|
||||
// __SCROLWINH_G__
|
||||
// _WX_GENERIC_SCROLLWIN_H_
|
||||
|
@ -235,6 +235,15 @@ extern void PixelToHIMETRIC(LONG *x, LONG *y);
|
||||
// to invert the mask each time we pass one/get one to/from Windows
|
||||
extern HBITMAP wxInvertMask(HBITMAP hbmpMask, int w = 0, int h = 0);
|
||||
|
||||
// get (x, y) from DWORD - notice that HI/LOWORD can *not* be used because they
|
||||
// will fail on system with multiple monitors where the coords may be negative
|
||||
//
|
||||
// these macros are standard now (Win98) but some older headers don't have them
|
||||
#ifndef GET_X_LPARAM
|
||||
#define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
|
||||
#define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
|
||||
#endif // GET_X_LPARAM
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// small helper classes
|
||||
// ---------------------------------------------------------------------------
|
||||
@ -337,6 +346,12 @@ inline bool wxStyleHasBorder(long style)
|
||||
wxSUNKEN_BORDER | wxDOUBLE_BORDER)) != 0;
|
||||
}
|
||||
|
||||
// find the window for HWND which is part of some wxWindow, returns just the
|
||||
// corresponding wxWindow for HWND which just is one
|
||||
//
|
||||
// may return NULL
|
||||
extern wxWindow *wxGetWindowFromHWND(WXHWND hwnd);
|
||||
|
||||
#endif // wxUSE_GUI
|
||||
|
||||
#endif
|
||||
|
@ -89,6 +89,7 @@ public:
|
||||
int GetNumVer() const;
|
||||
int GetNumHor() const;
|
||||
|
||||
// compatibility ctor
|
||||
#if WXWIN_COMPATIBILITY
|
||||
wxRadioBox(wxWindow *parent, wxFunction func, const char *title,
|
||||
int x = -1, int y = -1, int width = -1, int height = -1,
|
||||
|
@ -58,6 +58,9 @@ public:
|
||||
virtual bool MSWOnScroll(int orientation, WXWORD wParam,
|
||||
WXWORD pos, WXHWND control);
|
||||
|
||||
// a wxSpinButton can't do anything useful with focus, only wxSpinCtrl can
|
||||
virtual bool AcceptsFocus() const { return FALSE; }
|
||||
|
||||
protected:
|
||||
virtual wxSize DoGetBestSize() const;
|
||||
|
||||
|
@ -65,6 +65,8 @@ public:
|
||||
virtual bool Enable(bool enable = TRUE);
|
||||
virtual bool Show(bool show = TRUE);
|
||||
|
||||
virtual bool AcceptsFocus() const { return TRUE; }
|
||||
|
||||
protected:
|
||||
virtual void DoMoveWindow(int x, int y, int width, int height);
|
||||
virtual wxSize DoGetBestSize() const;
|
||||
|
@ -31,14 +31,19 @@ public:
|
||||
// set the delay after which the tooltip appears
|
||||
static void SetDelay(long milliseconds);
|
||||
|
||||
// implementation
|
||||
// implementation only from now on
|
||||
// -------------------------------
|
||||
|
||||
// should be called in responde to WM_MOUSEMOVE
|
||||
void RelayEvent(WXMSG *msg);
|
||||
|
||||
private:
|
||||
// the one and only one tooltip control we use - never access it directly
|
||||
// but use GetToolTipCtrl() which will create it when needed
|
||||
static WXHWND ms_hwndTT;
|
||||
|
||||
// create the tooltip ctrl if it doesn't exist yet and return its HWND
|
||||
WXHWND GetToolTipCtrl();
|
||||
static WXHWND GetToolTipCtrl();
|
||||
|
||||
// remove this tooltip from the tooltip control
|
||||
void Remove();
|
||||
|
@ -121,11 +121,11 @@ void wxPanel::OnSize(wxSizeEvent& WXUNUSED(event))
|
||||
|
||||
void wxPanel::OnNavigationKey( wxNavigationKeyEvent& event )
|
||||
{
|
||||
// the event is propagated downwards if the event emitter was our parent
|
||||
bool goingDown = event.GetEventObject() == GetParent();
|
||||
const wxWindowList& children = GetChildren();
|
||||
|
||||
// we're not interested in "notebook page change" events here
|
||||
if ( event.IsWindowChange() )
|
||||
// there is not much to do if we don't have children and we're not
|
||||
// interested in "notebook page change" events here
|
||||
if ( !children.GetCount() || event.IsWindowChange() )
|
||||
{
|
||||
wxWindow *parent = GetParent();
|
||||
if ( !parent || !parent->GetEventHandler()->ProcessEvent(event) )
|
||||
@ -143,7 +143,8 @@ void wxPanel::OnNavigationKey( wxNavigationKeyEvent& event )
|
||||
// next acceptable child
|
||||
wxWindowList::Node *node, *start_node;
|
||||
|
||||
const wxWindowList& children = GetChildren();
|
||||
// the event is propagated downwards if the event emitter was our parent
|
||||
bool goingDown = event.GetEventObject() == GetParent();
|
||||
|
||||
// we should start from the first/last control and not from the one which
|
||||
// had focus the last time if we're propagating the event downwards because
|
||||
|
@ -67,6 +67,10 @@
|
||||
#include "wx/resource.h"
|
||||
#endif
|
||||
|
||||
#if wxUSE_TOOLTIPS
|
||||
#include "wx/tooltip.h"
|
||||
#endif // wxUSE_TOOLTIPS
|
||||
|
||||
// OLE is used for drag-and-drop, clipboard, OLE Automation...
|
||||
#ifndef wxUSE_NORLANDER_HEADERS
|
||||
#if defined(__GNUWIN32__) || defined(__SC__) || defined(__SALFORDC__)
|
||||
@ -959,19 +963,24 @@ bool wxApp::ProcessMessage(WXMSG *wxmsg)
|
||||
{
|
||||
MSG *msg = (MSG *)wxmsg;
|
||||
HWND hWnd = msg->hwnd;
|
||||
wxWindow *wndThis = wxFindWinFromHandle((WXHWND)hWnd), *wnd;
|
||||
wxWindow *wndThis = wxGetWindowFromHWND((WXHWND)hWnd);
|
||||
|
||||
// for some composite controls (like a combobox), wndThis might be NULL
|
||||
// because the subcontrol is not a wxWindow, but only the control itself
|
||||
// is - try to catch this case
|
||||
while ( hWnd && !wndThis )
|
||||
#if wxUSE_TOOLTIPS
|
||||
// we must relay WM_MOUSEMOVE events to the tooltip ctrl if we want it to
|
||||
// popup the tooltip bubbles
|
||||
if ( wndThis && (msg->message == WM_MOUSEMOVE) )
|
||||
{
|
||||
hWnd = ::GetParent(hWnd);
|
||||
wndThis = wxFindWinFromHandle((WXHWND)hWnd);
|
||||
wxToolTip *tt = wndThis->GetToolTip();
|
||||
if ( tt )
|
||||
{
|
||||
tt->RelayEvent(wxmsg);
|
||||
}
|
||||
}
|
||||
#endif // wxUSE_TOOLTIPS
|
||||
|
||||
// Try translations first; find the youngest window with
|
||||
// a translation table.
|
||||
wxWindow *wnd;
|
||||
for ( wnd = wndThis; wnd; wnd = wnd->GetParent() )
|
||||
{
|
||||
if ( wnd->MSWTranslateMessage(wxmsg) )
|
||||
|
@ -38,24 +38,36 @@
|
||||
#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
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@ -74,7 +86,7 @@ LRESULT APIENTRY _EXPORT wxRadioBtnWndProc(HWND hWnd,
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// the pointer to standard radio button wnd proc
|
||||
static WXFARPROC s_wndprocRadioBtn = (WXFARPROC)NULL;
|
||||
static WNDPROC s_wndprocRadioBtn = (WNDPROC)NULL;
|
||||
|
||||
#endif // __WIN32__
|
||||
|
||||
@ -668,15 +680,17 @@ void wxRadioBox::Command(wxCommandEvent & event)
|
||||
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__
|
||||
@ -706,14 +720,21 @@ bool wxRadioBox::SetFont(const wxFont& font)
|
||||
::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
|
||||
{
|
||||
@ -727,7 +748,7 @@ long wxRadioBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
|
||||
|
||||
return (WXHBRUSH)brush->GetResourceHandle();
|
||||
}
|
||||
#endif
|
||||
#endif // Win32
|
||||
|
||||
// This is required for the radiobox to be sensitive to mouse input,
|
||||
// e.g. for Dialog Editor.
|
||||
@ -743,11 +764,10 @@ long wxRadioBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
|
||||
if (yPos < 10)
|
||||
return (long)HTCLIENT;
|
||||
}
|
||||
// fall through
|
||||
|
||||
default:
|
||||
return wxControl::MSWWindowProc(nMsg, wParam, lParam);
|
||||
break;
|
||||
}
|
||||
|
||||
return wxControl::MSWWindowProc(nMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@ -757,95 +777,103 @@ long wxRadioBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM 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);
|
||||
|
||||
wxCHECK_MSG( radiobox, 0, wxT("radio button without radio box?") );
|
||||
|
||||
#if wxUSE_TOOLTIPS && !defined(__GNUWIN32__)
|
||||
if ( msg == WM_NOTIFY )
|
||||
{
|
||||
NMHDR* hdr = (NMHDR *)lParam;
|
||||
if ( (int)hdr->code == TTN_NEEDTEXT )
|
||||
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
|
||||
{
|
||||
wxToolTip *tt = radiobox->GetToolTip();
|
||||
if ( tt )
|
||||
{
|
||||
TOOLTIPTEXT *ttt = (TOOLTIPTEXT *)lParam;
|
||||
ttt->lpszText = (wxChar *)tt->GetTip().c_str();
|
||||
|
||||
processed = TRUE;
|
||||
}
|
||||
long lDlgCode = ::CallWindowProc(s_wndprocRadioBtn, hwnd,
|
||||
message, wParam, lParam);
|
||||
return lDlgCode | DLGC_WANTARROWS;
|
||||
}
|
||||
}
|
||||
else // msg == WM_KEYDOWN
|
||||
#endif // wxUSE_TOOLTIPS
|
||||
{
|
||||
processed = TRUE;
|
||||
|
||||
int sel = radiobox->GetSelection();
|
||||
|
||||
switch ( wParam )
|
||||
#if wxUSE_TOOLTIPS
|
||||
case WM_NOTIFY:
|
||||
{
|
||||
case VK_UP:
|
||||
sel--;
|
||||
break;
|
||||
NMHDR* hdr = (NMHDR *)lParam;
|
||||
if ( (int)hdr->code == TTN_NEEDTEXT )
|
||||
{
|
||||
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;
|
||||
|
||||
case VK_RIGHT:
|
||||
sel += radiobox->GetNumVer();
|
||||
break;
|
||||
|
||||
case VK_TAB:
|
||||
wxToolTip *tooltip = radiobox->GetToolTip();
|
||||
if ( tooltip )
|
||||
{
|
||||
wxNavigationKeyEvent event;
|
||||
event.SetDirection(!(::GetKeyState(VK_SHIFT) & 0x100));
|
||||
event.SetWindowChange(FALSE);
|
||||
event.SetEventObject(radiobox);
|
||||
|
||||
if ( radiobox->GetEventHandler()->ProcessEvent(event) )
|
||||
return 0;
|
||||
TOOLTIPTEXT *ttt = (TOOLTIPTEXT *)lParam;
|
||||
ttt->lpszText = (wxChar *)tooltip->GetTip().c_str();
|
||||
}
|
||||
// fall through
|
||||
|
||||
default:
|
||||
processed = FALSE;
|
||||
}
|
||||
|
||||
if ( processed )
|
||||
{
|
||||
if ( sel >= 0 && sel < radiobox->Number() )
|
||||
{
|
||||
radiobox->SetSelection(sel);
|
||||
|
||||
// emulate the button click
|
||||
radiobox->SendNotificationEvent();
|
||||
// processed
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif // wxUSE_TOOLTIPS
|
||||
|
||||
case WM_KEYDOWN:
|
||||
{
|
||||
wxRadioBox *radiobox = (wxRadioBox *)
|
||||
::GetWindowLong(hwnd, GWL_USERDATA);
|
||||
|
||||
wxCHECK_MSG( radiobox, 0, wxT("radio button without radio box?") );
|
||||
|
||||
bool processed = TRUE;
|
||||
|
||||
int selOld = radiobox->GetSelection();
|
||||
int selNew = selOld;
|
||||
|
||||
switch ( wParam )
|
||||
{
|
||||
case VK_UP:
|
||||
selNew--;
|
||||
break;
|
||||
|
||||
case VK_LEFT:
|
||||
selNew -= radiobox->GetNumVer();
|
||||
break;
|
||||
|
||||
case VK_DOWN:
|
||||
selNew++;
|
||||
break;
|
||||
|
||||
case VK_RIGHT:
|
||||
selNew += radiobox->GetNumVer();
|
||||
break;
|
||||
|
||||
default:
|
||||
processed = FALSE;
|
||||
}
|
||||
|
||||
if ( processed )
|
||||
{
|
||||
// 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();
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( processed )
|
||||
return 0;
|
||||
|
||||
return ::CallWindowProc(CASTWNDPROC s_wndprocRadioBtn, hwnd, msg, wParam, lParam);
|
||||
return ::CallWindowProc(s_wndprocRadioBtn, hwnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
#endif // __WIN32__
|
||||
|
@ -893,30 +893,19 @@ void wxTextCtrl::OnChar(wxKeyEvent& event)
|
||||
// ourselves the fact that we got here means that the user code
|
||||
// decided to skip processing of this TAB - probably to let it
|
||||
// do its default job.
|
||||
//
|
||||
// NB: Notice that Ctrl-Tab is handled elsewhere and Alt-Tab is
|
||||
// handled by Windows
|
||||
{
|
||||
wxNavigationKeyEvent eventNav;
|
||||
eventNav.SetDirection(!event.ShiftDown());
|
||||
eventNav.SetWindowChange(FALSE);
|
||||
eventNav.SetWindowChange(event.ControlDown());
|
||||
eventNav.SetEventObject(this);
|
||||
|
||||
if ( GetParent()->GetEventHandler()->ProcessEvent(eventNav) )
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
event.Skip();
|
||||
return;
|
||||
}
|
||||
|
||||
// don't just call event.Skip() because this will cause TABs and ENTERs
|
||||
// be passed upwards and we don't always want this - instead process it
|
||||
// right here
|
||||
|
||||
// FIXME
|
||||
// no, we didn't process it
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
@ -36,14 +36,20 @@
|
||||
#include <commctrl.h>
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32_IE
|
||||
// minimal set of features by default
|
||||
#define _WIN32_IE 0x0200
|
||||
#endif
|
||||
|
||||
// VZ: normally, the trick with subclassing the tooltip control and processing
|
||||
// TTM_WINDOWFROMPOINT should work but, somehow, it doesn't. I leave the
|
||||
// code here for now (but it's not compiled) in case we need it later.
|
||||
//
|
||||
// For now, instead of this, we just add all radiobox buttons to the
|
||||
// tooltip control as well (see SetWindow) - this is probably less
|
||||
// efficient, but it works.
|
||||
#define wxUSE_TTM_WINDOWFROMPOINT 1
|
||||
// For now I use an ugly workaround and process TTN_NEEDTEXT directly in
|
||||
// radio button wnd proc - fixing TTM_WINDOWFROMPOINT code would be nice
|
||||
// because it would then work for all controls, not only radioboxes but for
|
||||
// now I don't understand what's wrong with it...
|
||||
#define wxUSE_TTM_WINDOWFROMPOINT 0
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// global variables
|
||||
@ -83,7 +89,7 @@ public:
|
||||
// version of it. So we always use the old size - if we ever start
|
||||
// using our lParam member, we'd have to check for comctl32 version
|
||||
// during run-time
|
||||
#if defined(_WIN32_IE) && (_WIN32_IE >= 0x0300)
|
||||
#if _WIN32_IE >= 0x0300
|
||||
cbSize = sizeof(TOOLINFO) - sizeof(LPARAM);
|
||||
#else // old headers
|
||||
cbSize = sizeof(TOOLINFO);
|
||||
@ -139,27 +145,36 @@ LRESULT APIENTRY wxToolTipWndProc(HWND hwndTT,
|
||||
if ( msg == TTM_WINDOWFROMPOINT )
|
||||
{
|
||||
LPPOINT ppt = (LPPOINT)lParam;
|
||||
// is the window under control a wxWindow?
|
||||
|
||||
// the window on which event occured
|
||||
HWND hwnd = ::WindowFromPoint(*ppt);
|
||||
|
||||
// return a HWND correspondign to wxWindow because only wxWindows are
|
||||
// associated with tooltips using TTM_ADDTOOL
|
||||
while ( hwnd && !wxFindWinFromHandle((WXHWND)hwnd) )
|
||||
{
|
||||
hwnd = ::GetParent(hwnd);
|
||||
}
|
||||
OutputDebugString("TTM_WINDOWFROMPOINT: ");
|
||||
OutputDebugString(wxString::Format("0x%08x => ", hwnd));
|
||||
|
||||
if ( hwnd )
|
||||
// return a HWND corresponding to a wxWindow because only wxWindows are
|
||||
// associated with tooltips using TTM_ADDTOOL
|
||||
wxWindow *win = wxGetWindowFromHWND((WXHWND)hwnd);
|
||||
|
||||
if ( win )
|
||||
{
|
||||
hwnd = GetHwndOf(win);
|
||||
OutputDebugString(wxString::Format("0x%08x\r\n", hwnd));
|
||||
|
||||
#if 0
|
||||
// modify the point too!
|
||||
RECT rect;
|
||||
GetWindowRect(hwnd, &rect);
|
||||
|
||||
ppt->x = rect.left;
|
||||
ppt->y = rect.top;
|
||||
|
||||
ppt->x = (rect.right - rect.left) / 2;
|
||||
ppt->y = (rect.bottom - rect.top) / 2;
|
||||
#endif // 0
|
||||
return (LRESULT)hwnd;
|
||||
}
|
||||
else
|
||||
{
|
||||
OutputDebugString("no window\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
return ::CallWindowProc(CASTWNDPROC gs_wndprocToolTip, hwndTT, msg, wParam, lParam);
|
||||
@ -268,6 +283,59 @@ void wxToolTip::Add(WXHWND hWnd)
|
||||
{
|
||||
wxLogDebug(_T("Failed to create the tooltip '%s'"), m_text.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// check for multiline toopltip
|
||||
int index = m_text.Find(_T('\n'));
|
||||
|
||||
if ( index != wxNOT_FOUND )
|
||||
{
|
||||
#if _WIN32_IE >= 0x0300
|
||||
if ( wxTheApp->GetComCtl32Version() >= 470 )
|
||||
{
|
||||
// use TTM_SETMAXWIDTH to make tooltip multiline using the
|
||||
// extent of its first line as max value
|
||||
HFONT hfont = (HFONT)SendTooltipMessage(GetToolTipCtrl(),
|
||||
WM_GETFONT,
|
||||
0, 0);
|
||||
if ( !hfont )
|
||||
{
|
||||
hfont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
|
||||
if ( !hfont )
|
||||
{
|
||||
wxLogLastError("GetStockObject(DEFAULT_GUI_FONT)");
|
||||
}
|
||||
}
|
||||
|
||||
HDC hdc = CreateCompatibleDC(NULL);
|
||||
if ( !hdc )
|
||||
{
|
||||
wxLogLastError("CreateCompatibleDC(NULL)");
|
||||
}
|
||||
|
||||
if ( !SelectObject(hdc, hfont) )
|
||||
{
|
||||
wxLogLastError("SelectObject(hfont)");
|
||||
}
|
||||
|
||||
SIZE sz;
|
||||
if ( !GetTextExtentPoint(hdc, m_text, index, &sz) )
|
||||
{
|
||||
wxLogLastError("GetTextExtentPoint");
|
||||
}
|
||||
|
||||
DeleteDC(hdc);
|
||||
|
||||
SendTooltipMessage(GetToolTipCtrl(), TTM_SETMAXTIPWIDTH,
|
||||
0, (void *)sz.cx);
|
||||
}
|
||||
#endif // comctl32.dll >= 4.70
|
||||
|
||||
// replace the '\n's with spaces because otherwise they appear as
|
||||
// unprintable characters in the tooltip string
|
||||
m_text.Replace(_T("\n"), _T(" "));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wxToolTip::SetWindow(wxWindow *win)
|
||||
@ -282,24 +350,30 @@ void wxToolTip::SetWindow(wxWindow *win)
|
||||
Add(m_window->GetHWND());
|
||||
}
|
||||
|
||||
#if 1 //!wxUSE_TTM_WINDOWFROMPOINT
|
||||
// and all of its subcontrols (e.g. radiobuttons in a radiobox) as well
|
||||
wxControl *control = wxDynamicCast(m_window, wxControl);
|
||||
if ( control )
|
||||
{
|
||||
size_t count = control->GetSubcontrols().GetCount();
|
||||
const wxArrayLong& subcontrols = control->GetSubcontrols();
|
||||
size_t count = subcontrols.GetCount();
|
||||
for ( size_t n = 0; n < count; n++ )
|
||||
{
|
||||
wxWindowID id = control->GetSubcontrols()[n];
|
||||
int id = subcontrols[n];
|
||||
HWND hwnd = GetDlgItem(GetHwndOf(m_window), id);
|
||||
|
||||
if ( hwnd )
|
||||
if ( !hwnd )
|
||||
{
|
||||
Add((WXHWND)hwnd);
|
||||
// may be it's a child of parent of the control, in fact?
|
||||
// (radiobuttons are subcontrols, i.e. children of the radiobox
|
||||
// for wxWindows but are its siblings at Windows level)
|
||||
hwnd = GetDlgItem(GetHwndOf(m_window->GetParent()), id);
|
||||
}
|
||||
|
||||
// must have it by now!
|
||||
wxASSERT_MSG( hwnd, _T("no hwnd for subcontrol?") );
|
||||
|
||||
Add((WXHWND)hwnd);
|
||||
}
|
||||
}
|
||||
#endif // !wxUSE_TTM_WINDOWFROMPOINT
|
||||
}
|
||||
|
||||
void wxToolTip::SetTip(const wxString& tip)
|
||||
|
@ -100,16 +100,6 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// macros
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// standard macros missing from some compilers headers
|
||||
#ifndef GET_X_LPARAM
|
||||
#define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
|
||||
#define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
|
||||
#endif // GET_X_LPARAM
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// global variables
|
||||
// ---------------------------------------------------------------------------
|
||||
@ -2293,6 +2283,13 @@ bool wxWindow::MSWCreate(int id,
|
||||
if ( width > -1 ) width1 = width;
|
||||
if ( height > -1 ) height1 = height;
|
||||
|
||||
// if we have wxTAB_TRAVERSAL style, we want WS_EX_CONTROLPARENT or
|
||||
// IsDialogMessage() won't work for us
|
||||
if ( GetWindowStyleFlag() & wxTAB_TRAVERSAL )
|
||||
{
|
||||
extendedStyle |= WS_EX_CONTROLPARENT;
|
||||
}
|
||||
|
||||
HWND hParent = (HWND)NULL;
|
||||
if ( parent )
|
||||
hParent = (HWND) parent->GetHWND();
|
||||
@ -3631,6 +3628,45 @@ wxWindow *wxGetActiveWindow()
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extern wxWindow *wxGetWindowFromHWND(WXHWND hWnd)
|
||||
{
|
||||
HWND hwnd = (HWND)hWnd;
|
||||
|
||||
// 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;
|
||||
if ( hwnd )
|
||||
{
|
||||
win = wxFindWinFromHandle((WXHWND)hwnd);
|
||||
if ( !win )
|
||||
{
|
||||
// native radiobuttons return DLGC_RADIOBUTTON here and for any
|
||||
// wxWindow class which overrides WM_GETDLGCODE processing to
|
||||
// do it as well, win would be already non NULL
|
||||
if ( ::SendMessage((HWND)hwnd, WM_GETDLGCODE,
|
||||
0, 0) & DLGC_RADIOBUTTON )
|
||||
{
|
||||
win = (wxWindow *)::GetWindowLong(hwnd, GWL_USERDATA);
|
||||
}
|
||||
else
|
||||
{
|
||||
// hwnd is not a wxWindow, try its parent next below
|
||||
hwnd = ::GetParent(hwnd);
|
||||
}
|
||||
}
|
||||
//else: it's a wxRadioButton, not a radiobutton from wxRadioBox
|
||||
}
|
||||
|
||||
while ( hwnd && !win )
|
||||
{
|
||||
win = wxFindWinFromHandle((WXHWND)hwnd);
|
||||
hwnd = ::GetParent(hwnd);
|
||||
}
|
||||
|
||||
return win;
|
||||
}
|
||||
|
||||
// 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;
|
||||
@ -3646,11 +3682,12 @@ void wxSetKeyboardHook(bool doIt)
|
||||
wxTheKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC) wxTheKeyboardHookProc, wxGetInstance(),
|
||||
|
||||
#if defined(__WIN32__) && !defined(__TWIN32__)
|
||||
GetCurrentThreadId());
|
||||
GetCurrentThreadId()
|
||||
// (DWORD)GetCurrentProcess()); // This is another possibility. Which is right?
|
||||
#else
|
||||
GetCurrentTask());
|
||||
GetCurrentTask()
|
||||
#endif
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user