TNB Library
TnbMfcAbstractButton.h
[詳解]
1#pragma once
13#include "TnbMfcCommon.h"
14
15
16
17#ifndef _TnbDOXYGEN //Document作成用シンボル
18#define BN_PUSHED_T 0x100
19#define BN_UNPUSHED_T 0x101
20#endif
21
22
23
24//TNB Library
25namespace TNB {
26namespace MFC {
27
28
29
80class CAbstractButton : public CWnd
81{
82 DEFSUPER(CWnd);
83public:
84
87 : m_shortcutKey(0), m_pushState(EP_Non), m_boHasHover(false)
88 , m_nowState(ES_Normal), m_lastState(EState(-1)), m_hFont(NULL), m_boInBmClick(false)
89 , m_boIsOnClickDisp(false), m_canSendDblClk(false), m_pressedMode(PM_Unused)
90 {
91 }
92
100 {
101 m_shortcutKey = other.m_shortcutKey;
102 m_hFont = other.m_hFont;
103 return *this;
104 }
105
107 virtual ~CAbstractButton(void)
108 {
109 }
110
117 void SetShortcutKey(TCHAR key)
118 {
119 m_shortcutKey = key;
120 }
121
128 {
129 CWnd* P = _super::GetParent();
130 if ( P != NULL )
131 {
132 P->SendMessage(DM_SETDEFID, _super::GetDlgCtrlID(), 0);
133 }
134 }
135
158 UINT GetState(void) const
159 {
160 ASSERT(::IsWindow(m_hWnd));
161 return static_cast<UINT>(::SendMessage(m_hWnd, BM_GETSTATE, 0, 0));
162 }
163
166 {
170 };
171
179 void SetPressedMode(bool isEnable)
180 {
181 m_pressedMode = isEnable ? PM_Lockable : PM_Unused;
182 }
183
192 {
193 m_pressedMode = pm;
194 }
195
196protected:
197
199 enum EState
200 {
205 };
206
213 {
214 return m_nowState;
215 }
216
223 {
224 m_nowState = s;
225 }
226
232 void SetSendDblClkMode(bool canSendDblClk)
233 {
234 m_canSendDblClk = canSendDblClk;
235 }
236
241 virtual void OnDrawButton(CDC* pDC) = 0;
242
249 virtual bool IsOnButton(const POINT& po) const
250 {
251 return ::WindowFromPoint(po) == m_hWnd;
252 }
253
260 {
261 if ( m_IsAlive() )
262 {
263 if ( ! _super::IsWindowEnabled() )
264 {
265 st = ES_Disable;
266 }
267 else if ( m_pushState == EP_Mouse )
268 {
269 st = ES_Pushed;
270 CPoint po = m_curpos;
271 ClientToScreen(&po);
272 if ( ! IsOnButton(po) )
273 {
274 st = ES_Normal;
275 }
276 }
277 else if ( m_pushState != EP_Non )
278 {
279 st = ES_Pushed;
280 }
281 else if ( m_boHasHover )
282 {
283 st = ES_Hover;
284 }
285 else
286 {
287 st = ES_Normal;
288 }
289 }
290 return st;
291 }
292
298 virtual bool HasFocus(void) const
299 {
300 return ::GetFocus() == m_hWnd;
301 }
302
307 virtual void OnClickButton(void)
308 {
309 }
310
316 virtual void OnChangeState(EState state)
317 {
318 }
319
332 virtual BOOL OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* _pResult)
333 {
334 if ( message == WM_COMMAND && lParam == reinterpret_cast<LPARAM>(m_hWnd) )
335 {
336 ASSERTLIB( (wParam & 0xFFFF) == static_cast<WPARAM>(GetDlgCtrlID()) );
337 ASSERTLIB( (BN_CLICKED * 0x10000) == 0 );
338 if ( (wParam & 0xFFFF0000) == 0 )
339 {
340 if ( ! m_boIsOnClickDisp )
341 {
343 }
344 else
345 {
346 m_boIsOnClickDisp = false;
347 }
348 }
349 }
350 return _super::OnChildNotify(message, wParam, lParam, _pResult);
351 }
352
362 virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
363 {
364 switch ( message )
365 {
366 case 0x0128/*WM_UPDATEUISTATE*/:
367 TTRACE0("WM_UPDATEUISTATE\n");
368 return 0;
369 case WM_ERASEBKGND:
370 TTRACE0("WM_ERASEBKGND\n");
371 return 0;
372 case WM_PRINTCLIENT:
373 TTRACE0("WM_PRINTCLIENT\n");
374 {
375 CDC* pDC = CDC::FromHandle(reinterpret_cast<HDC>(wParam));
376 if ( pDC != NULL )
377 {
378 OnDrawButton(pDC);
379 }
380 }
381 return 0;
382 case WM_PAINT:
383 TTRACE0("WM_PAINT\n");
384 {
385 CPaintDC dc(this); // 描画用のデバイス コンテキスト
386 OnDrawButton(&dc);
387 }
388 return 0;
389 case 0x031A/*WM_THEMECHANGED*/:
390 OnChangeState(m_nowState);
391 break;
392 case WM_SETFOCUS:
393 TTRACE0("WM_SETFOCUS\n");
394 OnChangeState(m_nowState);
395 m_RedrawWindow();
396 return 0;
397 case WM_KILLFOCUS:
398 TTRACE0("WM_KILLFOCUS\n");
399 if ( m_pushState != EP_Non && ! m_IsPressedLockMode() )
400 {
401 m_pushState = EP_Non;
402 ::ReleaseCapture();
403 m_HoverOff(false);
404 m_CheckNowState(false);
405 m_RedrawWindow();
406 }
407 else
408 {
409 OnChangeState(m_nowState);
410 }
411 m_RedrawWindow();
412 return 0;
413 case WM_GETDLGCODE:
414 TTRACE0("WM_GETDLGCODE\n");
415 if ( HasFocus() )
416 {
417 return DLGC_DEFPUSHBUTTON | DLGC_BUTTON;
418 }
419 return DLGC_UNDEFPUSHBUTTON | DLGC_BUTTON;
420 case WM_GETTEXTLENGTH:
421 TTRACE0("WM_GETTEXTLENGTH\n");
422 if ( m_shortcutKey != 0 )
423 {
424 return 2 * sizeof(TCHAR);
425 }
426 break;
427 case WM_GETTEXT:
428 TTRACE0("WM_GETTEXT\n");
429 if ( m_shortcutKey != 0 && wParam >= 2 )
430 {
431 TCHAR* P = reinterpret_cast<TCHAR*>(lParam);
432 *P++ = '&';
433 *P++ = m_shortcutKey;
434 return 2;
435 }
436 break;
437 case WM_KEYDOWN:
438 TTRACE2("WM_KEYDOWN 0x%04X,0x%04X\n",wParam,lParam);
439 if ( wParam == ' ' )
440 {
441 m_Push(EP_Key);
442 }
443 return 0;
444 case WM_KEYUP:
445 TTRACE2("WM_KEYUP 0x%04X,0x%04X\n",wParam,lParam);
446 if ( wParam == ' ' )
447 {
448 m_Unpush(EP_Key);
449 if ( m_IsPressedLockMode() )
450 {
451 m_Unpush(EP_Mouse);
452 }
453 }
454 return 0;
455 case WM_LBUTTONDOWN:
456 TTRACE0("WM_LBUTTONDOWN\n");
457// m_curpos.x = LOWORD(lParam);
458// m_curpos.y = HIWORD(lParam);
459 m_curpos = CPoint(lParam);
460 m_Push(m_boInBmClick ? EP_Key : EP_Mouse);
461 return 0;
462 case WM_LBUTTONUP:
463 TTRACE0("WM_LBUTTONUP\n");
464 m_Unpush(m_boInBmClick ? EP_Key : EP_Mouse);
465 return 0;
466 case WM_LBUTTONDBLCLK:
467 TTRACE0("WM_LBUTTONDBLCLK\n");
468 if ( ! m_canSendDblClk )
469 {
470 m_Push(EP_Mouse);
471 }
472 else
473 {
474 m_SendCommand(BN_DBLCLK/*BN_DOUBLECLICKED*/);
475 }
476 return 0;
477 case WM_MOUSEMOVE:
478 TTRACE1("WM_MOUSEMOVE %X\n", lParam);
479 m_curpos = CPoint(lParam);
480 if ( ! m_boHasHover && m_pushState == EP_Non )
481 {
482 m_HoverOn(true);
483 }
484 else
485 {
486 m_CheckNowState(true);
487 }
488 break;
489 case WM_ENABLE:
490 TTRACE0("WM_ENABLE\n");
491 m_CheckNowState(true);
492 return 0;
493 case WM_GETFONT:
494 TTRACE0("WM_GETFONT\n");
495 {
496 HFONT f = m_hFont;
497 if ( f == NULL )
498 {
499 f = reinterpret_cast<HFONT>(::SendMessage(::GetParent(m_hWnd), WM_GETFONT, 0, 0));
500 }
501 if ( f == NULL )
502 {
503 f = reinterpret_cast<HFONT>(::GetStockObject(SYSTEM_FONT));
504 }
505 return reinterpret_cast<LRESULT>(f);
506 }
507 break;
508 case WM_SETFONT:
509 TTRACE0("WM_SETFONT\n");
510 m_hFont = reinterpret_cast<HFONT>(wParam);
511 if ( lParam != 0 )
512 {
513 m_RedrawWindow();
514 }
515 return 0;
516 case WM_DESTROY:
517 TTRACE0("WM_DESTROY\n");
518 m_pushState = EP_Non;
519 m_boHasHover = false;
521 m_lastState = static_cast<EState>(-1);
522 m_hFont = NULL;
523 m_boInBmClick = false;
524 m_boIsOnClickDisp = false;
525 break;
526 case BM_CLICK:
527 TTRACE0("BM_CLICK\n");
528 {
529 m_boInBmClick = true;
530 LRESULT r = _super::WindowProc(message, wParam, lParam);
531 m_boInBmClick = false;
532 return r;
533 }
534 break;
535 case BM_GETSTATE:
536 TTRACE0("BM_GETSTATE\n");
537 {
538 UINT r = 0;
539 r |= (m_nowState == ES_Pushed) ? BST_PUSHED : 0;//強調
540 r |= HasFocus() ? BST_FOCUS : 0;//フォーカス
541 return r;
542 }
543 break;
544 case BM_SETSTATE:
545 TTRACE0("BM_SETSTATE\n");
546 if ( wParam == 0 )
547 {
548 m_Unpush(EP_Message);
549 }
550 else
551 {
552 m_Push(EP_Message);
553 }
554 return 0;
555 case 0x02A1/*WM_MOUSEHOVER*/:
556 TTRACE0("WM_MOUSEHOVER\n");
557 m_HoverOn(true);
558 break;
559 case 0x02A3/*WM_MOUSELEAVE*/:
560 TTRACE0("WM_MOUSELEAVE\n");
561 if ( m_boHasHover )
562 {
563 m_HoverOff(true);
564 }
565 else
566 {
567 m_CheckNowState(true);
568 }
569 break;
570 }
571 return _super::WindowProc(message, wParam, lParam);
572 }
573
579 virtual void PreSubclassWindow(void)
580 {
581 _super::ModifyStyle(0, SS_NOTIFY);
582 _super::PreSubclassWindow();
583 m_CheckNowState(false);
584 }
585
586private:
588 enum EPush
589 {
590 EP_Non,
591 EP_Mouse,
592 EP_Key,
593 EP_Message
594 };
595 EPush m_pushState;
596 bool m_boHasHover;
597 bool m_boInBmClick;
598 bool m_boIsOnClickDisp;
599 TCHAR m_shortcutKey;
600 HFONT m_hFont;
601 bool m_canSendDblClk;
602 EState m_nowState;
603 EState m_lastState;
604 CPoint m_curpos;
605 EPressMode m_pressedMode;
606 bool m_WithPressedMessage(void) const
607 {
608 return m_pressedMode != PM_Unused;
609 }
610 bool m_IsPressedLockMode(void) const
611 {
612 return m_pressedMode == PM_Lockable;
613 }
615 bool m_IsAlive(void) const
616 {
617 return !! ::IsWindow(GetSafeHwnd());
618 }
620 void m_SendCommand(UINT uCmd)
621 {
622 if ( m_IsAlive() )
623 {
624 MFCLIB::SendCommandMessage(this, uCmd);
625 }
626 }
628 void m_RedrawWindow(void)
629 {
630 if ( m_IsAlive() )
631 {
632 _super::RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
633 }
634 }
636 void m_CheckNowState(bool boRedraw)
637 {
638 if ( m_IsAlive() )
639 {
640 SetButtonState(OnCheckState(m_nowState));
641 if ( m_nowState != m_lastState )
642 {
643 m_lastState = m_nowState;
644 OnChangeState(m_nowState);
645 if ( boRedraw )
646 {
647 m_RedrawWindow();
648 }
649 }
650 }
651 }
653 void m_HoverOn(bool boRedraw)
654 {
655 #ifndef _WIN32_WCE
656 if ( ! m_boHasHover )
657 {
658 m_boHasHover = true;
659 m_CheckNowState(boRedraw);
660 m_SendCommand(BN_HILITE);
661 m_HoverSub();
662 }
663 #endif
664 }
666 void m_HoverOff(bool boRedraw)
667 {
668 #ifndef _WIN32_WCE
669 if ( m_boHasHover )
670 {
671 m_boHasHover = false;
672 m_CheckNowState(boRedraw);
673 m_SendCommand(BN_UNHILITE);
674 }
675 #endif
676 }
678 void m_Push(EPush ep)
679 {
680 if ( ! m_IsAlive() ) { return; }
681 if ( m_pushState == EP_Non )
682 {
683 m_pushState = ep;
684 if ( ! m_IsPressedLockMode() )
685 {
686 _super::SetCapture();
687 if ( m_WithPressedMessage() )
688 {
689 m_SendCommand(BN_PUSHED_T);
690 }
691 }
692 else
693 {
694 m_SendCommand(BN_PUSHED_T);
695 }
696 m_CheckNowState(true);
697 }
698 _super::SetFocus();
699 }
701 void m_Unpush(EPush ep)
702 {
703 if ( ! m_IsAlive() ) { return; }
704 if ( m_pushState != ep ) { return; }
705 m_pushState = EP_Non;
706 ::ReleaseCapture();
707 if ( ep != EP_Message )
708 {
709 CPoint po = m_curpos;
710 ClientToScreen(&po);
711 bool onButton = IsOnButton(po);
712 if ( ep == EP_Key || onButton )
713 {
714 m_boIsOnClickDisp = true;
716 if ( ! m_IsAlive() ) { return; }
717 #ifdef _WIN32_WCE
718 m_CheckNowState(false);
719 m_RedrawWindow();
720 if ( m_IsPressedLockMode() || m_WithPressedMessageMode() )
721 {
722 m_SendCommand(BN_UNPUSHED_T);
723 }
724 m_SendCommand(BN_CLICKED);
725 return;
726 #endif
727 if ( m_IsPressedLockMode() || m_WithPressedMessage() )
728 {
729 m_SendCommand(BN_UNPUSHED_T);
730 }
731 m_SendCommand(BN_CLICKED);
732 }
733 if ( ! onButton )
734 {
735 m_HoverOff(false);
736 }
737 }
738 m_CheckNowState(false);
739 m_RedrawWindow();
740 }
742 void m_HoverSub(void)
743 {
744 #ifndef _WIN32_WCE
745 TRACKMOUSEEVENT tme;
746 tme.cbSize = sizeof (TRACKMOUSEEVENT);
747 tme.hwndTrack = m_hWnd;
748 tme.dwHoverTime = HOVER_DEFAULT;
749 tme.dwFlags = TME_HOVER | TME_LEAVE;
750 ::_TrackMouseEvent(&tme);
751 #endif
752 }
753};
754
755
756
757}; //MFC
758}; //TNB
759
760
761
MFCコントロール共通のヘッダ
ウィンドウ管理.
HWND GetSafeHwnd(void) const
[取得] ウィンドウハンドル取得.
ボタンコントロール抽象クラス
void SetShortcutKey(TCHAR key)
[設定] ショートカットキー設定.
virtual void OnDrawButton(CDC *pDC)=0
[処理] 描画.
CAbstractButton(void)
コンストラクタ
CAbstractButton & operator=(const CAbstractButton &other)
コピーオペレータ.
virtual void OnChangeState(EState state)
[通知] 状態変化通知.
virtual EState OnCheckState(EState st)
[通知] 現在の状態確認通知
void SetPressedMode(bool isEnable)
[設定] プレスモード設定.
virtual BOOL OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT *_pResult)
[通知] for notifications from parent
EPressMode
プレスモード種
@ PM_Message
プレスメッセージ対応
@ PM_Lockable
プレスロック機能も有効
EState GetButtonState(void) const
[取得] ボタン状態取得.
virtual ~CAbstractButton(void)
デストラクタ
virtual void PreSubclassWindow(void)
[通知] subclassing/unsubclassing functions.
void SetSendDblClkMode(bool canSendDblClk)
[設定] ダブルクリックイベントサポート
void SetPressedMode(EPressMode pm)
[設定] プレスモード設定.
virtual bool HasFocus(void) const
[確認] フォーカスの有無
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
[通知] for processing Windows messages.
virtual void OnClickButton(void)
[通知] クリック.
void SetDefaultButtonStyle(void)
[設定] デフォルトボタンスタイル設定.
virtual bool IsOnButton(const POINT &po) const
[確認] ポイントがボタン上にあるか.
void SetButtonState(EState s)
[設定] ボタン状態設定.
UINT GetState(void) const
[取得] 状態取得.
LRESULT SendCommandMessage(CWnd *pCtrl, UINT cmd)
[処理] WM_COMMAND送信.
Definition: TnbMfcCommon.h:475
TNB Library
Definition: TnbDoxyTitle.txt:2