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:
Vadim Zeitlin 2000-01-23 23:23:46 +00:00
parent ae80f83724
commit 8614c46755
13 changed files with 360 additions and 181 deletions

View File

@ -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:

View File

@ -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_

View File

@ -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

View File

@ -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,

View File

@ -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;

View File

@ -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;

View File

@ -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();

View File

@ -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

View File

@ -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) )

View File

@ -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__

View File

@ -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();
}

View File

@ -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)

View File

@ -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
{