/***************************************************************************** * 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 # include /*for the link cursor*/ #endif //(WINVER < 0x0500) && defined(_WTL_VER) #include #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 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& operator=(HCURSOR hCursor) { m_hCursor = hCursor; return *this; } //////////////////////////////////////////////////////////////////////////// // CCursorT& 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 CCursorHandle; typedef CCursorT 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__