Nous voulons créer un bouton qui lorsque on le maintient enfoncé, il exécute une action jusqu'à ce que ce dernier soit relaché.
Pour y parvenir nous allons définir une classe personnalisée de CButton ou bien de CMFCButton (si nous voulons des fonctionnaliés en plus pour notre bouton). Mais CButton suffit pour ce que nous recherchons.
Voici la classe :
1. Lorsque l'on click sur le bouton la méthode OnLButtonDown() est appelée et dans cette dernière un thread exécutant la tâche en continue est automatique lancé.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 class CStayPressedButton : public CButton { DECLARE_DYNAMIC(CStayPressedButton) public: CStayPressedButton(); virtual ~CStayPressedButton(); LPVOID m_pThreadUserData; AFX_THREADPROC m_pUserActionThreadProc; public: static UINT CALLBACK ThreadProc(LPVOID lParam); HANDLE m_hFinished; DECLARE_MESSAGE_MAP() public: afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnLButtonUp(UINT nFlags, CPoint point); afx_msg void OnMouseMove(UINT nFlags, CPoint point); };
2. Lorsque l'on relache le bouton la méthode OnLButtonUp() signale au thread qu'il doit stopper.
3. Lorsque la souris se trouvant à l'état enfoncé et sort du rectangle englobant du bouton, la méthode OnMouseMove() signale également que le thread doit stopper.
4. m_pThreadUserData contient les données que vous voulez passer au thread
5. m_pUserActionThreadProc pointe sur la méthode qui est le point d'entrée de votre thread
6. ThreadProc() est le thread lancé en interne par CStayPressedButton
7. m_hFinished est un handle pour signaler l'évènement d'arrêt du thread
Dans votre boite de dialogue vous ajoutez un bouton sur votre resource et vous lui mappez une variable CButton que vous remplacer en CStayPressedButton
8. UserActionThreadProc est la méthode qui s'exécutera en boucle dans le thread de CStayPressedButton::ThreadProc()
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 class CMyDlg : public CDialog { // ... CStayPressedButton m_btnStayPressed; // bouton resté pressé = action en continue int m_i; // déclaration de votre donnée personnelle à passer à pThreadUserData static UINT UserActionThreadProc(LPVOID pThreadUserData); // votre méthode static s'exécutant en continue //...
9. m_i est un exemple d'une de vos variables qui sera passé à pThreadUserData dans votre méthode CMyDlg::UserActionThreadProc()
10. m_btnStayPressed est notre Stay Pressed Button.
11. Dans le CMyDlg::OnInitDialog() je prépare le CStayPressedButton
12. Votre méthode en continue
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 m_i = 2; // votre données personnelles m_btnStayPressed.m_pThreadUserData = (LPVOID) &m_i; m_btnStayPressed.m_pUserActionThreadProc = (AFX_THREADPROC)UserActionThreadProc;
Et maintenant le code du CStayPressedButton
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 UINT CMyDlg::UserActionThreadProc(LPVOID pThreadUserData) { int i = *((int*)pThreadUserData); // exemple d'utilisation // work, work, work still working on stay pressed button state... // put your code here in the thread loop... return 0; }
13. Code d'initialisation :
14. Tables des messages
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 IMPLEMENT_DYNAMIC(CStayPressedButton, CButton) CStayPressedButton::CStayPressedButton() { m_pThreadUserData = NULL; m_pUserActionThreadProc = NULL; m_hFinished = ::CreateEvent(NULL, FALSE, FALSE, NULL); } CStayPressedButton::~CStayPressedButton() { if(m_hFinished) ::CloseHandle(m_hFinished); }
15. Quand le bouton gauche de la souris est enfoncé l'action est lancé :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 BEGIN_MESSAGE_MAP(CStayPressedButton, CButton) ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() ON_WM_MOUSEMOVE() END_MESSAGE_MAP()
16. Quand le bouton gauche de la souris est relaché l'action est stoppé:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 void CStayPressedButton::OnLButtonDown(UINT nFlags, CPoint point) { if(m_pUserActionThreadProc == NULL) { CButton::OnLButtonDown(nFlags, point); return; } SetCapture(); AfxBeginThread((AFX_THREADPROC)ThreadProc, (LPVOID) this); CButton::OnLButtonDown(nFlags, point); }
17. Si la souris sort du rectangle du bouton l'action est aussi stoppé:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 void CStayPressedButton::OnLButtonUp(UINT nFlags, CPoint point) { if(GetCapture()) { ::SetEvent(m_hFinished); ReleaseCapture(); } CButton::OnLButtonUp(nFlags, point); }
18. Le thread du bouton
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 void CStayPressedButton::OnMouseMove(UINT nFlags, CPoint point) { if(GetCapture()) { CRect rect; GetClientRect(&rect); if( !rect.PtInRect(point) ) { ::SetEvent(m_hFinished); ReleaseCapture(); } } CButton::OnMouseMove(nFlags, point); }
Et Voilà
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 UINT CALLBACK CStayPressedButton::ThreadProc(LPVOID pParam) { CStayPressedButton* pBtn = (CStayPressedButton*)pParam; ASSERT_KINDOF(CStayPressedButton, pBtn); do { pBtn->m_pUserActionThreadProc(pBtn->m_pThreadUserData); } while(::WaitForSingleObject(pBtn->m_hFinished, 0) != WAIT_OBJECT_0); return 0; }![]()
Partager