Files
wxWidgets/src/msw/cursor.cpp
Vadim Zeitlin 55ccdb93e4 COW cleanup patch (1583966):
1. perform deep comparison for the classes for which it makes sense in the
   ports where this wasn't done yet
2. remove (shallow) comparison operators for the classes for which it does
   not make sense (such as wxBitmap)
3. makes wxBitmap use COW on all ports
4. adds wxObject::IsRefTo()
5. centralizes and improves COW docs


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@42752 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2006-10-30 19:26:48 +00:00

413 lines
12 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: src/msw/cursor.cpp
// Purpose: wxCursor class
// Author: Julian Smart
// Modified by:
// Created: 01/02/97
// RCS-ID: $Id$
// Copyright: (c) 1997-2003 Julian Smart and Vadim Zeitlin
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#include "wx/cursor.h"
#ifndef WX_PRECOMP
#include "wx/msw/missing.h" // IDC_HAND
#include "wx/utils.h"
#include "wx/app.h"
#include "wx/bitmap.h"
#include "wx/icon.h"
#include "wx/settings.h"
#include "wx/intl.h"
#include "wx/image.h"
#include "wx/module.h"
#endif
#include "wx/msw/private.h"
// define functions missing in MicroWin
#ifdef __WXMICROWIN__
static inline void DestroyCursor(HCURSOR) { }
static inline void SetCursor(HCURSOR) { }
#endif // __WXMICROWIN__
// ----------------------------------------------------------------------------
// private classes
// ----------------------------------------------------------------------------
class WXDLLEXPORT wxCursorRefData : public wxGDIImageRefData
{
public:
// the second parameter is used to tell us to delete the cursor when we're
// done with it (normally we shouldn't call DestroyCursor() this is why it
// doesn't happen by default)
wxCursorRefData(HCURSOR hcursor = 0, bool takeOwnership = false);
virtual ~wxCursorRefData() { Free(); }
virtual void Free();
// return the size of the standard cursor: notice that the system only
// supports the cursors of this size
static wxCoord GetStandardWidth();
static wxCoord GetStandardHeight();
private:
bool m_destroyCursor;
// standard cursor size, computed on first use
static wxSize ms_sizeStd;
};
// ----------------------------------------------------------------------------
// wxWin macros
// ----------------------------------------------------------------------------
IMPLEMENT_DYNAMIC_CLASS(wxCursor, wxGDIObject)
// ----------------------------------------------------------------------------
// globals
// ----------------------------------------------------------------------------
// Current cursor, in order to hang on to cursor handle when setting the cursor
// globally
static wxCursor *gs_globalCursor = NULL;
// ----------------------------------------------------------------------------
// private classes
// ----------------------------------------------------------------------------
class wxCursorModule : public wxModule
{
public:
virtual bool OnInit()
{
gs_globalCursor = new wxCursor;
return true;
}
virtual void OnExit()
{
delete gs_globalCursor;
gs_globalCursor = (wxCursor *)NULL;
}
};
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// wxCursorRefData
// ----------------------------------------------------------------------------
wxSize wxCursorRefData::ms_sizeStd;
wxCoord wxCursorRefData::GetStandardWidth()
{
if ( !ms_sizeStd.x )
ms_sizeStd.x = wxSystemSettings::GetMetric(wxSYS_CURSOR_X);
return ms_sizeStd.x;
}
wxCoord wxCursorRefData::GetStandardHeight()
{
if ( !ms_sizeStd.y )
ms_sizeStd.y = wxSystemSettings::GetMetric(wxSYS_CURSOR_Y);
return ms_sizeStd.y;
}
wxCursorRefData::wxCursorRefData(HCURSOR hcursor, bool destroy)
{
m_hCursor = (WXHCURSOR)hcursor;
if ( m_hCursor )
{
m_width = GetStandardWidth();
m_height = GetStandardHeight();
}
m_destroyCursor = destroy;
}
void wxCursorRefData::Free()
{
if ( m_hCursor )
{
#ifndef __WXWINCE__
if ( m_destroyCursor )
::DestroyCursor((HCURSOR)m_hCursor);
#endif
m_hCursor = 0;
}
}
// ----------------------------------------------------------------------------
// Cursors
// ----------------------------------------------------------------------------
wxCursor::wxCursor()
{
}
#if wxUSE_IMAGE
wxCursor::wxCursor(const wxImage& image)
{
// image has to be of the standard cursor size, otherwise we won't be able
// to create it
const int w = wxCursorRefData::GetStandardWidth();
const int h = wxCursorRefData::GetStandardHeight();
int hotSpotX = image.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_X);
int hotSpotY = image.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_Y);
int image_w = image.GetWidth();
int image_h = image.GetHeight();
wxASSERT_MSG( hotSpotX >= 0 && hotSpotX < image_w &&
hotSpotY >= 0 && hotSpotY < image_h,
_T("invalid cursor hot spot coordinates") );
wxImage imageSized(image); // final image of correct size
// if image is too small then place it in the center, resize it if too big
if ((w > image_w) && (h > image_h))
{
wxPoint offset((w - image_w)/2, (h - image_h)/2);
hotSpotX = hotSpotX + offset.x;
hotSpotY = hotSpotY + offset.y;
imageSized = image.Size(wxSize(w, h), offset);
}
else if ((w != image_w) || (h != image_h))
{
hotSpotX = int(hotSpotX * double(w) / double(image_w));
hotSpotY = int(hotSpotY * double(h) / double(image_h));
imageSized = image.Scale(w, h);
}
HCURSOR hcursor = wxBitmapToHCURSOR( wxBitmap(imageSized),
hotSpotX, hotSpotY );
#if wxUSE_WXDIB
if ( !hcursor )
{
wxLogWarning(_("Failed to create cursor."));
return;
}
#else
HCURSOR hcursor = 0;
#endif
m_refData = new wxCursorRefData(hcursor, true /* delete it later */);
}
#endif
wxCursor::wxCursor(const char WXUNUSED(bits)[],
int WXUNUSED(width),
int WXUNUSED(height),
int WXUNUSED(hotSpotX), int WXUNUSED(hotSpotY),
const char WXUNUSED(maskBits)[])
{
}
// MicroWin doesn't have support needed for the other ctors
#ifdef __WXMICROWIN__
wxCursor::wxCursor(const wxString& WXUNUSED(filename),
long WXUNUSED(kind),
int WXUNUSED(hotSpotX),
int WXUNUSED(hotSpotY))
{
}
wxCursor::wxCursor(int WXUNUSED(cursor_type))
{
}
#else // !__WXMICROWIN__
wxCursor::wxCursor(const wxString& filename,
long kind,
int hotSpotX,
int hotSpotY)
{
HCURSOR hcursor;
switch ( kind )
{
case wxBITMAP_TYPE_CUR_RESOURCE:
hcursor = ::LoadCursor(wxGetInstance(), filename);
break;
#ifndef __WXWINCE__
case wxBITMAP_TYPE_CUR:
hcursor = ::LoadCursorFromFile(filename);
break;
#endif
case wxBITMAP_TYPE_ICO:
hcursor = wxBitmapToHCURSOR
(
wxIcon(filename, wxBITMAP_TYPE_ICO),
hotSpotX,
hotSpotY
);
break;
case wxBITMAP_TYPE_BMP:
hcursor = wxBitmapToHCURSOR
(
wxBitmap(filename, wxBITMAP_TYPE_BMP),
hotSpotX,
hotSpotY
);
break;
default:
wxFAIL_MSG( _T("unknown cursor resource type") );
hcursor = NULL;
}
if ( hcursor )
{
m_refData = new wxCursorRefData(hcursor, true /* delete it later */);
}
}
// Cursors by stock number
wxCursor::wxCursor(int idCursor)
{
// all wxWidgets standard cursors
static const struct StdCursor
{
// is this a standard Windows cursor?
bool isStd;
// the cursor name or id
LPCTSTR name;
} stdCursors[] =
{
{ true, NULL }, // wxCURSOR_NONE
{ true, IDC_ARROW }, // wxCURSOR_ARROW
{ false, _T("WXCURSOR_RIGHT_ARROW") }, // wxCURSOR_RIGHT_ARROW
{ false, _T("WXCURSOR_BULLSEYE") }, // wxCURSOR_BULLSEYE
{ true, IDC_ARROW }, // WXCURSOR_CHAR
// Displays as an I-beam on XP, so use a cursor file
// { true, IDC_CROSS }, // WXCURSOR_CROSS
{ false, _T("WXCURSOR_CROSS") }, // WXCURSOR_CROSS
// See special handling below for wxCURSOR_HAND
// { false, _T("WXCURSOR_HAND") }, // wxCURSOR_HAND
{ true, IDC_HAND }, // wxCURSOR_HAND
{ true, IDC_IBEAM }, // WXCURSOR_IBEAM
{ true, IDC_ARROW }, // WXCURSOR_LEFT_BUTTON
{ false, _T("WXCURSOR_MAGNIFIER") }, // wxCURSOR_MAGNIFIER
{ true, IDC_ARROW }, // WXCURSOR_MIDDLE_BUTTON
{ true, IDC_NO }, // WXCURSOR_NO_ENTRY
{ false, _T("WXCURSOR_PBRUSH") }, // wxCURSOR_PAINT_BRUSH
{ false, _T("WXCURSOR_PENCIL") }, // wxCURSOR_PENCIL
{ false, _T("WXCURSOR_PLEFT") }, // wxCURSOR_POINT_LEFT
{ false, _T("WXCURSOR_PRIGHT") }, // wxCURSOR_POINT_RIGHT
{ true, IDC_HELP }, // WXCURSOR_QUESTION_ARROW
{ true, IDC_ARROW }, // WXCURSOR_RIGHT_BUTTON
{ true, IDC_SIZENESW }, // WXCURSOR_SIZENESW
{ true, IDC_SIZENS }, // WXCURSOR_SIZENS
{ true, IDC_SIZENWSE }, // WXCURSOR_SIZENWSE
{ true, IDC_SIZEWE }, // WXCURSOR_SIZEWE
{ true, IDC_SIZEALL }, // WXCURSOR_SIZING
{ false, _T("WXCURSOR_PBRUSH") }, // wxCURSOR_SPRAYCAN
{ true, IDC_WAIT }, // WXCURSOR_WAIT
{ true, IDC_WAIT }, // WXCURSOR_WATCH
{ false, _T("WXCURSOR_BLANK") }, // wxCURSOR_BLANK
{ true, IDC_APPSTARTING }, // wxCURSOR_ARROWWAIT
// no entry for wxCURSOR_MAX
};
wxCOMPILE_TIME_ASSERT( WXSIZEOF(stdCursors) == wxCURSOR_MAX,
CursorsIdArrayMismatch );
wxCHECK_RET( idCursor > 0 && (size_t)idCursor < WXSIZEOF(stdCursors),
_T("invalid cursor id in wxCursor() ctor") );
const StdCursor& stdCursor = stdCursors[idCursor];
bool deleteLater = !stdCursor.isStd;
HCURSOR hcursor = ::LoadCursor(stdCursor.isStd ? NULL : wxGetInstance(),
stdCursor.name);
// IDC_HAND may not be available on some versions of Windows.
if ( !hcursor && idCursor == wxCURSOR_HAND)
{
hcursor = ::LoadCursor(wxGetInstance(), _T("WXCURSOR_HAND"));
deleteLater = true;
}
if ( !hcursor )
{
wxLogLastError(_T("LoadCursor"));
}
else
{
m_refData = new wxCursorRefData(hcursor, deleteLater);
}
}
#endif // __WXMICROWIN__/!__WXMICROWIN__
wxCursor::~wxCursor()
{
}
// ----------------------------------------------------------------------------
// other wxCursor functions
// ----------------------------------------------------------------------------
wxGDIImageRefData *wxCursor::CreateData() const
{
return new wxCursorRefData;
}
// ----------------------------------------------------------------------------
// Global cursor setting
// ----------------------------------------------------------------------------
const wxCursor *wxGetGlobalCursor()
{
return gs_globalCursor;
}
void wxSetCursor(const wxCursor& cursor)
{
if ( cursor.Ok() )
{
::SetCursor(GetHcursorOf(cursor));
if ( gs_globalCursor )
*gs_globalCursor = cursor;
}
}