1. exchanged binary ROPs wxSET/wxCLEAR meaning for wxMSW to match wxGTK

2. bug with multiline messages in wxLogGui fixed
3. wxLogGui visual enhancements (for MSW, don't know how it looks elsewhere)
4. fixed 2 nice (i.e. BIG) memory leaks in wxImage::Rotate()
5. modified the text sample to show the mouse events too
6. documented strange behaviour of LEAVE_WINDOW mouse event under MSW


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@5958 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2000-02-11 02:41:07 +00:00
parent 1d81a219db
commit 4aff28fc9b
7 changed files with 195 additions and 84 deletions

View File

@@ -36,7 +36,7 @@ void MyThread::Foo(void)
// Call GUI here: // Call GUI here:
my_window->DrawSomething(); my_window->DrawSomething();
wxMutexGuiLeave(); wxMutexGuiLeave();
} }
\end{verbatim} \end{verbatim}
@@ -571,6 +571,24 @@ if (s)
\membersection{::wxGetNumberFromUser}\label{wxgetnumberfromuser} \membersection{::wxGetNumberFromUser}\label{wxgetnumberfromuser}
\func{wxColour}{wxGetColourFromUser}{\param{wxWindow *}{parent}, \parent{const wxColour\& }{colInit}}
Shows the colour selection dialog and returns the colour selected by user or
invalid colour (use \helpref{wxColour::Ok}{wxcolourok} to test whether a colour
is valid) if the dialog was cancelled.
\wxheading{Parameters}
\docparam{parent}{The parent window for the colour selection dialog}
\docparam{colInit}{If given, this will be the colour initially selected in the dialog.}
\wxheading{Include files}
<wx/colordlg.h>
\membersection{::wxGetNumberFromUser}\label{wxgetnumberfromuser}
\func{long}{wxGetNumberFromUser}{ \func{long}{wxGetNumberFromUser}{
\param{const wxString\& }{message}, \param{const wxString\& }{message},
\param{const wxString\& }{prompt}, \param{const wxString\& }{prompt},

View File

@@ -3,6 +3,12 @@
This event class contains information about mouse events. This event class contains information about mouse events.
See \helpref{wxWindow::OnMouseEvent}{wxwindowonmouseevent}. See \helpref{wxWindow::OnMouseEvent}{wxwindowonmouseevent}.
{\bf NB: } Note that under Windows mouse enter and leave events are not natively supported
by the system but are generated by wxWindows itself. This has several
drawbacks: the LEAVE\_WINDOW event might be received some time after the mouse
left the window and the state variables for it may have changed during this
time.
\wxheading{Derived from} \wxheading{Derived from}
\helpref{wxEvent}{wxevent} \helpref{wxEvent}{wxevent}

View File

@@ -1,10 +1,10 @@
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// Name: controls.cpp // Name: text.cpp
// Purpose: TextCtrl wxWindows sample // Purpose: TextCtrl wxWindows sample
// Author: Robert Roebling // Author: Robert Roebling
// Modified by: // Modified by:
// RCS-ID: $Id$ // RCS-ID: $Id$
// Copyright: (c) Robert Roebling, Julian Smart // Copyright: (c) Robert Roebling, Julian Smart, Vadim Zeitlin
// Licence: wxWindows license // Licence: wxWindows license
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
@@ -67,6 +67,7 @@ public:
void OnKeyUp(wxKeyEvent& event); void OnKeyUp(wxKeyEvent& event);
void OnChar(wxKeyEvent& event); void OnChar(wxKeyEvent& event);
void OnText(wxCommandEvent& event); void OnText(wxCommandEvent& event);
void OnMouseEvent(wxMouseEvent& event);
bool m_hasCapture; bool m_hasCapture;
@@ -241,6 +242,7 @@ BEGIN_EVENT_TABLE(MyTextCtrl, wxTextCtrl)
EVT_KEY_UP(MyTextCtrl::OnKeyUp) EVT_KEY_UP(MyTextCtrl::OnKeyUp)
EVT_CHAR(MyTextCtrl::OnChar) EVT_CHAR(MyTextCtrl::OnChar)
EVT_TEXT(-1, MyTextCtrl::OnText) EVT_TEXT(-1, MyTextCtrl::OnText)
EVT_MOUSE_EVENTS(MyTextCtrl::OnMouseEvent)
END_EVENT_TABLE() END_EVENT_TABLE()
void MyTextCtrl::LogEvent(const wxChar *name, wxKeyEvent& event) const void MyTextCtrl::LogEvent(const wxChar *name, wxKeyEvent& event) const
@@ -372,6 +374,69 @@ void MyTextCtrl::LogEvent(const wxChar *name, wxKeyEvent& event) const
} }
void MyTextCtrl::OnMouseEvent(wxMouseEvent& ev)
{
if ( !ev.Moving() )
{
wxString msg;
if ( ev.Entering() )
{
msg = _T("Mouse entered the window");
}
else if ( ev.Leaving() )
{
msg = _T("Mouse left the window");
}
else
{
// click event
wxString button;
bool dbl, up;
if ( ev.LeftDown() || ev.LeftUp() || ev.LeftDClick() )
{
button = _T("Left");
dbl = ev.LeftDClick();
up = ev.LeftUp();
}
else if ( ev.MiddleDown() || ev.MiddleUp() || ev.MiddleDClick() )
{
button = _T("Middle");
dbl = ev.MiddleDClick();
up = ev.MiddleUp();
}
else if ( ev.RightDown() || ev.RightUp() || ev.RightDClick() )
{
button = _T("Right");
dbl = ev.RightDClick();
up = ev.RightUp();
}
else
{
wxLogStatus(_T("Unknown mouse event"));
return;
}
msg.Printf(_T("%s mouse button %s"),
button.c_str(),
dbl ? _T("double clicked")
: up ? _T("released") : _T("clicked"));
}
msg << _T(" at (") << ev.GetX() << _T(", ") << ev.GetY() << _T(") ")
<< _T("Flags: ")
<< GetChar( ev.LeftDown(), _T('1') )
<< GetChar( ev.MiddleDown(), _T('2') )
<< GetChar( ev.RightDown(), _T('3') )
<< GetChar( ev.ControlDown(), _T('C') )
<< GetChar( ev.AltDown(), _T('A') )
<< GetChar( ev.ShiftDown(), _T('S') )
<< GetChar( ev.MetaDown(), _T('M') );
wxLogMessage(msg);
}
//else: we're not interested in mouse move events
}
void MyTextCtrl::OnText(wxCommandEvent& event) void MyTextCtrl::OnText(wxCommandEvent& event)
{ {
MyTextCtrl *win = (MyTextCtrl *)event.GetEventObject(); MyTextCtrl *win = (MyTextCtrl *)event.GetEventObject();

View File

@@ -2884,6 +2884,9 @@ wxImage wxImage::Rotate(double angle, const wxPoint & centre_of_rotation, bool i
} }
} }
delete [] data;
delete [] result_data;
return rotated; return rotated;
} }

View File

@@ -84,6 +84,7 @@ public:
// event handlers // event handlers
void OnOk(wxCommandEvent& event); void OnOk(wxCommandEvent& event);
void OnDetails(wxCommandEvent& event); void OnDetails(wxCommandEvent& event);
void OnListSelect(wxListEvent& event);
private: private:
// the data for the listctrl // the data for the listctrl
@@ -104,6 +105,7 @@ private:
BEGIN_EVENT_TABLE(wxLogDialog, wxDialog) BEGIN_EVENT_TABLE(wxLogDialog, wxDialog)
EVT_BUTTON(wxID_OK, wxLogDialog::OnOk) EVT_BUTTON(wxID_OK, wxLogDialog::OnOk)
EVT_BUTTON(wxID_MORE, wxLogDialog::OnDetails) EVT_BUTTON(wxID_MORE, wxLogDialog::OnDetails)
EVT_LIST_ITEM_SELECTED(-1, wxLogDialog::OnListSelect)
END_EVENT_TABLE() END_EVENT_TABLE()
#endif // wxUSE_LOG_DIALOG #endif // wxUSE_LOG_DIALOG
@@ -642,9 +644,27 @@ wxLogDialog::wxLogDialog(wxWindow *parent,
const wxArrayLong& times, const wxArrayLong& times,
const wxString& caption, const wxString& caption,
long style) long style)
: wxDialog(parent, -1, caption ), : wxDialog(parent, -1, caption )
m_messages(messages), m_severity(severity), m_times(times)
{ {
size_t count = messages.GetCount();
m_messages.Alloc(count);
m_severity.Alloc(count);
m_times.Alloc(count);
for ( size_t n = 0; n < count; n++ )
{
wxString msg = messages[n];
do
{
m_messages.Add(msg.BeforeFirst(_T('\n')));
msg = msg.AfterFirst(_T('\n'));
m_severity.Add(severity[n]);
m_times.Add(times[n]);
}
while ( !!msg );
}
m_showingDetails = FALSE; // not initially m_showingDetails = FALSE; // not initially
m_listctrl = (wxListCtrl *)NULL; m_listctrl = (wxListCtrl *)NULL;
@@ -676,7 +696,7 @@ wxLogDialog::wxLogDialog(wxWindow *parent,
btnOk->SetFocus(); btnOk->SetFocus();
if ( m_messages.GetCount() == 1 ) if ( count == 1 )
{ {
// no details... it's easier to disable a button than to change the // no details... it's easier to disable a button than to change the
// dialog layout depending on whether we have details or not // dialog layout depending on whether we have details or not
@@ -686,6 +706,14 @@ wxLogDialog::wxLogDialog(wxWindow *parent,
Centre(); Centre();
} }
void wxLogDialog::OnListSelect(wxListEvent& event)
{
// we can't just disable the control because this looks ugly under Windows
// (wrong bg colour, no scrolling...), but we still want to disable
// selecting items - it makes no sense here
m_listctrl->SetItemState(event.GetItem(), 0, wxLIST_STATE_SELECTED);
}
void wxLogDialog::OnOk(wxCommandEvent& WXUNUSED(event)) void wxLogDialog::OnOk(wxCommandEvent& WXUNUSED(event))
{ {
EndModal(wxID_OK); EndModal(wxID_OK);
@@ -712,7 +740,8 @@ void wxLogDialog::OnDetails(wxCommandEvent& WXUNUSED(event))
wxDefaultPosition, wxDefaultSize, wxDefaultPosition, wxDefaultSize,
wxSUNKEN_BORDER | wxSUNKEN_BORDER |
wxLC_REPORT | wxLC_REPORT |
wxLC_NO_HEADER ); wxLC_NO_HEADER |
wxLC_SINGLE_SEL);
m_listctrl->InsertColumn(0, _("Message")); m_listctrl->InsertColumn(0, _("Message"));
m_listctrl->InsertColumn(1, _("Time")); m_listctrl->InsertColumn(1, _("Time"));

View File

@@ -74,6 +74,10 @@ static const int MM_METRIC = 10;
static const double M_PI = 3.14159265358979323846; static const double M_PI = 3.14159265358979323846;
#endif // M_PI #endif // M_PI
// ROPs which don't have standard names (see "Ternary Raster Operations" in the
// MSDN docs for how this and other numbers in wxDC::Blit() are obtained)
#define DSTCOPY 0x00AA0029 // a.k.a. NOP operation
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// private functions // private functions
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -679,30 +683,19 @@ void wxDC::DoDrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask
HDC hdcMem = ::CreateCompatibleDC(GetHdc()); HDC hdcMem = ::CreateCompatibleDC(GetHdc());
::SelectObject(hdcMem, GetHbitmapOf(bmp)); ::SelectObject(hdcMem, GetHbitmapOf(bmp));
// this will only work if the transparent part of our bitmap is black // use MaskBlt() with ROP which doesn't do anything to dst in the mask
// because it is combined with the destination rectangle using OR, so // points
// it won't be really transparent otherwise - I don't know what to do
// about it, may be use MAKEROP4(SRCCOPY, DSTINVERT) twice? Or create a
// copy of the bitmap with the transparent part replaced with black
// pixels?
// GRG: now this works regardless of what the source bitmap
// contains in the area which is to be transparent.
//
bool ok = ::MaskBlt(GetHdc(), x, y, width, height, bool ok = ::MaskBlt(GetHdc(), x, y, width, height,
hdcMem, 0, 0, hdcMem, 0, 0,
hbmpMask, 0, 0, hbmpMask, 0, 0,
MAKEROP4(SRCCOPY, 0x00AA0029)) != 0; MAKEROP4(SRCCOPY, DSTCOPY)) != 0;
::DeleteDC(hdcMem); ::DeleteDC(hdcMem);
if ( !ok ) if ( !ok )
#endif // Win32 #endif // Win32
{ {
// VZ: this is incorrect, Blit() doesn't (and can't) draw // Rather than reproduce wxDC::Blit, let's do it at the wxWin API
// transparently, but it's still better than nothing at all // level
// GRG: Blit() *should* draw transparently when there is a mask
// Rather than reproduce wxDC::Blit, let's do it at the wxWin API level
wxMemoryDC memDC; wxMemoryDC memDC;
memDC.SelectObject(bmp); memDC.SelectObject(bmp);
@@ -1048,22 +1041,23 @@ void wxDC::SetRop(WXHDC dc)
switch (m_logicalFunction) switch (m_logicalFunction)
{ {
case wxCLEAR: rop = R2_BLACK; break;
case wxXOR: rop = R2_XORPEN; break; case wxXOR: rop = R2_XORPEN; break;
case wxINVERT: rop = R2_NOT; break; case wxINVERT: rop = R2_NOT; break;
case wxOR_REVERSE: rop = R2_MERGEPENNOT; break; case wxOR_REVERSE: rop = R2_MERGEPENNOT; break;
case wxAND_REVERSE: rop = R2_MASKPENNOT; break; case wxAND_REVERSE: rop = R2_MASKPENNOT; break;
case wxCLEAR: rop = R2_WHITE; break;
case wxSET: rop = R2_BLACK; break;
case wxOR_INVERT: rop = R2_MERGENOTPEN; break;
case wxAND: rop = R2_MASKPEN; break;
case wxOR: rop = R2_MERGEPEN; break;
case wxEQUIV: rop = R2_NOTXORPEN; break;
case wxNAND: rop = R2_NOTMASKPEN; break;
case wxAND_INVERT: rop = R2_MASKNOTPEN; break;
case wxCOPY: rop = R2_COPYPEN; break; case wxCOPY: rop = R2_COPYPEN; break;
case wxAND: rop = R2_MASKPEN; break;
case wxAND_INVERT: rop = R2_MASKNOTPEN; break;
case wxNO_OP: rop = R2_NOP; break; case wxNO_OP: rop = R2_NOP; break;
case wxSRC_INVERT: rop = R2_NOTCOPYPEN; break;
case wxNOR: rop = R2_NOTMERGEPEN; break; case wxNOR: rop = R2_NOTMERGEPEN; break;
case wxEQUIV: rop = R2_NOTXORPEN; break;
case wxSRC_INVERT: rop = R2_NOTCOPYPEN; break;
case wxOR_INVERT: rop = R2_MERGENOTPEN; break;
case wxNAND: rop = R2_NOTMASKPEN; break;
case wxOR: rop = R2_MERGEPEN; break;
case wxSET: rop = R2_WHITE; break;
default: default:
wxFAIL_MSG( wxT("unsupported logical function") ); wxFAIL_MSG( wxT("unsupported logical function") );
return; return;
@@ -1334,7 +1328,7 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest,
case wxNAND: dwRop = 0x007700E6; break; case wxNAND: dwRop = 0x007700E6; break;
case wxAND_INVERT: dwRop = 0x00220326; break; case wxAND_INVERT: dwRop = 0x00220326; break;
case wxCOPY: dwRop = SRCCOPY; break; case wxCOPY: dwRop = SRCCOPY; break;
case wxNO_OP: dwRop = 0x00AA0029; break; case wxNO_OP: dwRop = DSTCOPY; break;
case wxSRC_INVERT: dwRop = NOTSRCCOPY; break; case wxSRC_INVERT: dwRop = NOTSRCCOPY; break;
case wxNOR: dwRop = NOTSRCCOPY; break; case wxNOR: dwRop = NOTSRCCOPY; break;
default: default:
@@ -1347,46 +1341,14 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest,
if (useMask) if (useMask)
{ {
#ifdef __WIN32__ #ifdef __WIN32__
// prepare the mask bitmap
HBITMAP hbmpMask = wxInvertMask((HBITMAP)mask->GetMaskBitmap());
// select the correct brush: the current one by default, background one
// if none
HBRUSH hbrNew;
if ( m_brush.Ok() )
{
hbrNew = (HBRUSH)m_brush.GetResourceHandle();
}
else if ( m_backgroundBrush.Ok() )
{
hbrNew = (HBRUSH)m_backgroundBrush.GetResourceHandle();
}
else
{
hbrNew = 0;
}
HGDIOBJ hbrOld = hbrNew ? ::SelectObject(GetHdc(), hbrNew) : 0;
// we want the part of the image corresponding to the mask to be // we want the part of the image corresponding to the mask to be
// transparent, i.e. do PATCOPY there and apply dwRop elsewhere // transparent, so use "DSTCOPY" ROP for the mask points (the usual
// meaning of fg and bg is inverted which corresponds to wxWin notion
// GRG: PATCOPY is not transparent, as can be seen when blitting // of the mask which is also contrary to the Windows one)
// over a pattern: the 'transparent' area would be filled
// with the selected colour. We should use NOP instead, or
// do MaskBlt + BitBlt.
//
success = ::MaskBlt(GetHdc(), xdest, ydest, width, height, success = ::MaskBlt(GetHdc(), xdest, ydest, width, height,
GetHdcOf(*source), xsrc, ysrc, GetHdcOf(*source), xsrc, ysrc,
hbmpMask, 0, 0, (HBITMAP)mask->GetMaskBitmap(), 0, 0,
MAKEROP4(0x00AA0029, dwRop)) != 0; MAKEROP4(dwRop, DSTCOPY)) != 0;
if ( hbrNew )
{
(void)::SelectObject(GetHdc(), hbrOld);
}
::DeleteObject(hbmpMask);
if ( !success ) if ( !success )
#endif // Win32 #endif // Win32

View File

@@ -127,6 +127,10 @@ void wxRemoveHandleAssociation(wxWindow *win);
void wxAssociateWinWithHandle(HWND hWnd, wxWindow *win); void wxAssociateWinWithHandle(HWND hWnd, wxWindow *win);
wxWindow *wxFindWinFromHandle(WXHWND hWnd); wxWindow *wxFindWinFromHandle(WXHWND hWnd);
// this magical function is used to translate VK_APPS key presses to right
// mouse clicks
static void TranslateKbdEventToMouse(wxWindow *win, int *x, int *y, WPARAM *flags);
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// event tables // event tables
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -1998,20 +2002,11 @@ long wxWindow::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
// click because both usually pop up a context menu // click because both usually pop up a context menu
case VK_APPS: case VK_APPS:
{ {
// construct the key mask WPARAM flags;
WPARAM fwKeys = MK_RBUTTON; int x, y;
if ( (::GetKeyState(VK_CONTROL) & 0x100) != 0 )
fwKeys |= MK_CONTROL;
if ( (::GetKeyState(VK_SHIFT) & 0x100) != 0 )
fwKeys |= MK_SHIFT;
// simulate right mouse button click TranslateKbdEventToMouse(this, &x, &y, &flags);
DWORD dwPos = ::GetMessagePos(); processed = HandleMouseEvent(WM_RBUTTONDOWN, x, y, flags);
int x = GET_X_LPARAM(dwPos),
y = GET_Y_LPARAM(dwPos);
ScreenToClient(&x, &y);
processed = HandleMouseEvent(WM_RBUTTONDOWN, x, y, fwKeys);
} }
break; break;
#endif // VK_APPS #endif // VK_APPS
@@ -2027,7 +2022,21 @@ long wxWindow::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
case WM_SYSKEYUP: case WM_SYSKEYUP:
case WM_KEYUP: case WM_KEYUP:
processed = HandleKeyUp((WORD) wParam, lParam); #ifdef VK_APPS
// special case of VK_APPS: treat it the same as right mouse button
if ( wParam == VK_APPS )
{
WPARAM flags;
int x, y;
TranslateKbdEventToMouse(this, &x, &y, &flags);
processed = HandleMouseEvent(WM_RBUTTONUP, x, y, flags);
}
else
#endif // VK_APPS
{
processed = HandleKeyUp((WORD) wParam, lParam);
}
break; break;
case WM_SYSCHAR: case WM_SYSCHAR:
@@ -4168,3 +4177,22 @@ const char *wxGetMessageName(int message)
} }
} }
#endif //__WXDEBUG__ #endif //__WXDEBUG__
static void TranslateKbdEventToMouse(wxWindow *win, int *x, int *y, WPARAM *flags)
{
// construct the key mask
WPARAM& fwKeys = *flags;
fwKeys = MK_RBUTTON;
if ( (::GetKeyState(VK_CONTROL) & 0x100) != 0 )
fwKeys |= MK_CONTROL;
if ( (::GetKeyState(VK_SHIFT) & 0x100) != 0 )
fwKeys |= MK_SHIFT;
// simulate right mouse button click
DWORD dwPos = ::GetMessagePos();
*x = GET_X_LPARAM(dwPos);
*y = GET_Y_LPARAM(dwPos);
win->ScreenToClient(x, y);
}