/*****************************************************************************
* Cursor.h : Utility class for dealing with HCURSORs
*
* TODO: Summary of classes
*
*****************************************************************************/
#ifndef __CURSOR_H__
#define __CURSOR_H__
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#if (WINVER < 0x0500)
&& defined(_WTL_VER)
# include <atlctrls.h>
# include <atlctrlx.h> /*for the
link cursor*/
#endif //(WINVER < 0x0500) && defined(_WTL_VER)
#include <winuser.h>
#if (!defined(ASSERT) && defined(_ATL_VER))
# define ASSERT ATLASSERT
#endif//(!defined(ASSERT) && defined(_ATL_VER))
/*****************************************************************************
* CLASS:
* CCursorT
*
* PLATFORM:
* Windows, WTL 3,
WTL 7.x - should work with MFC & pure win32
*
* AUTHOR:
* [JED] Jason
"Lumberjack" De Arte
*
http://www.1001010.com/
* Copyright (c)
2002 Jason De Arte
* Code is AS-IS
& use at your own risk. It may work,
but then again, it probably won't :)
*
* DESCRIPTION:
* Simple utility
class for using HCURSORs.
* I needed
something that would wrap the existance/non-existence
of IDC_HAND
* It's not the
"end-all be-all" solution, but it fits my needs
*
* The design is
inspired by the WTL classes in ATLGDI.H
*
* USAGE:
* Just like you
would an HCURSOR
*
* HISTORY:
* 2002.Apr.09.JED
- created
*
*******************************************************************************/
// Simple enumeration of the predefined cursors
enum CursorEnum
{
curArrow = 32512, //
IDC_ARROW Standard arrow
curIBeam = 32513, //
IDC_IBEAM I-beam
curWait = 32514, //
IDC_WAIT Hourglass
curCross = 32515, //
IDC_CROSS Crosshair
curUpArrow = 32516, //
IDC_UPARROW Vertical arrow
curSize = 32640, //
IDC_SIZE Obsolete for
applications marked version 4.0 or later. Use IDC_SIZEALL
curIcon = 32641, //
IDC_ICON Obsolete for
applications marked version 4.0 or later
curSizeNWSE = 32642, //
IDC_SIZENWSE Double-pointed arrow
pointing northwest and southeast
curSizeNESW = 32643, //
IDC_SIZENESW Double-pointed arrow
pointing northeast and southwest
curSizeWE = 32644, //
IDC_SIZEWE Double-pointed arrow
pointing west and east
curSizeNS = 32645, //
IDC_SIZENS Double-pointed arrow
pointing north and south
curSizeAll = 32646, //
IDC_SIZEALL Four-pointed arrow pointing north, south,
east, and west
curNo =
32648, //
IDC_NO Slashed circle
curHand = 32649, //
IDC_HAND Windows 98/Me, Windows
2000/XP: Hand
curAppStarting = 32650, // IDC_APPSTARTING
Standard arrow and small hourglass
curHelp = 32651, //
IDC_HELP Arrow and question mark
cur_NULL = 0, //
Special, uninitialized state
cur_Created = 1, //
Special, this was created with ::CreateCursor()
};
// Did you know that all the system cursors (that I know
about when writing this code)
// range from 0x7f00 to 0x7f8b? It makes for a quick (& imperfect) sanity
check
#define SYS_CURSOR_MASK 0x7F00
//**************************************************************************************
//
// The class CCursorT
//
template <bool t_bManaged>
class CCursorT
{
private:
HCURSOR m_hCursor; //
What this class wraps
BOOL m_bMustNotDestroy; // if we know we shouldn't do it - we shouldn't do it.
CursorEnum m_id; // Useful during debugging
public:
////////////////////////////////////////////////////////////////////////////
//
CCursorT( CursorEnum cur ) : m_hCursor(NULL), m_id(cur_NULL), m_bMustNotDestroy(0)
{
CCursorT::LoadCursor(cur);
}
////////////////////////////////////////////////////////////////////////////
//
CCursorT( HCURSOR hCursor = NULL ) : m_hCursor(hCursor), m_id(cur_NULL), m_bMustNotDestroy(0)
{ }
////////////////////////////////////////////////////////////////////////////
//
virtual ~CCursorT()
{
DestroyCursor();
}
////////////////////////////////////////////////////////////////////////////
//
CCursorT<t_bManaged>& operator=(HCURSOR hCursor)
{
m_hCursor = hCursor;
return *this;
}
////////////////////////////////////////////////////////////////////////////
//
CCursorT<t_bManaged>& operator=(CursorEnum cur)
{
CCursorT::LoadCursor(cur);
return *this;
}
////////////////////////////////////////////////////////////////////////////
//
operator HCURSOR() const { return m_hCursor; }
////////////////////////////////////////////////////////////////////////////
//
bool IsNull() const { return(NULL==m_hCursor); }
////////////////////////////////////////////////////////////////////////////
//
bool IsValid() const { return(NULL!=m_hCursor); }
////////////////////////////////////////////////////////////////////////////
// Set our cursor as the active cursor
HCURSOR SetCursor() const
{
if( m_hCursor )
return ::SetCursor(m_hCursor);
return NULL;
}
////////////////////////////////////////////////////////////////////////////
// Display/Hide the currently displayed/active cursor
(which may or may not be ours)
static int
ShowActiveCursor(BOOL bShow)
{
return ::ShowCursor(bShow);
}
////////////////////////////////////////////////////////////////////////////
// Is the currently displayed/active cursor visible? (which may or may not be ours)
static BOOL IsActiveCursorVisible()
{
BOOL bVisible = FALSE;
CCursorT::GetActiveCursorInfo(&bVisible,NULL,NULL);
return bVisible;
}
////////////////////////////////////////////////////////////////////////////
// Set the position of the currently displayed cursor
(which may or may not be ours)
static BOOL SetActiveCursorPos(POINT pt)
{
return ::SetCursorPos(pt.x,pt.y);
}
////////////////////////////////////////////////////////////////////////////
// Get the
position of the currently displayed cursor (which may or may not be ours)
static POINT GetActiveCursorPos()
{
POINT pt = {0,0};
if( !::GetCursorPos(&pt) )
pt.x = pt.y = 0;
return pt;
}
////////////////////////////////////////////////////////////////////////////
// Get information about the currently displayed cursor
(which may or may not be ours)
static BOOL GetActiveCursorInfo(BOOL* pbVisible, HCURSOR* phCursor, POINT* pptScreenPos)
{
if(!pbVisible && !phCursor &&
!pptScreenPos )
{
ASSERT(!"If you don't pass in anything, I can't do
anything");
return FALSE;
}
#if(WINVER >= 0x0500)
CURSORINFO info = {0};
info.cbSize = sizeof(CURSORINFO);
if( ::GetCursorInfo(&info) )
{
if( pbVisible )
*pbVisible = ((info.flags&CURSOR_SHOWING)==CURSOR_SHOWING);
if( phCursor )
*phCursor = info.hCursor;
if( pptScreenPos )
*pptScreenPos = info.ptScreenPos;
return TRUE;
}
#endif
if( pbVisible )
{
ShowActiveCursor(FALSE);
int
nDisplayCount = ShowActiveCursor(TRUE);
if( nDisplayCount > 0 )
*pbVisible = TRUE;
*pbVisible = FALSE;
}
if( phCursor )
*phCursor = ::GetCursor();
if( pptScreenPos )
::GetCursorPos(pptScreenPos);
return TRUE;
}
////////////////////////////////////////////////////////////////////////////
// Get the HCURSOR of the currently displayed cursor
(which may or may not be ours)
static HCURSOR GetActiveCursor()
{
HCURSOR hc
= NULL;
CCursorT::GetActiveCursorInfo(NULL,&hc,NULL);
return hc;
}
#if 0
static BOOL SetActiveClipArea(LPCRECT lprcScreenArea)
{
// process must have WINSTA_WRITEATTRIBUTES
// call with NULL to remove clipping
return ClipCursor(lprcScreenArea);
}
#endif
#if 0
static BOOL GetActiveClipArea(RECT& rcScreenArea)
{
// process must have WINSTA_READATTRIBUTES
return GetClipCursor(&rcScreenArea);
}
#endif
////////////////////////////////////////////////////////////////////////////
//
void Attach( HCURSOR hCursor )
{
DestroyCursor();
m_hCursor = hCursor;
}
////////////////////////////////////////////////////////////////////////////
//
HCURSOR Detach()
{
HCURSOR hCursor = m_hCursor;
m_hCursor = NULL;
return hCursor;
}
////////////////////////////////////////////////////////////////////////////
// For naming convention compatability
with the rest of atlgdi.h
BOOL DeleteObject()
{
return DestroyCursor();
}
////////////////////////////////////////////////////////////////////////////
//
BOOL DestroyCursor()
{
BOOL bResult = TRUE;
if( t_bManaged && m_hCursor != NULL && !m_bMustNotDestroy )
{
// Do not use this function to destroy a shared cursor!
// The following functions obtain a shared cursor:
// * LoadCursor
// * LoadCursorFromFile
// * LoadImage (if you use the LR_SHARED flag)
// * CopyImage (if you use the LR_COPYRETURNORG flag and the hImage parameter is a shared cursor)
bResult = ::DestroyCursor(m_hCursor);
}
m_hCursor = NULL;
m_id = cur_NULL;
m_bMustNotDestroy = FALSE;
return bResult;
}
////////////////////////////////////////////////////////////////////////////
// creates a cursor from image data
BOOL CreateCursor( int xHotSpot,
int yHotSpot,
int nWidth,
int nHeight,
LPCVOID pvANDPlane,
LPCVOID pvXORPlane,
#if defined(_ATL_VER)
HINSTANCE hApplicationInstance
= _Module.GetModuleInstance()
#elif defined(_MFC_VER)
HINSTANCE hApplicationInstance
= AfxGetInstanceHandle()
#else
HINSTANCE hApplicationInstance
#endif
)
{
DestroyCursor();
m_hCursor = ::CreateCursor( hApplicationInstance, xHotSpot, yHotSpot, nWidth, nHeight, pvANDPlane, pvXORPlane );
if( NULL != m_hCursor )
{
m_id = cur_Created;
m_bMustNotDestroy = FALSE;
return TRUE;
}
return FALSE;
}
////////////////////////////////////////////////////////////////////////////
// Load a user defined cursor from resources
BOOL LoadCursor( LPCTSTR lpCursorName,
#if defined(_ATL_VER)
HINSTANCE hResourceInstance = _Module.GetResourceInstance()
#elif defined(_MFC_VER)
HINSTANCE hResourceInstance = AfxGetResourceHandle()
#else
HINSTANCE hResourceInstance
#endif
)
{
DestroyCursor();
m_hCursor = ::LoadCursor(hResourceInstance,lpCursorName);
if( m_hCursor )
{
m_bMustNotDestroy = (hResourceInstance!=NULL);
return TRUE;
}
return FALSE;
}
////////////////////////////////////////////////////////////////////////////
// Load a normal "predefined" cursor
BOOL LoadCursor(CursorEnum cur)
{
if( (SYS_CURSOR_MASK&cur) != SYS_CURSOR_MASK )
{
ASSERT(!"Not a valid cursor enum");
return FALSE;
}
// load the new cursor
if( CCursorT::LoadCursor( MAKEINTRESOURCE(cur), NULL ) )
{
m_id = cur;
}
else
{
//
// it failed?
//
// Maybe it was a special case cursor
//
switch( cur )
{
case curHand:
{
// the hand/link cursor is unavailable, get one from
those kind folks that wrote WTL
#if (WINVER < 0x0500)
&& defined(_WTL_VER)
CCursorT::CreateCursor( _AtlHyperLink_CursorData.xHotSpot,
_AtlHyperLink_CursorData.yHotSpot,
_AtlHyperLink_CursorData.cxWidth,
_AtlHyperLink_CursorData.cyHeight,
_AtlHyperLink_CursorData.arrANDPlane,
_AtlHyperLink_CursorData.arrXORPlane
);
#else
ASSERT(!"unable to load a hand cursor");
m_id = cur_NULL;
#endif //(WINVER < 0x0500) && defined(_WTL_VER)
}
break;
case curHelp:
ASSERT(!"TODO: support IDC_HELP");
m_id = cur_NULL;
break;
case curSize:
ASSERT(!"WinUser.h comments say
that IDC_SIZE is obsolete, I guess it finally is");
return CCursorT::LoadCursor(curSizeAll);
break;
case curIcon:
ASSERT(!"WinUser.h comments say
that IDC_ICON is obsolete, I guess it finally is");
return CCursorT::LoadCursor(curArrow);
break;
default:
ASSERT(!"Hmm, maybe we need to add other special case
cursors?");
m_id = cur_NULL;
}
}
return( NULL != m_hCursor );
}
};
//**************************************************************************************
//
// Helpful typedefs
//
typedef CCursorT<false> CCursorHandle;
typedef CCursorT<true> CCursor;
//**************************************************************************************
//
// Simple scope based set cursor/restore old cursor class
//
class CAutoWaitCursor : public CCursor
{
public:
CCursorHandle m_oldCursor;
CAutoWaitCursor( CursorEnum cursor = curWait ) : CCursor(cursor)
{
m_oldCursor = SetCursor();
}
~CAutoWaitCursor()
{
m_oldCursor.SetCursor();
}
};
#endif //__CURSOR_H__