////////////////////////////////////////////////////////////////////// // Gestion des boutons a la main ! // // Sylvain Marechal ////////////////////////////////////////////////////////////////////// #include #include #include "btctrl.h" #include "tooltip.h" extern "C" WINUSERAPI BOOL WINAPI TrackMouseEvent( LPTRACKMOUSEEVENT lpEventTrack); BOOL ( WINAPI * pfTrackMouseEvent)( LPTRACKMOUSEEVENT lpEventTrack); BOOL CBtCtrl::m_s_fTrackMouseEvent = FALSE; /*--------------------------------------------------------------------------- ** ** SETBTTEXT **--------------------------------------------------------------------------- ** ** DESCRIPTION ** --SetBtText-- ** ARGUMENTS ** Argument1: HWND hWnd ** Argument2: LPSTR pszText ** RETOUR/RESULTAT ** void ** DIAGNOSTIC ** IMPLEMENTATION ** REMARQUE ** Rev 04/03/99 **--------------------------------------------------------------------------*/ void SetBtText(HWND hWnd, LPSTR pszText) { CBtCtrl * pCtrl; pCtrl = (CBtCtrl *)GetWindowLong( hWnd, GWL_USERDATA ); strcpy (pCtrl->m_szToolTipText, pszText) ; } /*--------------------------------------------------------------------------- ** ** REGISTERBTWINPROC **--------------------------------------------------------------------------- ** ** DESCRIPTION ** --RegisterBtWinProc-- ** ARGUMENTS ** RETOUR/RESULTAT ** BOOL ** DIAGNOSTIC ** IMPLEMENTATION ** REMARQUE ** Rev 04/03/99 **--------------------------------------------------------------------------*/ BOOL RegisterBtWinProc() { static BOOL s_fRegister = 0; if( s_fRegister ) { return 0; } s_fRegister =TRUE; WNDCLASSEX wndclass; wndclass.cbSize = sizeof(WNDCLASSEX); wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; wndclass.lpfnWndProc = BtWinProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = GetModuleHandle(NULL); wndclass.hIcon = NULL; wndclass.hIconSm = NULL; wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); wndclass.hbrBackground = CreateSolidBrush (GetSysColor (COLOR_MENU)); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = "BTCTRL"; if (!RegisterClassEx (&wndclass)) { MessageBox (NULL, "RegisterClassEx() failed!", "Error", MB_OK); return (1); } return 0; } /*--------------------------------------------------------------------------- ** ** CREATEBTWINDOW **--------------------------------------------------------------------------- ** ** DESCRIPTION ** --CreateBtWindow-- ** ARGUMENTS ** Argument1: HWND hWnd ** Argument2: UINT IDCtrl ** Argument3: int x ** Argument4: int y ** Argument5: int cx ** Argument6: int cy ** Argument7: LPCTSTR lpBitmapNameOn ** Argument8: LPCTSTR lpBitmapNameOff ** Argumentp: LPCTSTR lpBitmapNameMove ** RETOUR/RESULTAT ** HWND ** DIAGNOSTIC ** IMPLEMENTATION ** REMARQUE ** Rev 04/03/99 **--------------------------------------------------------------------------*/ HWND CreateBtWindow( HWND hWnd, UINT IDCtrl, int x, int y, LPCTSTR lpBitmapNameOn, LPCTSTR lpBitmapNameOff, LPCTSTR lpBitmapNameMove ) { ButtonRes b; RegisterBtWinProc(); b.lpBitmapNameOn = lpBitmapNameOn; b.lpBitmapNameOff = lpBitmapNameOff; b.lpBitmapNameMove = lpBitmapNameMove; b.x = x; b.y = y; return CreateWindow( "BTCTRL", // Classe "", // Window Text (Caption) WS_CHILD| WS_VISIBLE, // Style x,y, // Position 0, 0, // Taille hWnd, // Fentre parente (HMENU)IDCtrl, // Identifiant de fenetre GetModuleHandle(NULL), (LPVOID)&b); } /*--------------------------------------------------------------------------- ** ** PASCAL BTWINPROC **--------------------------------------------------------------------------- ** ** DESCRIPTION ** --PASCAL BtWinProc-- ** ARGUMENTS ** Argument1: HWND hWnd ** Argument2: UINT Msg ** Argument3: WPARAM wParam ** Argument4: LPARAM lParam ** RETOUR/RESULTAT ** long FAR ** DIAGNOSTIC ** IMPLEMENTATION ** REMARQUE ** Rev 04/03/99 **--------------------------------------------------------------------------*/ long FAR PASCAL BtWinProc( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam ) { CBtCtrl * pCtrl; MSG message ; message.hwnd = hWnd; message.message = Msg; message.wParam = wParam; message.lParam = lParam; message.time = GetTickCount(); switch( Msg ) { case WM_CREATE: { pCtrl = new CBtCtrl( hWnd ); SetWindowLong( hWnd, GWL_USERDATA, (long)pCtrl ); pCtrl->OnCreate( (LPCREATESTRUCT) lParam ); return 0; } case WM_SIZE: { pCtrl = (CBtCtrl *)GetWindowLong( hWnd, GWL_USERDATA ); int nWidth = LOWORD(lParam); int nHeight = HIWORD(lParam); if( pCtrl->OnSize( nWidth, nHeight) ) return 0; break; } case WM_TIMER: { pCtrl = (CBtCtrl *)GetWindowLong( hWnd, GWL_USERDATA ); if( pCtrl->OnTimer() ) return 0; break; } case WM_PAINT: { pCtrl = (CBtCtrl *)GetWindowLong( hWnd, GWL_USERDATA ); if( pCtrl->OnPaint() ) return 0; break; } case WM_MOUSELEAVE: { pCtrl = (CBtCtrl *)GetWindowLong( hWnd, GWL_USERDATA ); if( pCtrl->OnMouseLeave() ) return 0; break; } case WM_MOUSEHOVER: { pCtrl = (CBtCtrl *)GetWindowLong( hWnd, GWL_USERDATA ); if( pCtrl->OnMouseHover() ) return 0; break; } case WM_LBUTTONUP: { pCtrl = (CBtCtrl *)GetWindowLong( hWnd, GWL_USERDATA ); if( pCtrl->OnLButtonUp() ) return 0; break; } case WM_LBUTTONDOWN: { pCtrl = (CBtCtrl *)GetWindowLong( hWnd, GWL_USERDATA ); if( pCtrl->OnLButtonDown() ) return 0; break; } case WM_CAPTURECHANGED: { pCtrl = (CBtCtrl *)GetWindowLong( hWnd, GWL_USERDATA ); break; } case WM_LBUTTONDBLCLK: { pCtrl = (CBtCtrl *)GetWindowLong( hWnd, GWL_USERDATA ); if( pCtrl->OnLButtonDblClk() ) return 0; break; } case WM_MOUSEMOVE: case WM_NCMOUSEMOVE: { pCtrl = (CBtCtrl *)GetWindowLong( hWnd, GWL_USERDATA ); message.pt.x = LOWORD(lParam); // horizontal position of cursor message.pt.y = HIWORD(lParam); // vertical position of cursor ClientToScreen( hWnd, &message.pt ); // Faire suivre les messages souris a la fenetre tooltip (bulle d'aide) SendMessage( pCtrl->m_hWndTT, TTM_RELAYEVENT, 0, (LPARAM) (LPMSG) &message ); if( pCtrl->OnMouseMove(LOWORD(lParam),HIWORD(lParam)) ) return 0; break; } case WM_NCDESTROY: { pCtrl = (CBtCtrl *)GetWindowLong( hWnd, GWL_USERDATA ); pCtrl->OnNCDestroy(); delete pCtrl; return 0; } case WM_NOTIFY: { // Le ctrl tooltip a ete declare de maniere a ce qu'il envoie // un message a cette fenetre chaque fois qu'il a besoin d'afficher le texte // dans sa bulle d'aide (LPSTR_TEXTCALLBACK) NMHDR FAR *ph = (NMHDR FAR*)lParam ; pCtrl = (CBtCtrl *)GetWindowLong( hWnd, GWL_USERDATA); if (ph->code == TTN_NEEDTEXT) { LPTOOLTIPTEXT pttt = (LPTOOLTIPTEXT)lParam ; strcpy( pttt->szText, pCtrl->m_szToolTipText) ; return 0 ; } } break; } return DefWindowProc( hWnd, Msg, wParam, lParam ); } /*--------------------------------------------------------------------------- ** ** CBTCTRL::CBTCTRL **--------------------------------------------------------------------------- ** ** DESCRIPTION ** --CBtCtrl::CBtCtrl-- ** ARGUMENTS ** Argument1: HWND hWnd ** RETOUR/RESULTAT ** ** DIAGNOSTIC ** IMPLEMENTATION ** REMARQUE ** Rev 04/03/99 **--------------------------------------------------------------------------*/ CBtCtrl::CBtCtrl( HWND hWnd ) : m_hWnd (hWnd) { m_szToolTipText[0] = (char)0; m_fKillFocus = FALSE; m_fOn = FALSE; m_fInRegion = FALSE; m_iTestInRegion = 0; } /*--------------------------------------------------------------------------- ** ** CBTCTRL::~CBTCTRL **--------------------------------------------------------------------------- ** ** DESCRIPTION ** --CBtCtrl::~CBtCtrl-- ** ARGUMENTS ** RETOUR/RESULTAT ** ** DIAGNOSTIC ** IMPLEMENTATION ** REMARQUE ** Rev 04/03/99 **--------------------------------------------------------------------------*/ CBtCtrl::~CBtCtrl() { } /*--------------------------------------------------------------------------- ** ** CBTCTRL::ONCREATE **--------------------------------------------------------------------------- ** ** DESCRIPTION ** --CBtCtrl::OnCreate-- ** ARGUMENTS ** Argument1: LPCREATESTRUCT lpCreateStruct ** RETOUR/RESULTAT ** BOOL ** DIAGNOSTIC ** IMPLEMENTATION ** REMARQUE ** Rev 04/03/99 **--------------------------------------------------------------------------*/ BOOL CBtCtrl::OnCreate( LPCREATESTRUCT lpCreateStruct) { // On enreg la fen si pas fait RegisterBtWinProc(); // On charge les ressources ButtonRes b; b = *(ButtonRes*)lpCreateStruct->lpCreateParams; m_hBmpOn = LoadBitmap( GetModuleHandle(NULL), b.lpBitmapNameOn ); m_hBmpOff = LoadBitmap( GetModuleHandle(NULL), b.lpBitmapNameOff ); m_hBmpMove = LoadBitmap( GetModuleHandle(NULL), b.lpBitmapNameMove ); // On ajuste la taille de la fenetre sur celle du 1° button et on cree // la region qui va bien BITMAP bm; GetObject(m_hBmpOn, sizeof(bm), (LPSTR)&bm); MoveWindow( m_hWnd, b.x, b.y, bm.bmWidth, bm.bmHeight, TRUE ); m_hRgn = CreateEllipticRgn( 0, 0, bm.bmWidth, bm.bmHeight ); SetWindowRgn( m_hWnd, m_hRgn, TRUE ); // Creation de la fenetre du tooltip (bule d'aide) (voir tooltip.cpp) // Ajout du tooltip (voir tooltip.cpp) m_hWndTT = CreateTooltipWindow( m_hWnd ); AddTooltip( m_hWnd, m_hWndTT ); m_hBmpCourant = m_hBmpOff; // On regarde si ca marche avec TrackMouseEvent() TRACKMOUSEEVENT t; t.cbSize = sizeof(TRACKMOUSEEVENT); t.dwFlags = TME_LEAVE; t.hwndTrack = m_hWnd; t.dwHoverTime = HOVER_DEFAULT; TrackMouseEvent( &t ); // Si ca marche pas, on cree un timer if( ! m_s_fTrackMouseEvent ) m_uTimer = SetTimer( m_hWnd, 1, 50, NULL ); return TRUE; } /*--------------------------------------------------------------------------- ** ** CBTCTRL::TRACKMOUSEEVENT **--------------------------------------------------------------------------- ** ** DESCRIPTION ** --CBtCtrl::TrackMouseEvent-- ** ARGUMENTS ** Argument1: LPTRACKMOUSEEVENT lpEventTrack ** RETOUR/RESULTAT ** BOOL ** DIAGNOSTIC ** IMPLEMENTATION ** REMARQUE ** Rev 08/03/99 **--------------------------------------------------------------------------*/ BOOL CBtCtrl::TrackMouseEvent( LPTRACKMOUSEEVENT lpEventTrack ) { static fFirst = TRUE; if( fFirst ) { fFirst = FALSE; HINSTANCE hLib = LoadLibrary( "user32.dll") ; pfTrackMouseEvent = ( BOOL ( WINAPI * )( LPTRACKMOUSEEVENT ) ) GetProcAddress( hLib, "TrackMouseEvent" ); if( ! pfTrackMouseEvent ) { m_s_fTrackMouseEvent = FALSE; return FALSE; } m_s_fTrackMouseEvent = TRUE; } if( pfTrackMouseEvent ) return (*pfTrackMouseEvent)( lpEventTrack ); return FALSE; } /*--------------------------------------------------------------------------- ** ** CBTCTRL::ONNCDESTROY **--------------------------------------------------------------------------- ** ** DESCRIPTION ** --CBtCtrl::OnNCDestroy-- ** ARGUMENTS ** Argument1: LPCREATESTRUCT lpCreateStruct ** RETOUR/RESULTAT ** BOOL ** DIAGNOSTIC ** IMPLEMENTATION ** REMARQUE ** Rev 05/03/99 **--------------------------------------------------------------------------*/ BOOL CBtCtrl::OnNCDestroy() { if( ! m_s_fTrackMouseEvent ) KillTimer( m_hWnd, m_uTimer ); return TRUE; } /*--------------------------------------------------------------------------- ** ** CBTCTRL::ONMOUSELEAVE **--------------------------------------------------------------------------- ** ** DESCRIPTION ** --CBtCtrl::OnMouseLeave-- ** ARGUMENTS ** RETOUR/RESULTAT ** BOOL ** DIAGNOSTIC ** IMPLEMENTATION ** REMARQUE ** Rev 08/03/99 **--------------------------------------------------------------------------*/ BOOL CBtCtrl::OnMouseLeave() { m_hBmpCourant = m_hBmpOff; InvalidateRect( m_hWnd, NULL, FALSE ); return TRUE; } /*--------------------------------------------------------------------------- ** ** CBTCTRL::ONMOUSEHOVER **--------------------------------------------------------------------------- ** ** DESCRIPTION ** --CBtCtrl::OnMouseHover-- ** ARGUMENTS ** RETOUR/RESULTAT ** BOOL ** DIAGNOSTIC ** IMPLEMENTATION ** REMARQUE ** Rev 11/03/99 **--------------------------------------------------------------------------*/ BOOL CBtCtrl::OnMouseHover() { return TRUE; } /*--------------------------------------------------------------------------- ** ** CBTCTRL::ONTIMER **--------------------------------------------------------------------------- ** ** DESCRIPTION ** --CBtCtrl::OnTimer-- ** ARGUMENTS ** RETOUR/RESULTAT ** BOOL ** DIAGNOSTIC ** IMPLEMENTATION ** REMARQUE ** Rev 05/03/99 **--------------------------------------------------------------------------*/ BOOL CBtCtrl::OnTimer() { POINT pt; GetCursorPos( &pt ); // Si pas ds la region if( ! PtInRegion( m_hRgn, pt.x, pt.y ) ) { // On affiche le bitmap pas ds la region if( m_hBmpCourant == m_hBmpMove ) { m_hBmpCourant = m_hBmpOff; InvalidateRect( m_hWnd, NULL, FALSE ); } } else { // Si appuye et qu'on revient ds la region if( m_fOn ) { if( m_hBmpCourant == m_hBmpOff ) { m_hBmpCourant = m_hBmpOn; InvalidateRect( m_hWnd, NULL, FALSE ); } } else { if( m_hBmpCourant == m_hBmpOff ) { m_hBmpCourant = m_hBmpMove; InvalidateRect( m_hWnd, NULL, FALSE ); } } } return TRUE; } /*--------------------------------------------------------------------------- ** ** CBTCTRL::ONLBUTTONDOWN **--------------------------------------------------------------------------- ** ** DESCRIPTION ** --CBtCtrl::OnLButtonDown-- ** ARGUMENTS ** RETOUR/RESULTAT ** BOOL ** DIAGNOSTIC ** IMPLEMENTATION ** REMARQUE ** Rev 04/03/99 **--------------------------------------------------------------------------*/ BOOL CBtCtrl::OnLButtonDown() { SetCapture( m_hWnd ); m_fOn = TRUE; m_hBmpCourant = m_hBmpOn; InvalidateRect( m_hWnd, NULL, FALSE ); return TRUE; } /*--------------------------------------------------------------------------- ** ** CBTCTRL::ONLBUTTONUP **--------------------------------------------------------------------------- ** ** DESCRIPTION ** --CBtCtrl::OnLButtonUp-- ** ARGUMENTS ** RETOUR/RESULTAT ** BOOL ** DIAGNOSTIC ** IMPLEMENTATION ** REMARQUE ** Rev 04/03/99 **--------------------------------------------------------------------------*/ BOOL CBtCtrl::OnLButtonUp() { if( m_fOn ) { m_fOn = FALSE; ReleaseCapture(); // On ne lance le message que si on est dans la zone if( m_hBmpCourant == m_hBmpOn ) SendMessage( GetParent(m_hWnd), WM_COMMAND, GetDlgCtrlID(m_hWnd), (LPARAM)0 ); m_hBmpCourant = m_hBmpOff; InvalidateRect( m_hWnd, NULL, FALSE ); } return TRUE; } /*--------------------------------------------------------------------------- ** ** CBTCTRL::ONLBUTTONDBLCLK **--------------------------------------------------------------------------- ** ** DESCRIPTION ** --CBtCtrl::OnLButtonDblClk-- ** ARGUMENTS ** RETOUR/RESULTAT ** BOOL ** DIAGNOSTIC ** IMPLEMENTATION ** REMARQUE ** Rev 04/03/99 **--------------------------------------------------------------------------*/ BOOL CBtCtrl::OnLButtonDblClk() { SendMessage( GetParent(m_hWnd), WM_COMMAND, GetDlgCtrlID(m_hWnd), (LPARAM)0 ); return TRUE; } /*--------------------------------------------------------------------------- ** ** CBTCTRL::ONMOUSEMOVE **--------------------------------------------------------------------------- ** ** DESCRIPTION ** --CBtCtrl::OnMouseMove-- ** ARGUMENTS ** RETOUR/RESULTAT ** BOOL ** DIAGNOSTIC ** IMPLEMENTATION ** REMARQUE ** Rev 04/03/99 **--------------------------------------------------------------------------*/ BOOL CBtCtrl::OnMouseMove( int x, int y) { if( m_hBmpCourant != m_hBmpMove && ! m_fOn ) { m_hBmpCourant = m_hBmpMove; InvalidateRect( m_hWnd, NULL, FALSE ); } if( m_hBmpCourant == m_hBmpOff && m_fOn ) { m_hBmpCourant = m_hBmpOn; InvalidateRect( m_hWnd, NULL, FALSE ); } if( m_s_fTrackMouseEvent ) { TRACKMOUSEEVENT t; t.cbSize = sizeof(TRACKMOUSEEVENT); t.dwFlags = TME_LEAVE; t.hwndTrack = m_hWnd; t.dwHoverTime = HOVER_DEFAULT; TrackMouseEvent( &t ); } if( m_fOn ) { POINT pt; RECT rect; BOOL fInRegion; GetCursorPos( &pt ); #ifdef CA_MARCHE // On ne teste que tous le x fois car la fonction echoue souvent sous NT // PS : CA MARCHE PAS SOUS NT if( m_iTestInRegion == 0 ) fInRegion = PtInRegion( m_hRgn, pt.x, pt.y ); else fInRegion = m_fInRegion; m_iTestInRegion = (m_iTestInRegion + 1)%10; #else ScreenToClient( m_hWnd, &pt ); rect.left = 0; rect.right = m_nWidth; rect.top = 0; rect.bottom = m_nHeight; fInRegion = PtInRect( &rect, pt ); #endif if( ! fInRegion ) { if( m_hBmpCourant != m_hBmpOff ) { m_hBmpCourant = m_hBmpOff; InvalidateRect( m_hWnd, NULL, FALSE ); } } else { if( m_hBmpCourant == m_hBmpOff ) { m_hBmpCourant = m_hBmpOn; InvalidateRect( m_hWnd, NULL, FALSE ); } } } return TRUE; } /*--------------------------------------------------------------------------- ** ** CBTCTRL::ONSIZE **--------------------------------------------------------------------------- ** ** DESCRIPTION ** --CBtCtrl::OnSize-- ** ARGUMENTS ** Argument1: int nWidth ** Argument2: int nHeight ** RETOUR/RESULTAT ** BOOL ** DIAGNOSTIC ** IMPLEMENTATION ** REMARQUE ** Rev 04/03/99 **--------------------------------------------------------------------------*/ BOOL CBtCtrl::OnSize( int nWidth, int nHeight) { m_nWidth = nWidth; m_nHeight = nHeight; // Informer le tooltip que la taille de la fenetre a bouge SetTooltipInfo( m_hWnd, m_hWndTT ); return TRUE; } /*--------------------------------------------------------------------------- ** ** CBTCTRL::ONPAINT **--------------------------------------------------------------------------- ** ** DESCRIPTION ** --CBtCtrl::OnPaint-- ** ARGUMENTS ** RETOUR/RESULTAT ** BOOL ** DIAGNOSTIC ** IMPLEMENTATION ** REMARQUE ** Rev 04/03/99 **--------------------------------------------------------------------------*/ BOOL CBtCtrl::OnPaint() { PAINTSTRUCT ps; HDC hDC; hDC = BeginPaint (m_hWnd, &ps); HDC hDCMem = ::CreateCompatibleDC(hDC); HGDIOBJ hOld = ::SelectObject( hDCMem, m_hBmpCourant ); ::BitBlt( hDC, 0, 0, m_nWidth, m_nHeight, hDCMem, 0, 0, SRCCOPY ); SelectObject( hDCMem, hOld ); ::ReleaseDC( m_hWnd, hDCMem ); EndPaint (m_hWnd, &ps); return TRUE; }